- // ==UserScript==
- // @name Comment Scraper
- // @namespace discord.gg/-----
- // @version 2
- // @description MacOS like comment scrape into discord webhook
- // @author Simon (dork)
- // @match https://www.kogama.com/games/play/*
- // @grant none
- // ==/UserScript==
-
- (function () {
- "use strict";
-
- const MAX_FILE_SIZE = 8 * 1024 * 1024; // 9mb Webhook file limit | DO NOT CHANGE
- let processedRequests = 0;
- let totalPages = 0;
- let isMenuVisible = true;
-
- const extractGameIdFromUrl = () => {
- const match = window.location.pathname.match(/\/games\/play\/([^/]+)\//);
- return match ? match[1] : null;
- };
-
- const extractGameTitle = () => {
- const titleElement = document.querySelector("section._10ble h1.game-title");
- return titleElement ? titleElement.textContent.trim() : "Unknown Game";
- };
-
- const createMenu = () => {
- const style = document.createElement("style");
- style.innerHTML = `
- #u7465 {
- position: fixed;
- top: 20px;
- left: 20px;
- width: 280px;
- background: #fff;
- color: #333;
- border-radius: 12px;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
- z-index: 9999;
- transition: all 0.3s ease;
- display: block;
- padding: 20px;
- }
- #u7465 .top-bar {
- height: 30px;
- background: #f1f1f1;
- border-top-left-radius: 12px;
- border-top-right-radius: 12px;
- display: flex;
- justify-content: flex-start;
- align-items: center;
- padding: 0 10px;
- cursor: move;
- }
- #u7465 .top-bar .button {
- width: 12px;
- height: 12px;
- border-radius: 50%;
- background-color: #ff5f57;
- margin-right: 6px;
- cursor: pointer;
- }
- #u7465 .top-bar .minimize {
- background-color: #ffbd2e;
- }
- #u7465 .top-bar .close {
- background-color: #ff5f57;
- }
- #u7465 .top-bar .maximize {
- background-color: #27c93f;
- }
- #u7465 .top-bar .button:hover {
- opacity: 0.7;
- }
- #u7465 h1 {
- font-size: 18px;
- margin: 10px;
- color: #333;
- text-align: center;
- font-weight: 600;
- }
- #u7465 input, #u7465 button {
- width: calc(100% - 20px);
- padding: 10px;
- margin: 8px 0;
- border-radius: 8px;
- border: 1px solid #ddd;
- box-sizing: border-box;
- background-color: #f9f9f9;
- font-size: 14px;
- color: #333;
- }
- #u7465 input:focus, #u7465 button:focus {
- outline: none;
- border-color: #007aff;
- }
- #u7465 button {
- background: linear-gradient(45deg, #ff79c6, #ff9a8b, #9b59b6);
- color: white;
- cursor: pointer;
- transition: transform 0.2s, background-color 0.2s;
- border: none;
- }
- #u7465 button:hover {
- transform: scale(1.05);
- background-color: #d45e9b;
- }
- #u7465 button:active {
- background-color: #c34b7a;
- }
- #u7465 #progress {
- font-size: 14px;
- text-align: center;
- margin-top: 10px;
- color: #555;
- }
- `;
- document.head.appendChild(style);
-
- const menu = document.createElement("div");
- menu.id = "u7465";
- menu.innerHTML = `
- <div class="top-bar">
- <div class="button close"></div>
- <div class="button minimize"></div>
- <div class="button maximize"></div>
- </div>
- <h1>Comment Scraper</h1>
- <input id="webhook-url" type="text" placeholder="Webhook URL">
- <input id="total-pages" type="number" placeholder="Total Pages">
- <button id="start-button">Start Scraping</button>
- <div id="progress">Progress: 0 / 0</div>
- `;
- document.body.appendChild(menu);
-
- makeDraggable(menu);
-
- document.getElementById("total-pages").addEventListener("input", (e) => {
- totalPages = parseInt(e.target.value, 10);
- updateProgress();
- });
-
- document
- .querySelector(".close")
- .addEventListener("click", () => toggleMenuVisibility(false));
- document
- .querySelector(".minimize")
- .addEventListener("click", () => toggleMenuVisibility(true));
- };
-
- const toggleMenuVisibility = (isVisible) => {
- const menu = document.getElementById("u7465");
- menu.style.display = isVisible ? "block" : "none";
- isMenuVisible = isVisible;
- };
-
- const makeDraggable = (element) => {
- let isDragging = false,
- startX,
- startY,
- initialX,
- initialY;
- const topBar = element.querySelector(".top-bar");
- topBar.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) {
- processedRequests++;
- 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: ${totalPages}\n\n▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃\n\n `;
- };
-
- const updateProgress = () => {
- const progressText = `${processedRequests} / ${totalPages}`;
- document.getElementById(
- "progress"
- ).textContent = `Progress: ${progressText}`;
- };
-
- const processAllComments = async (webhookUrl) => {
- const fetchPromises = [];
- let currentPage = 1;
-
- while (currentPage <= totalPages) {
- 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;
- a;
-
- let fileDataBuffer = currentFileData + formattedData;
-
- if (new Blob([fileDataBuffer]).size > MAX_FILE_SIZE) {
- const gameTitle = extractGameTitle().replace(/[\/\\?%*:|"<>]/g, "_");
- await sendFileToWebhook(
- webhookUrl,
- fileDataBuffer,
- `${gameTitle}_comments_${fileCount}.txt`
- );
- fileCount++;
- fileDataBuffer = formattedData;
- }
-
- if (fileDataBuffer) {
- const gameTitle = extractGameTitle().replace(/[\/\\?%*:|"<>]/g, "_");
- await sendFileToWebhook(
- webhookUrl,
- fileDataBuffer,
- `${gameTitle}_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(totalPages) || totalPages <= 0) {
- alert("Please fill all fields correctly.");
- return;
- }
-
- processedRequests = 0;
- updateProgress();
-
- await processAllComments(webhookUrl);
- };
-
- createMenu();
- document
- .getElementById("start-button")
- .addEventListener("click", startProcess);
- })();