mydealz Comment Scraper & Markdown Exporter

A new userscript

// ==UserScript==
// @name        mydealz Comment Scraper & Markdown Exporter
// @description     A new userscript
// @version     1.0.1
// @match       https://*.mydealz.de/*
// @icon        https://www.mydealz.de/favicon.ico
// @namespace https://greasyfork.org/users/1462137
// ==/UserScript==
(function() {
'use strict';

let isProcessing = false;
let allComments = [];
let currentPage = 1;
let totalPages = 1;

function createScrapeButton() {
const button = document.createElement('button');
        button.style.position = 'fixed';
        button.style.top = '20px';
        button.style.right = '20px';
        button.style.zIndex = '10000';
        button.style.backgroundColor = '#007bff';
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.padding = '10px 15px';
        button.style.borderRadius = '5px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '14px';
        button.style.fontWeight = 'bold';
        button.textContent = 'Scrape Comments';
        button.id = 'scrape-comments-btn';
        document.body.appendChild(button);
}

function showProgress(message) {
const button = document.getElementById('scrape-comments-btn');
if (button) {
            button.textContent = message;
} else {
            console.log(message);
}
}

async function expandAllReplies() {
const replyButtons = document.querySelectorAll('button[data-t="moreReplies"]');

for (const button of replyButtons) {
            button.click();
            console.log('Expanded replies for button: ' + button.textContent.trim());
await new Promise(resolve => setTimeout(resolve, 1000));
}
}

function extractCommentData(commentElement) {
const username = commentElement.querySelector('.user button')?.textContent?.trim() || '';
const timestamp = commentElement.querySelector('time')?.textContent?.trim() || '';
const text = commentElement.querySelector('.comment-body .userHtml-content')?.textContent?.trim() || '';
const likes = commentElement.querySelector('.comment-like')?.textContent?.trim() || '0';
const helpful = commentElement.querySelector('.comment-helpful')?.textContent?.trim() || '0';
const funny = commentElement.querySelector('.comment-funny')?.textContent?.trim() || '0';

return {
            username,
            timestamp,
            text,
            likes,
            helpful,
            funny
};
}

function extractAllCommentsFromPage() {
const commentItems = document.querySelectorAll('.commentList-item');
const comments = [];

        commentItems.forEach(item => {
const mainCommentData = extractCommentData(item);
const replyElements = item.querySelectorAll('.comment-replies-item');
const replies = [];

            replyElements.forEach(replyElement => {
const replyData = extractCommentData(replyElement);
                replies.push(replyData);
});

const commentObject = {
...mainCommentData,
                replies: replies
};

            comments.push(commentObject);
});

        allComments.push(...comments);
        console.log('Extracted ' + comments.length + ' comments from current page');
}

async function navigateToNextPage() {
const nextButton = document.querySelector('button[aria-label="Nächste Seite"]:not(.button--disabled)');
if (nextButton) {
            nextButton.click();
await new Promise(resolve => setTimeout(resolve, 3000));
return true;
}
return false;
}

function getTotalPages() {
const lastPageButton = document.querySelector('button[aria-label="Letzte Seite"]');
if (lastPageButton && lastPageButton.textContent) {
const pageNumber = parseInt(lastPageButton.textContent.trim());
return isNaN(pageNumber) ? 1 : pageNumber;
}
return 1;
}

function generateMarkdown() {
let markdown = '# mydealz Comments\n\n';

const dealTitle = document.querySelector('h1').textContent;
        markdown += `**Deal:** ${dealTitle}\n\n`;

        markdown += `**URL:** ${window.location.href}\n\n`;

        markdown += `**Total Comments:** ${allComments.length}\n\n`;

        allComments.forEach((comment, index) => {
            markdown += `## Comment by ${comment.username} (${comment.timestamp})\n\n`;
            markdown += `${comment.text}\n\n`;
            markdown += `**Reactions:** 👍 ${comment.likes} | 🔥 ${comment.helpful} | 😄 ${comment.funny}\n\n`;

if (comment.replies && comment.replies.length > 0) {
                comment.replies.forEach(reply => {
                    markdown += `### Reply by ${reply.username} (${reply.timestamp})\n\n`;
                    markdown += `${reply.text}\n\n`;
                    markdown += `**Reactions:** 👍 ${reply.likes} | 🔥 ${reply.helpful} | 😄 ${reply.funny}\n\n`;
});
}

if (index < allComments.length - 1) {
                markdown += '---\n\n';
}
});

return markdown;
}

function downloadMarkdown(content) {
const blob = new Blob([content], {type: 'text/markdown'});
const url = URL.createObjectURL(blob);
const anchor = document.createElement('a');
        anchor.href = url;
        anchor.download = 'mydealz-comments-' + Date.now() + '.md';
        document.body.appendChild(anchor);
        anchor.click();
        document.body.removeChild(anchor);
URL.revokeObjectURL(url);
}

async function scrapeAllComments() {
if (isProcessing) {
            alert('Scraping already in progress');
return;
}

        isProcessing = true;
        showProgress('Starting scrape...');

        totalPages = getTotalPages();
        currentPage = 1;
        allComments = [];

while (currentPage <= totalPages) {
            showProgress('Processing page ' + currentPage + ' of ' + totalPages);
await expandAllReplies();
await new Promise(resolve => setTimeout(resolve, 2000));
            extractAllCommentsFromPage();

if (currentPage < totalPages) {
await navigateToNextPage();
await new Promise(resolve => setTimeout(resolve, 3000));
}

            currentPage++;
}

        showProgress('Generating markdown...');
const content = generateMarkdown();
        downloadMarkdown(content);
        showProgress('Download complete!');
await new Promise(resolve => setTimeout(resolve, 2000));
        showProgress('Scrape Comments');
        isProcessing = false;
}

function init() {
if (!window.location.href.includes('/deals/')) {
            console.log('Not on a deal page');
return;
}

        createScrapeButton();

const button = document.getElementById('scrape-comments-btn');
if (button) {
            button.addEventListener('click', scrapeAllComments);
}

        console.log('mydealz Comment Scraper initialized');
}

if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
} else {
        init();
}
})();