Telegram AI Content Curator for Business Owners

Monitors Telegram channels, identifies AI & automation updates, and rewrites them for business owners

Size

52.7 KB

Version

1.1.1

Created

Feb 4, 2026

Updated

14 days ago

1// ==UserScript==
2// @name		Telegram AI Content Curator for Business Owners
3// @description		Monitors Telegram channels, identifies AI & automation updates, and rewrites them for business owners
4// @version		1.1.1
5// @match		https://*.web.telegram.org/*
6// @icon		https://web.telegram.org/a/favicon-unread.svg
7// @grant		GM.getValue
8// @grant		GM.setValue
9// @grant		GM.deleteValue
10// @grant		GM.listValues
11// ==/UserScript==
12(function() {
13    'use strict';
14
15    console.log('🚀 Telegram AI Content Curator initialized');
16
17    // ===== UTILITY FUNCTIONS =====
18    
19    function debounce(func, wait) {
20        let timeout;
21        return function executedFunction(...args) {
22            const later = () => {
23                clearTimeout(timeout);
24                func(...args);
25            };
26            clearTimeout(timeout);
27            timeout = setTimeout(later, wait);
28        };
29    }
30
31    // ===== DATA MANAGEMENT =====
32    
33    async function saveUpdate(update) {
34        const updates = await GM.getValue('telegram_updates', []);
35        updates.unshift(update);
36        await GM.setValue('telegram_updates', updates);
37        console.log('💾 Update saved:', update.id);
38        return update;
39    }
40
41    async function getUpdates() {
42        return await GM.getValue('telegram_updates', []);
43    }
44
45    async function updateStatus(updateId, newStatus) {
46        const updates = await GM.getValue('telegram_updates', []);
47        const update = updates.find(u => u.id === updateId);
48        if (update) {
49            update.status = newStatus;
50            update.statusChangedAt = new Date().toISOString();
51            await GM.setValue('telegram_updates', updates);
52            console.log(`✅ Status updated for ${updateId}: ${newStatus}`);
53        }
54    }
55
56    async function deleteUpdate(updateId) {
57        const updates = await GM.getValue('telegram_updates', []);
58        const filtered = updates.filter(u => u.id !== updateId);
59        await GM.setValue('telegram_updates', filtered);
60        console.log(`🗑️ Update deleted: ${updateId}`);
61    }
62
63    async function updateEditedContent(updateId, editedContent) {
64        const updates = await GM.getValue('telegram_updates', []);
65        const update = updates.find(u => u.id === updateId);
66        if (update) {
67            update.editedContent = editedContent;
68            update.lastEditedAt = new Date().toISOString();
69            await GM.setValue('telegram_updates', updates);
70            console.log(`✏️ Content edited for ${updateId}`);
71        }
72    }
73
74    // ===== AI PROCESSING =====
75    
76    async function classifyContent(messageText, channelName) {
77        console.log('🤖 Classifying content with AI...');
78        
79        try {
80            const prompt = `אני צריכה שתסווג את ההודעה הבאה מערוץ טלגרם "${channelName}".
81
82ההודעה:
83"""
84${messageText}
85"""
86
87סווג את ההודעה לפי הקריטריונים הבאים:
88
89**כלול רק אם מתקיים לפחות אחד:**
90- הצגת כלי AI או אוטומציה חדש
91- שיפור משמעותי לכלי קיים
92- דוגמה לשימוש עסקי ב-AI
93- אוטומציה שחוסכת זמן, כסף או כוח אדם
94- חיבור בין AI לתהליכים עסקיים יומיומיים
95
96**פסול אם מתקיים אחד מהבאים:**
97- תוכן טכני למפתחים בלבד
98- קוד, API או ארכיטקטורה ללא הקשר עסקי
99- חדשות כלליות ללא שימוש מעשי
100- ספקולציות, שמועות או הייפ
101- תוכן שאינו רלוונטי לעסקים קטנים ובינוניים
102
103החזר את התשובה בפורמט JSON.`;
104
105            const classification = await RM.aiCall(prompt, {
106                type: 'json_schema',
107                json_schema: {
108                    name: 'content_classification',
109                    schema: {
110                        type: 'object',
111                        properties: {
112                            isRelevant: { 
113                                type: 'boolean',
114                                description: 'האם התוכן רלוונטי לבעלות העסק'
115                            },
116                            relevanceReason: { 
117                                type: 'string',
118                                description: 'הסבר קצר למה התוכן רלוונטי או לא'
119                            },
120                            category: { 
121                                type: 'string',
122                                enum: ['כלי חדש', 'שיפור כלי קיים', 'דוגמה עסקית', 'אוטומציה', 'חיבור AI לעסק', 'לא רלוונטי']
123                            },
124                            businessValue: { 
125                                type: 'string',
126                                enum: ['גבוה', 'בינוני', 'נמוך']
127                            }
128                        },
129                        required: ['isRelevant', 'relevanceReason', 'category', 'businessValue']
130                    }
131                }
132            });
133
134            console.log('✅ Classification result:', classification);
135            return classification;
136        } catch (error) {
137            console.error('❌ AI classification failed:', error);
138            return {
139                isRelevant: false,
140                relevanceReason: 'שגיאה בסיווג',
141                category: 'לא רלוונטי',
142                businessValue: 'נמוך'
143            };
144        }
145    }
146
147    async function analyzeBusinessValue(messageText, classification) {
148        console.log('🤖 Analyzing business value with AI...');
149        
150        try {
151            const prompt = `נתחה את הערך העסקי של העדכון הבא:
152
153"""
154${messageText}
155"""
156
157קטגוריה: ${classification.category}
158רמת ערך: ${classification.businessValue}
159
160ספק ניתוח מפורט:`;
161
162            const analysis = await RM.aiCall(prompt, {
163                type: 'json_schema',
164                json_schema: {
165                    name: 'business_value_analysis',
166                    schema: {
167                        type: 'object',
168                        properties: {
169                            mainInnovation: { 
170                                type: 'string',
171                                description: 'מה החידוש המרכזי'
172                            },
173                            targetAudience: { 
174                                type: 'string',
175                                description: 'למי זה רלוונטי כבעלת עסק'
176                            },
177                            businessProcess: { 
178                                type: 'string',
179                                description: 'איזה תהליך עסקי זה משפר'
180                            },
181                            practicalValue: { 
182                                type: 'string',
183                                description: 'מה הערך המעשי והיישומי'
184                            },
185                            keyBenefits: {
186                                type: 'array',
187                                items: { type: 'string' },
188                                description: '3-5 נקודות בולטות של ערך עסקי',
189                                minItems: 3,
190                                maxItems: 5
191                            }
192                        },
193                        required: ['mainInnovation', 'targetAudience', 'businessProcess', 'practicalValue', 'keyBenefits']
194                    }
195                }
196            });
197
198            console.log('✅ Business value analysis:', analysis);
199            return analysis;
200        } catch (error) {
201            console.error('❌ Business value analysis failed:', error);
202            return null;
203        }
204    }
205
206    async function rewriteForBusinessOwners(messageText, analysis) {
207        console.log('🤖 Rewriting content for business owners...');
208        
209        try {
210            const prompt = `שכתב את התוכן הבא לקהילת בעלות עסקים:
211
212תוכן מקורי:
213"""
214${messageText}
215"""
216
217ניתוח ערך עסקי:
218- חידוש מרכזי: ${analysis.mainInnovation}
219- קהל יעד: ${analysis.targetAudience}
220- תהליך עסקי: ${analysis.businessProcess}
221- ערך מעשי: ${analysis.practicalValue}
222
223כללי כתיבה:
224- שפה פשוטה וברורה
225- ללא מונחים טכניים אלא אם הכרחי
226- פנייה לבעלות עסקים
227- מיקוד בתוצאה ולא בטכנולוגיה
228- טון קהילתי, נגיש ומעורר סקרנות
229
230הטקסט חייב לענות על:
231- למה זה חשוב לי כבעלת עסק
232- איך אני יכולה להשתמש בזה בפועל
233- מה יוצא לי מזה עכשיו
234
235צור תוכן מעובד:`;
236
237            const rewritten = await RM.aiCall(prompt, {
238                type: 'json_schema',
239                json_schema: {
240                    name: 'rewritten_content',
241                    schema: {
242                        type: 'object',
243                        properties: {
244                            communityPost: { 
245                                type: 'string',
246                                description: 'תקציר קצר בגובה פוסט קהילה'
247                            },
248                            telegramMessage: { 
249                                type: 'string',
250                                description: 'ניסוח קצר שמתאים להודעת טלגרם או סטורי'
251                            },
252                            callToAction: { 
253                                type: 'string',
254                                description: 'שאלה או קריאה לפעולה שמעודדת דיון בקהילה'
255                            }
256                        },
257                        required: ['communityPost', 'telegramMessage', 'callToAction']
258                    }
259                }
260            });
261
262            console.log('✅ Content rewritten:', rewritten);
263            return rewritten;
264        } catch (error) {
265            console.error('❌ Content rewriting failed:', error);
266            return null;
267        }
268    }
269
270    async function processMessage(messageText, channelName, messageUrl) {
271        console.log('🔄 Processing new message...');
272        
273        // Step 1: Classify
274        const classification = await classifyContent(messageText, channelName);
275        
276        if (!classification.isRelevant) {
277            console.log('⏭️ Message not relevant, skipping');
278            return null;
279        }
280
281        // Step 2: Analyze business value
282        const analysis = await analyzeBusinessValue(messageText, classification);
283        
284        if (!analysis) {
285            console.log('⚠️ Failed to analyze business value');
286            return null;
287        }
288
289        // Step 3: Rewrite content
290        const rewritten = await rewriteForBusinessOwners(messageText, analysis);
291        
292        if (!rewritten) {
293            console.log('⚠️ Failed to rewrite content');
294            return null;
295        }
296
297        // Step 4: Create update object
298        const update = {
299            id: `update_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
300            originalText: messageText,
301            channelName: channelName,
302            messageUrl: messageUrl,
303            classification: classification,
304            analysis: analysis,
305            rewritten: rewritten,
306            status: 'new',
307            priority: classification.businessValue === 'גבוה' ? 'high' : 'normal',
308            createdAt: new Date().toISOString(),
309            statusChangedAt: new Date().toISOString()
310        };
311
312        // Step 5: Save
313        await saveUpdate(update);
314        
315        console.log('✅ Message processed successfully');
316        return update;
317    }
318
319    // ===== UI COMPONENTS =====
320    
321    function createMainUI() {
322        const container = document.createElement('div');
323        container.id = 'telegram-curator-panel';
324        container.innerHTML = `
325            <div class="curator-header">
326                <h2>🤖 AI Content Curator</h2>
327                <div class="curator-actions">
328                    <button id="curator-refresh-btn" class="curator-btn curator-btn-primary">
329                        🔄 רענן
330                    </button>
331                    <button id="curator-toggle-btn" class="curator-btn curator-btn-secondary">
332                        ➖ מזער
333                    </button>
334                </div>
335            </div>
336            <div class="curator-filters">
337                <button class="curator-filter-btn active" data-filter="all">הכל</button>
338                <button class="curator-filter-btn" data-filter="new">חדש</button>
339                <button class="curator-filter-btn" data-filter="approved">אושר</button>
340                <button class="curator-filter-btn" data-filter="rejected">נדחה</button>
341                <button class="curator-filter-btn" data-filter="high">עדיפות גבוהה</button>
342            </div>
343            <div id="curator-updates-list" class="curator-updates-list">
344                <div class="curator-loading">טוען עדכונים...</div>
345            </div>
346        `;
347
348        // Add styles
349        const styles = `
350            #telegram-curator-panel {
351                position: fixed;
352                top: 20px;
353                left: 20px;
354                width: 450px;
355                max-height: 80vh;
356                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
357                border-radius: 16px;
358                box-shadow: 0 20px 60px rgba(0,0,0,0.3);
359                z-index: 999999;
360                display: flex;
361                flex-direction: column;
362                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
363                overflow: hidden;
364                transition: all 0.3s ease;
365            }
366
367            #telegram-curator-panel.minimized {
368                max-height: 60px;
369            }
370
371            #telegram-curator-panel.minimized .curator-filters,
372            #telegram-curator-panel.minimized .curator-updates-list {
373                display: none;
374            }
375
376            .curator-header {
377                padding: 16px 20px;
378                background: rgba(255,255,255,0.1);
379                backdrop-filter: blur(10px);
380                display: flex;
381                justify-content: space-between;
382                align-items: center;
383                border-bottom: 1px solid rgba(255,255,255,0.2);
384            }
385
386            .curator-header h2 {
387                margin: 0;
388                color: white;
389                font-size: 18px;
390                font-weight: 600;
391            }
392
393            .curator-actions {
394                display: flex;
395                gap: 8px;
396            }
397
398            .curator-btn {
399                padding: 8px 16px;
400                border: none;
401                border-radius: 8px;
402                cursor: pointer;
403                font-size: 14px;
404                font-weight: 500;
405                transition: all 0.2s;
406            }
407
408            .curator-btn-primary {
409                background: white;
410                color: #667eea;
411            }
412
413            .curator-btn-primary:hover {
414                transform: translateY(-2px);
415                box-shadow: 0 4px 12px rgba(255,255,255,0.3);
416            }
417
418            .curator-btn-secondary {
419                background: rgba(255,255,255,0.2);
420                color: white;
421            }
422
423            .curator-btn-secondary:hover {
424                background: rgba(255,255,255,0.3);
425            }
426
427            .curator-filters {
428                padding: 12px 20px;
429                display: flex;
430                gap: 8px;
431                flex-wrap: wrap;
432                background: rgba(255,255,255,0.05);
433            }
434
435            .curator-filter-btn {
436                padding: 6px 14px;
437                border: 1px solid rgba(255,255,255,0.3);
438                background: transparent;
439                color: white;
440                border-radius: 20px;
441                cursor: pointer;
442                font-size: 13px;
443                transition: all 0.2s;
444            }
445
446            .curator-filter-btn:hover {
447                background: rgba(255,255,255,0.1);
448            }
449
450            .curator-filter-btn.active {
451                background: white;
452                color: #667eea;
453                border-color: white;
454            }
455
456            .curator-updates-list {
457                flex: 1;
458                overflow-y: auto;
459                padding: 16px;
460            }
461
462            .curator-loading {
463                text-align: center;
464                color: white;
465                padding: 40px 20px;
466                font-size: 14px;
467            }
468
469            .curator-update-card {
470                background: white;
471                border-radius: 12px;
472                padding: 16px;
473                margin-bottom: 12px;
474                box-shadow: 0 4px 12px rgba(0,0,0,0.1);
475                transition: all 0.2s;
476            }
477
478            .curator-update-card:hover {
479                transform: translateY(-2px);
480                box-shadow: 0 8px 20px rgba(0,0,0,0.15);
481            }
482
483            .curator-update-header {
484                display: flex;
485                justify-content: space-between;
486                align-items: flex-start;
487                margin-bottom: 12px;
488            }
489
490            .curator-update-meta {
491                flex: 1;
492            }
493
494            .curator-channel-name {
495                font-weight: 600;
496                color: #667eea;
497                font-size: 14px;
498                margin-bottom: 4px;
499            }
500
501            .curator-update-time {
502                font-size: 12px;
503                color: #999;
504            }
505
506            .curator-badges {
507                display: flex;
508                gap: 6px;
509                flex-wrap: wrap;
510            }
511
512            .curator-badge {
513                padding: 4px 10px;
514                border-radius: 12px;
515                font-size: 11px;
516                font-weight: 500;
517            }
518
519            .curator-badge-new {
520                background: #4ade80;
521                color: white;
522            }
523
524            .curator-badge-approved {
525                background: #3b82f6;
526                color: white;
527            }
528
529            .curator-badge-rejected {
530                background: #ef4444;
531                color: white;
532            }
533
534            .curator-badge-high {
535                background: #f59e0b;
536                color: white;
537            }
538
539            .curator-badge-category {
540                background: #e5e7eb;
541                color: #374151;
542            }
543
544            .curator-content-section {
545                margin: 12px 0;
546            }
547
548            .curator-section-title {
549                font-size: 12px;
550                font-weight: 600;
551                color: #6b7280;
552                margin-bottom: 6px;
553                text-transform: uppercase;
554            }
555
556            .curator-original-text {
557                font-size: 13px;
558                color: #4b5563;
559                background: #f9fafb;
560                padding: 10px;
561                border-radius: 8px;
562                border-right: 3px solid #667eea;
563                max-height: 80px;
564                overflow-y: auto;
565                line-height: 1.5;
566            }
567
568            .curator-rewritten-text {
569                font-size: 14px;
570                color: #1f2937;
571                background: #f0fdf4;
572                padding: 12px;
573                border-radius: 8px;
574                border-right: 3px solid #4ade80;
575                line-height: 1.6;
576                white-space: pre-wrap;
577            }
578
579            .curator-benefits-list {
580                list-style: none;
581                padding: 0;
582                margin: 8px 0;
583            }
584
585            .curator-benefits-list li {
586                padding: 6px 0;
587                font-size: 13px;
588                color: #374151;
589                display: flex;
590                align-items: flex-start;
591            }
592
593            .curator-benefits-list li:before {
594                content: "✓";
595                color: #4ade80;
596                font-weight: bold;
597                margin-left: 8px;
598                flex-shrink: 0;
599            }
600
601            .curator-update-actions {
602                display: flex;
603                gap: 8px;
604                margin-top: 12px;
605                padding-top: 12px;
606                border-top: 1px solid #e5e7eb;
607            }
608
609            .curator-action-btn {
610                flex: 1;
611                padding: 8px 12px;
612                border: none;
613                border-radius: 8px;
614                cursor: pointer;
615                font-size: 13px;
616                font-weight: 500;
617                transition: all 0.2s;
618            }
619
620            .curator-action-btn-approve {
621                background: #3b82f6;
622                color: white;
623            }
624
625            .curator-action-btn-approve:hover {
626                background: #2563eb;
627            }
628
629            .curator-action-btn-reject {
630                background: #ef4444;
631                color: white;
632            }
633
634            .curator-action-btn-reject:hover {
635                background: #dc2626;
636            }
637
638            .curator-action-btn-copy {
639                background: #10b981;
640                color: white;
641            }
642
643            .curator-action-btn-copy:hover {
644                background: #059669;
645            }
646
647            .curator-action-btn-edit {
648                background: #f59e0b;
649                color: white;
650            }
651
652            .curator-action-btn-edit:hover {
653                background: #d97706;
654            }
655
656            .curator-action-btn-delete {
657                background: #6b7280;
658                color: white;
659            }
660
661            .curator-action-btn-delete:hover {
662                background: #4b5563;
663            }
664
665            .curator-empty-state {
666                text-align: center;
667                padding: 40px 20px;
668                color: white;
669            }
670
671            .curator-empty-state-icon {
672                font-size: 48px;
673                margin-bottom: 16px;
674            }
675
676            .curator-empty-state-text {
677                font-size: 16px;
678                margin-bottom: 8px;
679            }
680
681            .curator-empty-state-subtext {
682                font-size: 13px;
683                opacity: 0.8;
684            }
685
686            .curator-edit-modal {
687                position: fixed;
688                top: 0;
689                left: 0;
690                right: 0;
691                bottom: 0;
692                background: rgba(0,0,0,0.7);
693                display: flex;
694                align-items: center;
695                justify-content: center;
696                z-index: 1000000;
697            }
698
699            .curator-edit-content {
700                background: white;
701                border-radius: 16px;
702                padding: 24px;
703                width: 90%;
704                max-width: 600px;
705                max-height: 80vh;
706                overflow-y: auto;
707            }
708
709            .curator-edit-header {
710                display: flex;
711                justify-content: space-between;
712                align-items: center;
713                margin-bottom: 20px;
714            }
715
716            .curator-edit-title {
717                font-size: 20px;
718                font-weight: 600;
719                color: #1f2937;
720            }
721
722            .curator-edit-close {
723                background: none;
724                border: none;
725                font-size: 24px;
726                cursor: pointer;
727                color: #6b7280;
728            }
729
730            .curator-edit-textarea {
731                width: 100%;
732                min-height: 200px;
733                padding: 12px;
734                border: 2px solid #e5e7eb;
735                border-radius: 8px;
736                font-size: 14px;
737                font-family: inherit;
738                resize: vertical;
739                margin-bottom: 16px;
740            }
741
742            .curator-edit-textarea:focus {
743                outline: none;
744                border-color: #667eea;
745            }
746
747            .curator-edit-actions {
748                display: flex;
749                gap: 12px;
750                justify-content: flex-end;
751            }
752
753            .curator-updates-list::-webkit-scrollbar {
754                width: 8px;
755            }
756
757            .curator-updates-list::-webkit-scrollbar-track {
758                background: rgba(255,255,255,0.1);
759                border-radius: 4px;
760            }
761
762            .curator-updates-list::-webkit-scrollbar-thumb {
763                background: rgba(255,255,255,0.3);
764                border-radius: 4px;
765            }
766
767            .curator-updates-list::-webkit-scrollbar-thumb:hover {
768                background: rgba(255,255,255,0.5);
769            }
770            
771            /* Hover Tooltip Styles */
772            .curator-hover-tooltip {
773                position: fixed;
774                background: white;
775                border-radius: 12px;
776                box-shadow: 0 10px 40px rgba(0,0,0,0.2);
777                z-index: 1000000;
778                max-width: 400px;
779                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
780                animation: tooltipFadeIn 0.2s ease;
781            }
782            
783            @keyframes tooltipFadeIn {
784                from {
785                    opacity: 0;
786                    transform: translateY(-10px);
787                }
788                to {
789                    opacity: 1;
790                    transform: translateY(0);
791                }
792            }
793            
794            .curator-tooltip-loading {
795                padding: 20px;
796                text-align: center;
797            }
798            
799            .curator-tooltip-header {
800                display: flex;
801                align-items: center;
802                gap: 8px;
803                padding: 16px;
804                border-bottom: 1px solid #e5e7eb;
805            }
806            
807            .curator-tooltip-icon {
808                font-size: 20px;
809            }
810            
811            .curator-tooltip-title {
812                font-weight: 600;
813                color: #1f2937;
814                font-size: 15px;
815                flex: 1;
816            }
817            
818            .curator-tooltip-badge {
819                background: #667eea;
820                color: white;
821                padding: 4px 10px;
822                border-radius: 12px;
823                font-size: 11px;
824                font-weight: 500;
825            }
826            
827            .curator-tooltip-loader {
828                padding: 20px;
829                text-align: center;
830            }
831            
832            .curator-loader-spinner {
833                width: 40px;
834                height: 40px;
835                border: 3px solid #e5e7eb;
836                border-top-color: #667eea;
837                border-radius: 50%;
838                animation: spin 0.8s linear infinite;
839                margin: 0 auto 12px;
840            }
841            
842            @keyframes spin {
843                to { transform: rotate(360deg); }
844            }
845            
846            .curator-tooltip-loader p {
847                margin: 0;
848                color: #6b7280;
849                font-size: 13px;
850            }
851            
852            .curator-tooltip-not-relevant {
853                padding: 16px;
854            }
855            
856            .curator-tooltip-reason {
857                margin: 12px 0 0 0;
858                color: #6b7280;
859                font-size: 13px;
860                line-height: 1.5;
861            }
862            
863            .curator-tooltip-relevant {
864                max-height: 500px;
865                overflow-y: auto;
866            }
867            
868            .curator-tooltip-content {
869                padding: 16px;
870            }
871            
872            .curator-tooltip-section {
873                margin-bottom: 16px;
874            }
875            
876            .curator-tooltip-section:last-child {
877                margin-bottom: 0;
878            }
879            
880            .curator-tooltip-section strong {
881                display: block;
882                color: #374151;
883                font-size: 12px;
884                margin-bottom: 8px;
885            }
886            
887            .curator-tooltip-text {
888                margin: 0;
889                color: #1f2937;
890                font-size: 14px;
891                line-height: 1.6;
892                background: #f0fdf4;
893                padding: 12px;
894                border-radius: 8px;
895                border-right: 3px solid #4ade80;
896            }
897            
898            .curator-tooltip-benefits {
899                list-style: none;
900                padding: 0;
901                margin: 0;
902            }
903            
904            .curator-tooltip-benefits li {
905                padding: 6px 0;
906                font-size: 13px;
907                color: #374151;
908                display: flex;
909                align-items: flex-start;
910                line-height: 1.5;
911            }
912            
913            .curator-tooltip-benefits li:before {
914                content: "✓";
915                color: #4ade80;
916                font-weight: bold;
917                margin-left: 8px;
918                flex-shrink: 0;
919            }
920            
921            .curator-tooltip-actions {
922                display: flex;
923                gap: 8px;
924                padding: 12px 16px;
925                border-top: 1px solid #e5e7eb;
926                background: #f9fafb;
927                border-radius: 0 0 12px 12px;
928            }
929            
930            .curator-tooltip-btn {
931                flex: 1;
932                padding: 8px 12px;
933                border: none;
934                border-radius: 8px;
935                cursor: pointer;
936                font-size: 12px;
937                font-weight: 500;
938                transition: all 0.2s;
939            }
940            
941            .curator-tooltip-btn-save {
942                background: #667eea;
943                color: white;
944            }
945            
946            .curator-tooltip-btn-save:hover {
947                background: #5568d3;
948            }
949            
950            .curator-tooltip-btn-copy {
951                background: #10b981;
952                color: white;
953            }
954            
955            .curator-tooltip-btn-copy:hover {
956                background: #059669;
957            }
958            
959            .curator-tooltip-btn-close {
960                background: #e5e7eb;
961                color: #6b7280;
962                flex: 0 0 auto;
963                padding: 8px 12px;
964            }
965            
966            .curator-tooltip-btn-close:hover {
967                background: #d1d5db;
968            }
969            
970            /* Notification Styles */
971            .curator-notification {
972                position: fixed;
973                top: 20px;
974                right: 20px;
975                background: #10b981;
976                color: white;
977                padding: 12px 20px;
978                border-radius: 8px;
979                box-shadow: 0 10px 30px rgba(0,0,0,0.2);
980                z-index: 1000001;
981                font-size: 14px;
982                font-weight: 500;
983                opacity: 0;
984                transform: translateY(-20px);
985                transition: all 0.3s ease;
986            }
987            
988            .curator-notification-show {
989                opacity: 1;
990                transform: translateY(0);
991            }
992        `;
993
994        const styleSheet = document.createElement('style');
995        styleSheet.textContent = styles;
996        document.head.appendChild(styleSheet);
997
998        return container;
999    }
1000
1001    function createUpdateCard(update) {
1002        const card = document.createElement('div');
1003        card.className = 'curator-update-card';
1004        card.dataset.updateId = update.id;
1005        card.dataset.status = update.status;
1006        card.dataset.priority = update.priority;
1007
1008        const statusBadge = update.status === 'new' ? 'חדש' : 
1009            update.status === 'approved' ? 'אושר' : 
1010                update.status === 'rejected' ? 'נדחה' : update.status;
1011
1012        const statusClass = `curator-badge-${update.status}`;
1013        
1014        const benefits = update.analysis?.keyBenefits || [];
1015        const benefitsHTML = benefits.map(b => `<li>${b}</li>`).join('');
1016
1017        card.innerHTML = `
1018            <div class="curator-update-header">
1019                <div class="curator-update-meta">
1020                    <div class="curator-channel-name">${update.channelName}</div>
1021                    <div class="curator-update-time">${new Date(update.createdAt).toLocaleString('he-IL')}</div>
1022                </div>
1023                <div class="curator-badges">
1024                    <span class="curator-badge ${statusClass}">${statusBadge}</span>
1025                    ${update.priority === 'high' ? '<span class="curator-badge curator-badge-high">עדיפות גבוהה</span>' : ''}
1026                    <span class="curator-badge curator-badge-category">${update.classification.category}</span>
1027                </div>
1028            </div>
1029
1030            <div class="curator-content-section">
1031                <div class="curator-section-title">📝 טקסט מקורי</div>
1032                <div class="curator-original-text">${update.originalText}</div>
1033            </div>
1034
1035            ${update.analysis ? `
1036                <div class="curator-content-section">
1037                    <div class="curator-section-title">💡 ערך עסקי</div>
1038                    <ul class="curator-benefits-list">
1039                        ${benefitsHTML}
1040                    </ul>
1041                </div>
1042            ` : ''}
1043
1044            ${update.rewritten ? `
1045                <div class="curator-content-section">
1046                    <div class="curator-section-title">✨ תוכן מעובד</div>
1047                    <div class="curator-rewritten-text">${update.editedContent || update.rewritten.communityPost}</div>
1048                </div>
1049            ` : ''}
1050
1051            <div class="curator-update-actions">
1052                ${update.status === 'new' ? `
1053                    <button class="curator-action-btn curator-action-btn-approve" data-action="approve">
1054                        ✓ אשר
1055                    </button>
1056                    <button class="curator-action-btn curator-action-btn-reject" data-action="reject">
1057                        ✗ דחה
1058                    </button>
1059                ` : ''}
1060                <button class="curator-action-btn curator-action-btn-copy" data-action="copy">
1061                    📋 העתק
1062                </button>
1063                <button class="curator-action-btn curator-action-btn-edit" data-action="edit">
1064                    ✏️ ערוך
1065                </button>
1066                <button class="curator-action-btn curator-action-btn-delete" data-action="delete">
1067                    🗑️ מחק
1068                </button>
1069            </div>
1070        `;
1071
1072        // Add event listeners
1073        card.querySelectorAll('[data-action]').forEach(btn => {
1074            btn.addEventListener('click', async (e) => {
1075                const action = e.target.dataset.action;
1076                await handleUpdateAction(update.id, action, update);
1077            });
1078        });
1079
1080        return card;
1081    }
1082
1083    async function handleUpdateAction(updateId, action, update) {
1084        console.log(`🎬 Action: ${action} for update ${updateId}`);
1085
1086        switch(action) {
1087        case 'approve':
1088            await updateStatus(updateId, 'approved');
1089            await refreshUI();
1090            break;
1091
1092        case 'reject':
1093            await updateStatus(updateId, 'rejected');
1094            await refreshUI();
1095            break;
1096
1097        case 'copy':
1098            const textToCopy = update.editedContent || update.rewritten?.communityPost || update.originalText;
1099            await GM.setClipboard(textToCopy);
1100            alert('✅ הטקסט הועתק ללוח');
1101            break;
1102
1103        case 'edit':
1104            showEditModal(update);
1105            break;
1106
1107        case 'delete':
1108            if (confirm('האם למחוק עדכון זה?')) {
1109                await deleteUpdate(updateId);
1110                await refreshUI();
1111            }
1112            break;
1113        }
1114    }
1115
1116    function showEditModal(update) {
1117        const modal = document.createElement('div');
1118        modal.className = 'curator-edit-modal';
1119        
1120        const currentText = update.editedContent || update.rewritten?.communityPost || '';
1121        
1122        modal.innerHTML = `
1123            <div class="curator-edit-content">
1124                <div class="curator-edit-header">
1125                    <h3 class="curator-edit-title">✏️ עריכת תוכן</h3>
1126                    <button class="curator-edit-close"></button>
1127                </div>
1128                <textarea class="curator-edit-textarea" placeholder="ערוך את התוכן כאן...">${currentText}</textarea>
1129                <div class="curator-edit-actions">
1130                    <button class="curator-action-btn curator-action-btn-approve" id="save-edit-btn">
1131                        💾 שמור
1132                    </button>
1133                    <button class="curator-action-btn curator-action-btn-delete" id="cancel-edit-btn">
1134                        ✕ ביטול
1135                    </button>
1136                </div>
1137            </div>
1138        `;
1139
1140        document.body.appendChild(modal);
1141
1142        const closeModal = () => modal.remove();
1143
1144        modal.querySelector('.curator-edit-close').addEventListener('click', closeModal);
1145        modal.querySelector('#cancel-edit-btn').addEventListener('click', closeModal);
1146        
1147        modal.querySelector('#save-edit-btn').addEventListener('click', async () => {
1148            const newText = modal.querySelector('.curator-edit-textarea').value;
1149            await updateEditedContent(update.id, newText);
1150            closeModal();
1151            await refreshUI();
1152        });
1153
1154        modal.addEventListener('click', (e) => {
1155            if (e.target === modal) closeModal();
1156        });
1157    }
1158
1159    async function refreshUI(filter = 'all') {
1160        const listContainer = document.getElementById('curator-updates-list');
1161        if (!listContainer) return;
1162
1163        listContainer.innerHTML = '<div class="curator-loading">טוען עדכונים...</div>';
1164
1165        const updates = await getUpdates();
1166        
1167        let filteredUpdates = updates;
1168        
1169        if (filter === 'new') {
1170            filteredUpdates = updates.filter(u => u.status === 'new');
1171        } else if (filter === 'approved') {
1172            filteredUpdates = updates.filter(u => u.status === 'approved');
1173        } else if (filter === 'rejected') {
1174            filteredUpdates = updates.filter(u => u.status === 'rejected');
1175        } else if (filter === 'high') {
1176            filteredUpdates = updates.filter(u => u.priority === 'high');
1177        }
1178
1179        listContainer.innerHTML = '';
1180
1181        if (filteredUpdates.length === 0) {
1182            listContainer.innerHTML = `
1183                <div class="curator-empty-state">
1184                    <div class="curator-empty-state-icon">📭</div>
1185                    <div class="curator-empty-state-text">אין עדכונים להצגה</div>
1186                    <div class="curator-empty-state-subtext">עדכונים חדשים יופיעו כאן אוטומטית</div>
1187                </div>
1188            `;
1189        } else {
1190            filteredUpdates.forEach(update => {
1191                const card = createUpdateCard(update);
1192                listContainer.appendChild(card);
1193            });
1194        }
1195
1196        console.log(`✅ UI refreshed with ${filteredUpdates.length} updates`);
1197    }
1198
1199    // ===== MESSAGE MONITORING =====
1200    
1201    let currentTooltip = null;
1202    let processingCache = new Map();
1203    
1204    function removeTooltip() {
1205        if (currentTooltip) {
1206            currentTooltip.remove();
1207            currentTooltip = null;
1208        }
1209    }
1210    
1211    function createLoadingTooltip(messageElement) {
1212        removeTooltip();
1213        
1214        const tooltip = document.createElement('div');
1215        tooltip.className = 'curator-hover-tooltip curator-tooltip-loading';
1216        tooltip.innerHTML = `
1217            <div class="curator-tooltip-header">
1218                <span class="curator-tooltip-icon">🤖</span>
1219                <span class="curator-tooltip-title">מעבד הודעה...</span>
1220            </div>
1221            <div class="curator-tooltip-loader">
1222                <div class="curator-loader-spinner"></div>
1223                <p>AI מנתח את התוכן</p>
1224            </div>
1225        `;
1226        
1227        positionTooltip(tooltip, messageElement);
1228        document.body.appendChild(tooltip);
1229        currentTooltip = tooltip;
1230        
1231        return tooltip;
1232    }
1233    
1234    function createContentTooltip(messageElement, result) {
1235        removeTooltip();
1236        
1237        if (!result.isRelevant) {
1238            const tooltip = document.createElement('div');
1239            tooltip.className = 'curator-hover-tooltip curator-tooltip-not-relevant';
1240            tooltip.innerHTML = `
1241                <div class="curator-tooltip-header">
1242                    <span class="curator-tooltip-icon">⏭️</span>
1243                    <span class="curator-tooltip-title">לא רלוונטי</span>
1244                </div>
1245                <p class="curator-tooltip-reason">${result.classification.relevanceReason}</p>
1246            `;
1247            
1248            positionTooltip(tooltip, messageElement);
1249            document.body.appendChild(tooltip);
1250            currentTooltip = tooltip;
1251            return;
1252        }
1253        
1254        const tooltip = document.createElement('div');
1255        tooltip.className = 'curator-hover-tooltip curator-tooltip-relevant';
1256        tooltip.innerHTML = `
1257            <div class="curator-tooltip-header">
1258                <span class="curator-tooltip-icon"></span>
1259                <span class="curator-tooltip-title">תוכן רלוונטי!</span>
1260                <span class="curator-tooltip-badge">${result.classification.category}</span>
1261            </div>
1262            
1263            <div class="curator-tooltip-content">
1264                <div class="curator-tooltip-section">
1265                    <strong>📝 ניסוח לקהילה:</strong>
1266                    <p class="curator-tooltip-text">${result.rewritten.communityPost}</p>
1267                </div>
1268                
1269                <div class="curator-tooltip-section">
1270                    <strong>💡 ערך עסקי:</strong>
1271                    <ul class="curator-tooltip-benefits">
1272                        ${result.analysis.keyBenefits.slice(0, 3).map(b => `<li>${b}</li>`).join('')}
1273                    </ul>
1274                </div>
1275            </div>
1276            
1277            <div class="curator-tooltip-actions">
1278                <button class="curator-tooltip-btn curator-tooltip-btn-save" data-action="save">
1279                    💾 שמור לפאנל
1280                </button>
1281                <button class="curator-tooltip-btn curator-tooltip-btn-copy" data-action="copy">
1282                    📋 העתק
1283                </button>
1284                <button class="curator-tooltip-btn curator-tooltip-btn-close" data-action="close">
12851286                </button>
1287            </div>
1288        `;
1289        
1290        positionTooltip(tooltip, messageElement);
1291        document.body.appendChild(tooltip);
1292        currentTooltip = tooltip;
1293        
1294        // Add event listeners
1295        tooltip.querySelector('[data-action="save"]').addEventListener('click', async () => {
1296            await saveUpdate(result.update);
1297            await refreshUI();
1298            removeTooltip();
1299            showNotification('✅ נשמר בהצלחה!');
1300        });
1301        
1302        tooltip.querySelector('[data-action="copy"]').addEventListener('click', async () => {
1303            await GM.setClipboard(result.rewritten.communityPost);
1304            showNotification('✅ הועתק ללוח!');
1305        });
1306        
1307        tooltip.querySelector('[data-action="close"]').addEventListener('click', () => {
1308            removeTooltip();
1309        });
1310    }
1311    
1312    function positionTooltip(tooltip, messageElement) {
1313        const rect = messageElement.getBoundingClientRect();
1314        const tooltipWidth = 400;
1315        const tooltipMaxHeight = 500;
1316        
1317        // Position to the left of the message
1318        let left = rect.left - tooltipWidth - 20;
1319        let top = rect.top;
1320        
1321        // If not enough space on the left, position on the right
1322        if (left < 20) {
1323            left = rect.right + 20;
1324        }
1325        
1326        // If not enough space on the right either, position below
1327        if (left + tooltipWidth > window.innerWidth - 20) {
1328            left = rect.left;
1329            top = rect.bottom + 10;
1330        }
1331        
1332        // Make sure it doesn't go off screen vertically
1333        if (top + tooltipMaxHeight > window.innerHeight) {
1334            top = window.innerHeight - tooltipMaxHeight - 20;
1335        }
1336        
1337        if (top < 20) {
1338            top = 20;
1339        }
1340        
1341        tooltip.style.left = `${left}px`;
1342        tooltip.style.top = `${top}px`;
1343    }
1344    
1345    function showNotification(message) {
1346        const notification = document.createElement('div');
1347        notification.className = 'curator-notification';
1348        notification.textContent = message;
1349        document.body.appendChild(notification);
1350        
1351        setTimeout(() => {
1352            notification.classList.add('curator-notification-show');
1353        }, 10);
1354        
1355        setTimeout(() => {
1356            notification.classList.remove('curator-notification-show');
1357            setTimeout(() => notification.remove(), 300);
1358        }, 2000);
1359    }
1360    
1361    async function processMessageOnHover(messageElement, messageText, channelName, messageUrl) {
1362        const cacheKey = `${channelName}_${messageText.substring(0, 100)}`;
1363        
1364        // Check cache first
1365        if (processingCache.has(cacheKey)) {
1366            const cached = processingCache.get(cacheKey);
1367            createContentTooltip(messageElement, cached);
1368            return;
1369        }
1370        
1371        // Show loading tooltip
1372        createLoadingTooltip(messageElement);
1373        
1374        try {
1375            // Step 1: Classify
1376            const classification = await classifyContent(messageText, channelName);
1377            
1378            if (!classification.isRelevant) {
1379                const result = { isRelevant: false, classification };
1380                processingCache.set(cacheKey, result);
1381                createContentTooltip(messageElement, result);
1382                return;
1383            }
1384            
1385            // Step 2: Analyze business value
1386            const analysis = await analyzeBusinessValue(messageText, classification);
1387            
1388            if (!analysis) {
1389                const result = { isRelevant: false, classification: { relevanceReason: 'שגיאה בניתוח' } };
1390                createContentTooltip(messageElement, result);
1391                return;
1392            }
1393            
1394            // Step 3: Rewrite content
1395            const rewritten = await rewriteForBusinessOwners(messageText, analysis);
1396            
1397            if (!rewritten) {
1398                const result = { isRelevant: false, classification: { relevanceReason: 'שגיאה בניסוח' } };
1399                createContentTooltip(messageElement, result);
1400                return;
1401            }
1402            
1403            // Create update object (but don't save yet)
1404            const update = {
1405                id: `update_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
1406                originalText: messageText,
1407                channelName: channelName,
1408                messageUrl: messageUrl,
1409                classification: classification,
1410                analysis: analysis,
1411                rewritten: rewritten,
1412                status: 'new',
1413                priority: classification.businessValue === 'גבוה' ? 'high' : 'normal',
1414                createdAt: new Date().toISOString(),
1415                statusChangedAt: new Date().toISOString()
1416            };
1417            
1418            const result = {
1419                isRelevant: true,
1420                classification,
1421                analysis,
1422                rewritten,
1423                update
1424            };
1425            
1426            processingCache.set(cacheKey, result);
1427            createContentTooltip(messageElement, result);
1428            
1429        } catch (error) {
1430            console.error('❌ Error processing message on hover:', error);
1431            removeTooltip();
1432        }
1433    }
1434    
1435    function extractMessageData(messageElement) {
1436        try {
1437            // Extract message text
1438            const textElement = messageElement.querySelector('.text-content, .message-content, [class*="text"], [class*="message"]');
1439            const messageText = textElement ? textElement.textContent.trim() : '';
1440
1441            if (!messageText || messageText.length < 50) {
1442                return null;
1443            }
1444
1445            // Extract channel name
1446            const channelElement = document.querySelector('.chat-info-title, .peer-title, [class*="title"]');
1447            const channelName = channelElement ? channelElement.textContent.trim() : 'Unknown Channel';
1448
1449            // Create message URL
1450            const messageUrl = window.location.href;
1451
1452            return {
1453                messageText,
1454                channelName,
1455                messageUrl
1456            };
1457        } catch (error) {
1458            console.error('❌ Error extracting message data:', error);
1459            return null;
1460        }
1461    }
1462
1463    const processedMessages = new Set();
1464    let hoverTimeout = null;
1465
1466    async function monitorMessages() {
1467        const messages = document.querySelectorAll('.message, [class*="Message"], .bubble');
1468        
1469        for (const message of messages) {
1470            const messageId = message.getAttribute('data-message-id') || message.id;
1471            
1472            if (!messageId || processedMessages.has(messageId)) {
1473                continue;
1474            }
1475
1476            processedMessages.add(messageId);
1477            
1478            // Add hover listeners
1479            message.addEventListener('mouseenter', () => {
1480                clearTimeout(hoverTimeout);
1481                hoverTimeout = setTimeout(() => {
1482                    const data = extractMessageData(message);
1483                    if (data) {
1484                        processMessageOnHover(message, data.messageText, data.channelName, data.messageUrl);
1485                    }
1486                }, 500); // Wait 500ms before processing
1487            });
1488            
1489            message.addEventListener('mouseleave', () => {
1490                clearTimeout(hoverTimeout);
1491                // Don't remove tooltip immediately - let user interact with it
1492                setTimeout(() => {
1493                    if (currentTooltip && !currentTooltip.matches(':hover')) {
1494                        removeTooltip();
1495                    }
1496                }, 300);
1497            });
1498        }
1499        
1500        // Keep tooltip open when hovering over it
1501        if (currentTooltip) {
1502            currentTooltip.addEventListener('mouseleave', () => {
1503                setTimeout(() => {
1504                    if (currentTooltip && !currentTooltip.matches(':hover')) {
1505                        removeTooltip();
1506                    }
1507                }, 300);
1508            });
1509        }
1510    }
1511
1512    const debouncedMonitor = debounce(monitorMessages, 1000);
1513
1514    function setupMessageObserver() {
1515        const observer = new MutationObserver(debouncedMonitor);
1516        
1517        const targetNode = document.querySelector('.messages-container, #column-center, [class*="messages"]') || document.body;
1518        
1519        observer.observe(targetNode, {
1520            childList: true,
1521            subtree: true
1522        });
1523
1524        console.log('👀 Message observer started');
1525    }
1526
1527    // ===== INITIALIZATION =====
1528    
1529    async function init() {
1530        console.log('🚀 Initializing Telegram AI Content Curator...');
1531
1532        // Wait for page to load
1533        await new Promise(resolve => {
1534            if (document.readyState === 'complete') {
1535                resolve();
1536            } else {
1537                window.addEventListener('load', resolve);
1538            }
1539        });
1540
1541        // Create UI
1542        const ui = createMainUI();
1543        document.body.appendChild(ui);
1544
1545        // Setup event listeners
1546        document.getElementById('curator-refresh-btn').addEventListener('click', () => {
1547            const activeFilter = document.querySelector('.curator-filter-btn.active');
1548            const filter = activeFilter ? activeFilter.dataset.filter : 'all';
1549            refreshUI(filter);
1550        });
1551
1552        document.getElementById('curator-toggle-btn').addEventListener('click', () => {
1553            ui.classList.toggle('minimized');
1554            const btn = document.getElementById('curator-toggle-btn');
1555            btn.textContent = ui.classList.contains('minimized') ? '➕ הרחב' : '➖ מזער';
1556        });
1557
1558        document.querySelectorAll('.curator-filter-btn').forEach(btn => {
1559            btn.addEventListener('click', (e) => {
1560                document.querySelectorAll('.curator-filter-btn').forEach(b => b.classList.remove('active'));
1561                e.target.classList.add('active');
1562                refreshUI(e.target.dataset.filter);
1563            });
1564        });
1565
1566        // Initial UI load
1567        await refreshUI();
1568
1569        // Start monitoring messages
1570        setupMessageObserver();
1571
1572        console.log('✅ Telegram AI Content Curator ready!');
1573    }
1574
1575    // Start the extension
1576    init();
1577
1578})();
Telegram AI Content Curator for Business Owners | Robomonkey