SoftJustman

Steam comments cleaner

Aug 27th, 2017 (edited)
13,640
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.     Execute this code on https://steamcommunity.com/my/commenthistory
  3.  
  4.     The newest versions are available on BitBucket: https://bitbucket.org/SoftJustman/steamcommentscleaner
  5.  
  6.     Created by Justman (steamcommunity.com/id/justman666)
  7.     Specially for Miped.ru
  8.  
  9.     Special thx for script testers from Reddit :)
  10. */
  11.  
  12. /*
  13.     Changable constants
  14. */
  15. var FIRST_PAGE_TO_CLEAR = 1; // Number of first page to be cleared
  16. var LAST_PAGE_TO_CLEAR = -1; // Number of last page to clear. -1 if you need to delete all of them
  17. // Example (2, 2) will clear 2nd page only
  18. var PRINT_EXECUTED_COMMANDS = false; // Print everything script does (It's a lot)
  19.  
  20. /*
  21.     Constants
  22. */
  23. var COMMENTS_PAGE = "https://steamcommunity.com/my/commenthistory"; // URL to page with comments
  24. var FORUMS_JS_URL = [
  25.     "https://community.cloudflare.steamstatic.com/public/javascript/global.js",
  26.     "https://steamcommunity-a.akamaihd.net/public/javascript/forums.js",
  27.     "https://community.edgecast.steamstatic.com/public/javascript/forums.js"
  28. ]; // URL to page with forums.js
  29. var FORUM_JS_LOAD_TIMEOUT = 10000; // ms
  30. var USER_STEAM_PROFILE_URL = jQuery("#global_actions > a").attr("href").replace(/\/$/, ""); // https://steamcommunity.com/id/$ID
  31. var PAGE_REQUESTS_INTERVAL = 1000; // ms
  32. var TIMESTAMP_DIFF = 3; // Maximum difference between timestamps
  33. var REGEXP =
  34. {
  35.     "body": /<body.{1,}?>([.\s\S]{1,})<\/body>/, // Body innerHTML (No depending on attributes)
  36.     "link": /^(.{1,}?)(?:\?(.{1,}?))?$/, // Link -> url + data
  37.     "initFTopic": /InitializeForumTopic\s?\([^"]+?(?:"[^"]+?"[^"]+?)+?[^"]+?\);/, // Protected from ); in quotes
  38.     "initCThread": /InitializeCommentThread\s?\([^"]+?(?:"[^"]+?"[^"]+?)+?[^"]+?\);/ // Protected from ); in quotes
  39. };
  40.  
  41. /*
  42.     Utility
  43. */
  44. var pages_amount = jQuery(".pageLinks .pagelink:last").html(); // Amount of pages
  45. if (!pages_amount) {
  46.     pages_amount = 1;
  47. } else {
  48.     pages_amount = +(pages_amount);
  49. }
  50. var pages = []; // Array with page bodies
  51. var comments = []; // Array with comments to clean
  52.  
  53. var execute = function(txt) // Replacer to eval to be able to see commands printed
  54. {
  55.     if (PRINT_EXECUTED_COMMANDS) {
  56.         console.log(txt);
  57.     }
  58.     eval(txt);
  59. }
  60.  
  61. /*
  62.     Functions
  63. */
  64. var loadPagesFrom = function(fromPageNumber, callback) // Loading page body with comments and adding it to pages as div
  65. {
  66.     if (fromPageNumber > pages_amount || (LAST_PAGE_TO_CLEAR != -1 && fromPageNumber > LAST_PAGE_TO_CLEAR)) {
  67.         console.log("    Loaded pages");
  68.         console.log(pages);
  69.         if (typeof callback == "function") {
  70.             callback();
  71.         }
  72.         return;
  73.     }
  74.     console.log("    Loading page #" + fromPageNumber);
  75.     if (location.search.match(new RegExp("p=" + fromPageNumber)) || fromPageNumber == 1) {
  76.         var elem = document.createElement("div");
  77.         elem.innerHTML = document.body.innerHTML;
  78.         pages.push(elem);
  79.         console.log("    Loaded page #" + fromPageNumber);
  80.         loadPagesFrom(fromPageNumber + 1, callback);
  81.         return;
  82.     }
  83.  
  84.     var search = location.search.replace(/\?/, ""); // Delete first ? if it exists
  85.     if (search) {
  86.         // Search is not empty
  87.         if (search.match(/p=[0-9]{1,}/)) {
  88.             // Page number is already stated (it must be 1)
  89.             search = search.replace(/p=[0-9]{1,}/, "p=" + fromPageNumber)
  90.         } else {
  91.             // No page number but have some search parameters
  92.             search += "&p=" + fromPageNumber;
  93.         }
  94.     } else {
  95.         // empty search
  96.         search = "p=" + fromPageNumber;
  97.     }
  98.     jQuery.ajax({
  99.         "success": function(data, status)
  100.         {
  101.             var inner = data.match(REGEXP.body)[1];
  102.             var elem = document.createElement("div");
  103.             elem.innerHTML = inner;
  104.             pages.push(elem);
  105.             console.log("    Loaded page #" + fromPageNumber);
  106.             loadPagesFrom(fromPageNumber + 1, callback);
  107.         },
  108.         "fail" : function()
  109.         {
  110.             console.error("    !!!Unable to load page");
  111.         },
  112.         "data": search,
  113.         "method": "GET",
  114.         "url": COMMENTS_PAGE
  115.     });
  116. };
  117.  
  118. var loadURLsFrom = function(fromPageNumber, callback) // Loading URLs and adding them to comments as objects
  119. {
  120.     if (fromPageNumber > pages.length) {
  121.         console.log("    Loaded URLs");
  122.         console.log(comments);
  123.         if (typeof callback == "function") {
  124.             callback();
  125.         }
  126.         return;
  127.     }
  128.     jQuery(pages[fromPageNumber - 1]).find(".commenthistory_comment .comment_item_title a").each(function(index, a)
  129.     {
  130.         var info = {}; // Info about comment
  131.         var link = a.href;
  132.         link = link.replace(/#/,"/"); // Getting rid of # (replacable with /)
  133.         if (link.match(/\/discussions\//)) {
  134.             info["isForum"] = true;
  135.         } else {
  136.             info["isForum"] = false;
  137.         }
  138.         var m = link.match(REGEXP.link);
  139.         info["link"] = link; // Full link
  140.         info["url"] = m[1]; // Link with no GET arguments
  141.         info["data"] = m[2]; // GET arguments (key=val&key=val...)
  142.         if (info["data"] && info["data"].match(/tscn=[0-9]{1,}/)) {
  143.             info["timestamp"] = info["data"].match(/tscn=([0-9]{1,})/)[1]; // Timestamp
  144.         }
  145.         if (info["isForum"]) {
  146.             if (info["data"] && info["data"].match(/tscn=/)) {
  147.                 info["isForumTopic"] = false;
  148.             } else {
  149.                 info["isForumTopic"] = true;
  150.             }
  151.         }
  152.         info["text"] = jQuery(a).closest(".commenthistory_comment").find(".comment_text").text().replace(/\s/g, "");
  153.         comments.push(info);
  154.     });
  155.     console.log("    Loaded URLs from page #" + (fromPageNumber + FIRST_PAGE_TO_CLEAR - 1));
  156.     loadURLsFrom(fromPageNumber + 1, callback);
  157. }
  158.  
  159. var clearURLfromIndex = function(index, callback) // Clearing comment form comments array by its index
  160. {
  161.     if (index >= comments.length) {
  162.         console.log("    Cleared URLs");
  163.         console.log(comments);
  164.         if (typeof callback == "function") {
  165.             window.location.hash = ""; // Removing previously set hash
  166.             callback();
  167.         }
  168.         return;
  169.     }
  170.     window.location.hash = "#p0"; // Can't initialize Comment thread without this hash (Crutch ._ .)
  171.     jQuery.ajax({
  172.         "success": function(data, status)
  173.         {
  174.             try {
  175.                 comments[index]["html"] = document.createElement("div");
  176.                 comments[index]["html"].innerHTML = data;
  177.                 if (jQuery(comments[index]["html"]).find("#message").length) {
  178.                     throw new Error(jQuery(comments[index]["html"]).find("#message").text());
  179.                 }
  180.                 if (comments[index]["isForum"]) {
  181.                     var initFTopic = jQuery(comments[index]["html"]).find("script:contains(InitializeForumTopic)").html(); // Code to be executed
  182.                     initFTopic = initFTopic.match(REGEXP.initFTopic)[0]; // Getting main command
  183.                     execute(initFTopic);
  184.                     var initCThread = jQuery(comments[index]["html"]).find("script:contains(InitializeCommentThread)").html(); // Code to be executed
  185.                     initCThread = initCThread.match(REGEXP.initCThread)[0]; // Getting main command
  186.                     initCThread = initCThread.replace(/\{/, "{\"no_paging\": true, "); // Adding no paging to prevent error
  187.                     execute(initCThread);
  188.                     if (comments[index]["isForumTopic"]) {
  189.                         // Topic
  190.                         var deleteTopic = jQuery(comments[index]["html"]).find(".forum_op a[href*=\"DeleteTopic\"]");
  191.                         var argument = jQuery(deleteTopic).attr("href").match(/\(([.\s\S]{1,}?)\)/)[1].replace(/[\s'"]/g, "");
  192.                         new Ajax.Request(
  193.                             g_rgForumTopics[argument].GetActionURL("deletetopic"), {
  194.                             "method": "POST",
  195.                             "parameters": g_rgForumTopics[argument].ParametersWithDefaults()
  196.                         });
  197.                     } else {
  198.                         // Message
  199.                         var messagesByUser = jQuery(comments[index]["html"]).find(".commentthread_comment .commentthread_comment_avatar a[href*=\"" + USER_STEAM_PROFILE_URL + "\"]").closest(".commentthread_comment"); // Messages on the page by user
  200.                         var ifFoundMessage = false;
  201.                         messagesByUser.each(function(i, message)
  202.                         {
  203.                             var text = jQuery(message).find(".commentthread_comment_text").text().replace(/\s/g, ""); // innerText of message
  204.                             var timestamp = jQuery(message).find(".commentthread_comment_timestamp").attr("data-timestamp"); // Timestamp of message
  205.                             if (text == comments[index]["text"] && Math.abs(+(timestamp) - +(comments[index]["timestamp"])) < TIMESTAMP_DIFF) {
  206.                                 var deleteComment = jQuery(message).find("a[href*=\"DeleteComment\"]").attr("href");
  207.                                 if (!deleteComment) {
  208.                                     throw new Error("\nWas unable to find \"Delete\" button. Possibly you can't delete message from this group\n");
  209.                                 }
  210.                                 deleteComment = deleteComment.replace(/javascript:/, "");
  211.                                 var arguments = deleteComment.match(/\(([.\s\S]{1,}?),([.\s\S]{1,}?)\)/); // Arguments
  212.                                 // arguments looks like: " 'STRING' ". It may have [\s'"] in it
  213.                                 execute("g_rgCommentThreads[" + arguments[1] + "].GetForumTopic().m_rgForumData.permissions.can_moderate = 1;"); // Need to prevent confirmation (execute is used just to be able to replace it with console.log. Also this is effective as we keep argument as it was at DeleteComment())
  214.                                 execute("g_rgCommentThreads[" + arguments[1] + "].DeleteComment(" + arguments[2] + ");");
  215.                                 ifFoundComment = true;
  216.                                 return false; // break
  217.                             }
  218.                         });
  219.                     }
  220.                 } else {
  221.                     // Comment
  222.                     if (comments[index]["url"].match(/\/id\//) && !jQuery(comments[index]["html"]).find(".commentthread_comments").length) {
  223.                         throw new Error("\nCan not delete comment. As profile owner locked his page and deleted you from friends\n");
  224.                     }
  225.                     var initCThread = jQuery(comments[index]["html"]).find("script:contains(InitializeCommentThread)").html(); // Code to be executed
  226.                     initCThread = initCThread.match(REGEXP.initCThread)[0]; // Getting main command
  227.                     initCThread = initCThread.replace(/\{/, "{\"no_paging\": true, "); // Adding no paging to prevent error
  228.                     execute(initCThread);
  229.                     var commentsByUser = jQuery(comments[index]["html"]).find(".commentthread_comment .commentthread_comment_avatar a[href*=\"" + USER_STEAM_PROFILE_URL + "\"]").closest(".commentthread_comment"); // Comments on the page by user
  230.                     var ifFoundComment = false;
  231.                     commentsByUser.each(function(i, comment)
  232.                     {
  233.                         var text = jQuery(comment).find(".commentthread_comment_text").text().replace(/\s/g, ""); // innerText of comment
  234.                         var timestamp = jQuery(comment).find(".commentthread_comment_timestamp").attr("data-timestamp"); // Timestamp of comment
  235.                         if (text == comments[index]["text"] && Math.abs(+(timestamp) - +(comments[index]["timestamp"])) < TIMESTAMP_DIFF) {
  236.                             var deleteComment = jQuery(comment).find("a[href*=\"DeleteComment\"]").attr("href").replace(/javascript:/, "");
  237.                             if (!deleteComment) {
  238.                                 throw new Error("\nWas unable to find \"Delete\" button\n");
  239.                             }
  240.                             execute(deleteComment);
  241.                             ifFoundComment = true;
  242.                             return false; // break
  243.                         }
  244.                     });
  245.                     if (!ifFoundComment) {
  246.                         throw new Error("\nWas unable to find users comment\n");
  247.                     }
  248.                 }
  249.                 console.log("    Cleaned comment #" + (index + 1));
  250.             } catch (e) {
  251.                 console.error("    !!! Can not clean comment #" + (index + 1));
  252.                 console.error(comments[index]);
  253.                 console.error(e);
  254.             }
  255.             var nextTimeout = setTimeout(function() { clearURLfromIndex(index + 1, callback); }, PAGE_REQUESTS_INTERVAL);
  256.         },
  257.         "fail" : function()
  258.         {
  259.             console.error("    !!!Unable to send request");
  260.         },
  261.         "data": comments[index]["data"],
  262.         "method": "GET",
  263.         "url": comments[index]["url"]
  264.     });
  265. };
  266.  
  267. var loadForumJS = function(i, callback, onFail)
  268. {
  269.     var timeout = setTimeout(function () { // Setting timeout as reject of load is not supported with getScript
  270.         console.error("    Error occured loading forum.js #" + i + " - timeout");
  271.         if (i + 1 < FORUMS_JS_URL.length) {
  272.             // Still have some links
  273.             console.error("    Trying next link");
  274.             loadForumJS(i + 1, callback, onFail); // Trying another one
  275.         } else {
  276.             // Tryed everything
  277.             console.error("    Mo links left");
  278.             if (typeof onFail == "function") {
  279.                 onFail();
  280.             }
  281.         }
  282.     }, FORUM_JS_LOAD_TIMEOUT);
  283.  
  284.     console.log("    Trying forum.js #" + i + ". Will try next in " + (FORUM_JS_LOAD_TIMEOUT / 1000) + " seconds if this wont work");
  285.     jQuery.getScript(FORUMS_JS_URL[i]).done(function() { // Require forum.js to delete forum messages
  286.         // Needed script is loaded and no errors detected
  287.         console.log("    Loaded forum.js #" + i);
  288.         clearTimeout(timeout); // Stop timeout
  289.         if (typeof callback == "function") {
  290.             callback();
  291.         }
  292.     }).fail(function() {
  293.         console.error("    Error occurred loading forum.js #" + i);
  294.         console.error("    Trying next link");
  295.         if (i + 1 < FORUMS_JS_URL.length) {
  296.             loadForumJS(i + 1, callback, onFail); // Trying another one
  297.         } else {
  298.             if (typeof onFail == "function") {
  299.                 onFail();
  300.             }
  301.         }
  302.     });
  303.  
  304. };
  305.  
  306. /*
  307.     Main
  308. */
  309.  
  310. loadForumJS(0, function()
  311. {
  312.     loadPagesFrom(FIRST_PAGE_TO_CLEAR, function()
  313.     {
  314.         loadURLsFrom(1, function()
  315.         {
  316.             clearURLfromIndex(0, function()
  317.             {
  318.                 alert("Done");
  319.             });
  320.         });
  321.     });
  322. }, function()
  323. {
  324.     alert("Can not load forum.js!");
  325. });
Add Comment
Please, Sign In to add comment