PokerHistory

Records all Poker history.

  1. // ==UserScript==
  2. // @name PokerHistory
  3. // @namespace http://www.torn.com/
  4. // @version 1.2
  5. // @description Records all Poker history.
  6. // @author bot_7420 [2937420]
  7. // @match https://www.torn.com/page.php?sid=holdem*
  8. // @run-at document-body
  9. // @grant GM_addStyle
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. "use strict";
  14.  
  15. let db = null;
  16. let messageBoxObserver = null;
  17.  
  18. initIndexDB();
  19.  
  20. window.onload = function () {
  21. initCSS();
  22. initControlPanel();
  23. initPokerObserver();
  24. };
  25.  
  26. function initIndexDB() {
  27. const openRequest = indexedDB.open("scriptPokerHistoryDB", 1);
  28. openRequest.onupgradeneeded = function (e) {
  29. console.log("PokerHistory: initIndexDB open onupgradeneeded");
  30. db = e.target.result;
  31. if (!db.objectStoreNames.contains("messageStore")) {
  32. console.log("PokerHistory: initIndexDB open onupgradeneeded create store");
  33. const objectStore = db.createObjectStore("messageStore", { keyPath: "autoId", autoIncrement: true });
  34. }
  35. };
  36. openRequest.onsuccess = function (e) {
  37. console.log("PokerHistory: initIndexDB open onsuccess");
  38. db = e.target.result;
  39. };
  40. openRequest.onerror = function (e) {
  41. console.error("PokerHistory: initIndexDB open onerror");
  42. console.dir(e);
  43. };
  44. }
  45.  
  46. function dbWrite(message) {
  47. if (!db || !message) {
  48. return;
  49. }
  50.  
  51. const transaction = db.transaction(["messageStore"], "readwrite");
  52. transaction.oncomplete = (event) => {
  53. //console.log("PokerHistory: dbWrite transaction oncomplete [" + message.text + "]");
  54. };
  55. transaction.onerror = (event) => {
  56. console.error("PokerHistory: dbWrite transaction onerror [" + message.text + "]");
  57. };
  58.  
  59. const store = transaction.objectStore("messageStore");
  60. const request = store.put(message);
  61. request.onsuccess = (event) => {};
  62. }
  63.  
  64. function dbReadAll() {
  65. if (!db) {
  66. console.error("PokerHistory: dbReadAll db is null");
  67. }
  68.  
  69. const transaction = db.transaction(["messageStore"], "readonly");
  70. transaction.oncomplete = (event) => {
  71. console.log("PokerHistory: dbReadAll transaction oncomplete");
  72. };
  73. transaction.onerror = (event) => {
  74. console.error("PokerHistory: dbReadAll transaction onerror");
  75. };
  76.  
  77. const store = transaction.objectStore("messageStore");
  78. return new Promise((resolve, reject) => {
  79. const resultList = [];
  80. store.openCursor().onerror = (event) => {
  81. resolve(resultList);
  82. };
  83. store.openCursor().onsuccess = (event) => {
  84. const cursor = event.target.result;
  85. if (cursor) {
  86. resultList.push(cursor.value);
  87. cursor.continue();
  88. } else {
  89. resolve(resultList);
  90. }
  91. };
  92. });
  93. }
  94.  
  95. function initPokerObserver() {
  96. const $poker = $("div.holdemWrapper___D71Gy");
  97. const observerConfig = { attributes: false, childList: true, subtree: false };
  98. const observer = new MutationObserver(() => {
  99. reObserveMessageBox();
  100. });
  101. if ($poker.length === 1) {
  102. console.log("PokerHistory: observe poker page");
  103. observer.observe($poker[0], observerConfig);
  104. reObserveMessageBox();
  105. }
  106. }
  107.  
  108. function reObserveMessageBox() {
  109. console.log("PokerHistory: reObserveMessageBox");
  110. if (!messageBoxObserver) {
  111. messageBoxObserver = new MutationObserver((mutated) => {
  112. handleMessageBoxChange(mutated);
  113. });
  114. }
  115. messageBoxObserver.disconnect();
  116. const $messageWrap = $("div.holdemWrapper___D71Gy div.messagesWrap___tBx9u");
  117. const observerConfig = { attributes: true, childList: true, subtree: false };
  118. messageBoxObserver.observe($messageWrap[0], observerConfig);
  119. }
  120.  
  121. function handleMessageBoxChange(mutated) {
  122. if (mutated.length >= 40) {
  123. console.log("PokerHistory: handlePokerBoxChange disregarded " + mutated.length);
  124. return;
  125. }
  126.  
  127. for (const mutation of mutated) {
  128. for (const node of mutation.addedNodes) {
  129. if (node.classList.contains("message___RlFXd")) {
  130. let message = {
  131. timestamp: new Date().getTime() / 1000,
  132. text: node.innerText,
  133. };
  134. dbWrite(message);
  135. }
  136. }
  137. }
  138. }
  139.  
  140. function initCSS() {
  141. const isDarkmode = $("body").hasClass("dark-mode");
  142. GM_addStyle(`.poker-control-panel-popup {
  143. position: fixed;
  144. top: 10%;
  145. left: 15%;
  146. border-radius: 10px;
  147. padding: 10px;
  148. background: ${isDarkmode ? "#282828" : "#F0F0F0"};
  149. z-index: 1000;
  150. display: none;
  151. }
  152.  
  153. .poker-control-panel-results {
  154. padding: 10px;
  155. }
  156.  
  157. .poker-control-player {
  158. margin: 4px 4px 4px 4px !important;
  159. display: inline-block !important;
  160. }
  161.  
  162. .poker-control-panel-overlay {
  163. position: fixed;
  164. top: 0;
  165. left: 0;
  166. background: ${isDarkmode ? "#404040" : "#B0B0B0"};
  167. width: 100%;
  168. height: 100%;
  169. opacity: 0.7;
  170. z-index: 900;
  171. display: none;
  172. }
  173.  
  174. .poker-control-panel-item {
  175. display: inline-block;
  176. margin: 2px 2px 2px 2px;
  177. }`);
  178. }
  179.  
  180. function initControlPanel() {
  181. const $title = $("div#top-page-links-list");
  182. if ($title.length === 0) {
  183. console.log("PokerHistory: nowhere to put control panel button");
  184. }
  185. const $controlBtn = $(`<a id="pokerHistoryControl" class="t-clear h c-pointer right last">
  186. <span class="icon-wrap svg-icon-wrap">
  187. <span class="link-icon-svg">
  188. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 10.33"><defs><style>.cls-1{opacity:0.35;}.cls-2{fill:#fff;}.cls-3{fill:#777;}</style></defs><g id="Слой_2" data-name="Слой 2"><g id="icons"><g class="cls-1"><path class="cls-2" d="M10,5.67a2,2,0,0,1-4,0,1.61,1.61,0,0,1,0-.39A1.24,1.24,0,0,0,7.64,3.7a2.19,2.19,0,0,1,.36,0A2,2,0,0,1,10,5.67ZM8,1C3,1,0,5.37,0,5.37s3.22,5,8,5c5.16,0,8-5,8-5S13.14,1,8,1ZM8,9a3.34,3.34,0,1,1,3.33-3.33A3.33,3.33,0,0,1,8,9Z"></path></g><path class="cls-3" d="M10,4.67a2,2,0,0,1-4,0,1.61,1.61,0,0,1,0-.39A1.24,1.24,0,0,0,7.64,2.7a2.19,2.19,0,0,1,.36,0A2,2,0,0,1,10,4.67ZM8,0C3,0,0,4.37,0,4.37s3.22,5,8,5c5.16,0,8-5,8-5S13.14,0,8,0ZM8,8a3.34,3.34,0,1,1,3.33-3.33A3.33,3.33,0,0,1,8,8Z"></path></g></g></svg>
  189. </span>
  190. </span>
  191. <span>PokerHistory</span>
  192. </a>`);
  193. $title.append($controlBtn);
  194.  
  195. const $controlPanelDiv = $(`<div id="pokerControlPanel" class="poker-control-panel-popup">control</div>`);
  196. const $controlPanelOverlayDiv = $(`<div id="pokerControlOverlayPanel" class="poker-control-panel-overlay"></div>`);
  197. $controlPanelDiv.html(`
  198. <textarea readonly id="poker-results" cols="120" rows="30"></textarea>
  199. `);
  200.  
  201. $title.append($controlPanelDiv);
  202. $title.append($controlPanelOverlayDiv);
  203.  
  204. $controlBtn.click(function () {
  205. dbReadAll().then((result) => {
  206. let text = "";
  207. for (const message of result) {
  208. const timeStr = formatDateString(new Date(message.timestamp * 1000));
  209. text += timeStr + " " + message.text + "\n";
  210. }
  211. text += "Found " + result.length + " records\n";
  212. const $textarea = $("textarea#poker-results");
  213. $textarea.val(text);
  214. $textarea.scrollTop($textarea[0].scrollHeight);
  215. });
  216.  
  217. $controlPanelDiv.fadeToggle(200);
  218. $controlPanelOverlayDiv.fadeToggle(200);
  219. });
  220.  
  221. $controlPanelOverlayDiv.click(function () {
  222. $controlPanelDiv.fadeOut(200);
  223. $controlPanelOverlayDiv.fadeOut(200);
  224. });
  225. }
  226.  
  227. function formatDateString(date) {
  228. const pad = (v) => {
  229. return v < 10 ? "0" + v : v;
  230. };
  231. let year = date.getFullYear();
  232. let month = pad(date.getMonth() + 1);
  233. let day = pad(date.getDate());
  234. let hour = pad(date.getHours());
  235. let min = pad(date.getMinutes());
  236. let sec = pad(date.getSeconds());
  237. return year + "/" + month + "/" + day + " " + hour + ":" + min + ":" + sec;
  238. }
  239. })();