Contexto Hack

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

当前为 2024-06-15 提交的版本,查看 最新版本

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