Comment Scraper

Draggable and easy to use comment scraper. Made for personal use with the goal to look for malware advertisements.

当前为 2025-01-20 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Comment Scraper
// @namespace    discord.gg/@simonvhs
// @version      1.6
// @description  Draggable and easy to use comment scraper. Made for personal use with the goal to look for malware advertisements.
// @author       Simon (dork)
// @match        https://www.kogama.com/games/play/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const MAX_FILE_SIZE = 8 * 1024 * 1024; // Newest Webhook file size limit
    let processed_requests = 0;
    let total_pages = 0;

    const extractGameIdFromUrl = () => {
        const match = window.location.pathname.match(/\/games\/play\/([^/]+)\//);
        return match ? match[1] : null;
    };

    const createMenu = () => {
        const style = document.createElement('style');
        style.innerHTML = `
            #ayaka-menu {
                position: fixed;
                top: 20px;
                left: 20px;
                width: 300px;
                background: #121212;
                color: white;
                border-radius: 10px;
                padding: 20px;
                box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
                font-family: Arial, sans-serif;
                z-index: 9999;
            }
            #ayaka-menu h1 {
                font-size: 18px;
                margin-bottom: 10px;
                text-align: center;
                color: #72bcd4;
            }
            #ayaka-menu input, #ayaka-menu button {
                width: 100%;
                margin: 10px 0;
                padding: 10px;
                border-radius: 5px;
                border: none;
            }
            #ayaka-menu input {
                background: #1e1e1e;
                color: white;
            }
            #ayaka-menu button {
                background: linear-gradient(90deg, #6dd5fa, #1e90ff);
                color: white;
                cursor: pointer;
                transition: transform 0.2s;
            }
            #ayaka-menu button:hover {
                transform: scale(1.05);
            }
            #ayaka-progress {
                font-size: 14px;
                text-align: center;
                margin-top: 10px;
            }
        `;
        document.head.appendChild(style);

        const menu = document.createElement('div');
        menu.id = 'ayaka-menu';
        menu.innerHTML = `
            <h1>Comment Scraper</h1>
            <input id="webhook-url" type="text" placeholder="Webhook URL">
            <input id="total-pages" type="number" placeholder="Total Pages">
            <button id="send-button">Send</button>
            <div id="ayaka-progress">Progress: 0 / 0</div>
        `;
        document.body.appendChild(menu);

        makeDraggable(menu);

        document.getElementById('total-pages').addEventListener('input', (e) => {
            total_pages = parseInt(e.target.value, 10);
            updateProgress();
        });
    };

    const makeDraggable = (element) => {
        let isDragging = false, startX, startY, initialX, initialY;
        element.addEventListener('mousedown', (e) => {
            isDragging = true;
            startX = e.clientX;
            startY = e.clientY;
            initialX = element.offsetLeft;
            initialY = element.offsetTop;
            document.addEventListener('mousemove', onDrag);
            document.addEventListener('mouseup', onStopDrag);
        });

        const onDrag = (e) => {
            if (!isDragging) return;
            const dx = e.clientX - startX;
            const dy = e.clientY - startY;
            element.style.left = `${initialX + dx}px`;
            element.style.top = `${initialY + dy}px`;
        };

        const onStopDrag = () => {
            isDragging = false;
            document.removeEventListener('mousemove', onDrag);
            document.removeEventListener('mouseup', onStopDrag);
        };
    };

    const fetchPage = async (url) => {
        const response = await fetch(url);
        if (response.ok) {
            processed_requests++;
            updateProgress();
            return await response.json();
        } else {
            throw new Error(`Failed to fetch ${url}`);
        }
    };

    const sendFileToWebhook = async (webhookUrl, fileData, fileName) => {
        const blob = new Blob([fileData], { type: 'text/plain' });
        const formData = new FormData();
        formData.append('file', blob, fileName);

        const response = await fetch(webhookUrl, {
            method: 'POST',
            body: formData,
        });

        if (!response.ok) {
            throw new Error('Failed to send file');
        }

        console.log('File sent successfully');
    };

    const formatCommentData = (comment) => {
        const content = JSON.parse(comment._data).data || 'No Content';
        const createdAt = new Date(comment.created).toLocaleString();
        return `[${createdAt}] ${comment.profile_username} (${comment.profile_id}): ${content}`;
    };

    const generateMetadata = () => {
        const date = new Date().toLocaleString();
        const gameId = extractGameIdFromUrl();
        return `Date: ${date}\nGame ID: ${gameId}\nTotal Pages: ${total_pages}\n\n▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃\n\n `;
    };

    const updateProgress = () => {
        const progressText = `${processed_requests} / ${total_pages}`;
        document.getElementById('ayaka-progress').textContent = `Progress: ${progressText}`;
    };

    const processAllComments = async (webhookUrl) => {
        const fetchPromises = [];
        let currentPage = 1;

        while (currentPage <= total_pages) {
            const pageUrl = `https://www.kogama.com/game/${extractGameIdFromUrl()}/comment/?page=${currentPage}&count=400`;
            fetchPromises.push(fetchPage(pageUrl));
            currentPage++;
        }

        try {
            const allPageResults = await Promise.all(fetchPromises);
            let allComments = [];
            allPageResults.forEach((result) => {
                if (result.data) {
                    allComments = allComments.concat(result.data);
                }
            });

            allComments.sort((a, b) => new Date(b.created) - new Date(a.created));

            const formattedData = allComments.map(formatCommentData).join('\n');
            const totalComments = formattedData.split('\n').length;

            let currentFileData = generateMetadata();
            let currentFileSize = 0;
            let fileCount = 1;

            let fileDataBuffer = currentFileData + formattedData;

            if (new Blob([fileDataBuffer]).size > MAX_FILE_SIZE) {
                await sendFileToWebhook(webhookUrl, fileDataBuffer, `comments_${fileCount}.txt`);
                fileCount++;
                fileDataBuffer = formattedData;
            }

            if (fileDataBuffer) {
                await sendFileToWebhook(webhookUrl, fileDataBuffer, `comments_${fileCount}.txt`);
            }

            console.log('All comments processed and files sent!');
        } catch (err) {
            console.error('Error processing comments:', err);
        }
    };

    const startProcess = async () => {
        const webhookUrl = document.getElementById('webhook-url').value;

        if (!webhookUrl || isNaN(total_pages) || total_pages <= 0) {
            alert('Please fill all fields correctly.');
            return;
        }

        processed_requests = 0;
        updateProgress();

        await processAllComments(webhookUrl);
    };

    createMenu();
    document.getElementById('send-button').addEventListener('click', startProcess);
})();