Author

Topic: [HACK] One-click mod report, not for the faint of heart (Read 2056 times)

copper member
Activity: 2562
Merit: 2510
Spear the bees
It's not really that important, but I know that some users care about their stats and don't want bad reports. Maybe there could be a counter of some sort, so if the post was reported let's say 5 times by 5 different users, it would be shown. That way, those who are sensitive to seeing bad reports don't have to act on it if they can see that the previous reports have stayed unhandled by the mods.
Redundant reports do not count as bad: they are batched as the same outcome. In reality, redundant reports may serve as a way to reduce the waiting time of severe reports, regarding malware or global-level issues. Unclear whether reports are queued or stacked in the same order for all moderators.
I've set the default refresh time to 20 seconds, but it is easily adjusted if you desire. I'm sure you could incorporate something similar in to the extension itself if you wanted, but this seemed easier.
Suggested timing/modifications for active users: adjust refresh time to 750-2000ms after submitting report to optimize forum delays to "real-time updates" without any excess refreshes. Lowest time between posts/reports is 4 seconds; experimentally a half dozen new pages per second.
legendary
Activity: 2212
Merit: 7064
"multi post" button does that.
Yeah I guess this would be the same and it's shorter then alternative I was using.

As far as modifying BPIP extension, even if I stick with predefined buttons and no configuration, there are still some issues to consider. Some people will not want to install the whole BPIP extension if they want only post reporting so I would need to make it so I can still update this standalone version if needed. I'll see what I can do but it's probably not going to be quick.
I am glad you are considering it, and there is really no need to rush anything so make it in your own time.
With all this updates I think that BPIP extension will soon have to be renamed to something more suiting, like BPIP+Plus or BPIP2 Smiley
legendary
Activity: 3654
Merit: 8909
https://bpip.org
I would add consecutive post report as one more default option in extension.

"multi post" button does that.

As far as modifying BPIP extension, even if I stick with predefined buttons and no configuration, there are still some issues to consider. Some people will not want to install the whole BPIP extension if they want only post reporting so I would need to make it so I can still update this standalone version if needed. I'll see what I can do but it's probably not going to be quick.
legendary
Activity: 2212
Merit: 7064
I've made some changes to this extension so it feels like a good time to bump the thread. The main change is a report tracker that shows if you have reported a post and what the status of the report is
How complicated is to add this one-click mode report as optional experimental feature in BPIP extension?
I don't want to install anything else in my browser and I am using BPIP all the time, so I guess I want firmware update with new features for ultimate all-in-one extesnion Cheesy

PS
I would add consecutive post report as one more default option in extension.
legendary
Activity: 3654
Merit: 8909
https://bpip.org
You forgot to say that every user must extract the downloaded zip file before "Load unpacked" so that the extension file is easy to find.

Thanks, I've clarified the instructions in the OP.
legendary
Activity: 1064
Merit: 1228
Playgram - The Telegram Casino
Suchmoon, thanks a lot for making this extension because honestly this is what I needed all along to report posts faster than usual.

Actually I should take some time to understand how to install it in crhome [after considering the risks], but I think 10 minutes is enough time to understand it properly. You forgot to say that every user must extract the downloaded zip file before "Load unpacked" so that the extension file is easy to find. But good because now this extension is working for me. Thanks



It seems the forum page to me has really changed now. LOL

legendary
Activity: 3668
Merit: 6382
Looking for campaign manager? Contact icopress!
I was considering it, but to make it really usable I would have to create a whole UI for configuring those report buttons because users can't modify the code of an extension that's installed permanently.

Not necessarily.
A simpler approach could be to make a poll, see the 5-10 most frequent options and add those.
Maybe, if not difficult, add flag for each of those option whether to be added or not + one flag for real vs demo mode.
But that's all. I was not implying anything fancy (which means unnecessary work), no. Just the useful part.
legendary
Activity: 3654
Merit: 8909
https://bpip.org
It shows only if you have reported the post, is it possible to add an optional feature to show if the post was reported by someone else together with displaying the status of that report? It's not really that important, but I know that some users care about their stats and don't want bad reports. Maybe there could be a counter of some sort, so if the post was reported let's say 5 times by 5 different users, it would be shown. That way, those who are sensitive to seeing bad reports don't have to act on it if they can see that the previous reports have stayed unhandled by the mods.    

Unfortunately the extension can't see what other users reported.

This basically just prevents me from reporting the same post twice, because sometimes I do a lot of reports and it takes mods some time to get through them, so there is a high chance that I'll come across a previously reported post that's still unhandled. That'd be a waste of time for mods.

Even if I could know that someone else reported it, that wouldn't be very useful without knowing why they reported it, and that may raise privacy issues. At any rate that's not possible.

I've just thrown together a very basic Tampermonkey script which will refresh your report history automatically every x number of seconds if you have it open in a tab. The tab doesn't need to be in focus. I've set the default refresh time to 20 seconds, but it is easily adjusted if you desire. I'm sure you could incorporate something similar in to the extension itself if you wanted, but this seemed easier.

I was thinking about automatic refresh but that solves only part of the real-time tracking issue. I would also have to implement something to update the post status in tabs that are already open, and there is also the delay - I might have 100 posts queued for reporting - so I would need to track the queue as well.

Is it difficult to make this part of the BPIP extension, as yet another optional feature?
To say that it would be a great addition it's an understatement.

I was considering it, but to make it really usable I would have to create a whole UI for configuring those report buttons because users can't modify the code of an extension that's installed permanently.
legendary
Activity: 3668
Merit: 6382
Looking for campaign manager? Contact icopress!
Is it difficult to make this part of the BPIP extension, as yet another optional feature?
To say that it would be a great addition it's an understatement.
legendary
Activity: 2268
Merit: 18711
After you report a few posts and want to see the updated status you would need to refresh the report history again, and reload any threads/post histories.
I've just thrown together a very basic Tampermonkey script which will refresh your report history automatically every x number of seconds if you have it open in a tab. The tab doesn't need to be in focus. I've set the default refresh time to 20 seconds, but it is easily adjusted if you desire. I'm sure you could incorporate something similar in to the extension itself if you wanted, but this seemed easier.

Just paste the code below in to a new Tampermonkey script.

Code:
// ==UserScript==
// @name        Report List Refresher
// @description Refreshes your report page every x seconds
// @include     https://bitcointalk.org/index.php?action=reportlist;mine
// ==/UserScript==

// Change the number before *1000 to your desired time in seconds. Default 20.

setTimeout(function(){ location.reload(); }, 20*1000);

is it possible to add an optional feature to show if the post was reported by someone else together with displaying the status of that report?
That would only be possible if the mod was given access to the forum moderators' global report queue and history, which is obviously never going to happen.
legendary
Activity: 2730
Merit: 7065
I've made some changes to this extension so it feels like a good time to bump the thread. The main change is a report tracker that shows if you have reported a post and what the status of the report is:
It shows only if you have reported the post, is it possible to add an optional feature to show if the post was reported by someone else together with displaying the status of that report? It's not really that important, but I know that some users care about their stats and don't want bad reports. Maybe there could be a counter of some sort, so if the post was reported let's say 5 times by 5 different users, it would be shown. That way, those who are sensitive to seeing bad reports don't have to act on it if they can see that the previous reports have stayed unhandled by the mods.     
legendary
Activity: 3654
Merit: 8909
https://bpip.org
Apparently it's been a while:

Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.


I've made some changes to this extension so it feels like a good time to bump the thread. The main change is a report tracker that shows if you have reported a post and what the status of the report is:

Loading...

Bad reports are shown in red, unhandled in yellow, good in green - I don't have an example because it's quite rare to have an existing post with a good report - and the one-click buttons will not be shown for such posts (but you can still use the regular "Report to moderator" link).

The way this works is very primitive. You need to open your report history. The extension collects your reports. Then when you open a thread or a user's post history, it will show the status on posts that have been reported. Obviously this has some limitations, for example the status is not real-time. After you report a few posts and want to see the updated status you would need to refresh the report history again, and reload any threads/post histories.

This works reasonably well for my workflow. I typically open the report history first, then open a bunch of tabs with non-overlapping content - e.g. multiple spam megathreads - and all previously reported posts are marked by the extension. New reports will not duplicate because the same post can't be in multiple threads. Then I need to refresh the report history only if I want to start working on a different set of content.

This would not work well if you open a number of overlapping tabs (e.g. threads and user post histories). It might be possible to track reports in real time as you click those reporting buttons but it seemed like too much hassle for me.

Other changes:
  • Added link to My Reports in the main menu: Loading...
  • Added support for Chrome (and possibly Edge).
  • Cleaned up and refactored the code. For example the code that creates report buttons moved to create_all_controls function.
  • Reduced some of the delays (still fits into the 4 second throttling limit), increased default queue size to 100, and added an exception if the queue is full so you will see the red border on the post immediately if you reach the limit.

