המלצה | נמאס לכם כל יום לעבור על כל המתחמים טופ? סקיפט לקבלת התוכנות החדשות והודעות החדשות ועדכוני AI החדשים ממתחמים טופ למייל פעם ביום
-
מכניסים לגוגל סקיפט ומאשרים,
לא לשכוח להוסיף מייל
ומפתח API של גמיני
// ============================================================
// מתמחים טופ - דיגסט יומי: תוכנות חדשות שנוצרו + עדכוני AI
// גרסה: 2.2 (רוטציית 6 מפתחות + 7 מודלי Gemini + עד 350 מילים בסך הכל!)
// פועל לצד שלוחה 7 ללא שום התנגשות (קידומת ייחודית: mm_*)
// ============================================================var MM_CONFIG = {
forumBaseUrl: 'https://mitmachim.top',
recentApiUrl: 'https://mitmachim.top/api/recent',
unreadApiUrl: 'https://mitmachim.top/api/unread',// מזהה אשכול חדשות ה-AI הרשמי
aiTopicId: 95167,
aiTopicUrl: 'https://mitmachim.top/topic/95167/שיתוף-מה-חדש-בבינה-מלאכותית-נספח-עדכוני-פיצ-רים-ודיונים',// הגבלה קריטית: סך כל המילים בכל הדיגסט ביחד לא יעלה על 350 מילים!
maxTotalWords: 350,
maxSoftwareItems: 8,
maxAiPostsToScan: 15,triggerHour: 22,
triggerTimeZone: 'Asia/Jerusalem',email: {
senderName: 'מתמחים טופ - עדכונים יומיים',
subjectPrefix: 'מתמחים טופ: תוכנות חדשות ו-AI - '
},defaultRecipients: 'כאן לרשום מייל',
// 7 מודלי Gemini לסריקה לפי סדר עדיפות מדויק
geminiModels: [
'gemini-3-flash-preview',
'gemini-2.5-flash',
'gemini-3.5-flash-lite',
'gemini-3.1-flash-lite',
'gemini-2.5-flash-lite'
],// מאגר 6 מפתחות API - אם אחד נכשל עובר מיידית לבא בתור!
apiKeys: [
'כאן לרשום מפתח API',
'',
'',
'',
'',
''
],maxOutputTokens: 1500,
disableThinking: true,
temperature: 0.2,
retryDelayMs: 600
};// ========== הפונקציה הראשית ==========
function mm_digestMain() {
try {
Logger.log('=== מתמחים טופ - דיגסט יומי מתחיל ===');if (mm_alreadySentToday()) { Logger.log('כבר נשלח דיגסט מתמחים להיום - מדלג על הרצה חוזרת'); return; } var recipients = mm_getRecipients(); if (recipients.length === 0) { Logger.log('לא הוגדרו נמענים - מפסיק'); return; } var days = ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת']; var todayName = days[new Date().getDay()]; var hebrewDate = mm_hebrewDate(); var dateStr = new Date().toLocaleDateString('he-IL'); // 1. שלב א': איתור וסינון תוכנות חדשות בלבד מהפורום (מהיום בלבד!) Logger.log('--- שלב 1: חיפוש תוכנות חדשות שנוצרו/פורסמו היום ---'); var softwareItems = mm_fetchAndFilterNewSoftware(); Logger.log('נמצאו %s תוכנות חדשות אמיתיות מהיום', softwareItems.length); // 2. שלב ב': שליפת עדכוני AI מאשכול ה-AI (מהיום בלבד!) Logger.log('--- שלב 2: שליפת עדכוני AI מאשכול %s ---', MM_CONFIG.aiTopicId); var aiUpdates = mm_fetchTodayAiThreadUpdates(); Logger.log('נמצאו %s עדכוני AI רלוונטיים מהיום', aiUpdates.length); if (softwareItems.length === 0 && aiUpdates.length === 0) { Logger.log('אין תוכנות חדשות ואין עדכוני AI חדשים מהיום - לא נשלח מייל ריק'); return; } // 3. הגבלה קשיחה: סך כל המילים בכל הדיגסט כולו ביחד לא יעלה על 350 מילים! var limited = mm_enforceTotalWordLimit(softwareItems, aiUpdates, MM_CONFIG.maxTotalWords); softwareItems = limited.softwareItems; aiUpdates = limited.aiUpdates; Logger.log('סך מילים כולל בדיגסט: %s (מקסימום מותר: %s)', limited.totalWords, MM_CONFIG.maxTotalWords); // 4. עיצוב ושליחת המייל var htmlBody = mm_formatDigestEmail(softwareItems, aiUpdates, dateStr, todayName, hebrewDate, limited.totalWords); var subject = MM_CONFIG.email.subjectPrefix + dateStr + ' (' + softwareItems.length + ' תוכנות, ' + aiUpdates.length + ' עדכוני AI)'; for (var r = 0; r < recipients.length; r++) { MailApp.sendEmail({ to: recipients[r], subject: subject, htmlBody: htmlBody, name: MM_CONFIG.email.senderName }); Logger.log('מייל נשלח בהצלחה אל: %s', recipients[r]); } for (var s = 0; s < softwareItems.length; s++) { mm_markTopicSent(softwareItems[s].tid || softwareItems[s].url); } mm_markSentToday(); Logger.log('=== דיגסט מתמחים טופ הסתיים בהצלחה! סך מילים: %s ===', limited.totalWords);} catch (e) {
Logger.log('!!! שגיאה בהרצת דיגסט מתמחים: %s', e.stack || e.message);
}
}// ========== הגבלת מילים קפדנית: עד 350 מילים בסך הכל ==========
function mm_countWords(str) {
if (!str) return 0;
return str.trim().split(/\s+/).filter(function(w) { return w.length > 0; }).length;
}function mm_enforceTotalWordLimit(softwareItems, aiUpdates, maxLimit) {
var limit = maxLimit || 350;
var currentWords = 0;for (var i = 0; i < softwareItems.length; i++) {
currentWords += mm_countWords(softwareItems[i].softwareName) + mm_countWords(softwareItems[i].summary);
}
for (var j = 0; j < aiUpdates.length; j++) {
currentWords += mm_countWords(aiUpdates[j].headline) + mm_countWords(aiUpdates[j].bulletSummary);
}if (currentWords <= limit) {
return { softwareItems: softwareItems, aiUpdates: aiUpdates, totalWords: currentWords };
}Logger.log('חריגת מילים: נמצאו ' + currentWords + ' מילים. מקצץ לעד ' + limit + ' מילים בסך הכל...');
var totalItems = softwareItems.length + aiUpdates.length;
var targetWordsPerItem = Math.floor((limit - 20) / Math.max(1, totalItems));var trimmedSoftware = [];
var wordsUsed = 0;for (var s = 0; s < softwareItems.length; s++) {
var item = softwareItems[s];
var words = (item.summary || '').split(/\s+/).filter(Boolean);
if (words.length > targetWordsPerItem) {
item.summary = words.slice(0, targetWordsPerItem).join(' ') + '.';
}
wordsUsed += mm_countWords(item.softwareName) + mm_countWords(item.summary);
trimmedSoftware.push(item);
}var trimmedAi = [];
for (var a = 0; a < aiUpdates.length; a++) {
var ai = aiUpdates[a];
var remaining = limit - wordsUsed;
if (remaining <=
break;var aiWords = (ai.bulletSummary || '').split(/\s+/).filter(Boolean); if (aiWords.length > Math.min(targetWordsPerItem, remaining - 5)) { ai.bulletSummary = aiWords.slice(0, Math.min(targetWordsPerItem, remaining - 5)).join(' ') + '.'; } wordsUsed += mm_countWords(ai.headline) + mm_countWords(ai.bulletSummary); trimmedAi.push(ai);}
return { softwareItems: trimmedSoftware, aiUpdates: trimmedAi, totalWords: wordsUsed };
}// ========== שליפת תוכנות חדשות בלבד ==========
function mm_fetchAndFilterNewSoftware() {
var qualifiedSoftware = [];
var rawTopics = mm_fetchRecentTopics();
var todayStart = mm_getTodayStartTimestamp();for (var i = 0; i < rawTopics.length; i++) {
if (qualifiedSoftware.length >= MM_CONFIG.maxSoftwareItems) break;var topic = rawTopics[i]; var tid = String(topic.tid || topic.slug); var topicTimestamp = topic.timestamp || topic.lastposttime || 0; if (topicTimestamp < todayStart || mm_isTopicSent(tid)) continue; var title = (topic.title || '').trim(); if (mm_isObviouslyNotSoftware(title)) continue; var firstPostContent = mm_fetchTopicFirstPost(topic.tid, topic.slug); if (!firstPostContent || firstPostContent.length < 30) continue; try { var evaluation = mm_evaluateSoftwareWithGemini(title, firstPostContent, topic.categoryName || ''); if (evaluation && evaluation.isNewSoftware) { qualifiedSoftware.push({ tid: tid, title: title, softwareName: evaluation.softwareName || title, summary: evaluation.summary, version: evaluation.version || '', url: MM_CONFIG.forumBaseUrl + '/topic/' + (topic.slug || topic.tid), author: topic.user ? (topic.user.username || topic.user.displayname) : 'חבר פורום' }); Logger.log('✓ אושרה תוכנה חדשה: %s', title); } else { Logger.log('✗ סונן (אינו תוכנה חדשה): %s', title); } Utilities.sleep(250); } catch (err) { Logger.log('שגיאה בניתוח נושא "%s": %s', title, err.message); }}
return qualifiedSoftware;
}function mm_isObviouslyNotSoftware(title) {
var lower = title.toLowerCase();
var skipPhrases = [
'עזרה', 'איך לעשות', 'מישהו יודע', 'למה לא עובד', 'בעיה ב', 'שגיאה',
'מחפש תוכנה', 'האם יש', 'בקשה:', 'דחוף', 'שאלה', 'לא מצליח', 'התקנה נכשלה',
'האם אפשר', 'בירור', 'חוות דעת', 'מחיר', 'קנייה', 'מכירה', 'מחשב נייד'
];
for (var i = 0; i < skipPhrases.length; i++) {
if (lower.indexOf(skipPhrases[i]) !== -1 && lower.indexOf('הורדה') === -1 && lower.indexOf('תוכנה חדשה') === -1) {
return true;
}
}
return false;
}function mm_fetchRecentTopics() {
try {
var endpoints = [MM_CONFIG.recentApiUrl, MM_CONFIG.unreadApiUrl];
for (var e = 0; e < endpoints.length; e++) {
var jsonStr = mm_fetchUrl(endpoints[e]);
if (jsonStr) {
var data = JSON.parse(jsonStr);
if (data.topics && data.topics.length > 0) return data.topics;
}
}
return [];
} catch (e) {
Logger.log('שגיאה בשליפת נושאים אחרונים: %s', e.message);
return [];
}
}function mm_fetchTopicFirstPost(tid, slug) {
try {
var url = MM_CONFIG.forumBaseUrl + '/api/topic/' + (slug || tid);
var jsonStr = mm_fetchUrl(url);
if (!jsonStr) return '';
var data = JSON.parse(jsonStr);
if (data.posts && data.posts.length > 0) {
return mm_stripHtml(data.posts[0].content || '').substring(0, 3000);
}
return '';
} catch (e) {
return '';
}
}function mm_evaluateSoftwareWithGemini(title, content, category) {
var prompt = 'אתה מסנן קפדני של עדכוני פורום מחשבים. המטרה: לזהות אך ורק תוכנות, אפליקציות, כלים או תוספים חדשים שנוצרו או פורסמו להורדה.\n'
+ 'כללים מחמירים:\n'
+ '1. אם הפוסט הוא שאלה, בקשת עזרה, בעיה טכנית, שאלת ייעוץ, בקשת תוכנה (למשל "מחפש תוכנה ל..."), או דיון כללי - החזר מיד isNewSoftware: false!\n'
+ '2. רק אם מדובר ביוצר שמשתף כלי/תוכנה שהוא פיתח, או שחרור של תוכנה/כלי חדש להורדה - החזר isNewSoftware: true.\n'
+ '3. ספק סיכום קצרצר ותמציתי ביותר בעברית (משפט אחד או שניים בלבד, עד 25 מילים). המייל כולו מוגבל ל-350 מילים!\n'
+ '4. החזר אך ורק JSON תקין במבנה הבא ללא שום טקסט נוסף:\n'
+ '{\n'
+ ' "isNewSoftware": true/false,\n'
+ ' "softwareName": "שם התוכנה או הכלי",\n'
+ ' "summary": "סיכום תמציתי של משפט עד שניים.",\n'
+ ' "version": "גרסה אם קיימת"\n'
+ '}\n\n'
+ 'כותרת הפוסט: ' + title + '\n'
+ 'תוכן הפוסט:\n' + content.substring(0, 2000);var res = mm_callGemini(prompt);
var cleanJson = res.text.replace(/json/gi, '').replace(//g, '').trim();
try {
return JSON.parse(cleanJson);
} catch (err) {
var jsonMatch = cleanJson.match(/{[\s\S]*}/);
if (jsonMatch) return JSON.parse(jsonMatch[0]);
return null;
}
}// ========== שליפת עדכוני AI מאשכול 95167 ==========
function mm_fetchTodayAiThreadUpdates() {
try {
var todayStart = mm_getTodayStartTimestamp();
var topicApiUrl = MM_CONFIG.forumBaseUrl + '/api/topic/' + MM_CONFIG.aiTopicId;
var jsonStr = mm_fetchUrl(topicApiUrl);
if (!jsonStr) return [];var data = JSON.parse(jsonStr); var posts = data.posts || []; var postCount = data.postcount || 0; if (postCount > 20 && data.pagination && data.pagination.pageCount > 1) { var lastPageUrl = topicApiUrl + '?page=' + data.pagination.pageCount; var lastPageJson = mm_fetchUrl(lastPageUrl); if (lastPageJson) { var lastPageData = JSON.parse(lastPageJson); if (lastPageData.posts && lastPageData.posts.length > 0) { posts = lastPageData.posts; } } } var todayPosts = []; for (var i = posts.length - 1; i >= 0 && todayPosts.length < MM_CONFIG.maxAiPostsToScan; i--) { var p = posts[i]; var postTime = p.timestamp || 0; if (postTime >= todayStart) { var cleanText = mm_stripHtml(p.content || ''); if (cleanText.length > 40) { todayPosts.push({ pid: p.pid, index: p.index, user: p.user ? (p.user.username || p.user.displayname) : 'משתמש', content: cleanText.substring(0, 2500) }); } } } if (todayPosts.length === 0) return []; var combinedContent = todayPosts.map(function(item, idx) { return '[' + (idx + 1) + '] מאת ' + item.user + ':\n' + item.content; }).join('\n\n--- פוסט הבא ---\n\n'); var prompt = 'להלן פוסטים חדשים שפורסמו היום בפורום מתמחים טופ באשכול עדכוני בינה מלאכותית (AI).\n' + 'משימתך:\n' + '1. סנן שיחות סרק, שאלות טכניות פרטיות או תודות.\n' + '2. חלץ וסכם את החדשות והפיצ\'רים האמיתיים של בינה מלאכותית שנחשפו היום.\n' + '3. מגבלת מילים קריטית: סך כל המילים בכל הדיגסט מוגבל לעד 350 מילים! כתוב סיכום של משפט אחד בלבד (עד 20 מילים לפריט).\n' + '4. החזר אך ורק מערך JSON תקין ללא שום טקסט נוסף:\n' + '[\n' + ' {\n' + ' "headline": "כותרת קצרה של החידוש",\n' + ' "bulletSummary": "משפט תמציתי ומדויק על מה שהתחדש.",\n' + ' "sourceUser": "שם המשתמש ששיתף"\n' + ' }\n' + ']\n\n' + combinedContent; var res = mm_callGemini(prompt); var cleanJson = res.text.replace(/```json/gi, '').replace(/```/g, '').trim(); var parsedList = []; try { parsedList = JSON.parse(cleanJson); } catch (e) { var match = cleanJson.match(/\[[\s\S]*\]/); if (match) parsedList = JSON.parse(match[0]); } for (var k = 0; k < parsedList.length; k++) { parsedList[k].url = MM_CONFIG.aiTopicUrl; } return parsedList;} catch (err) {
Logger.log('שגיאה בשליפת עדכוני אשכול AI: %s', err.message);
return [];
}
}// ========== עיצוב המייל (עד 350 מילים) ==========
function mm_formatDigestEmail(softwareItems, aiUpdates, dateStr, todayName, hebrewDate, totalWords) {
var softwareHtml = '';
if (softwareItems.length > 0) {
softwareHtml += '<div style="margin-bottom:24px;">'
+ '<div style="display:flex; align-items:center; margin-bottom:12px; border-bottom:2px solid #3b82f6; padding-bottom:6px;">'
+ '<span style="background:#3b82f6; color:#ffffff; font-size:11px; font-weight:bold; padding:2px 8px; border-radius:4px; margin-left:6px;">חדש בקהילה</span>'
+ '<h2 style="color:#0f172a; font-size:17px; margin:0; font-weight:800;">
תוכנות וכלים חדשים שפותחו/שוחררו היום (' + softwareItems.length + ')</h2>'
+ '</div>';for (var i = 0; i < softwareItems.length; i++) { var item = softwareItems[i]; softwareHtml += '<div style="background:#f8fafc; border:1px solid #e2e8f0; border-radius:8px; padding:14px 16px; margin-bottom:12px;">' + '<div style="display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:4px;">' + '<h3 style="color:#1e3a8a; font-size:15px; font-weight:700; margin:0; line-height:1.4;">' + (i + 1) + '. ' + item.softwareName + '</h3>' + (item.version ? '<span style="background:#e0e7ff; color:#3730a3; font-size:11px; font-weight:700; padding:2px 6px; border-radius:4px;">' + item.version + '</span>' : '') + '</div>' + '<p style="color:#334155; font-size:14px; line-height:1.65; margin:0 0 8px;">' + item.summary + '</p>' + '<div style="display:flex; justify-content:space-between; align-items:center; font-size:12px; color:#64748b;">' + '<span>שותף ע"י: <strong>' + item.author + '</strong></span>' + '<a href="' + item.url + '" target="_blank" style="color:#2563eb; text-decoration:none; font-weight:bold;">לפוסט המלא ולהורדה בפורום ←</a>' + '</div>' + '</div>'; } softwareHtml += '</div>';} else {
softwareHtml += '<div style="padding:12px; background:#f8fafc; border-radius:8px; border:1px dashed #cbd5e1; color:#64748b; font-size:13px; margin-bottom:20px; text-align:center;">'
+ 'לא פורסמו היום תוכנות חדשות נוספות שפותחו בקהילה.'
+ '</div>';
}var aiHtml = '';
if (aiUpdates.length > 0) {
aiHtml += '<div style="margin-bottom:20px;">'
+ '<div style="display:flex; align-items:center; margin-bottom:12px; border-bottom:2px solid #8b5cf6; padding-bottom:6px;">'
+ '<span style="background:#8b5cf6; color:#ffffff; font-size:11px; font-weight:bold; padding:2px 8px; border-radius:4px; margin-left:6px;">אשכול AI</span>'
+ '<h2 style="color:#0f172a; font-size:17px; margin:0; font-weight:800;">
מה חדש בבינה מלאכותית היום (' + aiUpdates.length + ')</h2>'
+ '</div>';for (var j = 0; j < aiUpdates.length; j++) { var ai = aiUpdates[j]; aiHtml += '<div style="border-right:3px solid #8b5cf6; background:#faf5ff; padding:10px 14px; margin-bottom:10px; border-radius:0 6px 6px 0;">' + '<h4 style="color:#581c87; font-size:14px; font-weight:700; margin:0 0 3px;">' + (j + 1) + '. ' + ai.headline + '</h4>' + '<p style="color:#334155; font-size:13.5px; line-height:1.6; margin:0 0 5px;">' + ai.bulletSummary + '</p>' + '<div style="font-size:12px; color:#7e22ce;">' + (ai.sourceUser ? '<span>משתף: ' + ai.sourceUser + ' • </span>' : '') + '<a href="' + ai.url + '" target="_blank" style="color:#7e22ce; font-weight:bold; text-decoration:none;">צפה באשכול ה-AI בפורום ←</a>' + '</div>' + '</div>'; } aiHtml += '</div>';} else {
aiHtml += '<div style="padding:12px; background:#f8fafc; border-radius:8px; border:1px dashed #cbd5e1; color:#64748b; font-size:13px; margin-bottom:20px; text-align:center;">'
+ 'לא היו עדכוני AI חדשים היום באשכול הייעודי.'
+ '</div>';
}return '<!DOCTYPE html><html dir="rtl" lang="he"><head><meta charset="UTF-8"></head>'
+ '<body style="font-family:Arial,Helvetica,sans-serif; direction:rtl; text-align:right; max-width:640px; margin:0 auto; padding:16px; background-color:#f1f5f9;">'
+ '<div style="background:linear-gradient(135deg,#0f172a 0%,#1e1b4b 100%); color:#ffffff; padding:24px 20px; border-radius:12px 12px 0 0; text-align:center;">'
+ '<span style="display:inline-block; background:rgba(59,130,246,0.3); color:#93c5fd; font-size:11px; font-weight:bold; padding:3px 10px; border-radius:999px; margin-bottom:8px;">מתמחים טופ • דיגסט יומי תמציתי</span>'
+ '<h1 style="margin:2px 0 5px; font-size:22px; font-weight:800; letter-spacing:-0.5px;">חדשות תוכנה ובינה מלאכותית</h1>'
+ '<p style="margin:0; font-size:13px; opacity:0.85;">יום ' + todayName + ', ' + dateStr + ' • ' + totalWords + ' מילים בדיגסט</p>'
+ '</div>'
+ '<div style="background:#ffffff; padding:22px 20px; border:1px solid #e2e8f0; border-top:none;">'
+ softwareHtml
+ aiHtml
+ '</div>'
+ '<div style="background:#f8fafc; padding:14px 20px; border-radius:0 0 12px 12px; border:1px solid #e2e8f0; border-top:none; text-align:center; font-size:12px; color:#64748b;">'
+ 'נשלח אוטומטית ממתמחים טופ • ' + hebrewDate + ' • דיגסט קצר (עד 350 מילים) מבוסס Gemini'
+ '</div></body></html>';
}// ========== קריאה ל-Gemini עם רוטציית מפתחות ומודלים ==========
function mm_getAllApiKeys() {
var props = PropertiesService.getScriptProperties();
var scriptPropKey = props.getProperty('MM_GEMINI_API_KEY') || props.getProperty('AI7_GEMINI_API_KEY');
var allKeys = [];
if (scriptPropKey) allKeys.push(scriptPropKey);
if (MM_CONFIG.apiKeys && MM_CONFIG.apiKeys.length > 0) {
for (var i = 0; i < MM_CONFIG.apiKeys.length; i++) {
var k = MM_CONFIG.apiKeys[i];
if (k && allKeys.indexOf(k) === -1) allKeys.push(k);
}
}
return allKeys;
}function mm_callGemini(prompt) {
var models = MM_CONFIG.geminiModels;
var keys = mm_getAllApiKeys();
var lastError = null;if (keys.length === 0) throw new Error('לא נמצאו מפתחות Gemini מוגדרים');
for (var m = 0; m < models.length; m++) {
var model = models[m];for (var k = 0; k < keys.length; k++) { var apiKey = keys[k]; try { var resultText = mm_geminiApiCall(prompt, model, apiKey); Logger.log('MM: הצלחה עם מודל %s באמצעות מפתח #%s', model, (k + 1)); return { text: resultText, model: model, keyIndex: k }; } catch (err) { lastError = err; Logger.log('MM: מפתח #%s נכשל עם מודל %s (%s). מנסה מפתח חלופי...', (k + 1), model, err.message); if (k < keys.length - 1) Utilities.sleep(MM_CONFIG.retryDelayMs); } } Logger.log('MM: כל %s המפתחות נכשלו עבור מודל %s. עובר למודל הבא ברשימה...', keys.length, model);}
throw new Error('כל המודלים וכל המפתחות נכשלו. שגיאה אחרונה: ' + (lastError ? lastError.message : 'לא ידועה'));
}function mm_geminiApiCall(prompt, model, apiKey) {
if (!apiKey) throw new Error('מפתח API ריק');var url = 'https://generativelanguage.googleapis.com/v1beta/models/' + model + ':generateContent?key=' + apiKey;
var generationConfig = {
temperature: MM_CONFIG.temperature || 0.2,
maxOutputTokens: MM_CONFIG.maxOutputTokens || 1500
};if (MM_CONFIG.disableThinking) {
generationConfig.thinkingConfig = { thinkingBudget: 0 };
}var body = {
contents: [{ parts: [{ text: prompt }] }],
generationConfig: generationConfig
};var headers = {
'Content-Type': 'application/json',
'x-goog-api-key': apiKey
};if (apiKey.indexOf('AQ.') === 0 || apiKey.indexOf('ya29.') === 0) {
headers['Authorization'] = 'Bearer ' + apiKey;
}var options = {
method: 'post',
contentType: 'application/json',
headers: headers,
payload: JSON.stringify(body),
muteHttpExceptions: true
};var r = UrlFetchApp.fetch(url, options);
var code = r.getResponseCode();if (code >= 300) {
throw new Error('Gemini API HTTP ' + code + ': ' + r.getContentText().substring(0, 200));
}var data = JSON.parse(r.getContentText());
var candidate = data.candidates && data.candidates[0];if (!candidate || !candidate.content || !candidate.content.parts) {
throw new Error('התקבלה תשובה ריקה מ-Gemini');
}var textParts = [];
for (var p = 0; p < candidate.content.parts.length; p++) {
var part = candidate.content.parts[p];
if (part.text && !part.thought) textParts.push(part.text);
}var out = textParts.join('').trim();
if (!out && candidate.content.parts[0] && candidate.content.parts[0].text) {
out = candidate.content.parts[0].text.trim();
}if (!out) throw new Error('התקבל טקסט ריק מ-Gemini');
return out;
}// ========== עזרים, זמנים ונעילת יום ==========
function mm_getTodayStartTimestamp() {
var now = new Date();
var start = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
return start.getTime();
}function mm_todayKey() {
return Utilities.formatDate(new Date(), MM_CONFIG.triggerTimeZone, 'yyyy-MM-dd');
}function mm_alreadySentToday() {
var props = PropertiesService.getScriptProperties();
return props.getProperty('MM_LAST_SENT_DATE') === mm_todayKey();
}function mm_markSentToday() {
PropertiesService.getScriptProperties().setProperty('MM_LAST_SENT_DATE', mm_todayKey());
}function mm_getRecipients() {
var props = PropertiesService.getScriptProperties();
var raw = props.getProperty('MM_RECIPIENTS') || MM_CONFIG.defaultRecipients;
return raw.split(',').map(function(s) { return s.trim(); }).filter(function(s) { return s.length > 0; });
}function mm_getSentTopics() {
var raw = PropertiesService.getScriptProperties().getProperty('MM_SENT_TOPICS');
if (!raw) return {};
try { return JSON.parse(raw); } catch (e) { return {}; }
}function mm_markTopicSent(key) {
var sent = mm_getSentTopics();
sent[key] = new Date().getTime();
var cutoff = new Date().getTime() - (14 * 24 * 60 * 60 * 1000);
for (var k in sent) {
if (sent[k] < cutoff) delete sent[k];
}
PropertiesService.getScriptProperties().setProperty('MM_SENT_TOPICS', JSON.stringify(sent));
}function mm_isTopicSent(key) {
return !!mm_getSentTopics()[key];
}function mm_clearHistory() {
PropertiesService.getScriptProperties().deleteProperty('MM_SENT_TOPICS');
PropertiesService.getScriptProperties().deleteProperty('MM_LAST_SENT_DATE');
Logger.log('היסטוריית מתמחים טופ אופסה בהצלחה');
}function mm_fetchUrl(url) {
try {
var r = UrlFetchApp.fetch(url, {
method: 'get',
muteHttpExceptions: true,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
'Accept': 'application/json, text/html;q=0.9,/;q=0.8',
'Accept-Language': 'he-IL,he;q=0.9,en-US;q=0.8,en;q=0.7'
}
});
if (r.getResponseCode() >= 300) return null;
return r.getContentText('UTF-8');
} catch (e) {
return null;
}
}function mm_stripHtml(s) {
if (!s) return '';
return s.replace(/<[^>]+>/g, ' ')
.replace(/ /g, ' ')
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, "'")
.replace(/&#(\d+);/g, function(_, n) { return String.fromCharCode(parseInt(n)); })
.replace(/\s+/g, ' ')
.trim();
}function mm_hebrewDate() {
try {
var now = new Date();
var month = now.getMonth() + 1;
var hebrewMonths = ['שבט','אדר','ניסן','אייר','סיוון','תמוז','אב','אלול','תשרי','חשוון','כסלו','טבת'];
return now.getDate() + ' ב' + hebrewMonths[month - 1] + ' ' + (now.getFullYear() + 3760);
} catch (e) {
return new Date().toLocaleDateString('he-IL');
}
}// ========== פונקציות הפעלה ידנית (ללא התנגשות) ==========
function בדיקת_דיגסט_מתמחים() {
PropertiesService.getScriptProperties().deleteProperty('MM_LAST_SENT_DATE');
Logger.log('מתחיל בדיקה ידנית של דיגסט מתמחים טופ...');
mm_digestMain();
return 'בדיקת מתמחים הושלמה - בדוק את לוג הביצוע ואת תיבת המייל שלך!';
}function איפוס_נעילת_מתמחים() {
mm_clearHistory();
return 'נעילת מתמחים טופ והיסטוריית הפוסטים אופסו בהצלחה';
}function הגדרת_טריגר_מתמחים() {
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() === 'mm_digestMain') {
ScriptApp.deleteTrigger(triggers[i]);
}
}ScriptApp.newTrigger('mm_digestMain')
.timeBased()
.everyDays(1)
.atHour(MM_CONFIG.triggerHour)
.inTimezone(MM_CONFIG.triggerTimeZone)
.create();Logger.log('נוצר טריגר יומי ייעודי למתמחים טופ לשעה %s:00', MM_CONFIG.triggerHour);
return 'טריגר יומי נוצר בהצלחה לשעה ' + MM_CONFIG.triggerHour + ':00';
} -
מכניסים לגוגל סקיפט ומאשרים,
לא לשכוח להוסיף מייל
ומפתח API של גמיני
// ============================================================
// מתמחים טופ - דיגסט יומי: תוכנות חדשות שנוצרו + עדכוני AI
// גרסה: 2.2 (רוטציית 6 מפתחות + 7 מודלי Gemini + עד 350 מילים בסך הכל!)
// פועל לצד שלוחה 7 ללא שום התנגשות (קידומת ייחודית: mm_*)
// ============================================================var MM_CONFIG = {
forumBaseUrl: 'https://mitmachim.top',
recentApiUrl: 'https://mitmachim.top/api/recent',
unreadApiUrl: 'https://mitmachim.top/api/unread',// מזהה אשכול חדשות ה-AI הרשמי
aiTopicId: 95167,
aiTopicUrl: 'https://mitmachim.top/topic/95167/שיתוף-מה-חדש-בבינה-מלאכותית-נספח-עדכוני-פיצ-רים-ודיונים',// הגבלה קריטית: סך כל המילים בכל הדיגסט ביחד לא יעלה על 350 מילים!
maxTotalWords: 350,
maxSoftwareItems: 8,
maxAiPostsToScan: 15,triggerHour: 22,
triggerTimeZone: 'Asia/Jerusalem',email: {
senderName: 'מתמחים טופ - עדכונים יומיים',
subjectPrefix: 'מתמחים טופ: תוכנות חדשות ו-AI - '
},defaultRecipients: 'כאן לרשום מייל',
// 7 מודלי Gemini לסריקה לפי סדר עדיפות מדויק
geminiModels: [
'gemini-3-flash-preview',
'gemini-2.5-flash',
'gemini-3.5-flash-lite',
'gemini-3.1-flash-lite',
'gemini-2.5-flash-lite'
],// מאגר 6 מפתחות API - אם אחד נכשל עובר מיידית לבא בתור!
apiKeys: [
'כאן לרשום מפתח API',
'',
'',
'',
'',
''
],maxOutputTokens: 1500,
disableThinking: true,
temperature: 0.2,
retryDelayMs: 600
};// ========== הפונקציה הראשית ==========
function mm_digestMain() {
try {
Logger.log('=== מתמחים טופ - דיגסט יומי מתחיל ===');if (mm_alreadySentToday()) { Logger.log('כבר נשלח דיגסט מתמחים להיום - מדלג על הרצה חוזרת'); return; } var recipients = mm_getRecipients(); if (recipients.length === 0) { Logger.log('לא הוגדרו נמענים - מפסיק'); return; } var days = ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת']; var todayName = days[new Date().getDay()]; var hebrewDate = mm_hebrewDate(); var dateStr = new Date().toLocaleDateString('he-IL'); // 1. שלב א': איתור וסינון תוכנות חדשות בלבד מהפורום (מהיום בלבד!) Logger.log('--- שלב 1: חיפוש תוכנות חדשות שנוצרו/פורסמו היום ---'); var softwareItems = mm_fetchAndFilterNewSoftware(); Logger.log('נמצאו %s תוכנות חדשות אמיתיות מהיום', softwareItems.length); // 2. שלב ב': שליפת עדכוני AI מאשכול ה-AI (מהיום בלבד!) Logger.log('--- שלב 2: שליפת עדכוני AI מאשכול %s ---', MM_CONFIG.aiTopicId); var aiUpdates = mm_fetchTodayAiThreadUpdates(); Logger.log('נמצאו %s עדכוני AI רלוונטיים מהיום', aiUpdates.length); if (softwareItems.length === 0 && aiUpdates.length === 0) { Logger.log('אין תוכנות חדשות ואין עדכוני AI חדשים מהיום - לא נשלח מייל ריק'); return; } // 3. הגבלה קשיחה: סך כל המילים בכל הדיגסט כולו ביחד לא יעלה על 350 מילים! var limited = mm_enforceTotalWordLimit(softwareItems, aiUpdates, MM_CONFIG.maxTotalWords); softwareItems = limited.softwareItems; aiUpdates = limited.aiUpdates; Logger.log('סך מילים כולל בדיגסט: %s (מקסימום מותר: %s)', limited.totalWords, MM_CONFIG.maxTotalWords); // 4. עיצוב ושליחת המייל var htmlBody = mm_formatDigestEmail(softwareItems, aiUpdates, dateStr, todayName, hebrewDate, limited.totalWords); var subject = MM_CONFIG.email.subjectPrefix + dateStr + ' (' + softwareItems.length + ' תוכנות, ' + aiUpdates.length + ' עדכוני AI)'; for (var r = 0; r < recipients.length; r++) { MailApp.sendEmail({ to: recipients[r], subject: subject, htmlBody: htmlBody, name: MM_CONFIG.email.senderName }); Logger.log('מייל נשלח בהצלחה אל: %s', recipients[r]); } for (var s = 0; s < softwareItems.length; s++) { mm_markTopicSent(softwareItems[s].tid || softwareItems[s].url); } mm_markSentToday(); Logger.log('=== דיגסט מתמחים טופ הסתיים בהצלחה! סך מילים: %s ===', limited.totalWords);} catch (e) {
Logger.log('!!! שגיאה בהרצת דיגסט מתמחים: %s', e.stack || e.message);
}
}// ========== הגבלת מילים קפדנית: עד 350 מילים בסך הכל ==========
function mm_countWords(str) {
if (!str) return 0;
return str.trim().split(/\s+/).filter(function(w) { return w.length > 0; }).length;
}function mm_enforceTotalWordLimit(softwareItems, aiUpdates, maxLimit) {
var limit = maxLimit || 350;
var currentWords = 0;for (var i = 0; i < softwareItems.length; i++) {
currentWords += mm_countWords(softwareItems[i].softwareName) + mm_countWords(softwareItems[i].summary);
}
for (var j = 0; j < aiUpdates.length; j++) {
currentWords += mm_countWords(aiUpdates[j].headline) + mm_countWords(aiUpdates[j].bulletSummary);
}if (currentWords <= limit) {
return { softwareItems: softwareItems, aiUpdates: aiUpdates, totalWords: currentWords };
}Logger.log('חריגת מילים: נמצאו ' + currentWords + ' מילים. מקצץ לעד ' + limit + ' מילים בסך הכל...');
var totalItems = softwareItems.length + aiUpdates.length;
var targetWordsPerItem = Math.floor((limit - 20) / Math.max(1, totalItems));var trimmedSoftware = [];
var wordsUsed = 0;for (var s = 0; s < softwareItems.length; s++) {
var item = softwareItems[s];
var words = (item.summary || '').split(/\s+/).filter(Boolean);
if (words.length > targetWordsPerItem) {
item.summary = words.slice(0, targetWordsPerItem).join(' ') + '.';
}
wordsUsed += mm_countWords(item.softwareName) + mm_countWords(item.summary);
trimmedSoftware.push(item);
}var trimmedAi = [];
for (var a = 0; a < aiUpdates.length; a++) {
var ai = aiUpdates[a];
var remaining = limit - wordsUsed;
if (remaining <=
break;var aiWords = (ai.bulletSummary || '').split(/\s+/).filter(Boolean); if (aiWords.length > Math.min(targetWordsPerItem, remaining - 5)) { ai.bulletSummary = aiWords.slice(0, Math.min(targetWordsPerItem, remaining - 5)).join(' ') + '.'; } wordsUsed += mm_countWords(ai.headline) + mm_countWords(ai.bulletSummary); trimmedAi.push(ai);}
return { softwareItems: trimmedSoftware, aiUpdates: trimmedAi, totalWords: wordsUsed };
}// ========== שליפת תוכנות חדשות בלבד ==========
function mm_fetchAndFilterNewSoftware() {
var qualifiedSoftware = [];
var rawTopics = mm_fetchRecentTopics();
var todayStart = mm_getTodayStartTimestamp();for (var i = 0; i < rawTopics.length; i++) {
if (qualifiedSoftware.length >= MM_CONFIG.maxSoftwareItems) break;var topic = rawTopics[i]; var tid = String(topic.tid || topic.slug); var topicTimestamp = topic.timestamp || topic.lastposttime || 0; if (topicTimestamp < todayStart || mm_isTopicSent(tid)) continue; var title = (topic.title || '').trim(); if (mm_isObviouslyNotSoftware(title)) continue; var firstPostContent = mm_fetchTopicFirstPost(topic.tid, topic.slug); if (!firstPostContent || firstPostContent.length < 30) continue; try { var evaluation = mm_evaluateSoftwareWithGemini(title, firstPostContent, topic.categoryName || ''); if (evaluation && evaluation.isNewSoftware) { qualifiedSoftware.push({ tid: tid, title: title, softwareName: evaluation.softwareName || title, summary: evaluation.summary, version: evaluation.version || '', url: MM_CONFIG.forumBaseUrl + '/topic/' + (topic.slug || topic.tid), author: topic.user ? (topic.user.username || topic.user.displayname) : 'חבר פורום' }); Logger.log('✓ אושרה תוכנה חדשה: %s', title); } else { Logger.log('✗ סונן (אינו תוכנה חדשה): %s', title); } Utilities.sleep(250); } catch (err) { Logger.log('שגיאה בניתוח נושא "%s": %s', title, err.message); }}
return qualifiedSoftware;
}function mm_isObviouslyNotSoftware(title) {
var lower = title.toLowerCase();
var skipPhrases = [
'עזרה', 'איך לעשות', 'מישהו יודע', 'למה לא עובד', 'בעיה ב', 'שגיאה',
'מחפש תוכנה', 'האם יש', 'בקשה:', 'דחוף', 'שאלה', 'לא מצליח', 'התקנה נכשלה',
'האם אפשר', 'בירור', 'חוות דעת', 'מחיר', 'קנייה', 'מכירה', 'מחשב נייד'
];
for (var i = 0; i < skipPhrases.length; i++) {
if (lower.indexOf(skipPhrases[i]) !== -1 && lower.indexOf('הורדה') === -1 && lower.indexOf('תוכנה חדשה') === -1) {
return true;
}
}
return false;
}function mm_fetchRecentTopics() {
try {
var endpoints = [MM_CONFIG.recentApiUrl, MM_CONFIG.unreadApiUrl];
for (var e = 0; e < endpoints.length; e++) {
var jsonStr = mm_fetchUrl(endpoints[e]);
if (jsonStr) {
var data = JSON.parse(jsonStr);
if (data.topics && data.topics.length > 0) return data.topics;
}
}
return [];
} catch (e) {
Logger.log('שגיאה בשליפת נושאים אחרונים: %s', e.message);
return [];
}
}function mm_fetchTopicFirstPost(tid, slug) {
try {
var url = MM_CONFIG.forumBaseUrl + '/api/topic/' + (slug || tid);
var jsonStr = mm_fetchUrl(url);
if (!jsonStr) return '';
var data = JSON.parse(jsonStr);
if (data.posts && data.posts.length > 0) {
return mm_stripHtml(data.posts[0].content || '').substring(0, 3000);
}
return '';
} catch (e) {
return '';
}
}function mm_evaluateSoftwareWithGemini(title, content, category) {
var prompt = 'אתה מסנן קפדני של עדכוני פורום מחשבים. המטרה: לזהות אך ורק תוכנות, אפליקציות, כלים או תוספים חדשים שנוצרו או פורסמו להורדה.\n'
+ 'כללים מחמירים:\n'
+ '1. אם הפוסט הוא שאלה, בקשת עזרה, בעיה טכנית, שאלת ייעוץ, בקשת תוכנה (למשל "מחפש תוכנה ל..."), או דיון כללי - החזר מיד isNewSoftware: false!\n'
+ '2. רק אם מדובר ביוצר שמשתף כלי/תוכנה שהוא פיתח, או שחרור של תוכנה/כלי חדש להורדה - החזר isNewSoftware: true.\n'
+ '3. ספק סיכום קצרצר ותמציתי ביותר בעברית (משפט אחד או שניים בלבד, עד 25 מילים). המייל כולו מוגבל ל-350 מילים!\n'
+ '4. החזר אך ורק JSON תקין במבנה הבא ללא שום טקסט נוסף:\n'
+ '{\n'
+ ' "isNewSoftware": true/false,\n'
+ ' "softwareName": "שם התוכנה או הכלי",\n'
+ ' "summary": "סיכום תמציתי של משפט עד שניים.",\n'
+ ' "version": "גרסה אם קיימת"\n'
+ '}\n\n'
+ 'כותרת הפוסט: ' + title + '\n'
+ 'תוכן הפוסט:\n' + content.substring(0, 2000);var res = mm_callGemini(prompt);
var cleanJson = res.text.replace(/json/gi, '').replace(//g, '').trim();
try {
return JSON.parse(cleanJson);
} catch (err) {
var jsonMatch = cleanJson.match(/{[\s\S]*}/);
if (jsonMatch) return JSON.parse(jsonMatch[0]);
return null;
}
}// ========== שליפת עדכוני AI מאשכול 95167 ==========
function mm_fetchTodayAiThreadUpdates() {
try {
var todayStart = mm_getTodayStartTimestamp();
var topicApiUrl = MM_CONFIG.forumBaseUrl + '/api/topic/' + MM_CONFIG.aiTopicId;
var jsonStr = mm_fetchUrl(topicApiUrl);
if (!jsonStr) return [];var data = JSON.parse(jsonStr); var posts = data.posts || []; var postCount = data.postcount || 0; if (postCount > 20 && data.pagination && data.pagination.pageCount > 1) { var lastPageUrl = topicApiUrl + '?page=' + data.pagination.pageCount; var lastPageJson = mm_fetchUrl(lastPageUrl); if (lastPageJson) { var lastPageData = JSON.parse(lastPageJson); if (lastPageData.posts && lastPageData.posts.length > 0) { posts = lastPageData.posts; } } } var todayPosts = []; for (var i = posts.length - 1; i >= 0 && todayPosts.length < MM_CONFIG.maxAiPostsToScan; i--) { var p = posts[i]; var postTime = p.timestamp || 0; if (postTime >= todayStart) { var cleanText = mm_stripHtml(p.content || ''); if (cleanText.length > 40) { todayPosts.push({ pid: p.pid, index: p.index, user: p.user ? (p.user.username || p.user.displayname) : 'משתמש', content: cleanText.substring(0, 2500) }); } } } if (todayPosts.length === 0) return []; var combinedContent = todayPosts.map(function(item, idx) { return '[' + (idx + 1) + '] מאת ' + item.user + ':\n' + item.content; }).join('\n\n--- פוסט הבא ---\n\n'); var prompt = 'להלן פוסטים חדשים שפורסמו היום בפורום מתמחים טופ באשכול עדכוני בינה מלאכותית (AI).\n' + 'משימתך:\n' + '1. סנן שיחות סרק, שאלות טכניות פרטיות או תודות.\n' + '2. חלץ וסכם את החדשות והפיצ\'רים האמיתיים של בינה מלאכותית שנחשפו היום.\n' + '3. מגבלת מילים קריטית: סך כל המילים בכל הדיגסט מוגבל לעד 350 מילים! כתוב סיכום של משפט אחד בלבד (עד 20 מילים לפריט).\n' + '4. החזר אך ורק מערך JSON תקין ללא שום טקסט נוסף:\n' + '[\n' + ' {\n' + ' "headline": "כותרת קצרה של החידוש",\n' + ' "bulletSummary": "משפט תמציתי ומדויק על מה שהתחדש.",\n' + ' "sourceUser": "שם המשתמש ששיתף"\n' + ' }\n' + ']\n\n' + combinedContent; var res = mm_callGemini(prompt); var cleanJson = res.text.replace(/```json/gi, '').replace(/```/g, '').trim(); var parsedList = []; try { parsedList = JSON.parse(cleanJson); } catch (e) { var match = cleanJson.match(/\[[\s\S]*\]/); if (match) parsedList = JSON.parse(match[0]); } for (var k = 0; k < parsedList.length; k++) { parsedList[k].url = MM_CONFIG.aiTopicUrl; } return parsedList;} catch (err) {
Logger.log('שגיאה בשליפת עדכוני אשכול AI: %s', err.message);
return [];
}
}// ========== עיצוב המייל (עד 350 מילים) ==========
function mm_formatDigestEmail(softwareItems, aiUpdates, dateStr, todayName, hebrewDate, totalWords) {
var softwareHtml = '';
if (softwareItems.length > 0) {
softwareHtml += '<div style="margin-bottom:24px;">'
+ '<div style="display:flex; align-items:center; margin-bottom:12px; border-bottom:2px solid #3b82f6; padding-bottom:6px;">'
+ '<span style="background:#3b82f6; color:#ffffff; font-size:11px; font-weight:bold; padding:2px 8px; border-radius:4px; margin-left:6px;">חדש בקהילה</span>'
+ '<h2 style="color:#0f172a; font-size:17px; margin:0; font-weight:800;">
תוכנות וכלים חדשים שפותחו/שוחררו היום (' + softwareItems.length + ')</h2>'
+ '</div>';for (var i = 0; i < softwareItems.length; i++) { var item = softwareItems[i]; softwareHtml += '<div style="background:#f8fafc; border:1px solid #e2e8f0; border-radius:8px; padding:14px 16px; margin-bottom:12px;">' + '<div style="display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:4px;">' + '<h3 style="color:#1e3a8a; font-size:15px; font-weight:700; margin:0; line-height:1.4;">' + (i + 1) + '. ' + item.softwareName + '</h3>' + (item.version ? '<span style="background:#e0e7ff; color:#3730a3; font-size:11px; font-weight:700; padding:2px 6px; border-radius:4px;">' + item.version + '</span>' : '') + '</div>' + '<p style="color:#334155; font-size:14px; line-height:1.65; margin:0 0 8px;">' + item.summary + '</p>' + '<div style="display:flex; justify-content:space-between; align-items:center; font-size:12px; color:#64748b;">' + '<span>שותף ע"י: <strong>' + item.author + '</strong></span>' + '<a href="' + item.url + '" target="_blank" style="color:#2563eb; text-decoration:none; font-weight:bold;">לפוסט המלא ולהורדה בפורום ←</a>' + '</div>' + '</div>'; } softwareHtml += '</div>';} else {
softwareHtml += '<div style="padding:12px; background:#f8fafc; border-radius:8px; border:1px dashed #cbd5e1; color:#64748b; font-size:13px; margin-bottom:20px; text-align:center;">'
+ 'לא פורסמו היום תוכנות חדשות נוספות שפותחו בקהילה.'
+ '</div>';
}var aiHtml = '';
if (aiUpdates.length > 0) {
aiHtml += '<div style="margin-bottom:20px;">'
+ '<div style="display:flex; align-items:center; margin-bottom:12px; border-bottom:2px solid #8b5cf6; padding-bottom:6px;">'
+ '<span style="background:#8b5cf6; color:#ffffff; font-size:11px; font-weight:bold; padding:2px 8px; border-radius:4px; margin-left:6px;">אשכול AI</span>'
+ '<h2 style="color:#0f172a; font-size:17px; margin:0; font-weight:800;">
מה חדש בבינה מלאכותית היום (' + aiUpdates.length + ')</h2>'
+ '</div>';for (var j = 0; j < aiUpdates.length; j++) { var ai = aiUpdates[j]; aiHtml += '<div style="border-right:3px solid #8b5cf6; background:#faf5ff; padding:10px 14px; margin-bottom:10px; border-radius:0 6px 6px 0;">' + '<h4 style="color:#581c87; font-size:14px; font-weight:700; margin:0 0 3px;">' + (j + 1) + '. ' + ai.headline + '</h4>' + '<p style="color:#334155; font-size:13.5px; line-height:1.6; margin:0 0 5px;">' + ai.bulletSummary + '</p>' + '<div style="font-size:12px; color:#7e22ce;">' + (ai.sourceUser ? '<span>משתף: ' + ai.sourceUser + ' • </span>' : '') + '<a href="' + ai.url + '" target="_blank" style="color:#7e22ce; font-weight:bold; text-decoration:none;">צפה באשכול ה-AI בפורום ←</a>' + '</div>' + '</div>'; } aiHtml += '</div>';} else {
aiHtml += '<div style="padding:12px; background:#f8fafc; border-radius:8px; border:1px dashed #cbd5e1; color:#64748b; font-size:13px; margin-bottom:20px; text-align:center;">'
+ 'לא היו עדכוני AI חדשים היום באשכול הייעודי.'
+ '</div>';
}return '<!DOCTYPE html><html dir="rtl" lang="he"><head><meta charset="UTF-8"></head>'
+ '<body style="font-family:Arial,Helvetica,sans-serif; direction:rtl; text-align:right; max-width:640px; margin:0 auto; padding:16px; background-color:#f1f5f9;">'
+ '<div style="background:linear-gradient(135deg,#0f172a 0%,#1e1b4b 100%); color:#ffffff; padding:24px 20px; border-radius:12px 12px 0 0; text-align:center;">'
+ '<span style="display:inline-block; background:rgba(59,130,246,0.3); color:#93c5fd; font-size:11px; font-weight:bold; padding:3px 10px; border-radius:999px; margin-bottom:8px;">מתמחים טופ • דיגסט יומי תמציתי</span>'
+ '<h1 style="margin:2px 0 5px; font-size:22px; font-weight:800; letter-spacing:-0.5px;">חדשות תוכנה ובינה מלאכותית</h1>'
+ '<p style="margin:0; font-size:13px; opacity:0.85;">יום ' + todayName + ', ' + dateStr + ' • ' + totalWords + ' מילים בדיגסט</p>'
+ '</div>'
+ '<div style="background:#ffffff; padding:22px 20px; border:1px solid #e2e8f0; border-top:none;">'
+ softwareHtml
+ aiHtml
+ '</div>'
+ '<div style="background:#f8fafc; padding:14px 20px; border-radius:0 0 12px 12px; border:1px solid #e2e8f0; border-top:none; text-align:center; font-size:12px; color:#64748b;">'
+ 'נשלח אוטומטית ממתמחים טופ • ' + hebrewDate + ' • דיגסט קצר (עד 350 מילים) מבוסס Gemini'
+ '</div></body></html>';
}// ========== קריאה ל-Gemini עם רוטציית מפתחות ומודלים ==========
function mm_getAllApiKeys() {
var props = PropertiesService.getScriptProperties();
var scriptPropKey = props.getProperty('MM_GEMINI_API_KEY') || props.getProperty('AI7_GEMINI_API_KEY');
var allKeys = [];
if (scriptPropKey) allKeys.push(scriptPropKey);
if (MM_CONFIG.apiKeys && MM_CONFIG.apiKeys.length > 0) {
for (var i = 0; i < MM_CONFIG.apiKeys.length; i++) {
var k = MM_CONFIG.apiKeys[i];
if (k && allKeys.indexOf(k) === -1) allKeys.push(k);
}
}
return allKeys;
}function mm_callGemini(prompt) {
var models = MM_CONFIG.geminiModels;
var keys = mm_getAllApiKeys();
var lastError = null;if (keys.length === 0) throw new Error('לא נמצאו מפתחות Gemini מוגדרים');
for (var m = 0; m < models.length; m++) {
var model = models[m];for (var k = 0; k < keys.length; k++) { var apiKey = keys[k]; try { var resultText = mm_geminiApiCall(prompt, model, apiKey); Logger.log('MM: הצלחה עם מודל %s באמצעות מפתח #%s', model, (k + 1)); return { text: resultText, model: model, keyIndex: k }; } catch (err) { lastError = err; Logger.log('MM: מפתח #%s נכשל עם מודל %s (%s). מנסה מפתח חלופי...', (k + 1), model, err.message); if (k < keys.length - 1) Utilities.sleep(MM_CONFIG.retryDelayMs); } } Logger.log('MM: כל %s המפתחות נכשלו עבור מודל %s. עובר למודל הבא ברשימה...', keys.length, model);}
throw new Error('כל המודלים וכל המפתחות נכשלו. שגיאה אחרונה: ' + (lastError ? lastError.message : 'לא ידועה'));
}function mm_geminiApiCall(prompt, model, apiKey) {
if (!apiKey) throw new Error('מפתח API ריק');var url = 'https://generativelanguage.googleapis.com/v1beta/models/' + model + ':generateContent?key=' + apiKey;
var generationConfig = {
temperature: MM_CONFIG.temperature || 0.2,
maxOutputTokens: MM_CONFIG.maxOutputTokens || 1500
};if (MM_CONFIG.disableThinking) {
generationConfig.thinkingConfig = { thinkingBudget: 0 };
}var body = {
contents: [{ parts: [{ text: prompt }] }],
generationConfig: generationConfig
};var headers = {
'Content-Type': 'application/json',
'x-goog-api-key': apiKey
};if (apiKey.indexOf('AQ.') === 0 || apiKey.indexOf('ya29.') === 0) {
headers['Authorization'] = 'Bearer ' + apiKey;
}var options = {
method: 'post',
contentType: 'application/json',
headers: headers,
payload: JSON.stringify(body),
muteHttpExceptions: true
};var r = UrlFetchApp.fetch(url, options);
var code = r.getResponseCode();if (code >= 300) {
throw new Error('Gemini API HTTP ' + code + ': ' + r.getContentText().substring(0, 200));
}var data = JSON.parse(r.getContentText());
var candidate = data.candidates && data.candidates[0];if (!candidate || !candidate.content || !candidate.content.parts) {
throw new Error('התקבלה תשובה ריקה מ-Gemini');
}var textParts = [];
for (var p = 0; p < candidate.content.parts.length; p++) {
var part = candidate.content.parts[p];
if (part.text && !part.thought) textParts.push(part.text);
}var out = textParts.join('').trim();
if (!out && candidate.content.parts[0] && candidate.content.parts[0].text) {
out = candidate.content.parts[0].text.trim();
}if (!out) throw new Error('התקבל טקסט ריק מ-Gemini');
return out;
}// ========== עזרים, זמנים ונעילת יום ==========
function mm_getTodayStartTimestamp() {
var now = new Date();
var start = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
return start.getTime();
}function mm_todayKey() {
return Utilities.formatDate(new Date(), MM_CONFIG.triggerTimeZone, 'yyyy-MM-dd');
}function mm_alreadySentToday() {
var props = PropertiesService.getScriptProperties();
return props.getProperty('MM_LAST_SENT_DATE') === mm_todayKey();
}function mm_markSentToday() {
PropertiesService.getScriptProperties().setProperty('MM_LAST_SENT_DATE', mm_todayKey());
}function mm_getRecipients() {
var props = PropertiesService.getScriptProperties();
var raw = props.getProperty('MM_RECIPIENTS') || MM_CONFIG.defaultRecipients;
return raw.split(',').map(function(s) { return s.trim(); }).filter(function(s) { return s.length > 0; });
}function mm_getSentTopics() {
var raw = PropertiesService.getScriptProperties().getProperty('MM_SENT_TOPICS');
if (!raw) return {};
try { return JSON.parse(raw); } catch (e) { return {}; }
}function mm_markTopicSent(key) {
var sent = mm_getSentTopics();
sent[key] = new Date().getTime();
var cutoff = new Date().getTime() - (14 * 24 * 60 * 60 * 1000);
for (var k in sent) {
if (sent[k] < cutoff) delete sent[k];
}
PropertiesService.getScriptProperties().setProperty('MM_SENT_TOPICS', JSON.stringify(sent));
}function mm_isTopicSent(key) {
return !!mm_getSentTopics()[key];
}function mm_clearHistory() {
PropertiesService.getScriptProperties().deleteProperty('MM_SENT_TOPICS');
PropertiesService.getScriptProperties().deleteProperty('MM_LAST_SENT_DATE');
Logger.log('היסטוריית מתמחים טופ אופסה בהצלחה');
}function mm_fetchUrl(url) {
try {
var r = UrlFetchApp.fetch(url, {
method: 'get',
muteHttpExceptions: true,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
'Accept': 'application/json, text/html;q=0.9,/;q=0.8',
'Accept-Language': 'he-IL,he;q=0.9,en-US;q=0.8,en;q=0.7'
}
});
if (r.getResponseCode() >= 300) return null;
return r.getContentText('UTF-8');
} catch (e) {
return null;
}
}function mm_stripHtml(s) {
if (!s) return '';
return s.replace(/<[^>]+>/g, ' ')
.replace(/ /g, ' ')
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, "'")
.replace(/&#(\d+);/g, function(_, n) { return String.fromCharCode(parseInt(n)); })
.replace(/\s+/g, ' ')
.trim();
}function mm_hebrewDate() {
try {
var now = new Date();
var month = now.getMonth() + 1;
var hebrewMonths = ['שבט','אדר','ניסן','אייר','סיוון','תמוז','אב','אלול','תשרי','חשוון','כסלו','טבת'];
return now.getDate() + ' ב' + hebrewMonths[month - 1] + ' ' + (now.getFullYear() + 3760);
} catch (e) {
return new Date().toLocaleDateString('he-IL');
}
}// ========== פונקציות הפעלה ידנית (ללא התנגשות) ==========
function בדיקת_דיגסט_מתמחים() {
PropertiesService.getScriptProperties().deleteProperty('MM_LAST_SENT_DATE');
Logger.log('מתחיל בדיקה ידנית של דיגסט מתמחים טופ...');
mm_digestMain();
return 'בדיקת מתמחים הושלמה - בדוק את לוג הביצוע ואת תיבת המייל שלך!';
}function איפוס_נעילת_מתמחים() {
mm_clearHistory();
return 'נעילת מתמחים טופ והיסטוריית הפוסטים אופסו בהצלחה';
}function הגדרת_טריגר_מתמחים() {
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() === 'mm_digestMain') {
ScriptApp.deleteTrigger(triggers[i]);
}
}ScriptApp.newTrigger('mm_digestMain')
.timeBased()
.everyDays(1)
.atHour(MM_CONFIG.triggerHour)
.inTimezone(MM_CONFIG.triggerTimeZone)
.create();Logger.log('נוצר טריגר יומי ייעודי למתמחים טופ לשעה %s:00', MM_CONFIG.triggerHour);
return 'טריגר יומי נוצר בהצלחה לשעה ' + MM_CONFIG.triggerHour + ':00';
}
שלום! נראה שהשיחה הזו מעניינת אותך, אבל עדיין אין לך חשבון.
נמאס לכם לגלול בין אותם הפוסטים בכל ביקור? כשנרשמים לחשבון, תמיד תחזרו בדיוק למקום שבו הייתם קודם, ותוכלו לבחור לקבל התראות על תגובות חדשות (בין אם במייל, ובין אם בהתראת פוש). תוכלו גם לשמור סימניות ולפרגן ב-upvote לפוסטים כדי להביע הערכה לחברי קהילה אחרים.
בעזרת התרומה שלך, הפוסט הזה יכול להיות אפילו טוב יותר 💗
הרשמה התחברות