RaaW2

Reddit as a Weapon script. Parts and idea by /u/noeatnosleep, enhanced by /u/enim, /u/creesch, and /u/djimbob. RaaW adds links for page-wide voting and reporting. It adds a 'report to /r/spam' link, an 'analyze user submission domains' link, and a 'report to /r/botwatchman' link to userpages. RaaW disables the np. domain. RaaW Adds a 'show source' button for comments. DISCLIAMER: Use this at your own risk. If the report button is misued, you could be shadowbanned.

当前为 2014-10-04 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name RaaW2
  3. // @version 2.5.6
  4. // @namespace RaaW2
  5. // @description Reddit as a Weapon script. Parts and idea by /u/noeatnosleep, enhanced by /u/enim, /u/creesch, and /u/djimbob. RaaW adds links for page-wide voting and reporting. It adds a 'report to /r/spam' link, an 'analyze user submission domains' link, and a 'report to /r/botwatchman' link to userpages. RaaW disables the np. domain. RaaW Adds a 'show source' button for comments. DISCLIAMER: Use this at your own risk. If the report button is misued, you could be shadowbanned.
  6. // @include http://www.reddit.com/user/*
  7. // @include http://www.reddit.com/r/*
  8. // @include http://*reddit.com/*
  9. // @include https://www.reddit.com/user/*
  10. // @include https://www.reddit.com/r/*
  11. // @include https://*reddit.com/*
  12. // @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js
  13. // ==/UserScript==
  14.  
  15. this.$ = this.jQuery = jQuery.noConflict(true);
  16.  
  17. var currentPage = document.URL;
  18. var parsedPage = currentPage.split('/');
  19. var modHash = null;
  20. var currentUser = null;
  21. var subreddit = null;
  22. var commentIDs = [];
  23. var topicIDs = [];
  24. var subredditList = [];
  25. var reportID = [];
  26.  
  27. var commentPage;
  28. commentPage = document.getElementsByClassName('comment');
  29.  
  30. function getHash(callback) {
  31. var query = new XMLHttpRequest();
  32. query.onreadystatechange = function () {
  33. if (query.readyState == 4) {
  34. var info = JSON.parse(query.responseText);
  35. modHash = info.data.modhash;
  36. callback();
  37. }
  38. }
  39. query.open('GET', 'http://www.reddit.com/api/me.json', true);
  40. query.send(null);
  41. }
  42.  
  43. function generateToolbar() {
  44. $(document).find('#header')[0].style.paddingTop = '18px';
  45. var newToolbar = document.createElement("div");
  46. newToolbar.id = "newToolbar";
  47. document.body.insertBefore(newToolbar, document.body.firstChild);
  48. var subredditbar = document.getElementById('sr-header-area');
  49. newToolbar.style.cssText = "color:black;background-color:'#f0f0f0';border-bottom:1px black solid;font-family:verdana, arial, helvetica, sans-serif;font-size:90%;height:12px;padding:3px 0px 3px 6px;text-transform:uppercase;width:100%;z-index:+999999;position:fixed;top:0;";
  50. newToolbar.style.backgroundColor = '#f0f0f0';
  51. newToolbar.style.paddingLeft = '6px';
  52. newToolbar.style.paddingTop = '3px';
  53. newToolbar.style.paddingBottom = '3px';
  54. newToolbar.style.top = '0px';
  55. newToolbar.innerHTML += " ";
  56. if (parsedPage[3] == 'user') {
  57. newToolbar.innerHTML += "<a id=reportComment style='color:black;' href='#'>REPORT ALL</a> <a id='botwatchmanSend' style='color:black;' href='#'> | /R/BOTWATCHMAN </a> <a id='analyzeSend' style='color:black;' href='#'> | ANALYZE </a> <a id='reportUserToSpam' style='color:black;' href='#'> | /R/SPAM </a> <a id='adminSend' style='color:black;' href='#'> | ADMIN </a> ";
  58. } else {
  59. newToolbar.innerHTML += " <a id='downvoteComment' style='color:black;' href='#'>DOWNVOTE ALL</a> <a id='upvoteComment' style='color:black;' href='#'> | UPVOTE ALL</a> <a id='composeNew' style='color:black;' href='#'> | COMPOSE </a>";
  60. }
  61.  
  62.  
  63. }
  64.  
  65. function doStuff() {
  66.  
  67. $('#reportComment').click(function (e) {
  68. var r = confirm("This will report all items on the page.");
  69. if (r === true) {
  70. alert('All items on this page were reported.');
  71. for (var i = 0; i < reportID.length; i++) {
  72. reportItem(i, 3);
  73. }
  74.  
  75. } else {
  76. alert('Report canceled');
  77. }
  78. });
  79.  
  80.  
  81. $('#downvoteComment').on('click', function (e) {
  82. theDownvoter();
  83. });
  84. $('#upvoteComment').on('click', function (e) {
  85. theUpvoter();
  86. });
  87. $('#reportUserToSpam').on('click', function (e) {
  88. reportToSpam();
  89. });
  90. $('#analyzeSend').on('click', function (e) {
  91. analyzeSend();
  92. });
  93. $('#botwatchmanSend').on('click', function (e) {
  94. botwatchmanSend();
  95. });
  96. $('#composeNew').on('click', function (e) {
  97. composeNew();
  98. });
  99. $('#adminSend').on('click', function (e) {
  100. adminSend();
  101. });
  102. }
  103.  
  104. function buildReportArray() {
  105. if (commentPage.length == 0) {
  106. var threads;
  107. threads = $('#siteTable').find('.thing');
  108. for (i = 0; i < threads.length; i++) {
  109. reportID.push(threads[i].getAttribute('data-fullname'));
  110. }
  111. } else if (commentPage.length != 0) {
  112. var threads;
  113. threads = $('.commentarea').find('.thing');
  114. for (i = 0; i < threads.length; i++) {
  115. reportID.push(threads[i].getAttribute('data-fullname'));
  116. }
  117. }
  118. }
  119.  
  120. function reportItem(index, num) {
  121. console.log('reportItem went')
  122. if (num == 3) {
  123. var fullname = topicIDs[index];
  124. } else {
  125. var fullname = commentIDs[index];
  126. }
  127. $.post('http://www.reddit.com/api/report', {
  128. 'reason': 'spam',
  129. 'thing_id': fullname,
  130. 'uh': modHash
  131. });
  132. }
  133.  
  134.  
  135. function theDownvoter() {
  136. if (parsedPage[3] == 'user') {
  137. var items = $('#siteTable').find('.arrow.down');
  138. Array.prototype.forEach.call(items, function (el, i) {
  139. setTimeout(function () {
  140. el.click();
  141. }, 100 + (i * 400));
  142. });
  143. return false;
  144. } else {
  145. if (commentPage.length == 0) {
  146. var items = $('#siteTable').find('.arrow.down');
  147. Array.prototype.forEach.call(items, function (el, i) {
  148. setTimeout(function () {
  149. el.click();
  150. }, 100 + (i * 400));
  151. });
  152. return false;
  153. } else {
  154. var items = $('.commentarea').find('.arrow.down');
  155. Array.prototype.forEach.call(items, function (el, i) {
  156. setTimeout(function () {
  157. el.click();
  158. }, 100 + (i * 400));
  159. });
  160. return false;
  161. }
  162. }
  163. }
  164.  
  165. function theUpvoter() {
  166. if (parsedPage[3] == 'user') {
  167. var items = $('#siteTable').find('.arrow.up');
  168. Array.prototype.forEach.call(items, function (el, i) {
  169. setTimeout(function () {
  170. el.click();
  171. }, 100 + (i * 400));
  172. });
  173. return false;
  174. } else {
  175. if (commentPage.length == 0) {
  176. var items = $('#siteTable').find('.arrow.up');
  177. Array.prototype.forEach.call(items, function (el, i) {
  178. setTimeout(function () {
  179. el.click();
  180. }, 100 + (i * 400));
  181. });
  182. return false;
  183. } else {
  184. var items = $('.commentarea').find('.arrow.up');
  185. Array.prototype.forEach.call(items, function (el, i) {
  186. setTimeout(function () {
  187. el.click();
  188. }, 100 + (i * 400));
  189. });
  190. return false;
  191. }
  192. }
  193. }
  194.  
  195.  
  196. function reportToSpam() {
  197. var username = $(document).find('.pagename.selected').text();
  198. window.open('http://www.reddit.com/r/spam/submit?title=overview for ' + username + '&resubmit=true&url=http://www.reddit.com/user/' + username);
  199. }
  200.  
  201. function analyzeSend() {
  202. var username = $(document).find('.pagename.selected').text();
  203. window.open('http://www.reddit.com/message/compose/?to=analyzereddit&subject=analyze&message=' + username);
  204. }
  205.  
  206. function botwatchmanSend() {
  207. var username = $(document).find('.pagename.selected').text();
  208. window.open('http://www.reddit.com/r/botwatchman/submit?title=overview for ' + username + '&url=http://www.reddit.com/user/' + username);
  209. }
  210.  
  211. function composeNew() {
  212. window.open('http://www.reddit.com/message/compose/');
  213. }
  214.  
  215. function adminSend() {
  216. var username = $(document).find('.pagename.selected').text();
  217. window.open('http://www.reddit.com/message/compose/?to=/r/reddit.com&message=' + /u/ + username);
  218. }
  219.  
  220.  
  221. //disable .np
  222.  
  223. if (document.documentElement.lang === 'np') {
  224. document.documentElement.lang = 'en-us';
  225. }
  226.  
  227. document.body.classList.add('subscriber');
  228.  
  229. delete_function = function (thread_root) {
  230. var elmnts = document.getElementsByClassName('id-' + thread_root)[0].querySelectorAll('form input[value="removed"]~span.option.error a.yes,a[onclick^="return big_mod_action($(this), -1)"]');
  231. for (var i = 0; i < elmnts.length; i++) {
  232. setTimeout(
  233. (function (_elmnt) {
  234. return function () {
  235. var event = document.createEvent('UIEvents');
  236. event.initUIEvent('click', true, true, window, 1);
  237. _elmnt.dispatchEvent(event);
  238. }
  239. })(elmnts[i]), 1500 * i); // 1.5s timeout prevents overloading reddit.
  240. };
  241. }
  242.  
  243. //source reveal (creesch)
  244.  
  245. $('.comments-page .comment .flat-list.buttons').each(function () { // this targets each flat-list belonging to comments on a comment page.
  246. $(this).append('<li><a class="view-source" href="javascript:void(0)">view source</a></li>'); // it then adds the view source button in the belonging function
  247. });
  248.  
  249. $('body').on('click', '.view-source', function () { // On clicking of the view source button we do what we want to do. Note that we start with body since that is a constant dom element. If you try to target added dom elements directly it will not work.
  250. var $this = $(this), // We posisbly want to reuse $(this), it is cleaner to define jquery objects you want to reuse.
  251. $parentThing = $this.closest('.thing'),
  252. thingId = $parentThing.attr('data-fullname'); // we need an id to throw at the api, luckily it is is present in the html.
  253.  
  254. if ($parentThing.find('#box-' + thingId).length) { // Lets see if we already did do this before.
  255. $parentThing.find('#box-' + thingId).toggle(); // we did, toggle
  256. } else { // we did not, grab the info.
  257. $.getJSON('/api/info.json?id=' + thingId, function () { // lets do an ajax call to grab the info we need.
  258. console.log("success"); // you can remove this, basically lets you know a json call is done.
  259. })
  260. .done(function (data) { // by doing the stuff we need to do in .done we make sure we have the data needed since ajax is async.
  261. var commentBody = data.data.children[0].data.body; // json is basically an object.
  262. var commentSourceBox = '<textarea style="display:block" rows="10" cols="50">' + commentBody + '</textarea>'; // build the source box.
  263. $parentThing.find('.flat-list').first().before(commentSourceBox); // and add it to the .thing, note that I use .first() if I didn't do that it would add the source box for all child comments as well.
  264. });
  265. }
  266. });
  267.  
  268.  
  269. //nuke (djimbob)
  270.  
  271. delete_function = function (thread_root) {
  272. var elmnts = document.getElementsByClassName('id-' + thread_root)[0].querySelectorAll('form input[value="removed"]~span.option.error a.yes,a[onclick^="return big_mod_action($(this), -1)"]');
  273. for (var i = 0; i < elmnts.length; i++) {
  274. setTimeout(
  275. (function (_elmnt) {
  276. return function () {
  277. var event = document.createEvent('UIEvents');
  278. event.initUIEvent('click', true, true, window, 1);
  279. _elmnt.dispatchEvent(event);
  280. }
  281. })(elmnts[i]), 1500 * i); // 1.5s timeout prevents overloading reddit.
  282. };
  283. }
  284.  
  285. if (document.querySelector('body.moderator')) { // only execute if you are a moderator
  286. var nuke_button = new Array();
  287. var divels = document.querySelectorAll('div.noncollapsed');
  288. var comment_ids = new Array();
  289. var use_image = false;
  290. // create img DOM element to clone
  291. if (use_image) {
  292. try {
  293. var img_element = document.createElement('img');
  294. img_element.setAttribute('alt', 'Nuke!');
  295. img_element.setAttribute('src', chrome.extension.getURL('nuke.png'));
  296. } catch (e) {
  297. use_image = false;
  298. }
  299. }
  300. for (var i = 0; i < divels.length; i++) {
  301. var author_link = divels[i].querySelector('p.tagline>a.author,p.tagline>span.author,p.tagline>em');
  302. // p.tagline>a.author is normal comment;
  303. // some author deleted comments seem to have either
  304. // p.tagline>span.author or p.tagline>em
  305.  
  306. comment_ids[i] = divels[i].getAttribute('data-fullname');
  307. // console.log(i + ':' + comment_ids);
  308. if (author_link) {
  309. // create link DOM element with img inside link
  310. nuke_button[i] = document.createElement('a')
  311. nuke_button[i].setAttribute('href', 'javascript:void(0)');
  312. nuke_button[i].setAttribute('title', 'Nuke!');
  313. nuke_button[i].setAttribute('id', 'nuke_' + i);
  314. if (use_image) {
  315. nuke_button[i].appendChild(img_element.cloneNode(true));
  316. } else {
  317. nuke_button[i].innerHTML = "[Nuke]";
  318. }
  319. // append after the author's name
  320. author_link.parentNode.insertBefore(nuke_button[i], author_link.nextSibling);
  321.  
  322. // Add listener for click; using IIFE to function with _i as value of i when created; not when click
  323. nuke_button[i].addEventListener('click', (function (_i) {
  324. return function () {
  325. var continue_thread = divels[_i].querySelectorAll('span.morecomments>a');
  326. var comment_str = " comments?";
  327. if (continue_thread.length > 0) {
  328. comment_str = "+ comments (more after expanding collapsed threads; there will be a pause before the first deletion to retrieve more comments)?";
  329. }
  330. var delete_button = divels[_i].querySelectorAll('form input[value="removed"]~span.option.error a.yes,a[onclick^="return big_mod_action($(this), -1)"]');
  331. // form input[value="removed"]~span.option.error a.yes -- finds the yes for normal deleting comments.
  332. // a.pretty-button.neutral finds the 'remove' button for flagged comments
  333. if (confirm("Are you sure you want to nuke the following " + delete_button.length + comment_str)) {
  334. for (var indx = 0; indx < continue_thread.length; indx++) {
  335. var elmnt = continue_thread[indx];
  336. setTimeout(
  337.  
  338. function () {
  339. var event = document.createEvent('UIEvents');
  340. event.initUIEvent('click', true, true, window, 1);
  341. elmnt.dispatchEvent(event);
  342. }, 2000 * indx); // wait two seconds before each ajax call before clicking each "load more comments"
  343. }
  344. if (indx > 0) {
  345. setTimeout(function () {
  346. delete_function(comment_ids[_i])
  347. },
  348. 2000 * (indx + 2)); // wait 4s after last ajax "load more comments"
  349. } else {
  350. delete_function(comment_ids[_i]); // call immediately if not "load more comments"
  351. }
  352. }
  353. }
  354. })(i)); // end of IIFE (immediately invoked function expression)
  355. }
  356. }
  357. }
  358.  
  359. //linkswapping
  360.  
  361. document.addEventListener("DOMContentLoaded", replaceLinks, false);
  362.  
  363. if (document.readyState === "complete") {
  364. replaceLinks();
  365. }
  366.  
  367. function replaceLinks() {
  368. Array.forEach(document.links, function (a) {
  369. a.href = a.href.replace("https://i.imgur.com", "http://imgur.com");
  370. a.href = a.href.replace("https://imgur.com", "http://imgur.com");
  371. });
  372. }
  373.  
  374. generateToolbar(), getHash(), buildReportArray(), doStuff();