您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically claim channel points
- // ==UserScript==
- // @name Twitch - Auto Channel Points
- // @name:zh-TW Twitch - 自動獲得忠誠點數
- // @namespace http://tampermonkey.net/
- // @version 2024.5.1
- // @description Automatically claim channel points
- // @description:zh-tw 自動獲得忠誠點數
- // @author Long
- // @match https://www.twitch.tv/*
- // @icon https://www.google.com/s2/favicons?domain=twitch.tv
- // @grant GM_addStyle
- // @grant GM_setValue
- // @grant GM_getValue
- // ==/UserScript==
- (function () {
- "use strict";
- GM_addStyle(`
- #total-got-points {
- display: inline-flex;
- position: relative;
- align-items: center;
- padding : 0 var(--button-padding-x) 0 var(--button-padding-x);
- text-decoration: none;
- white-space: nowrap;
- user-select: none;
- color: var(--color-text-alt-2);
- font-weight: var(--font-weight-semibold);
- border-radius: var(--border-radius-medium);
- font-size: var(--button-text-default);
- height: var(--button-size-default);
- --point-name: '自動領取忠誠點數';
- }
- #total-got-points:hover {
- background-color: var(--color-background-button-text-hover);
- }
- #total-got-points img {
- height: 2rem;
- width: 2rem;
- }
- #total-got-points img, #total-got-points svg {
- margin-right: 5px;
- }
- #total-got-points::before{
- content: var(--point-name);
- user-select: none;
- color: var(--color-text-tooltip);
- background-color: var(--color-background-tooltip);
- font-size: var(--font-size-6);
- border-radius: 0.4rem;
- padding: 0.5rem;
- max-width: 30rem;
- font-weight: var(--font-weight-semibold);
- right: 0;
- line-height: 1.2;
- pointer-events: none;
- position: absolute;
- text-align: left;
- white-space: nowrap;
- z-index: 2000;
- top: 50%;
- transform: translate(calc(100% + 5px), -50%);
- transition: all .2s ease-in-out;
- opacity: 0;
- }
- #total-got-points:hover::before{
- opacity: 1;
- }
- `);
- const ignorePathNames = [
- '/directory',
- ]
- const isPathIgnored = (pathname) => ignorePathNames.some(ignoredPath => pathname.startsWith(ignoredPath));
- // find button
- let findButtonRetry = 100;
- // get points
- const getPointsLoopMs = 1000;
- const gotPointsRegex = /\+?(\d+)/;
- let lastTimeGotPoints = null;
- let needToUpdateGotPoints = false;
- const startGetPointsLoop = () => {
- const GMkeyName = location.origin + location.pathname + ':auto-channel-points';
- let totalGotPoints = GM_getValue(GMkeyName, 0);
- showTotalGotPoints(totalGotPoints);
- window.getPointLoop = setInterval(function () {
- const $pointsSummaryButtons = document.querySelectorAll('[data-test-selector="community-points-summary"] button');
- const canGetPoints = $pointsSummaryButtons.length > 1;
- const $gotPointsEles = document.querySelectorAll('.pulse-animation');
- if (canGetPoints) {
- $pointsSummaryButtons[1].click();
- $pointsSummaryButtons[1].remove();
- console.log('[Twitch-Auto-Channel-Points] Getting points...');
- needToUpdateGotPoints = true;
- }
- if (needToUpdateGotPoints) {
- $gotPointsEles.forEach(($gotPointsEle) => {
- const matches = $gotPointsEle.textContent.match(gotPointsRegex);
- if (!matches) return;
- lastTimeGotPoints = parseInt(matches[1]);
- });
- if (!lastTimeGotPoints) return;
- totalGotPoints += lastTimeGotPoints;
- GM_setValue(GMkeyName, totalGotPoints);
- console.log("[Twitch-Auto-Channel-Points] Got points: ", lastTimeGotPoints);
- showTotalGotPoints(totalGotPoints);
- lastTimeGotPoints = null;
- needToUpdateGotPoints = false;
- }
- }, getPointsLoopMs);
- }
- const stopGetPointsLoop = () => {
- if (!window.getPointLoop) return;
- clearInterval(window.getPointLoop);
- window.getPointLoop = null;
- }
- const appendGotPointsElement = () => {
- const $totalGotPointsContainer = document.createElement('div');
- $totalGotPointsContainer.id = 'total-got-points';
- const $buttonDiv = document.querySelectorAll('.chat-input__buttons-container div')[0];
- $buttonDiv.appendChild($totalGotPointsContainer);
- const $pointImage = document.querySelector('.channel-points-icon__image');
- if ($pointImage) {
- const pointName = $pointImage.alt;
- $totalGotPointsContainer.style.setProperty('--point-name', '"自動領取' + pointName + '"');
- $totalGotPointsContainer.appendChild($pointImage.cloneNode(true));
- } else {
- $totalGotPointsContainer
- .appendChild(document.querySelector('.chat-input__buttons-container button svg')
- .cloneNode(true));
- }
- $totalGotPointsContainer.appendChild(document.createElement('span'));
- return document.querySelector('#total-got-points span');
- };
- const showTotalGotPoints = function (totalGotPoints) {
- let $gotPointsEle = document.querySelector('#total-got-points span');
- if (!$gotPointsEle) {
- $gotPointsEle = appendGotPointsElement();
- }
- $gotPointsEle.textContent = new Intl.NumberFormat().format(totalGotPoints);
- console.log("[Twitch-Auto-Channel-Points] totalGotPoints: ", totalGotPoints);
- };
- const startFindPointButtonLoop = () => {
- window.findPointButtonLoop = setInterval(function () {
- console.log('[Twitch-Auto-Channel-Points] find point-button...');
- let $pointButton = document.querySelector('[data-test-selector="community-points-summary"] button');
- if ($pointButton) {
- startGetPointsLoop();
- stopFindPointButtonLoop();
- console.log("[Twitch-Auto-Channel-Points] found point-button. start auto get points");
- } else if (!findButtonRetry) {
- stopFindPointButtonLoop();
- console.warn("[Twitch-Auto-Channel-Points] point-button not found.");
- }
- findButtonRetry--;
- }, 500);
- };
- const stopFindPointButtonLoop = () => {
- if (!window.findPointButtonLoop) return;
- clearInterval(window.findPointButtonLoop);
- window.findPointButtonLoop = null;
- }
- const handlePageLoaded = (pathname) => {
- if (isPathIgnored(pathname)) return;
- startFindPointButtonLoop();
- }
- const handlePageChanged = () => {
- window.navigation.addEventListener("navigate", (event) => {
- stopFindPointButtonLoop();
- stopGetPointsLoop();
- const url = new URL(event.destination.url);
- handlePageLoaded(url.pathname);
- });
- }
- const main = () => {
- handlePageLoaded(location.pathname);
- handlePageChanged();
- }
- main();
- })();