The code is now on GitHub, which makes it easier for me to maintain. If you're upgrading from the original version and need to preserve your custom changes, you can create a branch off the first commit (which matches the original version), apply your custom code, and cherry-pick or merge from the main branch. Or if you're averse to git for some reason, you can just pick any bits of code you like any way you like, I won't hold that against you.

The usual caveat still applies: this is barely tested code and probably broken in some mysterious ways. Use at your own risk.
legendary
Activity: 2240
Merit: 3150
₿uy / $ell ..oeleo ;(
Thank you guys, I think i'm blind. I opened that link at least 3 times and somehow I missed that temporary extensions button. Need more coffee Smiley
legendary
Activity: 3654
Merit: 8909
https://bpip.org
Maybe a stupid question but I seems that I can't find the Add Temporary Addon in the about:debugging on Tor.
No need to mention that I was away for a while and Tor updated and now this...

Have you clicked on "This Tor Browser" on the left hand side on the about:debugging page?

Yeah it should be under there.

Bookmark this link:

Code:
about:debugging#/runtime/this-firefox

(you'll need it every time you restart the browser)
legendary
Activity: 2268
Merit: 18711
Have you clicked on "This Tor Browser" on the left hand side on the about:debugging page?
legendary
Activity: 2240
Merit: 3150
₿uy / $ell ..oeleo ;(
Maybe a stupid question but I seems that I can't find the Add Temporary Addon in the about:debugging on Tor.
No need to mention that I was away for a while and Tor updated and now this...
legendary
Activity: 1582
Merit: 1059
nutildah-III / NFT2021-04-01
I knew I'd seen this somewhere before, and indeed, it was on a screenshot you sent me once OP, can't remember when or why... Allow me to necrobump this extremely useful script. I've been reporting "old-school" until now - god knows it's a sports discipline in itself, should be considered for Tokyo 20201 -, but those days are over starting.... now.

FR1980 Reporting 2.0 coming up, special thx to OP.
HCP
legendary
Activity: 2086
Merit: 4361
Not sure that I quote from locked topics often enough for that to be useful for me, especially since you can do it manually in just a few seconds. I might give it a whirl if you upload your code though. Maybe we could move it to be beside the current "Quote" button rather than in the reporting toolbar.
I'm not terribly happy with the current location either tbh, it was simply "path of least resistance" Tongue

I'm sure it'll be possible to move it wherever you want... it's just a matter of identifying the correct TD's or DIVs or whatever and inserting the button and input objects. Wink



Quote
A more pressing question, however: What are you using to change to that dark theme? I like the look of it. Tongue
A browser extension called Stylus: https://add0n.com/stylus.html (It's a fork of "Stylish" I believe)

and a modified version of "nex dark theme": https://userstyles.org/styles/173576/nex-dark-theme

My "current" version of the theme (made some alterations to fix a few little visual quirks):
Code:
.tborder {
    border: none;
    background-color: transparent;
    padding: 0
}

form#quickModForm > table.bordercolor > tbody > tr > td {
    padding: 0;
}

/*استثناء عناصر من الغاء الحدود*/
#frmLogin table.tborder,
#creator table.tborder,
.tborder table#smfheader+table,
.tborder table#smfheader+table+table,
div#helpmenu+div#helpmain {
    border: 1px solid #373b44 !important;
}

/**/
.tborder table#smfheader+table,
.tborder table#smfheader+table+table {
    border-top: none !important;
}

.tborder table#smfheader+table {
    border-bottom: none !important;
}
#upshrinkHeader2 { padding-bottom: 1px; }
/*--------استثناء عناصر من الغاء الحدود نهاية--------*/


/* خانات الادخال input */
input,
input[type="text"],
textarea,
select {
    outline: none;
    padding: 4px;
    transition: all 0.2s;
    border-radius: 3px;
}

input:disabled  {
    background-color: #25282f;
}

input[type="button"],
input[type="submit"] {
    cursor: pointer;
    padding: 2px 10px !important;
    transition: all 0.2s;
color: #fff;
}

input:focus, textarea:focus {
    border-color: #6393bf !important;
}


input, input[type="text"], textarea {
    border: 1px solid #aaa;
}

select {padding: 2px}




/* الردود منفصلة كصناديق
-----------------------*/
#bodyarea > form > table > tbody > tr > td > table {
    margin-top: 10px;
}

#bodyarea > form > table > tbody > tr:first-child > td > table {
    margin-top: 0;
}

#bodyarea #quickModForm .bordercolor {
    background-color: transparent;
}

#quickModForm .windowbg, #quickModForm #preview_body{
    background-color: #f7f7f7;
}
#quickModForm .windowbg2 { background-color: #fff; }

#quickModForm .windowbg,
#quickModForm .windowbg2 {
    padding: 0;
    border-radius: 5px;
}

form#quickModForm > table:first-child > tbody > tr:first-child  td.windowbg:first-child {
    border-radius: 0 0 5px 5px;
}

#quickModForm td.windowbg > table > tbody > tr > td+td,
#quickModForm td.windowbg2 > table > tbody > tr > td+td{
    padding-right: 25px !important;
    padding-left: 25px !important;
}

#quickModForm td.windowbg > table > tbody > tr > td.poster_info,
#quickModForm td.windowbg2 > table > tbody > tr > td.poster_info {
    padding-left: 10px;
    width: 14%;
    overflow: auto !important;
    border-radius: 5px 0 0 5px;
}

#quickModForm td.windowbg > table > tbody > tr > td.poster_info {
    background-color: #f3f3f3;
}

#quickModForm td.windowbg2 > table > tbody > tr > td.poster_info {
    background-color: #f7f7f7;
}
/*-------- نهاية الردود منفصلة كصناديق --------*/



/*-------------------------
تعديلات بداخل المواضيع
--------------------------*/
.post { padding-top:5px; }

/* اخفاء Re:.. */
/* .subject a {display: none} */

/* تغير لون الفواصل */
hr, .hrcolor {
color: #d2d2d2;
background-color: #d2d2d2;
}
/* نهاية تعديلات بداخل المواضيع */



/*-----------------------------------
الاقتباسات
------------------------------------*/
.quote {
    color: inherit;
}

.quote,
.quoteheader {
    background-color: transparent;
    border: none;
    margin-top: 0;
}

.quoteheader {
    margin-right: 3px;
}

.quoteheader:before {
content: url(https://i.ibb.co/W0hX5KP/qicon.png);
    opacity: 0.1;
margin: 0 5px;
}




.quoteheader,
.quote {
    border-left: 4px solid #ddd;
}

/*عند مرور الماوس*/
.quote:hover {
    border-left: 4px solid #ccc;
}

.quoteheader:hover,
.quoteheader:hover + .quote,
.quoteheader:hover,
.quoteheader:hover + .quote
{
    border-left: 4px solid #ccc;
}


/* الاقتباس اتجاة يمين
----------------------*/
div.post[dir='rtl'] .quoteheader,
div.post[dir='rtl']  .quote{
    border-right: 4px solid #ddd;
    border-left: 0 !important;
}

div.post[dir='rtl']  .quote:hover {
 border-right-color: #ccc;
}

/* عند مرور الماوس اتجاة يمين*/
div.post[dir='rtl'] .quote:hover
{
    border-right: 4px solid #ccc;
}

div.post[dir='rtl'] .quoteheader:hover,
div.post[dir='rtl'] .quoteheader:hover + .quote {
    border-right: 4px solid #ccc;
}
/*---------- نهاية الاقتباسات ------------*/



/*-----------------------------------
    تنسيق عنوان الموضوع
------------------------------------*/
#bodyarea table.tborder tr.catbg3,
#bodyarea table.tborder tr.catbg3 td {
    background-image: none;
    background-color: #5b7e9e;
}

tr.catbg3 #top_subject {
    padding-top: 5px;
    padding-bottom: 5px;
}

#bodyarea table.tborder tr.catbg3 td:first-child {
    border-radius: 5px 0 0 0;
}

#bodyarea table.tborder tr.catbg3 td:last-child {
    border-radius: 0 5px 0 0;
}
/*---------- نهاية تنسيق عنوان الموضوع ------------*/



#bodyarea > div.tborder > table.bordercolor {
    border-radius: 5px 5px 0 0;
}

.catbg, .catbg2, .catbg3 {
    border-bottom: 0;
}

.catbg, tr.catbg td, .catbg3, tr.catbg3 td,
.catbg2, tr.catbg2 td {
    background-image: none;
    background-color: #5b7e9e;
}

tr.catbg3 #top_subject {
    padding-top: 5px;
    padding-bottom: 5px;
}

table.bordercolor tr td.catbg3:first-child {
    border-radius: 5px 0 0 0;
}

table.bordercolor tr td.catbg3:last-child {
    border-radius: 0 5px 0 0;
}

.tborder > .catbg:first-child,
table.bordercolor tr td.catbg:first-child,
.catbg2:first-child {
    border-radius: 5px 5px 0 0;
}



.bordercolor {
    margin-top: 0 !important;
}

