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})();