Vidya Rays Automation Toolkit

Powerful automation toolkit for Vidya Rays with AI-powered content analysis, bulk article management, and productivity tools

Size

46.2 KB

Version

1.1.1

Created

Jan 15, 2026

Updated

19 days ago

1// ==UserScript==
2// @name		Vidya Rays Automation Toolkit
3// @description		Powerful automation toolkit for Vidya Rays with AI-powered content analysis, bulk article management, and productivity tools
4// @version		1.1.1
5// @match		https://*.vidyarays.com/*
6// @icon		https://vidyarays.com/wp-content/uploads/fbrfg/favicon.ico
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    console.log('Vidya Rays Automation Toolkit initialized');
12
13    // Utility function for debouncing
14    function debounce(func, wait) {
15        let timeout;
16        return function executedFunction(...args) {
17            const later = () => {
18                clearTimeout(timeout);
19                func(...args);
20            };
21            clearTimeout(timeout);
22            timeout = setTimeout(later, wait);
23        };
24    }
25
26    // Key Generation Automation Class
27    class KeyGenerationAutomator {
28        constructor() {
29            this.isRunning = false;
30            this.currentStep = 0;
31            this.maxSteps = 5;
32            this.adWaitTime = 15000; // 15 seconds
33            this.checkInterval = 500; // Check every 500ms
34            this.statusCallback = null;
35        }
36
37        setStatusCallback(callback) {
38            this.statusCallback = callback;
39        }
40
41        updateStatus(message, type = 'info') {
42            console.log(`[Key Gen] ${message}`);
43            if (this.statusCallback) {
44                this.statusCallback(message, type);
45            }
46        }
47
48        getCurrentStep() {
49            const stepElement = document.querySelector('.steps');
50            if (stepElement) {
51                const stepText = stepElement.textContent.trim();
52                const match = stepText.match(/(\d+)\/(\d+)/);
53                if (match) {
54                    return {
55                        current: parseInt(match[1]),
56                        total: parseInt(match[2])
57                    };
58                }
59            }
60            return null;
61        }
62
63        async clickAd() {
64            this.updateStatus('Looking for ad to click...', 'info');
65            
66            // Try to find and click the ad iframe or container
67            const adContainer = document.querySelector('.ad-content');
68            const adIframe = document.querySelector('#google_ads_iframe_\\/23318727983\\/studyrays_body_0');
69            
70            if (adContainer) {
71                this.updateStatus('Clicking on ad area...', 'info');
72                adContainer.click();
73                
74                // Also try clicking the iframe if it exists
75                if (adIframe) {
76                    adIframe.click();
77                }
78                
79                return true;
80            }
81            
82            this.updateStatus('Ad container not found', 'warning');
83            return false;
84        }
85
86        async waitForTimer(seconds) {
87            this.updateStatus(`Waiting ${seconds} seconds for ad timer...`, 'info');
88            
89            for (let i = seconds; i > 0; i--) {
90                this.updateStatus(`Timer: ${i} seconds remaining...`, 'info');
91                await new Promise(resolve => setTimeout(resolve, 1000));
92                
93                if (!this.isRunning) {
94                    this.updateStatus('Automation stopped by user', 'warning');
95                    return false;
96                }
97            }
98            
99            return true;
100        }
101
102        async clickVerifyButton() {
103            this.updateStatus('Looking for Verify button...', 'info');
104            
105            const verifyBtn = document.getElementById('verifyBtn');
106            if (verifyBtn) {
107                const isVisible = window.getComputedStyle(verifyBtn).display !== 'none';
108                const isEnabled = !verifyBtn.disabled;
109                
110                if (isVisible && isEnabled) {
111                    this.updateStatus('Clicking Verify button...', 'success');
112                    verifyBtn.click();
113                    return true;
114                } else {
115                    this.updateStatus(`Verify button not ready (visible: ${isVisible}, enabled: ${isEnabled})`, 'warning');
116                }
117            } else {
118                this.updateStatus('Verify button not found', 'warning');
119            }
120            
121            return false;
122        }
123
124        async waitForAdOverlay() {
125            this.updateStatus('Waiting for ad overlay to appear...', 'info');
126            
127            let attempts = 0;
128            const maxAttempts = 20; // 10 seconds
129            
130            while (attempts < maxAttempts) {
131                const adOverlay = document.getElementById('adOverlay');
132                if (adOverlay) {
133                    const isVisible = window.getComputedStyle(adOverlay).display !== 'none';
134                    if (isVisible) {
135                        this.updateStatus('Ad overlay detected!', 'success');
136                        return true;
137                    }
138                }
139                
140                await new Promise(resolve => setTimeout(resolve, 500));
141                attempts++;
142                
143                if (!this.isRunning) return false;
144            }
145            
146            this.updateStatus('Ad overlay did not appear', 'warning');
147            return false;
148        }
149
150        async processStep() {
151            const stepInfo = this.getCurrentStep();
152            if (!stepInfo) {
153                this.updateStatus('Could not detect current step', 'error');
154                return false;
155            }
156            
157            this.updateStatus(`Processing Step ${stepInfo.current}/${stepInfo.total}`, 'info');
158            
159            // Wait for ad overlay to be visible
160            const overlayAppeared = await this.waitForAdOverlay();
161            if (!overlayAppeared) {
162                this.updateStatus('Trying to proceed without overlay...', 'warning');
163            }
164            
165            // Click on the ad
166            await this.clickAd();
167            
168            // Wait for the required time (15 seconds)
169            const timerCompleted = await this.waitForTimer(15);
170            if (!timerCompleted) return false;
171            
172            // Additional wait to ensure timer is processed
173            await new Promise(resolve => setTimeout(resolve, 2000));
174            
175            // Click verify button
176            const verifyClicked = await this.clickVerifyButton();
177            if (!verifyClicked) {
178                this.updateStatus('Retrying verify button click...', 'warning');
179                await new Promise(resolve => setTimeout(resolve, 1000));
180                await this.clickVerifyButton();
181            }
182            
183            // Wait for page to process
184            await new Promise(resolve => setTimeout(resolve, 3000));
185            
186            return true;
187        }
188
189        async start() {
190            if (this.isRunning) {
191                this.updateStatus('Automation is already running!', 'warning');
192                return;
193            }
194            
195            this.isRunning = true;
196            this.updateStatus('🚀 Starting key generation automation...', 'success');
197            
198            try {
199                // Check initial step
200                const initialStep = this.getCurrentStep();
201                if (!initialStep) {
202                    this.updateStatus('Key generation page not detected. Please navigate to the key generation page first.', 'error');
203                    this.isRunning = false;
204                    return;
205                }
206                
207                this.updateStatus(`Starting from step ${initialStep.current}/${initialStep.total}`, 'info');
208                
209                // Process each step
210                while (this.isRunning) {
211                    const currentStepInfo = this.getCurrentStep();
212                    
213                    if (!currentStepInfo) {
214                        this.updateStatus('Lost track of steps. Stopping...', 'error');
215                        break;
216                    }
217                    
218                    if (currentStepInfo.current > currentStepInfo.total) {
219                        this.updateStatus('🎉 All steps completed! Key should be generated.', 'success');
220                        break;
221                    }
222                    
223                    // Process current step
224                    const success = await this.processStep();
225                    
226                    if (!success) {
227                        this.updateStatus('Step processing failed. Stopping automation.', 'error');
228                        break;
229                    }
230                    
231                    // Check if we've moved to the next step
232                    await new Promise(resolve => setTimeout(resolve, 2000));
233                    const newStepInfo = this.getCurrentStep();
234                    
235                    if (newStepInfo && newStepInfo.current === currentStepInfo.current) {
236                        this.updateStatus('Step did not advance. Retrying...', 'warning');
237                        await new Promise(resolve => setTimeout(resolve, 2000));
238                    }
239                    
240                    // Safety check - if we're on step 5/5 and verify button is gone, we're done
241                    if (currentStepInfo.current === 5) {
242                        const verifyBtn = document.getElementById('verifyBtn');
243                        if (!verifyBtn || window.getComputedStyle(verifyBtn).display === 'none') {
244                            this.updateStatus('🎉 Key generation completed!', 'success');
245                            break;
246                        }
247                    }
248                }
249                
250            } catch (error) {
251                console.error('Automation error:', error);
252                this.updateStatus(`Error: ${error.message}`, 'error');
253            } finally {
254                this.isRunning = false;
255                this.updateStatus('Automation stopped.', 'info');
256            }
257        }
258
259        stop() {
260            if (this.isRunning) {
261                this.updateStatus('Stopping automation...', 'warning');
262                this.isRunning = false;
263            }
264        }
265    }
266
267    // Article Management Functions
268    class ArticleManager {
269        constructor() {
270            this.articles = [];
271        }
272
273        async collectAllArticles() {
274            console.log('Collecting all articles from page...');
275            const articleElements = document.querySelectorAll('.entry-list-item article.entry');
276            this.articles = [];
277
278            articleElements.forEach((article, index) => {
279                const titleElement = article.querySelector('.entry-title a');
280                const excerptElement = article.querySelector('.entry-summary, .entry-content');
281                const imageElement = article.querySelector('.post-thumbnail img');
282                const categoriesElements = article.querySelectorAll('.entry-taxonomies .category-links a');
283                const tagsElements = article.querySelectorAll('.entry-taxonomies .tag-links a');
284
285                const articleData = {
286                    index: index + 1,
287                    title: titleElement?.textContent?.trim() || 'No title',
288                    url: titleElement?.href || '',
289                    excerpt: excerptElement?.textContent?.trim()?.substring(0, 200) || 'No excerpt',
290                    image: imageElement?.src || '',
291                    categories: Array.from(categoriesElements).map(a => a.textContent.trim()),
292                    tags: Array.from(tagsElements).map(a => a.textContent.trim()),
293                    element: article
294                };
295
296                this.articles.push(articleData);
297            });
298
299            console.log(`Collected ${this.articles.length} articles`);
300            return this.articles;
301        }
302
303        async exportArticlesToJSON() {
304            await this.collectAllArticles();
305            const exportData = {
306                exportDate: new Date().toISOString(),
307                totalArticles: this.articles.length,
308                articles: this.articles.map(a => ({
309                    title: a.title,
310                    url: a.url,
311                    excerpt: a.excerpt,
312                    categories: a.categories,
313                    tags: a.tags,
314                    image: a.image
315                }))
316            };
317
318            const jsonString = JSON.stringify(exportData, null, 2);
319            const blob = new Blob([jsonString], { type: 'application/json' });
320            const url = URL.createObjectURL(blob);
321            const a = document.createElement('a');
322            a.href = url;
323            a.download = `vidyarays-articles-${new Date().toISOString().split('T')[0]}.json`;
324            document.body.appendChild(a);
325            a.click();
326            document.body.removeChild(a);
327            URL.revokeObjectURL(url);
328
329            console.log('Articles exported to JSON');
330            return exportData;
331        }
332
333        async exportArticlesToCSV() {
334            await this.collectAllArticles();
335            const headers = ['Index', 'Title', 'URL', 'Categories', 'Tags', 'Excerpt'];
336            const rows = this.articles.map(a => [
337                a.index,
338                `"${a.title.replace(/"/g, '""')}"`,
339                a.url,
340                `"${a.categories.join(', ')}"`,
341                `"${a.tags.join(', ')}"`,
342                `"${a.excerpt.replace(/"/g, '""')}"`
343            ]);
344
345            const csvContent = [headers.join(','), ...rows.map(r => r.join(','))].join('\n');
346            const blob = new Blob([csvContent], { type: 'text/csv' });
347            const url = URL.createObjectURL(blob);
348            const a = document.createElement('a');
349            a.href = url;
350            a.download = `vidyarays-articles-${new Date().toISOString().split('T')[0]}.csv`;
351            document.body.appendChild(a);
352            a.click();
353            document.body.removeChild(a);
354            URL.revokeObjectURL(url);
355
356            console.log('Articles exported to CSV');
357        }
358
359        async copyArticleTitles() {
360            await this.collectAllArticles();
361            const titles = this.articles.map(a => a.title).join('\n');
362            await GM.setClipboard(titles);
363            console.log('Article titles copied to clipboard');
364            return titles;
365        }
366
367        async copyArticleURLs() {
368            await this.collectAllArticles();
369            const urls = this.articles.map(a => a.url).join('\n');
370            await GM.setClipboard(urls);
371            console.log('Article URLs copied to clipboard');
372            return urls;
373        }
374
375        filterByCategory(category) {
376            return this.articles.filter(a => 
377                a.categories.some(cat => cat.toLowerCase().includes(category.toLowerCase()))
378            );
379        }
380
381        filterByTag(tag) {
382            return this.articles.filter(a => 
383                a.tags.some(t => t.toLowerCase().includes(tag.toLowerCase()))
384            );
385        }
386
387        async highlightArticlesByKeyword(keyword) {
388            await this.collectAllArticles();
389            const matchingArticles = this.articles.filter(a => 
390                a.title.toLowerCase().includes(keyword.toLowerCase()) ||
391                a.excerpt.toLowerCase().includes(keyword.toLowerCase())
392            );
393
394            // Remove previous highlights
395            document.querySelectorAll('.vr-toolkit-highlight').forEach(el => {
396                el.classList.remove('vr-toolkit-highlight');
397            });
398
399            // Add highlights
400            matchingArticles.forEach(article => {
401                article.element.classList.add('vr-toolkit-highlight');
402            });
403
404            console.log(`Highlighted ${matchingArticles.length} articles matching "${keyword}"`);
405            return matchingArticles;
406        }
407    }
408
409    // AI-Powered Content Analysis
410    class AIContentAnalyzer {
411        async analyzeArticle(articleData) {
412            console.log('Analyzing article with AI:', articleData.title);
413            
414            try {
415                const analysis = await RM.aiCall(
416                    `Analyze this article and provide insights:\n\nTitle: ${articleData.title}\n\nExcerpt: ${articleData.excerpt}\n\nCategories: ${articleData.categories.join(', ')}\n\nProvide a comprehensive analysis.`,
417                    {
418                        type: "json_schema",
419                        json_schema: {
420                            name: "article_analysis",
421                            schema: {
422                                type: "object",
423                                properties: {
424                                    sentiment: { 
425                                        type: "string", 
426                                        enum: ["positive", "neutral", "negative"] 
427                                    },
428                                    mainTopics: { 
429                                        type: "array", 
430                                        items: { type: "string" } 
431                                    },
432                                    targetAudience: { type: "string" },
433                                    readabilityLevel: { 
434                                        type: "string",
435                                        enum: ["beginner", "intermediate", "advanced"]
436                                    },
437                                    keyInsights: { 
438                                        type: "array", 
439                                        items: { type: "string" } 
440                                    },
441                                    suggestedImprovements: { 
442                                        type: "array", 
443                                        items: { type: "string" } 
444                                    },
445                                    seoScore: { 
446                                        type: "number",
447                                        minimum: 0,
448                                        maximum: 10
449                                    }
450                                },
451                                required: ["sentiment", "mainTopics", "targetAudience", "readabilityLevel"]
452                            }
453                        }
454                    }
455                );
456
457                console.log('AI Analysis complete:', analysis);
458                return analysis;
459            } catch (error) {
460                console.error('AI analysis failed:', error);
461                throw error;
462            }
463        }
464
465        async generateSummary(articleData) {
466            console.log('Generating AI summary for:', articleData.title);
467            
468            try {
469                const summary = await RM.aiCall(
470                    `Create a concise 2-3 sentence summary of this article:\n\nTitle: ${articleData.title}\n\nExcerpt: ${articleData.excerpt}`
471                );
472
473                console.log('AI Summary generated');
474                return summary;
475            } catch (error) {
476                console.error('AI summary generation failed:', error);
477                throw error;
478            }
479        }
480
481        async suggestTags(articleData) {
482            console.log('Generating tag suggestions for:', articleData.title);
483            
484            try {
485                const tagSuggestions = await RM.aiCall(
486                    `Suggest 5-10 relevant tags for this article:\n\nTitle: ${articleData.title}\n\nExcerpt: ${articleData.excerpt}\n\nExisting tags: ${articleData.tags.join(', ')}`,
487                    {
488                        type: "json_schema",
489                        json_schema: {
490                            name: "tag_suggestions",
491                            schema: {
492                                type: "object",
493                                properties: {
494                                    suggestedTags: { 
495                                        type: "array", 
496                                        items: { type: "string" } 
497                                    },
498                                    reasoning: { type: "string" }
499                                },
500                                required: ["suggestedTags"]
501                            }
502                        }
503                    }
504                );
505
506                console.log('Tag suggestions generated:', tagSuggestions);
507                return tagSuggestions;
508            } catch (error) {
509                console.error('Tag suggestion failed:', error);
510                throw error;
511            }
512        }
513
514        async batchAnalyzeArticles(articles) {
515            console.log(`Starting batch analysis of ${articles.length} articles...`);
516            const results = [];
517
518            for (let i = 0; i < articles.length; i++) {
519                try {
520                    const analysis = await this.analyzeArticle(articles[i]);
521                    results.push({
522                        article: articles[i],
523                        analysis: analysis
524                    });
525                    console.log(`Analyzed ${i + 1}/${articles.length} articles`);
526                } catch (error) {
527                    console.error(`Failed to analyze article ${i + 1}:`, error);
528                    results.push({
529                        article: articles[i],
530                        error: error.message
531                    });
532                }
533            }
534
535            return results;
536        }
537    }
538
539    // UI Panel Manager
540    class ToolkitUI {
541        constructor(articleManager, aiAnalyzer, keyGenAutomator) {
542            this.articleManager = articleManager;
543            this.aiAnalyzer = aiAnalyzer;
544            this.keyGenAutomator = keyGenAutomator;
545            this.panel = null;
546            this.isVisible = false;
547            
548            // Set up key gen status callback
549            this.keyGenAutomator.setStatusCallback((message, type) => {
550                this.showKeyGenStatus(message, type);
551            });
552        }
553
554        createPanel() {
555            // Create panel container
556            this.panel = document.createElement('div');
557            this.panel.id = 'vr-automation-toolkit';
558            this.panel.innerHTML = `
559                <div class="vr-toolkit-header">
560                    <h3>🚀 Vidya Rays Toolkit</h3>
561                    <button class="vr-toolkit-close" title="Close">×</button>
562                </div>
563                <div class="vr-toolkit-content">
564                    <div class="vr-toolkit-section">
565                        <h4>🔑 Key Generation Automation</h4>
566                        <button class="vr-toolkit-btn vr-toolkit-btn-keygen" data-action="start-keygen">Start Auto Key Generation</button>
567                        <button class="vr-toolkit-btn vr-toolkit-btn-stop" data-action="stop-keygen">Stop Automation</button>
568                        <div id="vr-keygen-status" class="vr-keygen-status">
569                            <p>Click "Start Auto Key Generation" to begin automated key generation process.</p>
570                        </div>
571                    </div>
572                
573                    <div class="vr-toolkit-section">
574                        <h4>📊 Article Management</h4>
575                        <button class="vr-toolkit-btn" data-action="collect">Collect All Articles</button>
576                        <button class="vr-toolkit-btn" data-action="export-json">Export to JSON</button>
577                        <button class="vr-toolkit-btn" data-action="export-csv">Export to CSV</button>
578                        <button class="vr-toolkit-btn" data-action="copy-titles">Copy Titles</button>
579                        <button class="vr-toolkit-btn" data-action="copy-urls">Copy URLs</button>
580                    </div>
581                    
582                    <div class="vr-toolkit-section">
583                        <h4>🔍 Search & Filter</h4>
584                        <input type="text" class="vr-toolkit-input" id="vr-keyword-input" placeholder="Enter keyword to highlight...">
585                        <button class="vr-toolkit-btn" data-action="highlight">Highlight Articles</button>
586                        <button class="vr-toolkit-btn" data-action="clear-highlight">Clear Highlights</button>
587                    </div>
588                    
589                    <div class="vr-toolkit-section">
590                        <h4>🤖 AI Analysis</h4>
591                        <button class="vr-toolkit-btn vr-toolkit-btn-ai" data-action="analyze-first">Analyze First Article</button>
592                        <button class="vr-toolkit-btn vr-toolkit-btn-ai" data-action="batch-analyze">Batch Analyze (First 3)</button>
593                        <button class="vr-toolkit-btn vr-toolkit-btn-ai" data-action="generate-summary">Generate Summary</button>
594                    </div>
595                    
596                    <div class="vr-toolkit-section">
597                        <h4>📈 Statistics</h4>
598                        <div id="vr-toolkit-stats" class="vr-toolkit-stats">
599                            <p>Click "Collect All Articles" to see stats</p>
600                        </div>
601                    </div>
602                    
603                    <div class="vr-toolkit-section">
604                        <h4>📋 Results</h4>
605                        <div id="vr-toolkit-results" class="vr-toolkit-results">
606                            <p>Results will appear here...</p>
607                        </div>
608                    </div>
609                </div>
610            `;
611
612            document.body.appendChild(this.panel);
613            this.attachEventListeners();
614            console.log('Toolkit UI panel created');
615        }
616
617        attachEventListeners() {
618            // Close button
619            this.panel.querySelector('.vr-toolkit-close').addEventListener('click', () => {
620                this.togglePanel();
621            });
622
623            // Action buttons
624            this.panel.querySelectorAll('[data-action]').forEach(btn => {
625                btn.addEventListener('click', async (e) => {
626                    const action = e.target.dataset.action;
627                    await this.handleAction(action, e.target);
628                });
629            });
630        }
631
632        async handleAction(action, button) {
633            // Handle key generation actions separately (no loading state)
634            if (action === 'start-keygen') {
635                this.keyGenAutomator.start();
636                return;
637            }
638            
639            if (action === 'stop-keygen') {
640                this.keyGenAutomator.stop();
641                return;
642            }
643            
644            // For other actions, show loading state
645            const originalText = button.textContent;
646            button.textContent = '⏳ Processing...';
647            button.disabled = true;
648
649            try {
650                switch (action) {
651                    case 'collect':
652                        await this.handleCollectArticles();
653                        break;
654                    case 'export-json':
655                        await this.articleManager.exportArticlesToJSON();
656                        this.showResult('✅ Articles exported to JSON successfully!');
657                        break;
658                    case 'export-csv':
659                        await this.articleManager.exportArticlesToCSV();
660                        this.showResult('✅ Articles exported to CSV successfully!');
661                        break;
662                    case 'copy-titles':
663                        await this.articleManager.copyArticleTitles();
664                        this.showResult('✅ Article titles copied to clipboard!');
665                        break;
666                    case 'copy-urls':
667                        await this.articleManager.copyArticleURLs();
668                        this.showResult('✅ Article URLs copied to clipboard!');
669                        break;
670                    case 'highlight':
671                        await this.handleHighlight();
672                        break;
673                    case 'clear-highlight':
674                        document.querySelectorAll('.vr-toolkit-highlight').forEach(el => {
675                            el.classList.remove('vr-toolkit-highlight');
676                        });
677                        this.showResult('✅ Highlights cleared!');
678                        break;
679                    case 'analyze-first':
680                        await this.handleAnalyzeFirst();
681                        break;
682                    case 'batch-analyze':
683                        await this.handleBatchAnalyze();
684                        break;
685                    case 'generate-summary':
686                        await this.handleGenerateSummary();
687                        break;
688                }
689            } catch (error) {
690                console.error('Action failed:', error);
691                this.showResult(`❌ Error: ${error.message}`);
692            } finally {
693                button.textContent = originalText;
694                button.disabled = false;
695            }
696        }
697
698        showKeyGenStatus(message, type) {
699            const statusDiv = document.getElementById('vr-keygen-status');
700            if (!statusDiv) return;
701            
702            const timestamp = new Date().toLocaleTimeString();
703            const icon = type === 'success' ? '✅' : type === 'error' ? '❌' : type === 'warning' ? '⚠️' : 'ℹ️';
704            const colorClass = type === 'success' ? 'status-success' : type === 'error' ? 'status-error' : type === 'warning' ? 'status-warning' : 'status-info';
705            
706            const statusLine = document.createElement('p');
707            statusLine.className = `status-line ${colorClass}`;
708            statusLine.innerHTML = `<span class="status-time">[${timestamp}]</span> ${icon} ${message}`;
709            
710            statusDiv.appendChild(statusLine);
711            
712            // Keep only last 10 messages
713            while (statusDiv.children.length > 10) {
714                statusDiv.removeChild(statusDiv.firstChild);
715            }
716            
717            // Auto-scroll to bottom
718            statusDiv.scrollTop = statusDiv.scrollHeight;
719        }
720
721        async handleCollectArticles() {
722            const articles = await this.articleManager.collectAllArticles();
723            
724            // Update statistics
725            const categories = {};
726            const tags = {};
727            
728            articles.forEach(article => {
729                article.categories.forEach(cat => {
730                    categories[cat] = (categories[cat] || 0) + 1;
731                });
732                article.tags.forEach(tag => {
733                    tags[tag] = (tags[tag] || 0) + 1;
734                });
735            });
736
737            const statsHTML = `
738                <p><strong>Total Articles:</strong> ${articles.length}</p>
739                <p><strong>Categories:</strong> ${Object.keys(categories).length}</p>
740                <p><strong>Top Categories:</strong> ${Object.entries(categories).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([cat, count]) => `${cat} (${count})`).join(', ')}</p>
741                <p><strong>Total Tags:</strong> ${Object.keys(tags).length}</p>
742            `;
743
744            document.getElementById('vr-toolkit-stats').innerHTML = statsHTML;
745            this.showResult(`✅ Collected ${articles.length} articles successfully!`);
746        }
747
748        async handleHighlight() {
749            const keyword = document.getElementById('vr-keyword-input').value.trim();
750            if (!keyword) {
751                this.showResult('⚠️ Please enter a keyword to highlight');
752                return;
753            }
754
755            const matches = await this.articleManager.highlightArticlesByKeyword(keyword);
756            this.showResult(`✅ Highlighted ${matches.length} articles matching "${keyword}"`);
757        }
758
759        async handleAnalyzeFirst() {
760            await this.articleManager.collectAllArticles();
761            if (this.articleManager.articles.length === 0) {
762                this.showResult('⚠️ No articles found on this page');
763                return;
764            }
765
766            const firstArticle = this.articleManager.articles[0];
767            const analysis = await this.aiAnalyzer.analyzeArticle(firstArticle);
768
769            const resultHTML = `
770                <h5>📊 Analysis: ${firstArticle.title}</h5>
771                <p><strong>Sentiment:</strong> ${analysis.sentiment}</p>
772                <p><strong>Target Audience:</strong> ${analysis.targetAudience}</p>
773                <p><strong>Readability:</strong> ${analysis.readabilityLevel}</p>
774                <p><strong>SEO Score:</strong> ${analysis.seoScore || 'N/A'}/10</p>
775                <p><strong>Main Topics:</strong> ${analysis.mainTopics.join(', ')}</p>
776                ${analysis.keyInsights ? `<p><strong>Key Insights:</strong></p><ul>${analysis.keyInsights.map(i => `<li>${i}</li>`).join('')}</ul>` : ''}
777            `;
778
779            this.showResult(resultHTML);
780        }
781
782        async handleBatchAnalyze() {
783            await this.articleManager.collectAllArticles();
784            const articlesToAnalyze = this.articleManager.articles.slice(0, 3);
785            
786            if (articlesToAnalyze.length === 0) {
787                this.showResult('⚠️ No articles found on this page');
788                return;
789            }
790
791            this.showResult(`🔄 Analyzing ${articlesToAnalyze.length} articles... This may take a moment.`);
792            
793            const results = await this.aiAnalyzer.batchAnalyzeArticles(articlesToAnalyze);
794            
795            const resultHTML = `
796                <h5>📊 Batch Analysis Results</h5>
797                ${results.map((result, index) => `
798                    <div class="vr-analysis-result">
799                        <h6>${index + 1}. ${result.article.title}</h6>
800                        ${result.error ? `<p class="error">❌ ${result.error}</p>` : `
801                            <p><strong>Sentiment:</strong> ${result.analysis.sentiment} | 
802                            <strong>Level:</strong> ${result.analysis.readabilityLevel} | 
803                            <strong>SEO:</strong> ${result.analysis.seoScore || 'N/A'}/10</p>
804                            <p><strong>Topics:</strong> ${result.analysis.mainTopics.join(', ')}</p>
805                        `}
806                    </div>
807                `).join('')}
808            `;
809
810            this.showResult(resultHTML);
811        }
812
813        async handleGenerateSummary() {
814            await this.articleManager.collectAllArticles();
815            if (this.articleManager.articles.length === 0) {
816                this.showResult('⚠️ No articles found on this page');
817                return;
818            }
819
820            const firstArticle = this.articleManager.articles[0];
821            const summary = await this.aiAnalyzer.generateSummary(firstArticle);
822
823            const resultHTML = `
824                <h5>📝 AI Summary</h5>
825                <h6>${firstArticle.title}</h6>
826                <p>${summary}</p>
827            `;
828
829            this.showResult(resultHTML);
830        }
831
832        showResult(html) {
833            const resultsDiv = document.getElementById('vr-toolkit-results');
834            resultsDiv.innerHTML = html;
835        }
836
837        togglePanel() {
838            this.isVisible = !this.isVisible;
839            this.panel.style.display = this.isVisible ? 'block' : 'none';
840        }
841
842        createToggleButton() {
843            const button = document.createElement('button');
844            button.id = 'vr-toolkit-toggle';
845            button.innerHTML = '🚀';
846            button.title = 'Open Vidya Rays Automation Toolkit';
847            button.addEventListener('click', () => this.togglePanel());
848            document.body.appendChild(button);
849            console.log('Toolkit toggle button created');
850        }
851
852        addStyles() {
853            const styles = `
854                #vr-automation-toolkit {
855                    position: fixed;
856                    top: 50%;
857                    right: 20px;
858                    transform: translateY(-50%);
859                    width: 420px;
860                    max-height: 90vh;
861                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
862                    border-radius: 16px;
863                    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
864                    z-index: 999999;
865                    display: none;
866                    overflow: hidden;
867                    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
868                }
869
870                .vr-toolkit-header {
871                    background: rgba(255, 255, 255, 0.1);
872                    padding: 16px 20px;
873                    display: flex;
874                    justify-content: space-between;
875                    align-items: center;
876                    border-bottom: 1px solid rgba(255, 255, 255, 0.2);
877                }
878
879                .vr-toolkit-header h3 {
880                    margin: 0;
881                    color: #ffffff;
882                    font-size: 18px;
883                    font-weight: 600;
884                }
885
886                .vr-toolkit-close {
887                    background: rgba(255, 255, 255, 0.2);
888                    border: none;
889                    color: #ffffff;
890                    font-size: 24px;
891                    width: 32px;
892                    height: 32px;
893                    border-radius: 50%;
894                    cursor: pointer;
895                    display: flex;
896                    align-items: center;
897                    justify-content: center;
898                    transition: all 0.3s ease;
899                }
900
901                .vr-toolkit-close:hover {
902                    background: rgba(255, 255, 255, 0.3);
903                    transform: rotate(90deg);
904                }
905
906                .vr-toolkit-content {
907                    padding: 20px;
908                    max-height: calc(90vh - 70px);
909                    overflow-y: auto;
910                    background: #ffffff;
911                }
912
913                .vr-toolkit-content::-webkit-scrollbar {
914                    width: 8px;
915                }
916
917                .vr-toolkit-content::-webkit-scrollbar-track {
918                    background: #f1f1f1;
919                }
920
921                .vr-toolkit-content::-webkit-scrollbar-thumb {
922                    background: #667eea;
923                    border-radius: 4px;
924                }
925
926                .vr-toolkit-section {
927                    margin-bottom: 24px;
928                    padding-bottom: 20px;
929                    border-bottom: 1px solid #e0e0e0;
930                }
931
932                .vr-toolkit-section:last-child {
933                    border-bottom: none;
934                }
935
936                .vr-toolkit-section h4 {
937                    margin: 0 0 12px 0;
938                    color: #333333;
939                    font-size: 14px;
940                    font-weight: 600;
941                    text-transform: uppercase;
942                    letter-spacing: 0.5px;
943                }
944
945                .vr-toolkit-btn {
946                    width: 100%;
947                    padding: 10px 16px;
948                    margin-bottom: 8px;
949                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
950                    color: #ffffff;
951                    border: none;
952                    border-radius: 8px;
953                    font-size: 13px;
954                    font-weight: 500;
955                    cursor: pointer;
956                    transition: all 0.3s ease;
957                    box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
958                }
959
960                .vr-toolkit-btn:hover {
961                    transform: translateY(-2px);
962                    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
963                }
964
965                .vr-toolkit-btn:active {
966                    transform: translateY(0);
967                }
968
969                .vr-toolkit-btn:disabled {
970                    opacity: 0.6;
971                    cursor: not-allowed;
972                    transform: none;
973                }
974
975                .vr-toolkit-btn-keygen {
976                    background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
977                    box-shadow: 0 2px 8px rgba(17, 153, 142, 0.3);
978                }
979
980                .vr-toolkit-btn-keygen:hover {
981                    box-shadow: 0 4px 12px rgba(17, 153, 142, 0.4);
982                }
983
984                .vr-toolkit-btn-stop {
985                    background: linear-gradient(135deg, #ee0979 0%, #ff6a00 100%);
986                    box-shadow: 0 2px 8px rgba(238, 9, 121, 0.3);
987                }
988
989                .vr-toolkit-btn-stop:hover {
990                    box-shadow: 0 4px 12px rgba(238, 9, 121, 0.4);
991                }
992
993                .vr-toolkit-btn-ai {
994                    background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
995                    box-shadow: 0 2px 8px rgba(245, 87, 108, 0.3);
996                }
997
998                .vr-toolkit-btn-ai:hover {
999                    box-shadow: 0 4px 12px rgba(245, 87, 108, 0.4);
1000                }
1001
1002                .vr-toolkit-input {
1003                    width: 100%;
1004                    padding: 10px 12px;
1005                    margin-bottom: 8px;
1006                    border: 2px solid #e0e0e0;
1007                    border-radius: 8px;
1008                    font-size: 13px;
1009                    transition: border-color 0.3s ease;
1010                    box-sizing: border-box;
1011                }
1012
1013                .vr-toolkit-input:focus {
1014                    outline: none;
1015                    border-color: #667eea;
1016                }
1017
1018                .vr-keygen-status {
1019                    background: #f8f9fa;
1020                    padding: 12px;
1021                    border-radius: 8px;
1022                    font-size: 12px;
1023                    color: #333333;
1024                    max-height: 200px;
1025                    overflow-y: auto;
1026                    font-family: 'Courier New', monospace;
1027                }
1028
1029                .vr-keygen-status::-webkit-scrollbar {
1030                    width: 6px;
1031                }
1032
1033                .vr-keygen-status::-webkit-scrollbar-thumb {
1034                    background: #667eea;
1035                    border-radius: 3px;
1036                }
1037
1038                .status-line {
1039                    margin: 4px 0;
1040                    padding: 4px 8px;
1041                    border-radius: 4px;
1042                    line-height: 1.4;
1043                }
1044
1045                .status-time {
1046                    color: #666;
1047                    font-size: 11px;
1048                }
1049
1050                .status-success {
1051                    background: #d4edda;
1052                    color: #155724;
1053                }
1054
1055                .status-error {
1056                    background: #f8d7da;
1057                    color: #721c24;
1058                }
1059
1060                .status-warning {
1061                    background: #fff3cd;
1062                    color: #856404;
1063                }
1064
1065                .status-info {
1066                    background: #d1ecf1;
1067                    color: #0c5460;
1068                }
1069
1070                .vr-toolkit-stats {
1071                    background: #f8f9fa;
1072                    padding: 12px;
1073                    border-radius: 8px;
1074                    font-size: 13px;
1075                    color: #333333;
1076                }
1077
1078                .vr-toolkit-stats p {
1079                    margin: 6px 0;
1080                }
1081
1082                .vr-toolkit-results {
1083                    background: #f8f9fa;
1084                    padding: 12px;
1085                    border-radius: 8px;
1086                    font-size: 13px;
1087                    color: #333333;
1088                    max-height: 300px;
1089                    overflow-y: auto;
1090                }
1091
1092                .vr-toolkit-results h5 {
1093                    margin: 0 0 12px 0;
1094                    color: #667eea;
1095                    font-size: 14px;
1096                }
1097
1098                .vr-toolkit-results h6 {
1099                    margin: 8px 0 6px 0;
1100                    color: #333333;
1101                    font-size: 13px;
1102                }
1103
1104                .vr-toolkit-results p {
1105                    margin: 6px 0;
1106                    line-height: 1.5;
1107                }
1108
1109                .vr-toolkit-results ul {
1110                    margin: 6px 0;
1111                    padding-left: 20px;
1112                }
1113
1114                .vr-toolkit-results li {
1115                    margin: 4px 0;
1116                }
1117
1118                .vr-analysis-result {
1119                    background: #ffffff;
1120                    padding: 12px;
1121                    margin-bottom: 12px;
1122                    border-radius: 8px;
1123                    border-left: 4px solid #667eea;
1124                }
1125
1126                .vr-analysis-result .error {
1127                    color: #f5576c;
1128                }
1129
1130                #vr-toolkit-toggle {
1131                    position: fixed;
1132                    bottom: 30px;
1133                    right: 30px;
1134                    width: 60px;
1135                    height: 60px;
1136                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1137                    border: none;
1138                    border-radius: 50%;
1139                    font-size: 28px;
1140                    cursor: pointer;
1141                    box-shadow: 0 8px 24px rgba(102, 126, 234, 0.4);
1142                    z-index: 999998;
1143                    transition: all 0.3s ease;
1144                }
1145
1146                #vr-toolkit-toggle:hover {
1147                    transform: scale(1.1) rotate(10deg);
1148                    box-shadow: 0 12px 32px rgba(102, 126, 234, 0.5);
1149                }
1150
1151                .vr-toolkit-highlight {
1152                    outline: 3px solid #f5576c !important;
1153                    outline-offset: 4px;
1154                    background: rgba(245, 87, 108, 0.1) !important;
1155                    transition: all 0.3s ease;
1156                }
1157            `;
1158
1159            const styleElement = document.createElement('style');
1160            styleElement.textContent = styles;
1161            document.head.appendChild(styleElement);
1162            console.log('Toolkit styles added');
1163        }
1164    }
1165
1166    // Initialize the toolkit
1167    function init() {
1168        console.log('Initializing Vidya Rays Automation Toolkit...');
1169
1170        // Wait for page to be ready
1171        if (document.readyState === 'loading') {
1172            document.addEventListener('DOMContentLoaded', init);
1173            return;
1174        }
1175
1176        // Create instances
1177        const articleManager = new ArticleManager();
1178        const aiAnalyzer = new AIContentAnalyzer();
1179        const keyGenAutomator = new KeyGenerationAutomator();
1180        const toolkitUI = new ToolkitUI(articleManager, aiAnalyzer, keyGenAutomator);
1181
1182        // Initialize UI
1183        toolkitUI.addStyles();
1184        toolkitUI.createPanel();
1185        toolkitUI.createToggleButton();
1186
1187        console.log('✅ Vidya Rays Automation Toolkit ready!');
1188
1189        // Make instances available globally for debugging
1190        unsafeWindow.VRToolkit = {
1191            articleManager,
1192            aiAnalyzer,
1193            keyGenAutomator,
1194            toolkitUI
1195        };
1196    }
1197
1198    // Start initialization
1199    init();
1200
1201})();
Vidya Rays Automation Toolkit | Robomonkey