diff --git a/saviour-of-lost-souls/saviour-of-lost-souls.user.js b/saviour-of-lost-souls/saviour-of-lost-souls.user.js index 7471dfa..0996939 100644 --- a/saviour-of-lost-souls/saviour-of-lost-souls.user.js +++ b/saviour-of-lost-souls/saviour-of-lost-souls.user.js @@ -5,7 +5,7 @@ // @author Glorfindel // @updateURL https://raw.githubusercontent.com/Glorfindel83/SE-Userscripts/master/saviour-of-lost-souls/saviour-of-lost-souls.user.js // @downloadURL https://raw.githubusercontent.com/Glorfindel83/SE-Userscripts/master/saviour-of-lost-souls/saviour-of-lost-souls.user.js -// @version 0.5.2 +// @version 1.0 // @match *://meta.stackexchange.com/questions/* // @match *://meta.stackoverflow.com/questions/* // @match *://softwarerecs.stackexchange.com/questions/* @@ -38,7 +38,6 @@ waitForKeyElements('div.review-content div.question', function(jNode) { }); function main(question) { - console.log(question) // Check if author is likely to be a lost soul let owner = question.find('div.post-signature.owner'); if (owner.length == 0) @@ -56,13 +55,52 @@ function main(question) { if (numberOfReasons < 2) return; } + + // Which site? + let isMetaSE = location.host == 'meta.stackexchange.com'; + let isBeta = location.host == 'hardwarerecs.stackexchange.com'; - // My reputation; you need 5 reputation to comment + // My reputation let myReputation = parseInt($('a.my-profile div.-rep')[0].innerText.replace(/,/g, '')); - if (myReputation < 5) { - return; - } + let hasCommentPrivilege = myReputation >= (isMetaSE ? 5 : 50); + let hasFlagPrivilege = myReputation >= 15; + let hasUpvotePrivilege = myReputation >= 15; + let hasDownvotePrivilege = myReputation >= (isMetaSE ? 100 : 125); + let hasCloseVotePrivilege = myReputation >= (isBeta ? 500 : 3000); + let hasDeleteVotePrivilege = myReputation >= (isBeta ? 4000 : 20000); let isModerator = $("a.js-mod-inbox-button").length > 0; + // Can the script do anything? + if (!hasCommentPrivilege && !hasFlagPrivilege) + return; + + // Score; downvoted or not? + let downvoted = question.find('a.vote-down-on').length > 0; + let score = parseInt(question.find('div.js-vote-count')[0].innerText.replace(/,/g, '')); + + // Closed? + let status = $('div.question-status h2 b'); + let statusText = status.length > 0 ? status[0].innerText : ''; + let closed = statusText == 'marked' || statusText == 'put on hold' || statusText == 'closed'; + + // Is there any comment not by the author? + let comments = question.find('ul.comments-list'); + var hasNonOwnerComment = false; + comments.find('a.comment-user').each(function() { + if (!$(this).hasClass('owner')) { + hasNonOwnerComment = true; + } + }); + + // Determine which actions to take + // Comment + let shouldComment = hasCommentPrivilege && !hasNonOwnerComment; + // Downvote (not when the post is already on -3 or lower, to be slightly more welcoming) + let shouldDownvote = hasDownvotePrivilege && !downvoted && score > -3; + // Flag/vote to close + let shouldFlag = hasFlagPrivilege && !hasCloseVotePrivilege && !closed; + let shouldVoteToClose = hasCloseVotePrivilege && !closed; + // Vote to delete + let shouldVoteToDelete = (hasDeleteVotePrivilege && closed && score <= -3) || isModerator; // Add post menu button let menu = question.find('div.post-menu'); @@ -70,34 +108,86 @@ function main(question) { let button = $('lost soul'); menu.append(button); button.click(function() { - if (!confirm('Are you sure you want to down-/close-/delete vote and post a welcoming comment?')) - return; - - // Downvoted? - let downvoted = question.find('a.vote-down-on').length > 0; - - // Closed? - let status = $('div.question-status h2 b'); - let statusText = status.length > 0 ? status[0].innerText : ''; - let closed = statusText == 'marked' || statusText == 'put on hold' || statusText == 'closed'; - + // Generate HTML for dialog + var html = ` + `; + $(document.body).append($(html)); + }); + + // Define functions which can be called by the dialog + window.saviourOfLostSouls = {}; + saviourOfLostSouls.closeDialog = function() { + $("#modal-base").remove(); + }; + saviourOfLostSouls.submitDialog = function() { // Prepare votes/comments let postID = parseInt(question.attr('data-questionid')); - console.log('Lost soul #' + postID); let fkey = window.localStorage["se:fkey"].split(",")[0]; - // Is there any comment not by the author? - let comments = question.find('ul.comments-list'); - var nonOwnerComment = false; - comments.find('a.comment-user').each(function() { - if (!$(this).hasClass('owner')) { - nonOwnerComment = true; - } - }); - if (!nonOwnerComment) { + if (shouldComment || $("#sols-postCommentAnyway").prop("checked")) { // Post comment let author = owner.find('div.user-details a')[0].innerText; - + let comment = window.location.host === "softwarerecs.stackexchange.com" ? ("Hi " + author + ", welcome to [softwarerecs.se]! " + "This question does not appear to be about software recommendations, within [the scope defined on meta](https://softwarerecs.meta.stackexchange.com/questions/tagged/scope) and in the [help center](/help/on-topic). " + @@ -124,28 +214,26 @@ function main(question) { }); } - // Upvote all comments containing "welcome to" - comments.find("li").each(function() { - if ($(this).find("span.comment-copy")[0].innerText.toLowerCase().indexOf("welcome to") >= 0) { - // Click the "up" triangle - let upButtons = $(this).find("a.comment-up"); - if (upButtons.length > 0) { - upButtons[0].click(); + if (hasUpvotePrivilege) { + // Upvote all comments containing "welcome to" + comments.find("li").each(function() { + if ($(this).find("span.comment-copy")[0].innerText.toLowerCase().indexOf("welcome to") >= 0) { + // Click the "up" triangle + let upButtons = $(this).find("a.comment-up"); + if (upButtons.length > 0) { + upButtons[0].click(); + } } - } - }); + }); + } - // You can't flag without 15 rep - if (myReputation < 15) - return; - - if (myReputation >= 100 && !downvoted) { - // Downvote + if (shouldDownvote) { + // Downvote (not when the post is already on -3 or lower, to be slightly more welcoming) $.post({ url: "https://" + document.location.host + "/posts/" + postID + "/vote/3", // 3 = downvote data: "fkey=" + fkey, success: function () { - // TODO: set downvote button color + // NICETOHAVE: set downvote button color console.log("Downvote cast."); }, error: function (jqXHR, textStatus, errorThrown) { @@ -155,14 +243,14 @@ function main(question) { }); } - if (!closed) { - // Flag/vote to close (doesn't matter for the API call) + if (shouldFlag) { + // Flag/vote to close (which one doesn't matter for the API call) $.post({ url: "https://" + document.location.host + "/flags/questions/" + postID + "/close/add", data: "fkey=" + fkey + "&closeReasonId=OffTopic&closeAsOffTopicReasonId=" + (window.location.host === "softwarerecs.stackexchange.com" || window.location.host === "hardwarerecs.stackexchange.com" ? "1" : "8"), success: function () { - // TODO: update close vote count + // NICETOHAVE: update close vote count console.log("Close flag/vote cast."); }, error: function (jqXHR, textStatus, errorThrown) { @@ -170,14 +258,14 @@ function main(question) { console.log("Error: " + textStatus + " " + errorThrown); } }); - } else if (myReputation >= 20000 || isModerator) { + } else if (shouldVoteToDelete) { // Delete vote - // TODO, at least for non-moderators: only if score <= -3, maybe also if myReputation >= 10000 and question age >= 48 hours + // NICETOHAVE: maybe also if myReputation >= 10000 and question age >= 48 hours $.post({ url: "https://" + document.location.host + "/posts/" + postID + "/vote/10", // 10 = delete data: "fkey=" + fkey, success: function () { - // TODO: update delete vote count + // NICETOHAVE: update delete vote count console.log("Delete vote cast."); }, error: function (jqXHR, textStatus, errorThrown) { @@ -187,8 +275,7 @@ function main(question) { }); } - // Reload page; this is less elegant than waiting for all POST calls but it works. - window.setTimeout(() => window.location.reload(false), 800); - }); + // Reload page; this is less elegant than waiting for all POST calls, but it works. + window.setTimeout(() => window.location.reload(false), 1000); + }; } -