/* الهيدر */
.tborder #smfheader td.catbg:first-child {
    border-radius: 5px 0 0 0
}

.tborder #smfheader td.catbg:last-child {
    border-radius: 0 5px 0 0
}




/* اضافة لون للمواضيع المتحكمة من صاحب الموضوع  */
#bodyarea tr.catbg3+tr td.smalltext {
    background-color: #fffce5;
    border-bottom: 1px solid #ffde7b;
}
/*---------- نهاية موضوع متحكم ------------*/



/*-----------------------------------
  تغير الصور الشخصية لدائرية
-----------------------------------*/
#quickModForm td.windowbg > table > tbody > tr > td.poster_info img.avatar,
#quickModForm td.windowbg2 > table > tbody > tr > td.poster_info img.avatar,
table > tbody > tr > td.windowbg img.avatar,
form[name=pmFolder]  img.avatar {
    display: inline-block;
    vertical-align: middle;
    border-radius: 100px;
    -webkit-border-radius: 100px;
    -moz-border-radius: 100px;
    -ms-border-radius: 100px;
    -o-border-radius: 100px;
    object-fit: cover;
    border: 2px solid #fff;
    -webkit-background-size: cover;
    -moz-background-size: cover;
    background-size: cover;
    background: no-repeat center center;

    box-shadow: 2px 2px 4px 0px #aaa;
}

/* الحجم بالمنشورات */
#quickModForm td.windowbg > table > tbody > tr > td.poster_info img.avatar,
#quickModForm td.windowbg2 > table > tbody > tr > td.poster_info img.avatar,
form[name=pmFolder]  img.avatar /*بصفحة الرسائل*/ {
    height: 4rem;
    width: 4rem;
}

/* الحجم بصفحة العضوء */
table.bordercolor > tbody > tr > td.windowbg img.avatar {
    height: 5.75rem;
    width: 5.75rem;
}

/* الحجم بالهيدر العلوي */
#upshrinkHeader table > tbody > tr > td.windowbg img.avatar {
    height: 3.5rem;
    width: 3.5rem;
}

/* من الديف الحاويoverflow اخفاء  */
#quickModForm td.windowbg > table > tbody > tr > td.poster_info div[style^="overflow"],
#quickModForm td.windowbg2 > table > tbody > tr > td.poster_info div[style^="overflow"]{
    overflow: unset !important;
}
/*------ نهاية تغير الصور الشخصية لدائرية ------*/

/* اخفاء حدود القائمة العلوية */
.tborder table#smfheader+table,
.tborder table#smfheader+table+table {
    border: none !important;
}

div[style="border:2px solid orange; background-color:lightyellow; padding:10px; margin-bottom:5px"] {
    color: black
}
div[style="border:2px solid red; background-color:#FF9696; padding:10px; margin-bottom:5px"] {
    color: black
}
div[style="border:2px solid red; background-color:#FF9696; padding:10px; margin-bottom:5px"] a {
    color: #666666
}

/* خانات الادخال input */
input, textarea {
    border-color: #424448 !important;
    background-color: #191c23;
}
input:focus, textarea:focus {
    border-color:#567ee0 !important;
}

input[type="button"],
input[type="submit"] {
    border: none;
    background-color: #3F51B5;
    border-radius: 3px;
    padding: 4px 7px !important;
}
input[type="button"]:hover,
input[type="submit"]:hover {
    background-color: #5265d9;
}


/* الوان القوائم الفاتحة */
.titlebg, tr.titlebg th, tr.titlebg td, .titlebg2, tr.titlebg2 th, tr.titlebg2 td
{
    border: none;
    background-image: none;
    background-color: #373b44;
}

/* لون النصوص بالثيم الاسود*/
body, td, th, tr,
.nav, .nav:link, .nav:visited,
a.nav:hover,
.windowbg, #preview_body,
.quoteheader, .codeheader, .code,
.windowbg2, .windowbg3,
.titlebg2 a:link, .titlebg2 a:visited,
.titlebg, .titlebg a:link, .titlebg a:visited,
.titlebg, tr.titlebg th, tr.titlebg td, .titlebg2, tr.titlebg2 th, tr.titlebg2 td,
input, textarea

{
    color: #ccc
}


/* لون الخلفية بالثيم الاسود */
.windowbg, #preview_body {
    background-color: #25282f;
}


/* الروابط */
a:visited {
    color: #939dc5;
}

a:link {
    color: #939dc5;
}

a.ul[href^="https://bitcointalk.org/"]:hover {
    color: #89c775 !important
}

.edited {
    border-bottom-color: #d6d6d6;
}


div#bodyarea .maintab_back a:link, div#bodyarea .maintab_back a:visited, div#bodyarea .mirrortab_back a:link, div#bodyarea .mirrortab_back a:visited {
    color: #939dc5;
}


/* الوان خلفية الردود */
#quickModForm .windowbg, #quickModForm #preview_body,
#quickModForm .windowbg2 {
    background-color: #23262f;
}

#quickModForm td.windowbg > table > tbody > tr > td.poster_info,
#quickModForm td.windowbg2 > table > tbody > tr > td.poster_info {
    background-color: #20232b;
}


/* الفواصل */
hr, .hrcolor {
color: #393c44;
background-color: #393c44;
}



/* الوان الاقتباسات
--------------------------*/
.quoteheader, .quoteheader a {
    color: #737c9e;
}

.quoteheader,
.quote{
    border-left: 4px solid #3d444e;
   
}

.quote:hover
{
    border-left: 4px solid #62676f;
}

.quoteheader:hover,
.quoteheader:hover + .quote
{
    border-left: 4px solid #62676f;
}

/* الاقتباس اتجاة يمين
----------------------*/
div.post[dir='rtl'] .quoteheader,
div.post[dir='rtl']  .quote{
    border-right: 4px solid #3d444e;
}

div.post[dir='rtl']  .quote:hover {
 border-right-color: #62676f;
}

/* عند مرور الماوس اتجاة يمين*/
div.post[dir='rtl'] .quote:hover
{
    border-right: 4px solid #62676f;
}

div.post[dir='rtl'] .quoteheader:hover,
div.post[dir='rtl'] .quoteheader:hover + .quote {
    border-right: 4px solid #62676f;
}
/*---------- نهاية الوان الاقتباسات ------------*/



/* الصور الشخصية */

#quickModForm td.windowbg > table > tbody > tr > td.poster_info img.avatar,
#quickModForm td.windowbg2 > table > tbody > tr > td.poster_info img.avatar,
table > tbody > tr > td.windowbg img.avatar,
form[name=pmFolder]  img.avatar
{
    background-color: #fff;
    border-color: #323640;
    box-shadow: 2px 2px 4px 0px #121c27;

}


/* الوان عنوان الموضوع */

#bodyarea table.tborder tr.catbg3,
#bodyarea table.tborder tr.catbg3 td {
    background-color: #373b44;

}

.catbg, tr.catbg td, .catbg3, tr.catbg3 td,
.catbg2, tr.catbg2 td {
    background-color: #3f4554;
}

#bodyarea table.tborder tr.catbg3,
#bodyarea table.tborder tr.catbg3 td {
    background-color: #373b44;
}


/* اضافة لون للمواضيع المتحكمة من صاحب الموضوع  */
#bodyarea tr.catbg3+tr td.smalltext {
    background-color: #292d38;
    border-bottom-color: #373b44;
    color: #fff
}


/* ----------------
    تعديل الالوان
------------------*/
[style^="color: black"], [style^="color:black"] {
    color: #d6d6d6 !important;
}

[style^="color: green"], [style^="color:green"] {
    color: #5bb55b !important;
}

[style^="color: red"], [style^="color:red"] {
    color: #ff3434 !important;
}

[style^="color: blue"], [style^="color:blue"] {
    color: #1f81ff !important;
}

/**/

[style^="background-color: yellow"], [style^="background-color:yellow"] {
    color: #000;
}


/* الوان شريط الانتقال بالاسفل */
.titlebg2 {
    background-image: none;
    border: none;
    background-color: #2d313a;
    color: #d6d6d6;
}


