您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Statistiche board Bitcointalk con intestazione dinamica in base ai mesi selezionati
当前为
// ==UserScript== // @name Bitcointalk Board Stats (Dynamic Header) // @namespace http://tampermonkey.net/ // @version 1.9 // @description Statistiche board Bitcointalk con intestazione dinamica in base ai mesi selezionati // @author Ace // @match https://bitcointalk.org/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // Crea la pagina fittizia delle statistiche function createStatPage() { if (document.querySelector('#fake-stat-page')) return; const page = document.createElement('div'); page.id = 'fake-stat-page'; page.style.position = 'fixed'; page.style.top = '0'; page.style.left = '0'; page.style.width = '100%'; page.style.height = '100%'; page.style.backgroundColor = 'rgba(0,0,0,0.5)'; page.style.zIndex = '9999'; page.style.overflowY = 'auto'; page.style.fontFamily = 'Verdana, Arial, sans-serif'; page.style.fontSize = '14px'; page.innerHTML = ` <div style=" max-width: 950px; margin: 20px auto; background: white; padding: 20px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.2); border: 1px solid #ddd; "> <h2 style="text-align: center; margin-bottom: 20px; color: #2e3b4e;">Statistiche Board</h2> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">Board ID o nome:</label> <input type="text" id="board-id" value="28" style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 3px;"> </div> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">Mese corrente (inizio):</label> <input type="datetime-local" id="current-start" value="2025-08-01T00:00:00" style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 3px;"> </div> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">Mese corrente (fine):</label> <input type="datetime-local" id="current-end" value="2025-08-31T23:59:59" style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 3px;"> </div> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">Mese precedente (inizio):</label> <input type="datetime-local" id="previous-start" value="2025-07-01T00:00:00" style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 3px;"> </div> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">Mese precedente (fine):</label> <input type="datetime-local" id="previous-end" value="2025-07-31T23:59:59" style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 3px;"> </div> <div style="margin-bottom: 20px;"> <label style="display: inline-flex; align-items: center; cursor: pointer;"> <input type="checkbox" id="child-boards" style="margin-right: 8px;"> Includi child boards </label> </div> <button id="generate-stats" style=" width: 100%; padding: 10px; font-weight: bold; background: #2e3b4e; color: white; border: none; border-radius: 3px; cursor: pointer; ">Genera Statistiche</button> <div id="stats-preview" style="margin-top: 20px; display: none;"> <h3 style="border-bottom: 1px solid #eee; padding-bottom: 5px;">Anteprima Tabella</h3> <div id="preview-table" style="overflow-x: auto;"></div> </div> <div id="stats-output" style=" margin-top: 20px; padding: 15px; background: #f5f5f5; border-radius: 3px; border: 1px solid #ddd; min-height: 100px; display: none; "> <h3 style="border-bottom: 1px solid #eee; padding-bottom: 5px;">BBCode</h3> <textarea id="bbcode-output" style=" width: 100%; height: 300px; padding: 10px; font-family: monospace; border: 1px solid #ccc; border-radius: 3px; resize: vertical; "></textarea> <button id="copy-bbcode" style=" display: block; margin: 10px auto 0; padding: 8px 16px; background: #2e3b4e; color: white; border: none; border-radius: 3px; cursor: pointer; ">Copia BBCode</button> </div> <button id="close-page" style=" display: block; margin: 20px auto 0; padding: 8px 16px; font-weight: bold; background: #ccc; border: none; border-radius: 3px; cursor: pointer; ">Chiudi</button> </div> `; document.body.appendChild(page); document.querySelector('#close-page').onclick = () => page.remove(); document.querySelector('#generate-stats').onclick = generateStats; document.querySelector('#copy-bbcode').onclick = copyBBCode; } // Copia BBCode negli appunti function copyBBCode() { const textarea = document.querySelector('#bbcode-output'); textarea.select(); try { navigator.clipboard.writeText(textarea.value) .then(() => alert('BBCode copiato negli appunti!')) .catch(() => { document.execCommand('copy'); alert('BBCode copiato negli appunti!'); }); } catch (err) { document.execCommand('copy'); alert('BBCode copiato negli appunti!'); } } // Ottieni il nome del mese da una data function getMonthName(dateString) { const months = ['Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic']; const date = new Date(dateString); return months[date.getMonth()]; } // Genera le statistiche con intestazione dinamica async function generateStats() { const boardId = document.querySelector('#board-id').value.trim(); const currentStart = document.querySelector('#current-start').value; const currentEnd = document.querySelector('#current-end').value; const previousStart = document.querySelector('#previous-start').value; const previousEnd = document.querySelector('#previous-end').value; const childBoards = document.querySelector('#child-boards').checked; if (!boardId || !currentStart || !currentEnd || !previousStart || !previousEnd) { alert('Compila tutti i campi!'); return; } // Nomi dei mesi per l'intestazione const currentMonthName = getMonthName(currentStart); const previousMonthName = getMonthName(previousStart); const previewDiv = document.querySelector('#stats-preview'); const outputDiv = document.querySelector('#stats-output'); previewDiv.style.display = 'none'; outputDiv.style.display = 'none'; const loadingMsg = document.createElement('p'); loadingMsg.style.textAlign = 'center'; loadingMsg.style.color = '#666'; loadingMsg.textContent = 'Caricamento dati...'; previewDiv.parentNode.insertBefore(loadingMsg, previewDiv); try { // Fetch dati mese corrente const currentUrl = `https://api.ninjastic.space/posts/authors?board=${boardId}&child_boards=${childBoards}&after_date=${currentStart}&before_date=${currentEnd}&limit=1000`; const currentRes = await fetch(currentUrl); const currentJson = await currentRes.json(); // Fetch dati mese precedente const previousUrl = `https://api.ninjastic.space/posts/authors?board=${boardId}&child_boards=${childBoards}&after_date=${previousStart}&before_date=${previousEnd}&limit=1000`; const previousRes = await fetch(previousUrl); const previousJson = await previousRes.json(); if (currentJson.result !== "success" || previousJson.result !== "success") { loadingMsg.textContent = `Errore API: ${currentJson.message || previousJson.message || "Sconosciuto"}`; loadingMsg.style.color = 'red'; return; } const currentAuthors = currentJson.data.authors; const previousAuthors = previousJson.data.authors; // Crea mappa post mese precedente (author_uid -> count) const previousPostsMap = {}; previousAuthors.forEach(a => { previousPostsMap[a.author_uid] = a.count || 0; }); // Unisci e ordina gli utenti per post del mese corrente const allAuthors = [...currentAuthors]; allAuthors.sort((a, b) => (b.count || 0) - (a.count || 0)); // Anteprima tabella HTML let previewTable = ` <table style="width: 100%; border-collapse: collapse; margin-bottom: 15px; font-size: 13px;"> <tr style="background: #f0f0f0;"> <th style="padding: 8px; text-align: center; border: 1px solid #ddd; width: 5%;">Pos.</th> <th style="padding: 8px; text-align: left; border: 1px solid #ddd; width: 25%;">User</th> <th style="padding: 8px; text-align: center; border: 1px solid #ddd; width: 10%;">Post (${currentMonthName})</th> <th style="padding: 8px; text-align: center; border: 1px solid #ddd; width: 10%;">Post (${previousMonthName})</th> <th style="padding: 8px; text-align: center; border: 1px solid #ddd; width: 10%;">Change</th> <th style="padding: 8px; text-align: center; border: 1px solid #ddd; width: 10%;">BPIP</th> <th style="padding: 8px; text-align: center; border: 1px solid #ddd; width: 10%;">Ninjastic</th> </tr> `; allAuthors.forEach((a, index) => { const username = a.author || 'Sconosciuto'; const userUid = a.author_uid || ''; const currentCount = a.count || 0; const previousCount = previousPostsMap[userUid] || 0; const diff = currentCount - previousCount; const variationColor = diff >= 0 ? 'green' : 'red'; const variationText = diff >= 0 ? `▲${diff}` : `▼${Math.abs(diff)}`; const userLink = userUid ? `<a href="https://bitcointalk.org/index.php?action=profile;u=${userUid}" target="_blank">${username}</a>` : username; previewTable += ` <tr style="border: 1px solid #ddd;"> <td style="padding: 8px; border: 1px solid #ddd; text-align: center;">${index + 1}.</td> <td style="padding: 8px; border: 1px solid #ddd;">${userLink}</td> <td style="padding: 8px; border: 1px solid #ddd; text-align: center;">${currentCount}</td> <td style="padding: 8px; border: 1px solid #ddd; text-align: center;">${previousCount}</td> <td style="padding: 8px; border: 1px solid #ddd; text-align: center; color: ${variationColor};">${variationText}</td> <td style="padding: 8px; border: 1px solid #ddd; text-align: center;"> <a href="https://bpip.org/Profile?p=${username}" target="_blank"> <img src="https://www.talkimg.com/images/2023/08/03/GXlZb.png" width="15"> </a> </td> <td style="padding: 8px; border: 1px solid #ddd; text-align: center;"> <a href="https://ninjastic.space/user/${username}" target="_blank"> <img src="https://talkimg.com/images/2023/08/03/GwdMz.png" width="15"> </a> </td> </tr> `; }); previewTable += `</table>`; // BBCode con intestazione dinamica let bbcode = `[center][b][size=12pt]Statistiche Board[/size][/b][/center] [center][i]Confronto: ${previousMonthName} vs ${currentMonthName}[/i][/center] [table] [tr] [td][b]Pos.[/b][/td] [td][b]User[/b][/td] [td][b]Post (${currentMonthName})[/b][/td] [td][b]Post (${previousMonthName})[/b][/td] [td][b]Change[/b][/td] [td][b]BPIP[/b][/td] [td][b]Ninjastic[/b][/td] [/tr] `; allAuthors.forEach((a, index) => { const username = a.author || 'Sconosciuto'; const userUid = a.author_uid || ''; const currentCount = a.count || 0; const previousCount = previousPostsMap[userUid] || 0; const diff = currentCount - previousCount; const variationColor = diff >= 0 ? 'green' : 'red'; const variationText = diff >= 0 ? `[color=${variationColor}]▲${diff}[/color]` : `[color=${variationColor}]▼${Math.abs(diff)}[/color]`; const userLink = userUid ? `[url=https://bitcointalk.org/index.php?action=profile;u=${userUid}]${username}[/url]` : username; bbcode += `[tr] [td]${index + 1}.[/td] [td]${userLink}[/td] [td]${currentCount}[/td] [td]${previousCount}[/td] [td]${variationText}[/td] [td][url=https://bpip.org/Profile?p=${username}][img width=15]https://www.talkimg.com/images/2023/08/03/GXlZb.png[/img][/url][/td] [td][url=https://ninjastic.space/user/${username}][img width=15]https://talkimg.com/images/2023/08/03/GwdMz.png[/img][/url][/td] [/tr] `; }); bbcode += `[/table]`; // Mostra anteprima e BBCode loadingMsg.remove(); previewDiv.style.display = 'block'; outputDiv.style.display = 'block'; document.querySelector('#preview-table').innerHTML = previewTable; document.querySelector('#bbcode-output').value = bbcode; } catch (err) { console.error(err); loadingMsg.textContent = 'Errore durante il recupero dei dati.'; loadingMsg.style.color = 'red'; } } // Aggiunge pulsante Stat nella navbar function addStatButton() { const navbar = document.querySelector('table[style*="margin-left: 10px;"]'); if (!navbar) { setTimeout(addStatButton, 1000); return; } const lastCell = navbar.querySelector('td.maintab_last'); if (lastCell.querySelector('#stat-button')) return; const statButton = document.createElement('td'); statButton.id = 'stat-button'; statButton.className = 'maintab_back'; statButton.innerHTML = `<a href="javascript:void(0)" class="maintab_link" style="padding: 0 10px;">Stat</a>`; statButton.querySelector('a').onclick = createStatPage; navbar.querySelector('tr').insertBefore(statButton, lastCell); } window.addEventListener('load', () => setTimeout(addStatButton, 1000)); window.copyBBCode = copyBBCode; })();