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