/* ايقونات الرد و التعديل و الحذف */
img.reply_button {
    /* content: url(https://i.ibb.co/d6zXLq1/brown-quote.png); */
    content: url(https://talkimg.com/images/2023/11/15/zcmMD.png);
}
img.modify_button {
    /* content: url(https://i.ibb.co/dLtnpKp/brown-edit.png); */
    content: url(https://talkimg.com/images/2023/11/15/zc6Jf.png);
}
img.remove_button {
    /* content: url(https://i.ibb.co/vPDfyG9/brown-delete.png); */
    content: url(https://talkimg.com/images/2023/11/15/zcPpZ.png);
   
}


/* ايقونة الاقتباس */
.quoteheader:before {
content: url(https://i.ibb.co/QpYLk0v/qiconw.png) !important;
    opacity: 0.22;
}


/* لون الكود */
.code {
    background-color: #2f323c;
    border-color: #444850;
}


/*تحت التجربة*/
.windowbg2 {
    background-color: #262931;
}

.bordercolor {
    background-color: #363940;
}


body {
    background-color: #191c23;
    color: #fff
}


.windowbg3 {
    background-color: #22242b;
}


/*---------------------------------
 تغير خلفية القائمة العلوية مؤقتاً !!!
الافضل تخصيص الالوان اكثر حتى يكون اكثر تناسق هذا موقت
---------------------------------*/
/* delete this code If images are not displayed in the top menu*/

.maintab_back {
    background-image: url('https://i.ibb.co/v1vrm0d/maintab-back.gif')
}
.maintab_first {
    background-image: url('https://i.ibb.co/DKK4rrX/maintab-first.gif')
}
.maintab_last {
    background-image: url('https://i.ibb.co/C9QxkDg/maintab-last.gif')
}


.maintab_active_first {
    background-image: url('https://i.ibb.co/Q96FRdx/maintab-active-first.gif')
}
.maintab_active_back {
    background-image: url('https://i.ibb.co/5Tk3s5j/maintab-active-back.gif')
}
.maintab_active_last {
    background-image: url('https://i.ibb.co/drDZN4d/maintab-active-last.gif')
}
/* end top menu background image! code*/


/*------------------------------
    شريط التمرير الجانبي
------------------------------*/
    ::-webkit-scrollbar {
        width: 10px;
        height: 8px;
    }

    ::-webkit-scrollbar-track-piece {
        background-color: #23262f;          /*Global Track Peice(the slider noob.)*/
        -webkit-border-radius: 6px;
    }

    ::-webkit-scrollbar-thumb:vertical {
        height: 50px;
        background-color: #373b44;            /* Up/Down slider background*/
        -webkit-border-radius: 6px;
       
    }
 
    ::-webkit-scrollbar-thumb:horizontal {
        width: 50px;
        background-color: #373b44;            /* Side/Side slider background*/
        -webkit-border-radius: 3px;
    }


    /* الشريط بالكود */
    /* الحجم */
    .code::-webkit-scrollbar {
        width: 7px;
        height: 7px;
    }
   
    /*مقبض التمرير*/ 
    .code::-webkit-scrollbar-thumb:vertical {
        height: 50px;
        background-color: #13161c;            /* Up/Down slider background*/
        -webkit-border-radius: 6px;
       
    }

    /*خلفية شريط التمرير*/
    .code::-webkit-scrollbar-track-piece {
        background-color: #23262f;          /*Global Track Peice(the slider noob.)*/
        -webkit-border-radius: 6px;
    }


    /* نهاية الشريط بالكود */

.windowbg b a {
    color: white
}


/* ------ نهاية شريط التمرير الجانبي ------- */
legendary
Activity: 2268
Merit: 18711
Not sure that I quote from locked topics often enough for that to be useful for me, especially since you can do it manually in just a few seconds. I might give it a whirl if you upload your code though. Maybe we could move it to be beside the current "Quote" button rather than in the reporting toolbar.

A more pressing question, however: What are you using to change to that dark theme? I like the look of it. Tongue

Edit: Thanks. My aversion to installing unnecessary add-ons might stop me using it, though; was hoping it might have just been a quick and nasty user script. Still, at least its open source. I'll take a good look next time I've got some time to spare.
HCP
legendary
Activity: 2086
Merit: 4361
Ok... so someone posted something today regarding reporting posts from a user's post history, and someone linked back to this thread. Not sure why exactly, but that re-ignited my desire to see if there was a way to "automate" quoting of posts in locked topics...

And I managed to add in a "hack" that more or less works. It isn't automated to the point of simply giving me a "quote" button on locked threads... but it is as simple as copying a URL and clicking a button.

So, I now have a "quote" button and "locked quote URL" text box:




If I copy the "permalink" URL for a post in a locked topic... say the URL for Post #3 from the locked thread here: https://bitcointalksearch.org/topic/m.53575600

I can copy/paste that into the "locked quote URL" text box:




Then I can click the "quote" button and it will automagically redirect to a slightly custom "post" URL which includes a the custom "lockedtopic" value in URL which the board ignores but is useful for passing info Tongue:




et voilà, the script then automagically modifies the pre-populated "textArea.Value", so that the "link=topic=TOPIC_ID" value gets changed to "lockedtopic" value:


And you're free to copy/paste the correctly formatted quote, with correct topic link and timestamp as you please.

Like this:
That was a clever and imaginative way to troll though. Smart dude. Theymos should reward him first (merits maybe?), ban after.



KNOWN ISSUES/LIMITATIONS:

1. I've configured it to wipe the "subject" value, to avoid accidentally posting into the new thread with the subject line of the locked thread that you're quoting from. Not sure how to fix this so that the subject is the same as the "unlocked" thread you're trying to post to? Huh For now, the workaround is to simply copy/paste the "locked quote" from the newly opened "post" window to a different quickpost/reply box.

2. You can only do one quote at a time. I would guess that theoretically it should be possible to do a comma separated list of locked quote URLs and then have the script open multiple tabs at once, but that doesn't seem like much of a timer saver of doing them one at a time Undecided

3. Currently only works from "thread view" in an unlocked thread... It doesn't work from the "post history view"... as you need a guaranteed "unlocked topic" to send to the "post" action, otherwise you'll get the "This topic is locked, you are not allowed to post or modify messages..." error Undecided  Possible workaround would be to create my own topic somewhere that I'm never going to lock and use that as a "default"? Huh

4. The code is pretty hacky and could probably be tidied up and refactored Tongue

If anyone is interested, let me know and I can look at posting up the modifications required.
HCP
legendary
Activity: 2086
Merit: 4361
I thought it's 300 good reports... HCP, please report 52 posts and let us know if you see it Wink
Can finally confirm... you need to get it to 300 good reports... I had a bunch of "unhandled" that I had hoped would push me up, but eventually found a few "gems" to report. Once I hit that 300 "good" then the "view report history" function was available.
legendary
Activity: 1232
Merit: 1080
What a awesome idea especially the queue feature I think that something like this should be added in natively into the forum as a feature it would make reporting posts on mass much easier maybe only give the option to those that have over 5000 good reports or something.

What's the drawbacks of using this via Tor? I haven't really looked at the code used but can anyone verify whether this would compromise anonymity? I'm currently reporting hundreds of posts a day and if I could make that more efficient then I think that would benefit both the forum and myself.
copper member
Activity: 2562
Merit: 2510
Spear the bees
Let me just say, being able to report an entire page at once is amazing. How satisfying it is to see everything grayed out immediately...
Rather than add in buttons, just querySelectorAll("div.post") and immediately report_post with a pre-designated message. This definitely curbs burst-posting spammers, hard.

Most users outside of the * discussion boards will never need to see the use of my "MASS SPAM" button. Smiley

Addendum: increase your promise timeout value if you are reporting a lot of posts.
staff
Activity: 3304
Merit: 4115
Fantastic tool that I've only just come across I'm sure will help us curb the oncoming invasion of spam due to the recent surge in price. Always appreciate anyone who dedicates their time in improving the forum by reporting content. Haven't tested the code myself or used it, but thanks for making something like this!

I'm fully expecting next time theymos releases the reporting stats that at least 10 people have 100k reports Wink
copper member
Activity: 2562
Merit: 2510
Spear the bees
Bump. Doubled my reports over two days. Notched the accuracy up 1%.
legendary
Activity: 2758
Merit: 6830
I thought it's 300 good reports... HCP, please report 52 posts and let us know if you see it Wink
Ops... you are right. Just did some research and found this:

No, it's most likely 300 good reports.
I don't have the link, and my repot "baseline" is:
Quote
You have reported 313 posts with 97% accuracy (293 good, 11 bad, 9 unhandled).
Right okay. That's interesting. Let us know once you get those 7 good reports
I now have the link. Unfortunately, I didn't quite make the 300 mark, but overshot to 301 Tongue
Quote
You have reported 321 posts with 97% accuracy (301 good, 11 bad, 9 unhandled)
legendary
Activity: 3654
Merit: 8909
https://bpip.org
Is that page meant to display a list of posts you have reported? All I see is my a brief overview of my "stats"... "You have reported 248 posts with 100% accuracy..." etc... but I don't see a list? Huh
You need to report 500 posts to see that list.

I thought it's 300 good reports... HCP, please report 52 posts and let us know if you see it Wink
legendary
Activity: 2758
Merit: 6830
Is that page meant to display a list of posts you have reported? All I see is my a brief overview of my "stats"... "You have reported 248 posts with 100% accuracy..." etc... but I don't see a list? Huh
You need to get 300 good reports to see that list.

edit: 300 not 500.
HCP
legendary
Activity: 2086
Merit: 4361
Is that page meant to display a list of posts you have reported? All I see is my a brief overview of my "stats"... "You have reported 248 posts with 100% accuracy..." etc... but I don't see a list? Huh
legendary
Activity: 2240
Merit: 3150
₿uy / $ell ..oeleo ;(
That's perfect. Works great on chrome.
Just wondering if it is possible for someone to add a link to the report history on the menu? It's will be easy to click and see your report history. Now i have to report a random post just to click the link there.


Someone said I don't use enough spreads... so here you go:

Code:
[...document.querySelectorAll(".maintab_back")].slice(-1)[0].insertAdjacentHTML('beforebegin', 'My Reports');

Put it in the extension or in a userscript. Will add "MY REPORTS" before "LOGOUT". Adjust slice parameters to put it elsewhere.

That was quick, thank you Smiley
legendary
Activity: 3654
Merit: 8909
https://bpip.org
That's perfect. Works great on chrome.
Just wondering if it is possible for someone to add a link to the report history on the menu? It's will be easy to click and see your report history. Now i have to report a random post just to click the link there.


Someone said I don't use enough spreads... so here you go:

Code:
[...document.querySelectorAll(".maintab_back")].slice(-1)[0].insertAdjacentHTML('beforebegin', 'My Reports');

Put it in the extension content script bct-content.js (global code - outside of functions) or in a userscript. This will add "MY REPORTS" before "LOGOUT". Adjust slice parameters to put it elsewhere.
legendary
Activity: 2240
Merit: 3150
₿uy / $ell ..oeleo ;(
That's perfect. Works great on chrome.
Just wondering if it is possible for someone to add a link to the report history on the menu? It's will be easy to click and see your report history. Now i have to report a random post just to click the link there.
HCP
legendary
Activity: 2086
Merit: 4361
If anyone cares, I managed to get this working for Chrome... Tongue

I had to use the Mozilla webextension-polyfill library to wrap the script as it uses the browser.* namespace... Chrome insists on chrome.* Roll Eyes I also modified o_e_l_e_o's .css to fix the order of the buttons and also get the "Report as:" text into the correct place.

As always... this is "AT YOUR OWN RISK"... I accept no responsibility if you get banned for spamming mods! Tongue

1. Download the latest browser-polyfill.js from here, put it in the same directory as the other files from OP: https://github.com/mozilla/webextension-polyfill/releases
(HINT: click on the unpkg.com link... ie. for 0.4.0: https://unpkg.com/[email protected]/dist/)

2. Modify the manifest.json to reference the browser-polyfill.js BEFORE the other .js files and to fix the "version" error (apparently Chrome doesn't like the 'b' in 0.1b Roll Eyes):
Code:
{

  "manifest_version": 2,
  "name": "BCT Helper",
  "version": "0.1.1",

  "description": "Adds some automation for bitcointalk.org.",

  "content_scripts": [
    {
      "matches": [ "*://bitcointalk.org/*" ],
      "js": [ "browser-polyfill.js","bct-content.js" ],
      "css": [ "bct-content.css" ],
      "run_at": "document_idle"
    }
  ],

  "background":
  {
    "scripts": ["browser-polyfill.js","bct-background.js"]
  },
 
  "permissions": [
    "tabs"
  ]
}

3. Enable "Developer Mode" in Chrome Extension settings

4. Then click "Load unpacked" in Chrome Extension settings, browse to the directory where you placed all the files and click "Select Folder"


PROTIP: If you find that when you try to report a post, it opens a new tab in the background, but then doesn't appear to actually submit the report... try reading the OP again carefully Wink




NOTE: This fix is ONLY needed if you use o_e_l_e_o's .css!!!
This is the fix for .css to put the "Report as:" text on the right with the buttons.
Code:
div.post {
    border-left: 4px transparent solid;
}

div.post.post-wait {
    opacity: 0.5;
}

div.post.post-error {
    border-left: 4px red solid;
}

div.post.post-success {
    border-left: 4px yellow solid;
}

.bct-report-button-container {
    float: right;
    margin-top: 10px;
    margin-bottom: 40px;
}

.bct-report-input {
    float: right;
    margin-right: 4px;
    height: 16px;
}

.bct-report-button, .bct-report-button:hover {
    float: right;
    background-image: linear-gradient(#375F82, #88A6C0);
    border: 1px solid black;
    margin-left: 4px;
    padding: 3px 5px 3px 5px;
    transform: none;
    color: #ffffff;
}

.bct-report-button:hover {
    cursor: pointer;
}


NOTE: This fix is ONLY needed if you use o_e_l_e_o's .css!!!
This is the fix for the "copy from:" and "move to:" buttons and text boxes being in the wrong order

You need to replace the code in bct_content.js with the following:
Code:
console.log("BCT-CONTENT initialized");
console.log("Page: " + window.location.href);
console.log("Referrer: " + document.referrer);

function process_background_message(message, sender, send_response) {
    browser.runtime.onMessage.removeListener(process_background_message);
    console.log("Content script received background message: " + JSON.stringify(message));
    if (message.action == "bct-tab-open-report" || message.action == "bct-tab-submit-report") {
        if (message.comment !== undefined) {
            document.getElementsByName("comment")[0].value = message.comment;
        }
        document.getElementsByName("comment")[0].focus();
        message.result = "OK";
    }
    if (message.action == "bct-tab-submit-report") {
        // mod report counts as post/PM for throttling - add a delay
        setTimeout(() => {
            send_response(message);
            // Uncomment the next line to allow reports to be submitted automatically
            //document.querySelector("input[type=submit][value=Submit]").click();
        }, 5000);
    } else {
        send_response(message);
    }
    // this is needed to make the sender wait for a response
    return true;
}

function report_post(post_container, thread_id, post_id, report_comment, auto_submit) {
    post_container.classList.add("post-wait");

    let event_detail = {
        event_id: (Math.random().toString(36) + '000000000000000000').slice(2, 18),
        action_name: "bct-report",
        action_url: "https://bitcointalk.org/index.php?action=reporttm;topic=" + thread_id + ";msg=" + post_id,
        action_payload: { post_id: post_id, comment: report_comment, auto: auto_submit }
    };

    browser.runtime.sendMessage(event_detail)
        .then((message_response) => {
            //console.log("message_response: " + JSON.stringify(message_response));
            console.log("message_response size: " + JSON.stringify(message_response).length);
            post_container.classList.remove("post-wait", "post-error", "post-success");
            post_container.classList.add("post-success");
        })
        .catch((error) => {
            console.log("Data request failed:");
            console.log(error);
            post_container.classList.remove("post-wait", "post-error", "post-success");
            post_container.classList.add("post-error");
        })
    ;
   
}

function extract_ids_from_url(post_url) {
    let url_parts = post_url.split("#msg");
    let post_id = url_parts[1];
    let thread_id = url_parts[0].split(".msg")[0].split("?topic=")[1];
    return [thread_id, post_id];
}

function create_button(post_container, button_title, report_comment, text_field, auto_submit) {
    let button = document.createElement("button");
    button.className = "bct-report-button";
    button.innerText = button_title;
    button.title = report_comment;
    button.addEventListener("click", (e) => {
        e.preventDefault();
        if (text_field) {
            if (text_field.value.trim()) {
                report_comment += " " + text_field.value.trim();
            } else {
                alert("Required value missing");
                return;
            }
        }
        report_post(post_container, post_container.thread_id, post_container.post_id, report_comment, auto_submit);
    });
    return button;
}

function create_span(text) {
    let span = document.createElement("span");
    span.innerText = text;
    return span;
}

function create_text_field(hint) {
    let text_field = document.createElement("input");
    text_field.className = "bct-report-input";
    text_field.type = "text";
    text_field.placeholder = hint;
    return text_field;
}

// inject the buttons into each message
document.querySelectorAll("div.post").forEach(post_container => {
    // Try to determine thread ID and post ID
    let link_object = null;
    if (post_container.parentNode.classList.contains("td_headerandpost")) {
        // Thread view
        // post -> td.td_headerandpost -> table ... -> div#subject_123456
        link_object = post_container.parentNode.firstElementChild.querySelector("div[id^='subject_'] a");
    } else {
        // Other views: patrol, user's post history, user's thread history
        let post_url_start = "https://bitcointalk.org/index.php?topic=";
        // post -> td -> tr -> tbody -> tr ... -> a[href contains #msg123456]
        link_object = post_container.parentNode.parentNode.parentNode.firstElementChild.querySelector("a[href^='" + post_url_start + "'][href*='#msg']");
    }
    if (link_object) {
        [post_container.thread_id, post_container.post_id] = extract_ids_from_url(link_object.getAttribute("href"));
        if (post_container.thread_id && post_container.post_id) {
            let button_container = document.createElement("div");
            button_container.className = "bct-report-button-container";
            post_container.appendChild(button_container);
            button_container.appendChild(create_span("Report as: "));
            button_container.appendChild(create_button(post_container, "zero value", "zero-value shitpost", null, true));
            button_container.appendChild(create_button(post_container, "multi post", "two or more consecutive posts in 24h", null, true));
            button_container.appendChild(create_button(post_container, "cross spam", "spamming their service across multiple threads - please check post history", null, true));
            button_container.appendChild(create_button(post_container, "non-english", "non-English post on English board", null, true));
            let url_field = create_text_field("URL of the original");
            button_container.appendChild(url_field);
            button_container.appendChild(create_button(post_container, "copy from:", "copy-paste from:", url_field, true));
            let board_field = create_text_field("correct board name");
            button_container.appendChild(board_field);
            button_container.appendChild(create_button(post_container, "move to:", "wrong board, should be in", board_field, true));
        } else {
            console.log("Found div.post and post URL but couldn't determine thread/post ID.");
        }
    } else {
        console.log("Found div.post but couldn't find post URL.");       
    }
});

if (window.location.href.startsWith("https://bitcointalk.org/index.php?action=reporttm")) {
    document.getElementsByName("comment")[0].style.width = "80%";
    browser.runtime.onMessage.addListener(process_background_message);
}
if (window.location.href.startsWith("https://bitcointalk.org/index.php?board=")) {
    if (document.referrer &&
        document.referrer.startsWith("https://bitcointalk.org/index.php?action=reporttm") &&
        document.referrer.endsWith(";a") // after automatic submission
    ) {
        console.log("Attempting to close this tab...");
        browser.runtime.sendMessage({ action_name: "close-this-tab" });
    }
}
legendary
Activity: 2268
Merit: 18711
Definitely worth a bump.

I've found I can reduce the delay of 5000 on line 21 of bct-content.js to 4000 without running in to any problems.

I'll also post my edited .css file in case anyone wants to steal my appearance. Essentially I made the buttons all right aligned so they aren't directly in my eye line when reading, and made them blend in more with the general theme. Appearances and code below. If you do right align everything you will also need to switch the order of the "button_container.appendChild(url_field)" and "button_container.appendChild(create_button)" lines in bct-content.js, so the text boxes still appear in the correct place.



Code:
div.post {
    border-left: 4px transparent solid;
}

div.post.post-wait {
    opacity: 0.5;
}

div.post.post-error {
    border-left: 4px red solid;
}

div.post.post-success {
    border-left: 4px yellow solid;
}

.bct-report-button-container {
    margin-top: 10px;
    margin-bottom: 40px;
}

.bct-report-input {
    float: right;
    margin-right: 4px;
    height: 16px;
}

.bct-report-button, .bct-report-button:hover {
    float: right;
    background-image: linear-gradient(#375F82, #88A6C0);
    border: 1px solid black;
    margin-left: 4px;
    padding: 3px 5px 3px 5px;
    transform: none;
    color: #ffffff;
}

.bct-report-button:hover {
    cursor: pointer;
}
legendary
Activity: 3654
Merit: 8909
https://bpip.org
I'm kinda torn whether I should bump this. It's like giving a box of matches to a toddler.

Speaking of which, I recently earned a bad report by accidentally clicking one of these buttons on a post I didn't intend to report (it was Quickseller's post but as I said - total accident). So be careful. You get a few seconds to close the report tab before it gets submitted.
legendary
Activity: 2394
Merit: 6581
be constructive or S.T.F.U
 wish it was posted a long time ago, but better late than never, will try it and let you know if i find any issues. thanks Grin
legendary
Activity: 3654
Merit: 8909
https://bpip.org
Nice code, thanks Smiley
Is it possible to ask theymos to just implement it into the code?
And only activate it for those who e.g. has at least 1,000 good reports?
It would be awesome Smiley

There is a petition for a similar feature: https://bitcointalksearch.org/topic/suggestion-expansion-of-the-report-feature-to-benefit-both-mods-reporters-5103283

Perhaps if we pester theymos long enough he'll give in.
hero member
Activity: 1442
Merit: 629
Vires in Numeris
Nice code, thanks Smiley
Is it possible to ask theymos to just implement it into the code?
And only activate it for those who e.g. has at least 1,000 good reports?
It would be awesome Smiley
legendary
Activity: 2310
Merit: 2073
~snip~

It's super suchmoon!


For a long time I did not understand why I do not have an extended interface window. My mistake was in one lost character from the code field. I added your hack to Russian locale
legendary
Activity: 3654
Merit: 8909
https://bpip.org
Yeah, I've added a couple of buttons for myself. Changed in the bct-content.js file.
I'm not a programmer and figured it out pretty quickly. Other examples are definitely welcome though!

Awesome. Another one I use often is "multi posting" AKA "two or more consecutive posts in 24h". I'll post a small update later today with some other stuff than may come in useful.



I updated bct-content.js and bct-content.css with some small tweaks. CreateButton function has changed so if you had any customizations these will need to be slightly updated like this:

Code:
           button_container.appendChild(create_button(post_container, "button name", "comment to submit", null or text box - see below, true));

I added mouse-over on buttons to show the comment text that will be submitted, and added an option to pass a text field which allows to do something like this:

Loading...
Edited 2020-11-30 to fix a broken image

So in this example if you click the "copy from:" button the actual comment that gets submitted would be "copy-paste from: http://some.url/link", i.e. concatenates predefined text with what you enter in the box.
legendary
Activity: 1792
Merit: 1283
Everyone trying this out - please make sure to personalize the buttons and set up the comments you want to submit. You can create as many buttons as you want, as well as other stuff like drop downs or text fields. I'll try to come up with an example of a text field for a URL (e.g. when reporting plagiarism).

Yeah, I've added a couple of buttons for myself. Changed in the bct-content.js file.
I'm not a programmer and figured it out pretty quickly. Other examples are definitely welcome though!

Code:
if (link_object) {
        let [thread_id, post_id] = ExtractIdsFromUrl(link_object.getAttribute("href"));
        if (thread_id && post_id) {
            let button_container = document.createElement("div");
            button_container.className = "bct-report-button-container";
            post_container.appendChild(button_container);
            button_container.appendChild(CreateButton("zero value", post_container, thread_id, post_id, "zero-value shitpost", true));
            button_container.appendChild(CreateButton("cross spam", post_container, thread_id, post_id, "spamming their service across multiple threads - please check post history", true));
            button_container.appendChild(CreateButton("non-english", post_container, thread_id, post_id, "non-english post", true));
            button_container.appendChild(CreateButton("price speculation", post_container, thread_id, post_id, "Wrong board, should be in Speculation", true));
        }
legendary
Activity: 3654
Merit: 8909
https://bpip.org
Works great! Not too hard to set up, just followed the instructions.

On a side-note, finally something that's being released for Firefox first.
Lately I'd been seriously considering moving to Chrome, just because custom 'extensions' like these seem to be developed for Chrome first and then get ported to FF as an afterthought.

Just reported my first post using this tool:



I'm using Tor Browser, which is essentially Firefox, so I built it for Firefox. However the WebExtensions API is supposed to be portable so it might work in Chrome as well.



Everyone trying this out - please make sure to personalize the buttons and set up the comments you want to submit. You can create as many buttons as you want, as well as other stuff like drop downs or text fields. I'll try to come up with an example of a text field for a URL (e.g. when reporting plagiarism).
copper member
Activity: 2562
Merit: 2510
Spear the bees
Brilliant. This is exactly the kind of tool that we need to address the SpamHorde™.

(now if only there were a way to reduce the wait time once you've made X good reports)
legendary
Activity: 1792
Merit: 1283
Works great! Not too hard to set up, just followed the instructions.

On a side-note, finally something that's being released for Firefox first.
Lately I'd been seriously considering moving to Chrome, just because custom 'extensions' like these seem to be developed for Chrome first and then get ported to FF as an afterthought.

Just reported my first post using this tool:

legendary
Activity: 3654
Merit: 8909
https://bpip.org
Code:
BCT-CONTENT initialized
Page: https://bitcointalk.org/index.php?board=1.0
Referrer: https://bitcointalk.org/

This was after a report was made automatically, and it had reloaded to Bitcoin Discussion front page. So yeah, it seems to not be picking up the referrer correctly.

Edit: Wait wait wait, I think I know the issue, and it's got nothing to do with your code. Gimme 5.

Edit 2: Yeah, got it. So as part of my Firefox set up, in about:config I have network.http.referer.trimmingPolicy set to 2, which means it only sends the origin rather than full URL. Changing it back to 0 solves the problem.

Whew. I tried it in Firefox 64 and it worked. Was gonna yell at you that you must have some weird privacy settings Smiley

Although relying on referrer is a bit wonky. I should probably find a better way.
legendary
Activity: 2268
Merit: 18711
Code:
BCT-CONTENT initialized
Page: https://bitcointalk.org/index.php?board=1.0
Referrer: https://bitcointalk.org/

This was after a report was made automatically, and it had reloaded to Bitcoin Discussion front page. So yeah, it seems to not be picking up the referrer correctly.

Edit: Wait wait wait, I think I know the issue, and it's got nothing to do with your code. Gimme 5.

Edit 2: Yeah, got it. So as part of my Firefox set up, in about:config I have network.http.referer.trimmingPolicy set to 2, which means it only sends the origin rather than full URL. Changing it back to 0 solves the problem.
legendary
Activity: 3654
Merit: 8909
https://bpip.org
Firefox, no, yes. I had figured out as much - the URLs on my browser are correct, but the tabs don't close.

Weird. I just checked with Tor Browser, which is basically a Firefox clone, and it closed correctly. Can you add some extra logging at the top of bct-content.js:

Code:
console.log("Page: " + window.location.href);
console.log("Referrer: " + document.referrer);

Then reload the extension and check if it shows the referrer correctly, particularly after the submission. Ctrl+Shift+I, then Console to see the log.
legendary
Activity: 2268
Merit: 18711
Firefox, no, yes. I had figured out as much - the URLs on my browser are correct, but the tabs don't close.
legendary
Activity: 3654
Merit: 8909
https://bpip.org
On looking at your code further, I see the new tabs are supposed to close after auto-submitting. On mine they don't, and my rusty JavaScript knowledge isn't allowing me to figure out why.

Which browser are you using? Does the tab close if you click the "Submit" manually? Does the report page URL have ";a" at the end? Basically what it does after submission is this: if the referrer had ";a" in the URL - close the tab.

bct-content.js line 112 sends the message back to the background script to close the tab. This will happen after the page (the list of threads you're redirected to) is fully loaded.
bct-background.js line 70 receives the message and closes the tab.

I'll debug it on my end once I find some worthy shitposts to report Smiley
legendary
Activity: 2268
Merit: 18711
On looking at your code further, I see the new tabs are supposed to close after auto-submitting. On mine they don't, and my rusty JavaScript knowledge isn't allowing me to figure out why.
legendary
Activity: 3654
Merit: 8909
https://bpip.org
One small error I've found.

In bct-content.js, on line 63:
Code:
button.className = "post-report-button";

But your CSS file uses:
Code:
.bct-report-button

I've turned the buttons red and aligned them to the right, nestled nicely above "Report to moderator". Thanks again!

Edit: Actually, I didn't like the red either, so I've opted for a more familiar color scheme:



Thanks, I updated the class name in the OP.
legendary
Activity: 2268
Merit: 18711
One small error I've found.

In bct-content.js, on line 63:
Code:
button.className = "post-report-button";

But your CSS file uses:
Code:
.bct-report-button

I've turned the buttons red and aligned them to the right, nestled nicely above "Report to moderator". Thanks again!

Edit: Actually, I didn't like the red either, so I've opted for a more familiar color scheme:

legendary
Activity: 3654
Merit: 8909
https://bpip.org
Love this, and if I had 50 sMerits to give you I would. Reviewed the code, installed, works perfectly. Much better solution than the quick one I came up with given the queuing function.

Don't like your color scheme or position of the buttons, but that's easily fixed. Thank so much for taking the time to extract and share. I'll play around with it for a few days and let you know if I stumble across any issues.

You can change the colors in the CSS file obviously. I put the buttons on the bottom left so that there is no chance to accidentally confuse them with any other buttons like Edit or Report to moderator but you can inject them anywhere you like.

Edit: I should mention that queuing has certain limitations. "let PROMISE_TIMEOUT = 120000;" near the top of bct-background.js basically limits the time to wait for the report to be submitted to ~2 minutes. At 5 seconds between reports plus loading time it allows up to ~15 reports to be queued.
legendary
Activity: 2268
Merit: 18711
Love this, and if I had 50 sMerits to give you I would. Reviewed the code, installed, works perfectly. Much better solution than the quick one I came up with given the queuing function.

Don't like your color scheme or position of the buttons, but that's easily fixed. Thank so much for taking the time to extract and share. I'll play around with it for a few days and let you know if I stumble across any issues.
legendary
Activity: 3654
Merit: 8909
https://bpip.org
This originated here: https://bitcointalksearch.org/topic/m.49470283

And I completely support the idea raised by that thread, i.e. make it easier to report certain types of posts. But until/unless that feature gets implemented perhaps you'll find my approach useful.

Caveats

1. This is a browser extension. Never install browser extensions obtained from random strangers on the internet unless you know exactly what you're doing. I'm not responsible if this extension steals all your money and runs away with your spouse.

2. This is mostly-untested code. It's alpha quality at best. I gutted it out of a larger extension that I'm using for other purposes. Treat it as an example or an idea. Feel free to steal any bits and pieces that you like or do whatever you want with it.

3. It works in Firefox/Tor browser and may work in Chrome but again - untested. Probably won't work in mobile browsers.

4. You must have some knowledge of how WebExtensions and Promises work in order to make sense of the code. I'll try to explain below but a proper tutorial is out of the scope of this thread.

How this works

This is a browser extension built using WebExtensions API and consists of two main parts:

  • bct-content.js: content script, a copy of which runs on every Bitcointalk page once the extension is installed. Depending on which page it is, the content script will perform different actions:
    • Inside threads, on Patrol page, and in user's post/thread history it creates one-click buttons to report posts to moderators. Clicking one of the buttons sends a message to the other part of the extension, which handles queuing etc.
      Loading...
      Edited 2020-11-30 to fix a broken image
    • On the "Report to moderator" page it expands the comment field for better visibility. If the page was opened automatically by one of the above buttons, it inserts the pre-selected comment, waits a specified amount of time to comply with throttling, and clicks "Submit".
    • In the board view it closes the tab if it came from the automated post report, otherwise it does nothing.
  • bct-background.js: background script, which listens to messages from content scripts and for each message opens the "Report to moderator" in a new tab, which is then handled by the content script as described above. This is done without taking focus away from what you're doing so you can keep browsing and reporting other posts.

The code that runs between when you click your button and when the extension clicks the "Submit" button is wrapped in a Promise so it should succeed or fail as a whole. Please note though that the actual submission of the report is not verified, i.e. if there is a failure after "Submit" was clicked - Bitcointalk down, CF fire hydrant, etc - you'll have to double-check your report history to see if the report was submitted successfully.

If the code succeeds it will add a yellow border on the left side of the post being reported, if it fails - a red one. Styling is configurable in bct-content.css. o_e_l_e_o created a custom stylesheet for a "blend in" look-and-feel.

In case of a failure check console log and please let me know if there is a bug that's causing it.

How to install

Save the files posted below into one folder. In Firefox/Tor go to "about:debugging", click Load Temporary Add-on, and choose any file in the folder. If you're brave enough to use Chrome - you're gonna have to figure it out on your own HCP has figured out a way.

The actual clicking of the "Submit" button is commented out - see line 18 in bct-content.js. I would like to avoid spamming our dear moderators with a bunch of malformed reports if anything goes wrong. If you decide to use the extension you can test it first by manually clicking "Submit" and then uncomment the line once you're comfortable.

Line 19 sets the wait time before clicking "Submit". High activity accounts have a 4-seconds-betwen-posts allowance, so the default 5000ms delay works well with that. With a lower activity account you may run into throttling - adjust the delay as needed.

You can change button titles, report comments, add new buttons, etc around line 120 in bct-content.js.

Questions?

I'm sure I missed something or messed something up. Feel free to comment in the thread.

Files

manifest.json

Code:
{

  "manifest_version": 2,
  "name": "BCT Helper",
  "version": "0.1b",

  "description": "Adds some automation for bitcointalk.org.",

  "content_scripts": [
    {
      "matches": [ "*://bitcointalk.org/*" ],
      "js": [ "bct-content.js" ],
      "css": [ "bct-content.css" ],
      "run_at": "document_idle"
    }
  ],

  "background":
  {
    "scripts": ["bct-background.js"]
  },
  
  "permissions": [
    "tabs"
  ]
}

bct-content.css

Code:
div.post {
    border-left: 4px transparent solid;
}

div.post.post-wait {
    opacity: 0.5;
}

div.post.post-error {
    border-left: 4px red solid;
}

div.post.post-success {
    border-left: 4px yellow solid;
}

.bct-report-button-container {
    margin-top: 10px;
    background-color: #bbddbb;
}

.bct-report-input {
    margin-left: 5px;
    height: 12px;
}

.bct-report-button, .bct-report-button:hover {
    display: inline-block;
    border: 1px solid black;
    margin-left: 5px;
    padding: 1px 5px 1px 5px;
    transform: none;
}

.bct-report-button:hover {
    cursor: pointer;
}

bct-content.js

Code:
console.log("BCT-CONTENT initialized");
console.log("Page: " + window.location.href);
console.log("Referrer: " + document.referrer);

function process_background_message(message, sender, send_response) {
    browser.runtime.onMessage.removeListener(process_background_message);
    console.log("Content script received background message: " + JSON.stringify(message));
    if (message.action == "bct-tab-open-report" || message.action == "bct-tab-submit-report") {
        if (message.comment !== undefined) {
            document.getElementsByName("comment")[0].value = message.comment;
        }
        document.getElementsByName("comment")[0].focus();
        message.result = "OK";
    }
    if (message.action == "bct-tab-submit-report") {
        // mod report counts as post/PM for throttling - add a delay
        setTimeout(() => {
            send_response(message);
            // Uncomment the next line to allow reports to be submitted automatically
            //document.querySelector("input[type=submit][value=Submit]").click();
        }, 5000);
    } else {
        send_response(message);
    }
    // this is needed to make the sender wait for a response
    return true;
}

function report_post(post_container, thread_id, post_id, report_comment, auto_submit) {
    post_container.classList.add("post-wait");

    let event_detail = {
        event_id: (Math.random().toString(36) + '000000000000000000').slice(2, 18),
        action_name: "bct-report",
        action_url: "https://bitcointalk.org/index.php?action=reporttm;topic=" + thread_id + ";msg=" + post_id,
        action_payload: { post_id: post_id, comment: report_comment, auto: auto_submit }
    };

    browser.runtime.sendMessage(event_detail)
        .then((message_response) => {
            //console.log("message_response: " + JSON.stringify(message_response));
            console.log("message_response size: " + JSON.stringify(message_response).length);
            post_container.classList.remove("post-wait", "post-error", "post-success");
            post_container.classList.add("post-success");
        })
        .catch((error) => {
            console.log("Data request failed:");
            console.log(error);
            post_container.classList.remove("post-wait", "post-error", "post-success");
            post_container.classList.add("post-error");
        })
    ;
    
}

function extract_ids_from_url(post_url) {
    let url_parts = post_url.split("#msg");
    let post_id = url_parts[1];
    let thread_id = url_parts[0].split(".msg")[0].split("?topic=")[1];
    return [thread_id, post_id];
}

function create_button(post_container, button_title, report_comment, text_field, auto_submit) {
    let button = document.createElement("button");
    button.className = "bct-report-button";
    button.innerText = button_title;
    button.title = report_comment;
    button.addEventListener("click", (e) => {
        e.preventDefault();
        if (text_field) {
            if (text_field.value.trim()) {
                report_comment += " " + text_field.value.trim();
            } else {
                alert("Required value missing");
                return;
            }
        }
        report_post(post_container, post_container.thread_id, post_container.post_id, report_comment, auto_submit);
    });
    return button;
}

function create_span(text) {
    let span = document.createElement("span");
    span.innerText = text;
    return span;
}

function create_text_field(hint) {
    let text_field = document.createElement("input");
    text_field.className = "bct-report-input";
    text_field.type = "text";
    text_field.placeholder = hint;
    return text_field;
}

// inject the buttons into each message
document.querySelectorAll("div.post").forEach(post_container => {
    // Try to determine thread ID and post ID
    let link_object = null;
    if (post_container.parentNode.classList.contains("td_headerandpost")) {
        // Thread view
        // post -> td.td_headerandpost -> table ... -> div#subject_123456
        link_object = post_container.parentNode.firstElementChild.querySelector("div[id^='subject_'] a");
    } else {
        // Other views: patrol, user's post history, user's thread history
        let post_url_start = "https://bitcointalk.org/index.php?topic=";
        // post -> td -> tr -> tbody -> tr ... -> a[href contains #msg123456]
        link_object = post_container.parentNode.parentNode.parentNode.firstElementChild.querySelector("a[href^='" + post_url_start + "'][href*='#msg']");
    }
    if (link_object) {
        [post_container.thread_id, post_container.post_id] = extract_ids_from_url(link_object.getAttribute("href"));
        if (post_container.thread_id && post_container.post_id) {
            let button_container = document.createElement("div");
            button_container.className = "bct-report-button-container";
            post_container.appendChild(button_container);
            button_container.appendChild(create_span("Report as: "));
            button_container.appendChild(create_button(post_container, "zero value", "zero-value shitpost", null, true));
            button_container.appendChild(create_button(post_container, "multi post", "two or more consecutive posts in 24h", null, true));
            button_container.appendChild(create_button(post_container, "cross spam", "spamming their service across multiple threads - please check post history", null, true));
            button_container.appendChild(create_button(post_container, "non-english", "non-English post on English board", null, true));
            let url_field = create_text_field("URL of the original");
            button_container.appendChild(create_button(post_container, "copy from:", "copy-paste from:", url_field, true));
            button_container.appendChild(url_field);
            let board_field = create_text_field("correct board name");
            button_container.appendChild(create_button(post_container, "move to:", "wrong board, should be in", board_field, true));
            button_container.appendChild(board_field);
        } else {
            console.log("Found div.post and post URL but couldn't determine thread/post ID.");
        }
    } else {
        console.log("Found div.post but couldn't find post URL.");        
    }
});

if (window.location.href.startsWith("https://bitcointalk.org/index.php?action=reporttm")) {
    document.getElementsByName("comment")[0].style.width = "80%";
    browser.runtime.onMessage.addListener(process_background_message);
}
if (window.location.href.startsWith("https://bitcointalk.org/index.php?board=")) {
    if (document.referrer &&
        document.referrer.startsWith("https://bitcointalk.org/index.php?action=reporttm") &&
        document.referrer.endsWith(";a") // after automatic submission
    ) {
        console.log("Attempting to close this tab...");
        browser.runtime.sendMessage({ action_name: "close-this-tab" });
    }
}

bct-background.js

Code:
// This is an array of Promise.resolve functions that will be called sequentially with delay
let throttled_resolvers = [];
// Number of milliseconds to wait before resolving the next queued promise
let PROMISE_INTERVAL = 1300;
// Number of milliseconds to wait before rejecting the queued promise
let PROMISE_TIMEOUT = 120000;
// Number of milliseconds to wait for a tab to load
let TAB_TIMEOUT = 60000;

function handle_next_resolver() {
    let p = throttled_resolvers.shift();
    if (p === undefined) {
        setTimeout(handle_next_resolver, PROMISE_INTERVAL);
    }
    else {
        p.resolve();
    }
}

setTimeout(handle_next_resolver, PROMISE_INTERVAL);

function queue_promise() {
    return new Promise((resolve, reject) => {
        throttled_resolvers.push({ resolve: resolve });
        setTimeout(function () { reject(new Error("Queued promise has timed out.")); }, PROMISE_TIMEOUT);
    });
}

function check_if_tab_fully_loaded(tab) {

    function is_tab_complete(tab) {
        return tab.status === "complete" && tab.url !== "about:blank";
    }

    if (is_tab_complete(tab)) {
        return tab;
    } else {
        return new Promise((resolve, reject) => {

            const timer = setTimeout(
                function () {
                    browser.tabs.onUpdated.removeListener(on_updated);
                    if (is_tab_complete(tab)) {
                        resolve(tab);
                    } else {
                        reject(new Error("Tab status " + tab.status + ": " + tab.url));
                    }
                },
                TAB_TIMEOUT
            );
            
            function on_updated(tab_id, change_info, updated_tab) {
                if (tab_id == tab.id && is_tab_complete(updated_tab)) {
                    clearTimeout(timer);
                    browser.tabs.onUpdated.removeListener(on_updated);
                    resolve(updated_tab);
                }
            }

            browser.tabs.onUpdated.addListener(on_updated);

        });
    }
}

browser.runtime.onMessage.addListener(function(message, sender) {
    if (message.action_name === "close-this-tab") {
        //console.log("Background script closing tab:");
        //console.log(sender.tab);
        browser.tabs.remove(sender.tab.id);
    }
    else if (message.action_name === "bct-report") {
        /*
        Expected message format:
        {
            action_name: "bct-auto-report",
            action_url: "https://...",
            action_payload: { post_id: N, comment: "...", auto: true }
        }
        */
        let tab_url = message.action_url;
        let tab_action = "bct-tab-open-report";
        if (message.action_payload.auto) {
            tab_action = "bct-tab-submit-report";
            tab_url += ";a";
        }
        console.log(message);
        return queue_promise()
            .then(() =>
                browser.tabs.create({
                    url: tab_url,
                    windowId: sender.tab.windowId,
                    active: false
                })
            )
            .then((created_tab) => check_if_tab_fully_loaded(created_tab))
            .catch((error) => {
                error_message = "Tab load/check failed: " + error.message;
                console.log(error_message);
                throw new Error(error_message);
            })
            .then((loaded_tab) => browser.tabs.sendMessage(loaded_tab.id, { id: loaded_tab.id, action: tab_action, comment: message.action_payload.comment }))
            .then((tab_response) => {
                //console.log("Tab result: " + tab_response.result);
                message.action_result = tab_response.result;
                return message;
            })
            .catch((error) => {
                console.log("Request failed in the background:");
                console.log(error);
                throw new Error(error.message);
            })
            .finally(() => {
                setTimeout(handle_next_resolver, PROMISE_INTERVAL);
            })
        ;
    }
});

Local rules

cryptohunter and Thule are not allowed to post here. This thread is only about mod reporting and improvement thereof, not DT, merits, or anything else.

Jump to: