Contexto Hack

This is a Contexto Hack that Gives you the word of the day for everyday.

当前为 2023-07-05 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Contexto Hack
  3. // @namespace your-namespace-here
  4. // @version 2.2
  5. // @author longkidkoolstar
  6. // @description This is a Contexto Hack that Gives you the word of the day for everyday.
  7. // @icon https://styles.redditmedia.com/t5_72ajpm/styles/communityIcon_2y8kmvv8z6wa1.png?width=256&v=enabled&s=497ae2191ac283aadfc5da5941539fcc5a575e1b
  8. // @match https://contexto.me/*
  9. // @license CC BY-NC-ND 4.0
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @grant GM_xmlhttpRequest
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. // JSONBin.io configurations
  19. const binId = '649efcdbb89b1e2299b7c40c';
  20. const accessKey = '$2b$10$7aFXF1Powlysz7vBu8xY2u9QOHeJUxwtcE4d2cW2/AFg6AhZP4XR2';
  21.  
  22. // Function to check if a string contains the number 1 by itself
  23. function containsOne(str) {
  24. return /^\D*1\D*$/.test(str);
  25. }
  26.  
  27. // Retrieve saved words and game numbers from JSONBin.io
  28. let savedWords = {};
  29. let gameNumbers = {};
  30.  
  31. function fetchSavedWords() {
  32. // Check if saved words exist in the Tampermonkey storage
  33. const savedWordsData = GM_getValue('savedWordsData');
  34. if (savedWordsData) {
  35. savedWords = savedWordsData.savedWords;
  36. gameNumbers = savedWordsData.gameNumbers;
  37. console.log('Loaded saved words from Tampermonkey storage');
  38. updateSavedWordsGUI();
  39. }
  40.  
  41. // Fetch saved words from JSONBin.io every 20 seconds
  42. setInterval(() => {
  43. GM_xmlhttpRequest({
  44. method: 'GET',
  45. url: `https://api.jsonbin.io/v3/b/${binId}/latest`,
  46. headers: {
  47. 'Content-Type': 'application/json',
  48. 'X-Bin-Access-Token': accessKey,
  49. 'X-Access-Key': accessKey
  50. },
  51. onload: function(response) {
  52. if (response.status === 200) {
  53. const responseData = JSON.parse(response.responseText);
  54. if (responseData.record) {
  55. const recordData = responseData.record;
  56. if (recordData.savedWords) {
  57. savedWords = recordData.savedWords;
  58. }
  59. if (recordData.gameNumbers) {
  60. gameNumbers = recordData.gameNumbers;
  61. }
  62. }
  63. console.log('Read saved words successfully');
  64. updateSavedWordsGUI();
  65.  
  66. // Save fetched words to Tampermonkey storage
  67. const savedWordsData = {
  68. savedWords: savedWords,
  69. gameNumbers: gameNumbers
  70. };
  71. GM_setValue('savedWordsData', savedWordsData);
  72. console.log('Saved fetched words to Tampermonkey storage');
  73. }
  74. }
  75. });
  76. }, 20000); // Fetch every 20 seconds (20000 milliseconds)
  77. }
  78.  
  79.  
  80.  
  81.  
  82. // Function to save words and game numbers to JSONBin.io
  83. // Function to save words and game numbers to JSONBin.io
  84. function saveWordsToJSONBin() {
  85. GM_xmlhttpRequest({
  86. method: 'GET',
  87. url: `https://api.jsonbin.io/v3/b/${binId}`,
  88. headers: {
  89. 'Content-Type': 'application/json',
  90. 'X-Bin-Access-Token': accessKey,
  91. 'X-Access-Key': accessKey
  92. },
  93. onload: function(response) {
  94. if (response.status === 200) {
  95. const responseData = JSON.parse(response.responseText);
  96. const existingData = responseData.record;
  97.  
  98. // Merge existing data with new data
  99. const mergedData = {
  100. savedWords: { ...existingData.savedWords, ...savedWords },
  101. gameNumbers: { ...existingData.gameNumbers, ...gameNumbers }
  102. };
  103.  
  104. GM_xmlhttpRequest({
  105. method: 'PUT',
  106. url: `https://api.jsonbin.io/v3/b/${binId}`,
  107. headers: {
  108. 'Content-Type': 'application/json',
  109. 'X-Bin-Access-Token': accessKey,
  110. 'X-Access-Key': accessKey
  111. },
  112. data: JSON.stringify(mergedData),
  113. onload: function(response) {
  114. if (response.status === 200) {
  115. console.log('Words and game numbers saved successfully');
  116. }
  117. }
  118. });
  119. }
  120. }
  121. });
  122. }
  123.  
  124.  
  125. // Function to search for words and game numbers to save on the page
  126. let currentGameNumber = '';
  127.  
  128. function searchForWordsAndGameNumbers() {
  129. // Find the game number element on the page
  130. const gameNumberElement = document.querySelector('.info-bar span:nth-child(2)');
  131. currentGameNumber = gameNumberElement ? gameNumberElement.textContent.trim().replace('#', '') : '';
  132.  
  133. // Find all the div elements with class "row" on the page
  134. const rows = document.querySelectorAll('.row');
  135. for (let i = 0; i < rows.length; i++) {
  136. const row = rows[i];
  137. // Find all the span elements within the row
  138. const spans = row.querySelectorAll('span');
  139. let hasOne = false;
  140. let word = '';
  141. for (let j = 0; j < spans.length; j++) {
  142. const span = spans[j];
  143. if (containsOne(span.innerHTML)) {
  144. hasOne = true;
  145. } else {
  146. word = span.innerHTML;
  147. }
  148. }
  149. // Save the word and game number to the objects if the word has the number 1 by itself and it's not already saved
  150. if (hasOne && word && !savedWords[word]) {
  151. savedWords[word] = true;
  152. gameNumbers[word] = currentGameNumber; // Save the current game number instead of searching for it again
  153. // Log the game number for the saved word
  154. console.log(`Game number for ${word}: ${currentGameNumber}`);
  155. }
  156. }
  157.  
  158. // Save the updated objects to JSONBin.io
  159. saveWordsToJSONBin();
  160.  
  161. // Update the GUI with the saved words and game numbers
  162. updateSavedWordsGUI();
  163. }
  164.  
  165. // Function to reveal the word for the current game number
  166. function revealWordForCurrentGameNumber() {
  167. // Find the saved word for the current game number
  168. const savedWordsForCurrentGameNumber = Object.keys(savedWords).filter((word) => {
  169. return gameNumbers[word] === currentGameNumber;
  170. });
  171.  
  172. // Display the saved word in an alert box
  173. if (savedWordsForCurrentGameNumber.length > 0) {
  174. alert(`The word for game number ${currentGameNumber} is: ${savedWordsForCurrentGameNumber[0]}`);
  175. } else {
  176. alert(`No saved words for game number ${currentGameNumber}`);
  177. }
  178. }
  179.  
  180. // Create a button to reveal the word for the current game number
  181. const revealButton = document.createElement('button');
  182. revealButton.textContent = 'Reveal Word';
  183. revealButton.addEventListener('click', revealWordForCurrentGameNumber);
  184. document.body.appendChild(revealButton);
  185.  
  186. // Create a div element to hold the saved words GUI
  187. const savedWordsGUI = document.createElement('div');
  188. savedWordsGUI.id = 'saved-words-list';
  189. document.body.appendChild(savedWordsGUI);
  190.  
  191. // Create a button to show the saved words GUI
  192. const showSavedWordsButton = document.createElement('button');
  193. showSavedWordsButton.textContent = 'Saved Words';
  194. showSavedWordsButton.addEventListener('click', () => {
  195. savedWordsGUI.classList.add('open');
  196. });
  197. document.body.appendChild(showSavedWordsButton);
  198.  
  199. // Create a button to minimize the saved words GUI
  200. const minimizeSavedWordsButton = document.createElement('button');
  201. minimizeSavedWordsButton.innerHTML = '<img src="https://th.bing.com/th/id/R.6a6eda3ee63c80ebc02dc830b395324e?rik=t2E%2fYYP3IGbSsQ&pid=ImgRaw&r=0" alt="Close">';
  202. minimizeSavedWordsButton.addEventListener('click', () => {
  203. savedWordsGUI.classList.remove('open');
  204. });
  205. savedWordsGUI.appendChild(minimizeSavedWordsButton);
  206.  
  207.  
  208. // Create a list element to display the saved words
  209. const savedWordsList = document.createElement('ul');
  210. savedWordsGUI.appendChild(savedWordsList);
  211.  
  212. // Function to update the saved words GUI with the saved words and game numbers
  213. function updateSavedWordsGUI() {
  214. // Clear the current saved words list
  215. savedWordsList.innerHTML = '';
  216.  
  217. // Get all saved words sorted by game number
  218. const savedWordsSorted = Object.keys(gameNumbers).sort((a, b) => {
  219. return gameNumbers[a] - gameNumbers[b];
  220. });
  221.  
  222. // Add each saved word to the list
  223. for (let i = 0; i < savedWordsSorted.length; i++) {
  224. const word = savedWordsSorted[i];
  225. const gameNumber = gameNumbers[word];
  226. const listItem = document.createElement('li');
  227. listItem.textContent = `${word} (Game ${gameNumber})`;
  228. savedWordsList.appendChild(listItem);
  229. }
  230. }
  231.  
  232. // Update the saved words GUI with the saved words and game numbers
  233. updateSavedWordsGUI();
  234.  
  235. // Function to clear the saved words and game numbers from JSONBin.io
  236. function clearSavedWords() {
  237. savedWords = {};
  238. gameNumbers = {};
  239. saveWordsToJSONBin();
  240. updateSavedWordsGUI();
  241. alert('Saved words cleared');
  242. }
  243.  
  244. // Create a button to clear the saved words and game numbers
  245. const clearSavedWordsButton = document.createElement('button');
  246. clearSavedWordsButton.textContent = 'Clear Saved Words';
  247. clearSavedWordsButton.addEventListener('click', clearSavedWords);
  248. savedWordsGUI.appendChild(clearSavedWordsButton);
  249.  
  250. // Function to export the saved words and game numbers as JSON
  251. function exportSavedWords() {
  252. const savedWordsData = {
  253. savedWords: savedWords,
  254. gameNumbers: gameNumbers
  255. };
  256. const dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(savedWordsData));
  257. const downloadAnchorNode = document.createElement('a');
  258. downloadAnchorNode.setAttribute('href', dataStr);
  259. downloadAnchorNode.setAttribute('download', 'contexto_saved_words.json');
  260. document.body.appendChild(downloadAnchorNode); // required for firefox
  261. downloadAnchorNode.click();
  262. downloadAnchorNode.remove();
  263. }
  264.  
  265. // Create a button to export the saved words and game numbers
  266. const exportSavedWordsButton = document.createElement('button');
  267. exportSavedWordsButton.textContent = 'Export Saved Words';
  268. exportSavedWordsButton.addEventListener('click', exportSavedWords);
  269. savedWordsGUI.appendChild(exportSavedWordsButton);
  270.  
  271. // Function to import saved words and game numbers from JSON
  272. function importSavedWords() {
  273. const fileInput = document.createElement('input');
  274. fileInput.type = 'file';
  275. fileInput.accept = '.json';
  276. fileInput.addEventListener('change', () => {
  277. const file = fileInput.files[0];
  278. const reader = new FileReader();
  279. reader.onload = (e) => {
  280. try {
  281. const savedWordsData = JSON.parse(e.target.result);
  282. savedWords = savedWordsData.savedWords;
  283. gameNumbers = savedWordsData.gameNumbers;
  284. saveWordsToJSONBin();
  285. updateSavedWordsGUI();
  286. alert('Saved words imported');
  287. } catch (err) {
  288. alert('Error importing saved words');
  289. }
  290. };
  291. reader.readAsText(file);
  292. });
  293. fileInput.click();
  294. }
  295.  
  296. // Create a button to import saved words and game numbers
  297. const importSavedWordsButton = document.createElement('button');
  298. importSavedWordsButton.textContent = 'Import Saved Words';
  299. importSavedWordsButton.addEventListener('click', importSavedWords);
  300. savedWordsGUI.appendChild(importSavedWordsButton);
  301.  
  302. // Define CSS styles for the saved words GUI
  303. const css = `
  304. #saved-words-list {
  305. position: fixed;
  306. bottom: 0;
  307. right: 0;
  308. background-color: white;
  309. border: 2px solid black;
  310. border-radius: 5px 0 0 0;
  311. padding: 10px;
  312. max-height: 300px;
  313. overflow-y: auto;
  314. display: none;
  315. }
  316. #saved-words-list.open {
  317. display: block;
  318. }
  319. #saved-words-list button {
  320. margin: 5px;
  321. padding: 0;
  322. background: none;
  323. border: none;
  324. cursor: pointer;
  325. }
  326. #saved-words-list img {
  327. width: 20px;
  328. height: 20px;
  329. }
  330. `;
  331.  
  332. // Add the CSS styles to the page
  333. const style = document.createElement('style');
  334. style.innerHTML = css;
  335. document.head.appendChild(style);
  336.  
  337. // Fetch saved words and game numbers from JSONBin.io on page load
  338. fetchSavedWords();
  339.  
  340. // Search for words and game numbers to save on page load and every 5 seconds
  341. searchForWordsAndGameNumbers();
  342. setInterval(searchForWordsAndGameNumbers, 17000);//17 seconds
  343. })();