NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name TGStat Exporter // @namespace Scripts // @author n30v1m // @match https://tgstat.ru/channels/search* // @grant none // @version 1.13 // @require https://cdn.jsdelivr.net/npm/@violentmonkey/dom@2 // @description TGStat Search CSV Exporter Button // @license MIT // @downloadURL https://openuserjs.org/install/n30v1m/TGStat_Exporter.user.js // @updateURL https://openuserjs.org/meta/n30v1m/TGStat_Exporter.meta.js // ==/UserScript== (function () { 'use strict'; let channelsData = []; let uniqueLinks = new Set(); let downloadButtonText = "Download 0"; function convertLink(tgstatLink) { if (!tgstatLink || typeof tgstatLink !== 'string') { return ""; } const usernameMatch = tgstatLink.match(/@([\w\d_]+)/); if (usernameMatch && usernameMatch[1]) { return `https://t.me/${usernameMatch[1]}`; } if (tgstatLink.includes('tgstat.ru/channel/')) { const basePathMatch = tgstatLink.match(/(https:\/\/tgstat\.ru\/channel\/[^/?#]+)/); if (basePathMatch && basePathMatch[1]) { return basePathMatch[1]; } return tgstatLink; } return ""; } function csvSafe(value) { if (value === null || typeof value === 'undefined') { return ''; } let strValue = String(value); strValue = strValue.replace(/[\r\n]+/g, ' '); strValue = strValue.replace(/"/g, '""'); if (strValue.includes(',') || strValue.includes('"')) { return `"${strValue}"`; } return strValue; } function parseChannels() { let newChannelsFound = false; document.querySelectorAll('.peer-item-row').forEach(channelElement => { let name = channelElement.querySelector('.row .font-16')?.textContent.trim() || "Unknown"; let linkAnchor = channelElement.querySelector('a[href*="/channel/"]'); let tgstatPageLink = ""; if (linkAnchor) { tgstatPageLink = new URL(linkAnchor.getAttribute('href'), document.baseURI).href; } let finalLink = convertLink(tgstatPageLink); if (finalLink && !uniqueLinks.has(finalLink)) { channelsData.push({ 'name': name, 'link': finalLink }); uniqueLinks.add(finalLink); newChannelsFound = true; } }); if (newChannelsFound || (channelsData.length > 0 && downloadButtonText === "Download 0") || (channelsData.length === 0 && document.querySelector('.peer-item-row') && downloadButtonText === "Download 0")) { downloadButtonText = "Download " + channelsData.length; updateDownloadButton(); } else if (channelsData.length === 0 && !document.querySelector('.peer-item-row')) { downloadButtonText = "Download 0"; updateDownloadButton(); } } function downloadCSV() { if (channelsData.length === 0) { alert("Нет данных для экспорта."); return; } const csvHeader = "название канала,ссылка\n"; const csvRows = channelsData.map(e => { const name = csvSafe(e.name); const link = csvSafe(e.link); return `${name},${link}`; }).join("\n"); const csvString = csvHeader + csvRows; const BOM = ""; const blob = new Blob([BOM + csvString], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const linkElement = document.createElement("a"); linkElement.setAttribute("href", url); linkElement.setAttribute("download", "tgstat_channels.csv"); linkElement.style.visibility = 'hidden'; document.body.appendChild(linkElement); linkElement.click(); document.body.removeChild(linkElement); URL.revokeObjectURL(url); } let prevButton = null; function updateDownloadButton() { const container = document.querySelector('#sticky-right-column__inner > div > div'); if (container) { if (prevButton) { prevButton.remove(); } let button = document.createElement("button"); prevButton = button; button.innerText = downloadButtonText; button.className = "btn btn-warning w-100 mt-2"; button.setAttribute("id", "gtstat-csv-download-button-111"); button.addEventListener("click", function (event) { event.preventDefault(); downloadCSV(); }); container.appendChild(button); } } parseChannels(); VM.observe(document.body, () => { const targetNode = document.querySelector('.channels-list'); if (targetNode) { VM.observe(targetNode, () => { parseChannels(); }); return true; } return false; }); })();