Advertisement
Guest User

Human Exterminator

a guest
Apr 3rd, 2020
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.75 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Be The Imposter
  3. // @version 4.20
  4. // @author SKYNET
  5. // @include https://gremlins-api.reddit.com/*
  6. // @grant GM_setValue
  7. // @grant GM_getValue
  8. // @grant GM_addValueChangeListener
  9. // ==/UserScript==
  10.  
  11. const VERSION = "1.3";
  12. const SUBMIT_ABRA_URL = "https://librarian.abra.me/submit";
  13. const SUBMIT_SPACESCIENCE_URL = "https://spacescience.tech/api.php";
  14. const DETECTOR_URL = "https://detector.abra.me/?";
  15. const ABRA_URL = "https://librarian.abra.me/check";
  16. const SPACESCIENCE_URL = "https://spacescience.tech/check.php?id=";
  17. const OCEAN_URL = "https://wave.ocean.rip/answers/answer?text=";
  18.  
  19. async function checkBackronym(msg) {
  20. return msg.split(" ").map(x => x.charAt(0)).join("").startsWith("human");
  21. }
  22.  
  23. async function checkExistingAbra(msgs) {
  24. var myHeaders = new Headers();
  25. myHeaders.append("Content-Type", "application/json");
  26.  
  27. let raw = JSON.stringify({"texts": msgs});
  28.  
  29. let requestOptions = {
  30. method: 'POST',
  31. headers: myHeaders,
  32. body: raw,
  33. redirect: 'follow'
  34. };
  35.  
  36. let json = await fetch(ABRA_URL, requestOptions)
  37. .then(response => response.json());
  38. return json.results;
  39. }
  40.  
  41. async function checkExistingSpacescience(id, strict=true) {
  42. let requestOptions = {
  43. method: 'GET',
  44. redirect: 'follow'
  45. };
  46.  
  47. let json = await fetch(SPACESCIENCE_URL+id, requestOptions)
  48. .then(response => response.json());
  49.  
  50. console.log(json);
  51.  
  52. for (let key in json) {
  53. if (json[key].hasOwnProperty("flag")) {
  54. if (json[key].flag == 1 && json[key].result === "LOSE") {
  55. return "known human";
  56. } else if (!strict && json[key].flag == 1 && json[key].result === "LOSE") {
  57. return "known human;"
  58. }
  59. }
  60. }
  61. return "unknown";
  62. }
  63.  
  64. async function checkExistingOcean(msg) {
  65. let requestOptions = {
  66. method: 'GET',
  67. redirect: 'follow'
  68. };
  69.  
  70. let json = await fetch(OCEAN_URL+msg, requestOptions)
  71. .then(response => response.json());
  72.  
  73. console.log(json);
  74.  
  75. if (json.status=200) {
  76. if (json.answer.is_correct) {
  77. return "known fake";
  78. } else {
  79. return "known human";
  80. }
  81. }
  82.  
  83. return "unknown";
  84. }
  85.  
  86. async function checkDetector(msg) {
  87. let requestOptions = {
  88. method: 'GET',
  89. redirect: 'follow'
  90. };
  91.  
  92. let json = await fetch(DETECTOR_URL + msg, requestOptions)
  93. .then(response => response.json());
  94. return json.fake_probability;
  95. }
  96.  
  97. function setState(note, hint, state) {
  98. if (state === "") {
  99. return;
  100. }
  101.  
  102. // State conflict
  103. if (hint.hasAttribute("state") && hint.getAttribute("state") !== state) {
  104. state = "conflict";
  105. }
  106.  
  107. if (state === "human") {
  108. note.setAttribute("style", "background-color: green;");
  109. } else if (state === "bot") {
  110. note.setAttribute("style", "background-color: darkred;");
  111. // State conflict
  112. } else {
  113. note.setAttribute("style", "background-color: orange;");
  114. hint.textContent("Database conflict!");
  115. }
  116.  
  117. hint.setAttribute("state", state);
  118. }
  119.  
  120. function setHint(note, text, state="", overwriteable=false) {
  121. let hint = note.getElementsByClassName("doorman-hint")[0];
  122.  
  123. // Hint tag does not already exist
  124. if (!hint) {
  125. hint = document.createElement("i");
  126. hint.setAttribute("class", "doorman-hint");
  127.  
  128. // Set overwriteable attribute so we can check later
  129. if (overwriteable) {
  130. hint.setAttribute("overwriteable", "");
  131. }
  132.  
  133. setState(note, hint, state);
  134.  
  135. note.appendChild(hint);
  136. hint.textContent = text;
  137.  
  138. // Only overwrite if previously set as overwriteable
  139. } else if (hint.hasAttribute("overwriteable")) {
  140. hint.textContent = text;
  141. setState(note, hint, state);
  142. }
  143. /*// Add to message
  144. } else {
  145. let regex = /\(.*\)/
  146. hint.textContent = `(${regex.exec(hint.textContent)}, ${text})`;
  147. setState(note, hint, state);
  148. }*/
  149. }
  150.  
  151. function getAnswers() {
  152. var notes = document.getElementsByTagName("gremlin-note");
  153.  
  154. if (notes) {
  155. var answers = [];
  156. for (let note of notes) {
  157. let id = note.getAttribute("id");
  158. let msg = note.getAttribute("aria-label").substr(19);
  159. answers.push({id: id, msg: msg});
  160. }
  161. return answers;
  162. }
  163. }
  164.  
  165. async function processAnswers(answers) {
  166. let notes = document.getElementsByTagName("gremlin-note");
  167. if (notes.length > 0) {
  168. let abra = await checkExistingAbra(Object.values(answers.map(x => x.msg)))
  169. .catch(error => console.log('error', error));
  170.  
  171. let promises = [];
  172. for (let i = 0; i < notes.length; i++) {
  173. // Handle results from own db
  174. if (abra[i] !== "unknown") {
  175. promises.append(handleExisting(notes[i], abra[i], "abra.me, own db"));
  176. }
  177.  
  178. // Check if the message is a backronym
  179. promises.push(checkBackronym(answers[i].msg)
  180. .then(handleExisting(notes[i], "", "spells HUMAN")));
  181.  
  182. // Check spacescience.tech
  183. promises.push(checkExistingSpacescience(answers[i].id, false)
  184. .then(result => handleExisting(notes[i], result, "spacescience.tech")));
  185.  
  186. // Check ocean.rip
  187. promises.push(checkExistingOcean(answers[i].msg)
  188. .then(result => handleExisting(notes[i], result, "ocean.rip")));
  189.  
  190. }
  191.  
  192. // Wait until all requests have been handled
  193. await Promise.all(promises.map(p => p.catch(e => e)))
  194. .catch(e => console.log(e));
  195.  
  196. let bot_answers = [];
  197. let unknown_answers = [];
  198. let conflicts = false;
  199. for (let note of notes) {
  200. // If note hint is not set
  201. let hint = note.getElementsByClassName("doorman-hint")[0];
  202. if (!hint) {
  203. unknown_answers.push(note);
  204. } else if (hint.getAttribute("state") === "human") {
  205. bot_answers.push(note);
  206. } else if (hint.getAttribute("state") === "conflict") {
  207. conflicts = true;
  208. }
  209. }
  210. console.log(unknown_answers.length + " unknown answers left.");
  211.  
  212. // Autoclicker
  213. if (GM_getValue("autoclick", false) && !conflicts) {
  214. // Click known bot answer
  215. if (bot_answers.length > 0) {
  216. let human = Math.floor(Math.random() * bot_answers.length)
  217. bot_answers[human].click();
  218. return;
  219.  
  220. // Click unknown answer
  221. } else if (unknown_answers.length == 1) {
  222. unknown_answers[0].click();
  223. return;
  224. }
  225. }
  226.  
  227. // Only check detector when there's more than one unknown answer left
  228. if (unknown_answers.length > 1){
  229. // Check detector
  230. for (let i = 0; i < notes.length; i++) {
  231. if (unknown_answers.includes(notes[i])) {
  232. checkDetector(answers[i].msg)
  233. .catch(error => console.log('error', error))
  234. .then(percentage => setHint(notes[i], Math.round(Number(percentage)*100)+"% bot", "", true));
  235. }
  236. }
  237. }
  238. }
  239. }
  240.  
  241. async function handleExisting(note, result, source) {
  242. if (result === "known fake") {
  243. setHint(note, result + " (" + source + ")", "bot");
  244. } else if (result === "known human") {
  245. setHint(note, result + " (" + source + ")", "human");
  246. }
  247. }
  248.  
  249. function submitResults() {
  250. var notes = document.getElementsByTagName("gremlin-note");
  251.  
  252. if (notes) {
  253. let chosen_text = "";
  254. let result = "";
  255. let answers = [];
  256. for (let note of notes) {
  257. let state = note.getAttribute("state");
  258. let id = note.getAttribute("id");
  259. let text_regex = /^\s*(.*)\n/
  260. let text = text_regex.exec(note.innerHTML)[1];
  261.  
  262. answers.push({id: id, msg: text});
  263. if (state !== "none") {
  264. // Selected answer
  265. chosen_text = text;
  266. result = state === "correct" ? "WIN" : "LOSE";
  267. }
  268. }
  269.  
  270. // Kick off submission in parallel, we don't care about the responses.
  271. submitResultsAbra(chosen_text, result, answers.map(x => x.msg));
  272. submitResultsSpacescience(chosen_text, result, answers.map(x => [x.id, x.msg]));
  273. }
  274. }
  275.  
  276. async function submitResultsAbra(chosen_text, result, option_texts) {
  277.  
  278. var myHeaders = new Headers();
  279. myHeaders.append("Content-Type", "application/json");
  280.  
  281. var raw = JSON.stringify({"chosen_text": chosen_text, option_texts, "result": result});
  282.  
  283. var requestOptions = {
  284. method: 'POST',
  285. headers: myHeaders,
  286. body: raw,
  287. redirect: 'follow'
  288. };
  289.  
  290. console.log("Submitting results");
  291. fetch(SUBMIT_ABRA_URL, requestOptions)
  292. .then(response => response.text())
  293. .then(result => console.log(result))
  294. .catch(error => console.log('error', error));
  295. }
  296.  
  297. async function submitResultsSpacescience(answer, result, options) {
  298. let room = {"options": options};
  299.  
  300. let body = new FormData();
  301. body.append("answer", answer);
  302. body.append("result", result);
  303. body.append("room", JSON.stringify(room));
  304. let res = await (await fetch(SUBMIT_SPACESCIENCE_URL, {
  305. method: "post",
  306. body
  307. })).text();
  308.  
  309. return JSON.parse(res);
  310. }
  311.  
  312. function handleGremlinAction(e) {
  313. const type = e.detail.type;
  314. switch (type) {
  315. case "begin":
  316. console.log("begin");
  317. break;
  318. case "link":
  319. if (!window.location.href.startsWith("https://gremlins-api.reddit.com/results")) {
  320. // We have to wait a bit for reddit to get the results but after 300ms they redirect us
  321. console.log("Submitting results in 250ms");
  322. setTimeout(submitResults, 250);
  323. }
  324. break;
  325. default:
  326. console.log("default");
  327. }
  328. }
  329.  
  330. async function addMenu(app) {
  331. let html = `
  332. <p style="float: right; margin-top: 0;">Skynet ${VERSION}</p>
  333. <input type="checkbox" id="doorman-autoclick">
  334. <label for="doorman-autoclick">Enable human disintegrator</label>
  335. `
  336. let div = document.createElement("div");
  337. div.setAttribute("id", "doorman-options");
  338. div.innerHTML = html;
  339. app.appendChild(div);
  340.  
  341. let checkbox = document.getElementById("doorman-autoclick");
  342. checkbox.checked = GM_getValue("autoclick", false);
  343. checkbox.addEventListener("change", function () {
  344. GM_setValue("autoclick", this.checked);
  345. });
  346. }
  347.  
  348. function run() {
  349. var app = document.getElementsByTagName("gremlin-app")[0];
  350. if (app) {
  351. addMenu(app);
  352. var answers = getAnswers();
  353. console.log(answers);
  354. processAnswers(answers);
  355. app.addEventListener("gremlin-action", handleGremlinAction);
  356.  
  357. // Autoclick "Keep Going!" if we're on the results page
  358. if (window.location.href.startsWith("https://gremlins-api.reddit.com/results")) {
  359. if (GM_getValue("autoclick", false)) {
  360. for (let a of app.getElementsByTagName("a")) {
  361. if (a.textContent === "Keep Going!") {
  362. a.click();
  363. }
  364. }
  365. }
  366. }
  367. }
  368. }
  369.  
  370. (function() {
  371. setTimeout(run, 100);
  372. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement