RaaW

Reddit as a Weapon script. Parts and idea by /u/noeatnosleep, enhanced by /u/enim

当前为 2014-08-18 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name RaaW
  3. // @version 1.7.0
  4. // @namespace RaaW
  5. // @description Reddit as a Weapon script. Parts and idea by /u/noeatnosleep, enhanced by /u/enim
  6. // @include http://www.reddit.com/user/*
  7. // @include http://www.reddit.com/r/*
  8. // @include http://*reddit.com/*
  9. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js
  10. // ==/UserScript==
  11.  
  12. this.$ = this.jQuery = jQuery.noConflict(true);
  13.  
  14. var currentPage = document.URL;
  15. var parsedPage = currentPage.split('/');
  16. var modHash = null;
  17. var currentUser = null;
  18. var subreddit = null;
  19. var commentIDs = [];
  20. var topicIDs = [];
  21. var subredditList = [];
  22. var reportID = [];
  23.  
  24. var commentPage;
  25. commentPage = document.getElementsByClassName('comment');
  26.  
  27. function getHash(callback) {
  28. var query = new XMLHttpRequest();
  29. query.onreadystatechange = function () {
  30. if (query.readyState == 4) {
  31. var info = JSON.parse(query.responseText);
  32. modHash = info.data.modhash;
  33. callback();
  34. }
  35. }
  36. query.open('GET', 'http://www.reddit.com/api/me.json', true);
  37. query.send(null);
  38. }
  39.  
  40. function generateToolbar () {
  41. $(document).find('#header')[0].style.paddingTop='18px';
  42. var newToolbar = document.createElement("div");
  43. newToolbar.id = "newToolbar";
  44. document.body.insertBefore(newToolbar,document.body.firstChild);
  45. var subredditbar = document.getElementById('sr-header-area');
  46. 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;";
  47. newToolbar.style.backgroundColor='#f0f0f0';
  48. newToolbar.style.paddingLeft = '6px';
  49. newToolbar.style.paddingTop = '3px';
  50. newToolbar.style.paddingBottom = '3px';
  51. newToolbar.style.top='0px';
  52. newToolbar.innerHTML += "<a id='downvoteComment' style='color:black;' href='#'>DOWNVOTE ALL</a> | <a id='upvoteComment' style='color:black;' href='#'>UPVOTE ALL</a> |";
  53. if (commentPage.length == 0) {
  54. newToolbar.innerHTML += " <a id=reportComment style='color:black;' href='#'>REPORT POSTS</a> ";
  55. }
  56. else {
  57. newToolbar.innerHTML += "<a id=reportComment style='color:black;' href='#'> REPORT ALL</a> ";
  58. }
  59. if (parsedPage[3] == 'user'){
  60. newToolbar.innerHTML += "<a id='upvoteAndOpen' style='color:black;' href='#'> | OPEN AND UPVOTE </a> <a id='downvoteAndOpen' style='color:black;' href='#'> | OPEN AND DOWNVOTE </a> <a id='analyzeSend' style='color:black;' href='#'> | ANALYZE </a> <a id='reportUserToSpam' style='color:black;' href='#'> | REPORT ON /R/SPAM </a>";
  61. }
  62.  
  63. }
  64.  
  65.  
  66. function doStuff() {
  67. $('#reportComment').on('click',function(e) {
  68. for(var i = 0; i < reportID.length; i++) {reportItem(i, 3);}
  69. alert('All items on this page were reported.');
  70. });
  71. $('#downvoteComment').on('click',function(e){
  72. theDownvoter();
  73. });
  74. $('#upvoteComment').on('click',function(e){
  75. theUpvoter();
  76. });
  77. $('#upvoteAndOpen').on('click',function(e){
  78. clickYourUpvotes();
  79. });
  80. $('#downvoteAndOpen').on('click',function(e){
  81. clickYourDownvotes();
  82. });
  83. $('#reportUserToSpam').on('click',function(e){
  84. reportToSpam();
  85. });
  86. $('#analyzeSend').on('click',function(e){
  87. analyzeSend();
  88. });
  89. }
  90.  
  91. function buildReportArray() {
  92. if (commentPage.length == 0) {
  93. var threads;
  94. threads = $('#siteTable').find('.thing');
  95. for (i = 0; i < threads.length; i++) {
  96. reportID.push(threads[i].getAttribute('data-fullname'));
  97. }
  98. }
  99. else if (commentPage.length != 0) {
  100. var threads;
  101. threads = $('.commentarea').find('.thing');
  102. for (i = 0; i < threads.length; i++) {
  103. reportID.push(threads[i].getAttribute('data-fullname'));
  104. }
  105. }
  106. }
  107.  
  108. function reportItem(index, num) {
  109. if(num == 3) {var fullname = topicIDs[index];}
  110. else{var fullname = commentIDs[index];}
  111. $.post('http://www.reddit.com/api/report', {'id': fullname, 'uh': modHash});
  112. }
  113.  
  114.  
  115. function theDownvoter() {
  116. if (parsedPage[3] == 'user'){
  117. var items = $('#siteTable').find('.arrow.down');
  118. Array.prototype.forEach.call(items, function(el, i){
  119. setTimeout(function(){
  120. el.click();
  121. },100 + ( i * 400 ));
  122. });
  123. return false;
  124. }
  125. else {
  126. if (commentPage.length == 0) {
  127. var items = $('#siteTable').find('.arrow.down');
  128. Array.prototype.forEach.call(items, function(el, i){
  129. setTimeout(function(){
  130. el.click();
  131. },100 + ( i * 400 ));
  132. });
  133. return false;
  134. }
  135. else {
  136. var items = $('.commentarea').find('.arrow.down');
  137. Array.prototype.forEach.call(items, function(el, i){
  138. setTimeout(function(){
  139. el.click();
  140. },100 + ( i * 400 ));
  141. });
  142. return false;
  143. }
  144. }
  145. }
  146.  
  147. function theUpvoter() {
  148. if (parsedPage[3] == 'user'){
  149. var items = $('#siteTable').find('.arrow.up');
  150. Array.prototype.forEach.call(items, function(el, i){
  151. setTimeout(function(){
  152. el.click();
  153. },100 + ( i * 400 ));
  154. });
  155. return false;
  156. }
  157. else {
  158. if (commentPage.length == 0) {
  159. var items = $('#siteTable').find('.arrow.up');
  160. Array.prototype.forEach.call(items, function(el, i){
  161. setTimeout(function(){
  162. el.click();
  163. },100 + ( i * 400 ));
  164. });
  165. return false;
  166. }
  167. else {
  168. var items = $('.commentarea').find('.arrow.up');
  169. Array.prototype.forEach.call(items, function(el, i){
  170. setTimeout(function(){
  171. el.click();
  172. },100 + ( i * 400 ));
  173. });
  174. return false;
  175. }
  176. }
  177. }
  178.  
  179. function clickYourUpvotes() {
  180. var clickandupvote = [];
  181. $('#siteTable').find('.flat-list.buttons').find('.first').find('a.comments, a.bylink').each(function(index,value){
  182. clickandupvote.push($(this).attr('href'));
  183. });
  184. for (i=0;i < clickandupvote.length;i++){
  185. window.open(clickandupvote[i]);
  186. }
  187. var items = $('#siteTable').find('.arrow.up');
  188. Array.prototype.forEach.call(items, function(el, i){
  189. setTimeout(function(){
  190. el.click();
  191. },100 + ( i * 400 ));
  192. });
  193. return false;
  194. }
  195.  
  196. function clickYourDownvotes() {
  197. var clickandupvote = [];
  198. $('#siteTable').find('.flat-list.buttons').find('.first').find('a.comments, a.bylink').each(function(index,value){
  199. clickandupvote.push($(this).attr('href'));
  200. });
  201. for (i=0;i < clickandupvote.length;i++){
  202. window.open(clickandupvote[i]);
  203. }
  204. var items = $('#siteTable').find('.arrow.down');
  205. Array.prototype.forEach.call(items, function(el, i){
  206. setTimeout(function(){
  207. el.click();
  208. },100 + ( i * 400 ));
  209. });
  210. return false;
  211. }
  212. function reportToSpam(){
  213. var username = $(document).find('.pagename.selected').text();
  214. window.open('http://www.reddit.com/r/spam/submit?title=overview for '+ username + '&url=http://www.reddit.com/user/' + username );
  215. }
  216.  
  217. function analyzeSend(){
  218. var username = $(document).find('.pagename.selected').text();
  219. window.open('http://www.reddit.com/message/compose/?to=analyzereddit&subject=analyze&message='+ username);
  220. }
  221.  
  222. if (document.documentElement.lang === 'np') {
  223. document.documentElement.lang = 'en-us';
  224. }
  225. document.body.classList.add('subscriber');
  226.  
  227. delete_function = function(thread_root) {
  228. 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)"]');
  229. for(var i=0; i < elmnts.length; i++) {
  230. setTimeout(
  231. (function(_elmnt) {
  232. return function() {
  233. var event = document.createEvent('UIEvents');
  234. event.initUIEvent('click', true, true, window, 1);
  235. _elmnt.dispatchEvent(event);
  236. }}
  237. )(elmnts[i]), 1500*i); // 1.5s timeout prevents overloading reddit.
  238. };
  239. }
  240.  
  241. if(document.querySelector('body.moderator')){ // only execute if you are a moderator
  242. var nuke_button = new Array();
  243. var divels = document.querySelectorAll('div.noncollapsed');
  244. var comment_ids = new Array();
  245.  
  246.  
  247. for (var i = 0; i < divels.length; i++) {
  248. var author_link = divels[i].querySelector('p.tagline>a.author,p.tagline>span.author,p.tagline>em');
  249. // p.tagline>a.author is normal comment;
  250. // some author deleted comments seem to have either
  251. // p.tagline>span.author or p.tagline>em
  252. comment_ids[i] = divels[i].parentElement.parentElement.getAttribute('data-fullname');
  253. if(author_link) {
  254. // create link DOM element
  255. nuke_button[i] = document.createElement('a')
  256. nuke_button[i].setAttribute('href', 'javascript:void(0)');
  257. nuke_button[i].setAttribute('title', 'Nuke!');
  258. nuke_button[i].setAttribute('id', 'nuke_'+i);
  259. nuke_button[i].innerHTML= "[<strong>Nuke</strong>]";
  260. // append after the author's name
  261. author_link.parentNode.insertBefore(nuke_button[i], author_link.nextSibling);
  262.  
  263. // Add listener for click; using IIFE to function with _i as value of i when created; not when clicked
  264. nuke_button[i].addEventListener('click',
  265. (function(_i) {
  266. return function() {
  267. var continue_thread = divels[_i].parentElement.parentElement.querySelectorAll('span.morecomments>a');
  268. var comment_str = " comments?";
  269. if(continue_thread.length > 0) {
  270. comment_str = "+ comments (more after expanding collapsed threads; there will be a pause before the first deletion to retrieve more comments)?";
  271. }
  272. var delete_button = divels[_i].parentElement.parentElement.querySelectorAll('form input[value="removed"]~span.option.error a.yes,a[onclick^="return big_mod_action($(this), -1)"]');
  273. // form input[value="removed"]~span.option.error a.yes -- finds the yes for normal deleting comments.
  274. // a.pretty-button.neutral finds the 'remove' button for flagged comments
  275. if (confirm("Are you sure you want to nuke the following " + delete_button.length + comment_str)) {
  276. for (var indx=0; indx < continue_thread.length; indx++) {
  277. var elmnt = continue_thread[indx];
  278. setTimeout(
  279. function() {
  280. var event = document.createEvent('UIEvents');
  281. event.initUIEvent('click', true, true, window, 1);
  282. elmnt.dispatchEvent(event);
  283. }, 2000*indx); // wait two seconds before each ajax call before clicking each "load more comments"
  284. }
  285. if(indx > 0) {
  286. setTimeout(function() {delete_function(comment_ids[_i])},
  287. 2000*(indx + 2)); // wait 4s after last ajax "load more comments"
  288. } else {
  289. delete_function(comment_ids[_i]); // call immediately if not "load more comments"
  290. }
  291. }
  292. }
  293. }
  294. )(i)); // end of IIFE (immediately invoked function expression)
  295. }
  296. }
  297. }
  298.  
  299.  
  300. function reveal() {
  301. var l = window.document.location,
  302. h = l.href,
  303. q = l.search,
  304. u = h.substring(0, h.length - q.length) + ".json" + q;
  305. $.getJSON(u, function (json_data) {
  306.  
  307. var dom_data = (function () {
  308. var result = {},
  309. key;
  310. $.each($(".thing"), function () {
  311. var thingDom = this;
  312. if ($(this).css("display") === "none") {
  313. return;
  314. }
  315. $.each(this.className.split(" "), function () {
  316. if (this.indexOf("id-") === 0) {
  317. var thing_type_name = this.substr(3).split("_");
  318. if (typeof(result[thing_type_name[0]]) === "undefined") {
  319. result[thing_type_name[0]] = [];
  320. }
  321. result[thing_type_name[0]].push({
  322. name: thing_type_name[1],
  323. domObj: thingDom
  324. });
  325. }
  326. });
  327. });
  328. return result;
  329. })();
  330.  
  331. var json_result = {};
  332.  
  333. function gather_data(json_data) {
  334. var crawl = function (obj) {
  335. if (obj && obj.length) {
  336. $.each(obj, function () {
  337. crawl(this);
  338. });
  339. } else if (typeof(obj) === "object") {
  340. var kind = obj.kind;
  341. var data = obj.data;
  342. if (kind) {
  343. if (kind === "Listing") {
  344. crawl(data.children);
  345. } else if (data) {
  346. if (typeof(json_result[kind]) === "undefined") {
  347. json_result[kind] = {};
  348. }
  349. json_result[kind][data.id] = data;
  350. if (kind === "t1" && data.replies) {
  351. crawl(data.replies);
  352. }
  353. }
  354. }
  355. }
  356. };
  357. crawl(json_data);
  358. }
  359.  
  360. gather_data(json_data);
  361.  
  362. var enable_source = function (entry, text) {
  363. if (entry.find(".usertext-edit").size() > 0 || entry.find(".usertext-body").size() === 0) {
  364. return;
  365. }
  366. entry.find(".usertext-body").after("<div class=\"usertext-edit\" style=\"display:none;\"><div><textarea rows=\"1\" cols=\"1\" name=\"text\">" + text + "</textarea></div><div class=\"bottom-area\"><div class=\"usertext-buttons\"><button type=\"button\" class=\"cancel\" onclick=\"cancel_usertext(this)\">hide</button></div></div></div>");
  367. entry.find(".flat-list.buttons").append("<li><a class=\"edit-usertext\" href=\"javascript:void(0)\" onclick=\"return edit_usertext(this)\">source</a></li>");
  368. };
  369.  
  370.  
  371.  
  372. var update_t3_ui = function (domObj, data) {
  373. var thing = $(domObj);
  374. var entry = thing.children(".entry");
  375. var midcol = thing.children(".midcol");
  376. var score = data.score;
  377.  
  378.  
  379. if (dom_data.t3) {
  380. $.each(dom_data.t3, function () {
  381. var name = this.name;
  382. var domObj = this.domObj;
  383. var data = json_result.t3[name];
  384. if (!data) {
  385. $.getJSON("/by_id/t3_" + name + ".json", function (json_data) {
  386. update_t3_ui(domObj, json_data.data.children[0].data);
  387. });
  388. return;
  389. } else {
  390. update_t3_ui(domObj, data);
  391. }
  392. });
  393. }
  394. };
  395. update_ui();
  396. });
  397.  
  398. $(".button").on("click", function(ev) {
  399. console.log(this.id);
  400. if (this.id.indexOf("more_t1_") === 0) {
  401. var id = this.id.split("_")[2];
  402. console.log(id);
  403. }
  404. });
  405.  
  406. $(".author").on("mouseover", function (ev) {
  407. var username = $(this).text();
  408. var rev = $(this).next(".revelation");
  409. if (rev.size() === 0) {
  410. var tip = $("<span class=\"revelation\" style=\"position:relative;\"/>");
  411. $(this).after(tip);
  412. $.getJSON("/user/" + username + "/about.json", function (a) {
  413. tip.html(" (<span style=\"color:#B40404\"><b>" + a.data.link_karma + "</b> link karma</span>," + " <span style=\"color:#04B404\"><b>" + a.data.comment_karma + "</b> comment karma</span>, " + " <span style=\"color:#0404B4\"><b>" + parseInt((((new Date()).getTime() / 1000) - a.data.created_utc) / 86400, 10) + "</b> days</span>) ");
  414. });
  415. } else {
  416. rev.css("display", "");
  417. }
  418. }).on("mouseout", function (ev) {
  419. $(this).next(".revelation").css("display", "none");
  420. });
  421. }
  422. (function () {
  423. var s = document.createElement('script');
  424. s.textContent = "(" + reveal.toString() + ')();';
  425. document.head.appendChild(s);
  426. })();
  427.  
  428. generateToolbar(), getHash(),buildReportArray(), doStuff();