Twitch - Auto Channel Points

Automatically claim channel points

安装此脚本?
作者推荐脚本

您可能也喜欢Twitch - Auto Theatre

安装此脚本
  1. // ==UserScript==
  2. // @name Twitch - Auto Channel Points
  3. // @name:zh-TW Twitch - 自動獲得忠誠點數
  4. // @namespace http://tampermonkey.net/
  5. // @version 2024.5.1
  6. // @description Automatically claim channel points
  7. // @description:zh-tw 自動獲得忠誠點數
  8. // @author Long
  9. // @match https://www.twitch.tv/*
  10. // @icon https://www.google.com/s2/favicons?domain=twitch.tv
  11. // @grant GM_addStyle
  12. // @grant GM_setValue
  13. // @grant GM_getValue
  14. // ==/UserScript==
  15.  
  16. (function () {
  17. "use strict";
  18.  
  19. GM_addStyle(`
  20. #total-got-points {
  21. display: inline-flex;
  22. position: relative;
  23. align-items: center;
  24. padding : 0 var(--button-padding-x) 0 var(--button-padding-x);
  25. text-decoration: none;
  26. white-space: nowrap;
  27. user-select: none;
  28. color: var(--color-text-alt-2);
  29. font-weight: var(--font-weight-semibold);
  30. border-radius: var(--border-radius-medium);
  31. font-size: var(--button-text-default);
  32. height: var(--button-size-default);
  33. --point-name: '自動領取忠誠點數';
  34. }
  35.  
  36. #total-got-points:hover {
  37. background-color: var(--color-background-button-text-hover);
  38. }
  39.  
  40. #total-got-points img {
  41. height: 2rem;
  42. width: 2rem;
  43. }
  44.  
  45. #total-got-points img, #total-got-points svg {
  46. margin-right: 5px;
  47. }
  48.  
  49. #total-got-points::before{
  50. content: var(--point-name);
  51. user-select: none;
  52. color: var(--color-text-tooltip);
  53. background-color: var(--color-background-tooltip);
  54. font-size: var(--font-size-6);
  55. border-radius: 0.4rem;
  56. padding: 0.5rem;
  57. max-width: 30rem;
  58. font-weight: var(--font-weight-semibold);
  59. right: 0;
  60. line-height: 1.2;
  61. pointer-events: none;
  62. position: absolute;
  63. text-align: left;
  64. white-space: nowrap;
  65. z-index: 2000;
  66. top: 50%;
  67. transform: translate(calc(100% + 5px), -50%);
  68. transition: all .2s ease-in-out;
  69. opacity: 0;
  70. }
  71.  
  72. #total-got-points:hover::before{
  73. opacity: 1;
  74. }
  75. `);
  76.  
  77. const ignorePathNames = [
  78. '/directory',
  79. ]
  80. const isPathIgnored = (pathname) => ignorePathNames.some(ignoredPath => pathname.startsWith(ignoredPath));
  81.  
  82. // find button
  83. let findButtonRetry = 100;
  84. // get points
  85. const getPointsLoopMs = 1000;
  86. const gotPointsRegex = /\+?(\d+)/;
  87. let lastTimeGotPoints = null;
  88. let needToUpdateGotPoints = false;
  89.  
  90. const startGetPointsLoop = () => {
  91. const GMkeyName = location.origin + location.pathname + ':auto-channel-points';
  92. let totalGotPoints = GM_getValue(GMkeyName, 0);
  93. showTotalGotPoints(totalGotPoints);
  94. window.getPointLoop = setInterval(function () {
  95. const $pointsSummaryButtons = document.querySelectorAll('[data-test-selector="community-points-summary"] button');
  96. const canGetPoints = $pointsSummaryButtons.length > 1;
  97. const $gotPointsEles = document.querySelectorAll('.pulse-animation');
  98.  
  99. if (canGetPoints) {
  100. $pointsSummaryButtons[1].click();
  101. $pointsSummaryButtons[1].remove();
  102. console.log('[Twitch-Auto-Channel-Points] Getting points...');
  103.  
  104. needToUpdateGotPoints = true;
  105. }
  106.  
  107. if (needToUpdateGotPoints) {
  108. $gotPointsEles.forEach(($gotPointsEle) => {
  109. const matches = $gotPointsEle.textContent.match(gotPointsRegex);
  110. if (!matches) return;
  111.  
  112. lastTimeGotPoints = parseInt(matches[1]);
  113. });
  114.  
  115. if (!lastTimeGotPoints) return;
  116.  
  117. totalGotPoints += lastTimeGotPoints;
  118. GM_setValue(GMkeyName, totalGotPoints);
  119. console.log("[Twitch-Auto-Channel-Points] Got points: ", lastTimeGotPoints);
  120. showTotalGotPoints(totalGotPoints);
  121.  
  122. lastTimeGotPoints = null;
  123. needToUpdateGotPoints = false;
  124. }
  125. }, getPointsLoopMs);
  126. }
  127. const stopGetPointsLoop = () => {
  128. if (!window.getPointLoop) return;
  129. clearInterval(window.getPointLoop);
  130. window.getPointLoop = null;
  131. }
  132.  
  133. const appendGotPointsElement = () => {
  134. const $totalGotPointsContainer = document.createElement('div');
  135. $totalGotPointsContainer.id = 'total-got-points';
  136. const $buttonDiv = document.querySelectorAll('.chat-input__buttons-container div')[0];
  137. $buttonDiv.appendChild($totalGotPointsContainer);
  138. const $pointImage = document.querySelector('.channel-points-icon__image');
  139. if ($pointImage) {
  140. const pointName = $pointImage.alt;
  141. $totalGotPointsContainer.style.setProperty('--point-name', '"自動領取' + pointName + '"');
  142. $totalGotPointsContainer.appendChild($pointImage.cloneNode(true));
  143. } else {
  144. $totalGotPointsContainer
  145. .appendChild(document.querySelector('.chat-input__buttons-container button svg')
  146. .cloneNode(true));
  147. }
  148. $totalGotPointsContainer.appendChild(document.createElement('span'));
  149.  
  150. return document.querySelector('#total-got-points span');
  151. };
  152.  
  153. const showTotalGotPoints = function (totalGotPoints) {
  154. let $gotPointsEle = document.querySelector('#total-got-points span');
  155. if (!$gotPointsEle) {
  156. $gotPointsEle = appendGotPointsElement();
  157. }
  158. $gotPointsEle.textContent = new Intl.NumberFormat().format(totalGotPoints);
  159. console.log("[Twitch-Auto-Channel-Points] totalGotPoints: ", totalGotPoints);
  160. };
  161.  
  162. const startFindPointButtonLoop = () => {
  163. window.findPointButtonLoop = setInterval(function () {
  164. console.log('[Twitch-Auto-Channel-Points] find point-button...');
  165. let $pointButton = document.querySelector('[data-test-selector="community-points-summary"] button');
  166. if ($pointButton) {
  167. startGetPointsLoop();
  168. stopFindPointButtonLoop();
  169. console.log("[Twitch-Auto-Channel-Points] found point-button. start auto get points");
  170. } else if (!findButtonRetry) {
  171. stopFindPointButtonLoop();
  172. console.warn("[Twitch-Auto-Channel-Points] point-button not found.");
  173. }
  174. findButtonRetry--;
  175. }, 500);
  176. };
  177. const stopFindPointButtonLoop = () => {
  178. if (!window.findPointButtonLoop) return;
  179. clearInterval(window.findPointButtonLoop);
  180. window.findPointButtonLoop = null;
  181. }
  182.  
  183. const handlePageLoaded = (pathname) => {
  184. if (isPathIgnored(pathname)) return;
  185. startFindPointButtonLoop();
  186. }
  187. const handlePageChanged = () => {
  188. window.navigation.addEventListener("navigate", (event) => {
  189. stopFindPointButtonLoop();
  190. stopGetPointsLoop();
  191.  
  192. const url = new URL(event.destination.url);
  193. handlePageLoaded(url.pathname);
  194. });
  195. }
  196.  
  197. const main = () => {
  198. handlePageLoaded(location.pathname);
  199. handlePageChanged();
  200. }
  201. main();
  202. })();