// ==UserScript== // @name DeepSeek Toolkit - Chat Exporter // @namespace http://tampermonkey.net/ // @version 1.0.0 // @description Export DeepSeek conversations to text files. Requires DeepSeek Toolkit Core. // @author okagame // @match https://chat.deepseek.com/* // @grant none // @require https://update.greasyfork.icu/scripts/555353/1692447/DeepSeek%20Toolkit%20Core.js // @icon https://www.google.com/s2/favicons?sz=64&domain=deepseek.com // @license MIT // @run-at document-idle // @downloadURL none // ==/UserScript== (function() { 'use strict'; console.log('[Chat Exporter] Loading...'); // Wait for toolkit to be ready if (typeof window.DeepSeekToolkit === 'undefined') { console.error('[Chat Exporter] DeepSeek Toolkit Core not found!'); return; } // ==================== EXPORT LOGIC ==================== function capitalizeRole(role) { if (role === 'user') return 'User'; if (role === 'assistant') return 'Assistant'; return role.charAt(0).toUpperCase() + role.slice(1); } function extractMessages() { const containers = document.querySelectorAll('[data-message-id]'); const messages = []; console.log(`[Chat Exporter] Found ${containers.length} message containers`); containers.forEach((container, index) => { const role = container.getAttribute('data-message-author-role'); if (!role) { console.log(`[Chat Exporter] Container ${index}: no role`); return; } // Extract text using TreeWalker to get all text nodes const walker = document.createTreeWalker( container, NodeFilter.SHOW_TEXT, { acceptNode: function(node) { const parent = node.parentElement; if (!parent) return NodeFilter.FILTER_REJECT; // Skip UI elements const tagName = parent.tagName.toLowerCase(); if (['button', 'script', 'style', 'svg'].includes(tagName)) { return NodeFilter.FILTER_REJECT; } // Skip elements with role="button" if (parent.getAttribute('role') === 'button') { return NodeFilter.FILTER_REJECT; } // Skip if parent or any ancestor is a button if (parent.closest('button')) { return NodeFilter.FILTER_REJECT; } // Skip common UI class patterns const classList = parent.className || ''; if (typeof classList === 'string') { if (classList.includes('button') || classList.includes('icon') || classList.includes('toolbar') || classList.includes('menu')) { return NodeFilter.FILTER_REJECT; } } return NodeFilter.FILTER_ACCEPT; } } ); // Collect text nodes const textNodes = []; let node; while (node = walker.nextNode()) { const trimmed = node.textContent.trim(); if (trimmed && trimmed.length > 0) { // Filter out common UI strings if (!['Copy', 'Edit', 'Retry', 'Regenerate', 'Continue', 'Stop'].includes(trimmed)) { textNodes.push(trimmed); } } } // Join text nodes with spaces, then clean up let text = textNodes.join(' ').trim(); // Remove duplicate spaces text = text.replace(/\s+/g, ' '); if (text && text.length > 0) { console.log(`[Chat Exporter] Message ${index} (${role}): "${text.substring(0, 50)}..."`); messages.push({ role: capitalizeRole(role), text: text }); } }); console.log(`[Chat Exporter] Extracted ${messages.length} messages`); return messages; } function generateFileName(messages) { // Try page title first const title = document.querySelector('title')?.textContent?.trim(); if (title && !title.toLowerCase().includes('deepseek')) { const sanitized = title .slice(0, 40) .replace(/[^a-zA-Z0-9\s-]/g, '') .replace(/\s+/g, '_'); if (sanitized) return sanitized; } // Try first message if (messages.length > 0) { const firstWords = messages[0].text.split(/\s+/).slice(0, 5).join(' '); const sanitized = firstWords .toLowerCase() .replace(/[^a-z0-9 ]/g, '') .replace(/\s+/g, '_') .slice(0, 30); if (sanitized) return sanitized; } // Fallback to timestamp const date = new Date(); const y = date.getFullYear(); const m = String(date.getMonth() + 1).padStart(2, '0'); const d = String(date.getDate()).padStart(2, '0'); const h = String(date.getHours()).padStart(2, '0'); const min = String(date.getMinutes()).padStart(2, '0'); return `deepseek_chat_${y}${m}${d}_${h}${min}`; } function exportChat() { console.log('[Chat Exporter] Starting export...'); try { const messages = extractMessages(); if (messages.length === 0) { alert('No conversation found to export. Make sure there are messages in the current chat.'); return; } // Format content const date = new Date().toISOString(); const header = `DeepSeek Chat Export\nDate: ${date}\nMessages: ${messages.length}\n\n${'='.repeat(60)}\n\n`; const body = messages.map(m => `${m.role}:\n${m.text}`).join('\n\n---\n\n'); const content = header + body; // Create and download file const blob = new Blob([content], { type: 'text/plain;charset=utf-8' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = generateFileName(messages) + '.txt'; document.body.appendChild(link); link.click(); document.body.removeChild(link); // Cleanup setTimeout(() => URL.revokeObjectURL(url), 100); console.log(`[Chat Exporter] Successfully exported ${messages.length} messages`); } catch (error) { console.error('[Chat Exporter] Export failed:', error); alert('Export failed: ' + error.message); } } // ==================== REGISTER WITH TOOLKIT ==================== const EXPORT_ICON = ` `; const registered = window.DeepSeekToolkit.registerTool({ id: 'chat-exporter', name: 'Export Chat', icon: EXPORT_ICON, type: 'action', style: 'icon-button', onClick: exportChat }); if (registered) { console.log('[Chat Exporter] Successfully registered with toolkit'); } else { console.error('[Chat Exporter] Failed to register with toolkit'); } })();