您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Get Chaturbate token stats for individual rooms.
// ==UserScript== // @name ChaturbateTokenStats // @namespace http://tampermonkey.net/ // @version 2025-04-22 // @description Get Chaturbate token stats for individual rooms. // @author nyoob/seraphine24 // @match https://chaturbate.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=chaturbate.com // @grant none // @require https://code.jquery.com/jquery-3.6.0.min.js // ==/UserScript== const div = ` <div style="background-color: red; height: auto; width: 100%; position: static; overflow: hidden; display: block; padding: 5px 0px; text-align: center; box-sizing: border-box; font-size: 14px; font-weight: 400; font-family: UbuntuMedium, Helvetica, Arial, sans-serif; color: rgb(73, 73, 73);" ts="p" class="siteNotice"> <div class="wrapper seratkstats" style="background-color: crimson; padding: 15px; border-width: 1px; border-style: solid;"> <h2>Stop spending money on porn! You can watch for free.</h2> <div>Imagine what you could do with that money! Go on vacation, get something for your mother, buy furniture, save up for a car.</div> <div>Chaturbate is even worse than gambling, more addictive with less returns. The only thing with comparable dopamine output is heroin.</div> <div>Remember, the love you think you're receiving is fake. These models learned a lot of psychological tricks to get you to feel special so you spend your money on them.</div> <button class="seraBtn" onclick="getTkStats()">Load token stats</button> <button class="seraBtn seraDlBtn" onclick="dlTkTx()" disabled>Download Tx JSON</button> </div> </div> `; const styles = ` #site_notices .wrapper > div { margin-top: 8px; } .loadStats { color: blue; } .seratable { display: flex; justify-content: center; } .seratable td, .seratable th { border-bottom: 1px solid white; } .seraBtn { padding: 6px 12px; background-color: orange; border-radius: 8px; border: 1px solid pink; margin-top: 8px; } .seraBtn:disabled { background-color: gray; } `; window.getTkStats = () => { var all = [] function loadMore(last_tx_id) { fetch("/api/ts/tipping/token-stats/?max_transaction_id=" + last_tx_id + "&cashpage=0") .then((r) => r.json()) .then((r) => { all = [...all, ...Object.values(r.transactions)]; if(!r.txns_fully_loaded) { loadMore(r.transactions[r.transactions.length - 1].id) } else { localStorage.setItem("seraTkStats", JSON.stringify(all)); alert("finished loading tk stats"); window.location.reload(); } }) } loadMore(); } window.dlTkTx = () => { const stats = localStorage.getItem("seraTkStats"); var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(stats); var downloadAnchorNode = document.createElement('a'); downloadAnchorNode.setAttribute("href", dataStr); downloadAnchorNode.setAttribute("download", "transactions.json"); document.body.appendChild(downloadAnchorNode); // required for firefox downloadAnchorNode.click(); downloadAnchorNode.remove(); } const calculateTotalStats = () => { const data = JSON.parse(localStorage.getItem("seraTkStats")); var totalSpent = 0; var spentByUser = {}; data.forEach((e) => { if(e.description == "Tokens purchased") return; totalSpent += Math.abs(e.tokens); if(!spentByUser[e.username]) { spentByUser[e.username] = 0; } spentByUser[e.username] += Math.abs(e.tokens); }); spentByUser = Object.entries(spentByUser).sort(([,a],[,b]) => b-a); return {totalSpent, spentByUser}; } const tksToDollar = (tks) => { const minPrice = 0.079 const maxPrice = 0.109 return {min: (tks * minPrice).toFixed(2), max: (tks * maxPrice).toFixed(2)}; } (function() { // div $("#site_notices").append(div); // style $('html > head').append(`<style>${styles}</style>`); // stats const totalStats = calculateTotalStats(); const totalSpentInDollar = tksToDollar(totalStats.totalSpent); if(!totalStats) { $("#site_notices .wrapper").append(` <div class="seraAlert">Please load token stats. You have to be logged in to do that.<br/>Detailed stats will be shown after loading.</div> `) } else { $(".seraDlBtn").prop('disabled', false); $("#site_notices .wrapper").append(` <div>Total spent: ${totalStats.totalSpent}tks (in dollars: ${totalSpentInDollar.min}-${totalSpentInDollar.max})</div> <div> <details> <summary>Tks spent per user</summary> <div class="seratable"> <table><thead> <tr> <td class="">Username</td> <td class="">Tokens spent</td> <td class="">Min Dollars</td> <td class="">Max Dollars</td> </tr></thead> <tbody> ${totalStats.spentByUser.map(([user, spent]) => { const totalSpentInDollar = tksToDollar(spent); return `<tr> <td>${user}</td><td>${spent}tks</td> <td>${totalSpentInDollar.min}</td><td>${totalSpentInDollar.max}</td> </tr>`; }).join("")} </tbody> </table> </div> </details> </div> `) } })();