• חדש! שמירת נקודת עצירה במהלך ההאזנה

    חדש במערכת
    5
    14 הצבעות
    5 פוסטים
    155 צפיות
    ל
    @Shulem NO
  • 2 הצבעות
    40 פוסטים
    270 צפיות
    ל
    @יענקי-פולק לחינם כן לא מעונין לשלם
  • 21 הצבעות
    163 פוסטים
    13k צפיות
    נ
    יש הודעות מערכת ? type=nitoviya המודול מאפשר חיוג לכל יעד רגיל בישראל על ידי הקשת מספר הטלפון או מקש חיוג מקוצר אישי שהמאזין יצר לעצמו במודול. כפי שהיה בעבר.
  • 2 הצבעות
    3 פוסטים
    20 צפיות
    ד
    @מ.ל.ל כתב: @דורש-3 לא הבנתי אם זה על קבוצה בלבד או על כל שיחה שיש לי עם משתמש ? שאלה מצוינת. התשובה הקצרה: זה עובד בדיוק אותו דבר, כי בגוגל צ'אט גם שיחה פרטית עם משתמש בודד היא בעצם חלל (Space), רק מסוג אחר. קבוצה היא חלל מסוג SPACE, ושיחה פרטית אחד על אחד היא חלל מסוג DIRECT_MESSAGE. מרגע שיש לכם את המזהה של החלל הפרטי, כל שאר המנגנון זהה, אותה בדיקה מחזורית ואותה תגובה. ההבדל היחיד הוא איך משיגים את המזהה של השיחה הפרטית, ואיך מטפלים בכמה שיחות במקביל. נסביר את שניהם. איך משיגים את מזהה השיחה הפרטית עם משתמש מסוים יש שתי דרכים. הדרך הפשוטה: שהמשתמש פשוט ישלח הודעה ראשונה לחשבון הבוט. מרגע שהוא כתב, לבוט כבר יש שיחה פתוחה איתו, ואתם יכולים לראות את מזהה השיחה. אפשר לראות אותו בכתובת של הדפדפן כשפותחים את השיחה, בדיוק כמו שמצאנו את מזהה הקבוצה. הדרך התכנותית: לתת לקוד למצוא או לפתוח את השיחה לבד, לפי מזהה המשתמש. מזהה המשתמש נראה כמו users ואחריו מספר ארוך, והוא מופיע בשדה sender של כל הודעה שאותו אדם כותב. הנה פונקציה שמוצאת את השיחה הפרטית עם משתמש נתון, ואם אין עדיין שיחה, פותחת אחת: // מחזירה את מזהה השיחה הפרטית עם משתמש מסוים (users/1234...) function getDmSpace(userId) { const token = ScriptApp.getOAuthToken(); // קודם מנסים למצוא שיחה קיימת const find = UrlFetchApp.fetch( 'https://chat.googleapis.com/v1/spaces:findDirectMessage?name=' + encodeURIComponent(userId), { headers: { Authorization: 'Bearer ' + token }, muteHttpExceptions: true }); if (find.getResponseCode() === 200) { return JSON.parse(find.getContentText()).name; // spaces/XXXX } // אם אין - פותחים שיחה חדשה עם המשתמש const setup = UrlFetchApp.fetch('https://chat.googleapis.com/v1/spaces:setup', { method: 'post', contentType: 'application/json', headers: { Authorization: 'Bearer ' + token }, payload: JSON.stringify({ space: { spaceType: 'DIRECT_MESSAGE' }, memberships: [{ member: { name: userId, type: 'HUMAN' } }] }), muteHttpExceptions: true }); if (setup.getResponseCode() === 200) { return JSON.parse(setup.getContentText()).name; } console.log('לא הצלחתי לפתוח שיחה', setup.getContentText()); return null; } איך גורמים לבוט לענות לכמה שיחות פרטיות במקביל הטריק היחיד שצריך לשים לב אליו הוא נקודת ההתחלה. בגרסת הקבוצה שמרנו חותמת זמן אחת בשם last. כשיש כמה שיחות, צריך חותמת זמן נפרדת לכל שיחה, אחרת הן ידרסו אחת את השנייה. פותרים את זה פשוט על ידי שמירת החותמת עם מפתח שכולל את מזהה השיחה. הנה גרסה של הלולאה הראשית שעוברת על רשימת חללים, קבוצות או שיחות פרטיות, ומטפלת בכל אחת בנפרד: // רשימת החללים שהבוט מאזין להם - אפשר לערבב קבוצות ושיחות פרטיות const SPACES = [ 'spaces/PASTE_GROUP_ID', // קבוצה 'spaces/PASTE_DM_ID' // שיחה פרטית עם משתמש מסוים ]; function checkAll() { for (const space of SPACES) { checkOneSpace(space); } } function checkOneSpace(space) { const props = PropertiesService.getScriptProperties(); const key = 'last_' + space; // חותמת זמן נפרדת לכל חלל const last = props.getProperty(key); if (!last) { props.setProperty(key, new Date().toISOString()); return; } const res = Chat.Spaces.Messages.list(space, { pageSize: 15, orderBy: 'createTime desc' }); const fresh = (res.messages || []).filter(m => m.createTime > last); if (!fresh.length) return; props.setProperty(key, fresh[0].createTime); fresh.reverse(); for (const m of fresh) { if (isSelf(m)) continue; const t = (m.text || '').trim(); if (!t) continue; // בשיחה פרטית לרוב לא צריך מילת הפעלה, כי כל הודעה מכוונת לבוט const answer = ask(t); if (answer) postTo(space, answer); } } // כמו post מהמדריך, רק שמקבל לאיזה חלל לכתוב function postTo(space, text) { UrlFetchApp.fetch('https://chat.googleapis.com/v1/' + space + '/messages', { method: 'post', contentType: 'application/json', headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }, payload: JSON.stringify({ text: text }), muteHttpExceptions: true }); } שימו לב לשני דברים. ראשון, את הטריגר של הדקה מפנים עכשיו לפונקציה checkAll במקום לפונקציה של חלל בודד. שני, בשיחה פרטית בדרך כלל מוותרים על מילת ההפעלה, כי כל הודעה בשיחה אחד על אחד ממילא מכוונת לבוט, אז אפשר פשוט לענות על הכל. בקבוצה כן משאירים מילת הפעלה כדי שהבוט לא יתפרץ לכל שיחה. מכשול אחד ששווה לדעת עליו מראש בפתיחת שיחה פרטית יזומה מצד הבוט, כלומר כשהבוט הוא זה שמתחיל את השיחה עם מישהו שעדיין לא כתב לו, יש מגבלות תלוי בסוג החשבון וההגדרות. הדרך היציבה ביותר, שכמעט תמיד עובדת, היא שהמשתמש ישלח לבוט הודעה אחת ראשונה. מאותו רגע השיחה קיימת, הבוט רואה אותה, ויכול לענות לה חופשי. אם אתם בונים את זה למשפחה או לקבוצה סגורה, פשוט תבקשו מכל אחד לכתוב לבוט שלום פעם אחת בהתחלה, וזהו. בקיצור, אין הבדל מהותי בין קבוצה למשתמש בודד. שניהם חללים, ואותו קוד מטפל בשניהם. ההבדל היחיד הוא מאיפה משיגים את המזהה, ולשמור חותמת זמן נפרדת לכל שיחה.
  • ספר טלפונים עם זיהוי דיבור

    טיפים עצות והדגמות מהמשתמשים
    233
    2 הצבעות
    233 פוסטים
    12k צפיות
    א
    @יצחק-המוכשר אבל אני כבר לא מתעסק עם הקוד הזה
  • חיבור גוגל צ'אט לGoogle Apps Script

    פורום מפתחים API
    7
    0 הצבעות
    7 פוסטים
    114 צפיות
    ד
    @מאיר-מלמד חיבור Google Chat ל-Apps Script, ומשם לימות דרך גישור מדריך מעשי למי שיש לו הבנה טכנית בסיסית. מסביר כל שלב, מה עושים, איך, ולמה. הפתרון כאן רץ אצלי בפועל, ובסוף יש דרך לבדוק בעצמכם שכל חלק עובד. מה בונים, ולמה דווקא ככה המטרה: בוט שיושב בקבוצת Google Chat, קורא את מה שנכתב, ומגיב או מעביר את זה הלאה. בשלב השני גם מזרים את ההודעות לקו טלפון בימות המשיח, כדי שאנשים בלי צ'אט יוכלו לחייג ולשמוע. לפני שמתחילים, חשוב להבין שתי דרכים שלא עובדות, כי רוב האנשים מבזבזים עליהן ימים. הדרך הראשונה שנכשלת היא Webhook נכנס. זה החיבור הרשמי שגוגל מציעה, אבל הכפתור ליצור Webhook פשוט אפור בחשבון פרטי, והוא זמין רק בחשבון עסקי מסוג Workspace Business עם הרשאות מנהל. חשבון Gmail רגיל, וגם חשבון Workspace יחיד בתשלום, לא יכולים. הדרך השנייה שנכשלת היא רישום אפליקציית Chat רשמית ב-Google Cloud. גם היא דורשת Workspace, וגם שם נתקעים על הרשאות הוספה של האפליקציה לקבוצה. הדרך שכן עובדת, וכמעט אף אחד לא מדבר עליה, היא לא לרשום שום בוט ולא ליצור שום Webhook. במקום זה פותחים חשבון גוגל רגיל, מכניסים אותו לקבוצה כחבר רגיל, ומריצים סקריפט שכל דקה שואל את גוגל אם יש הודעות חדשות. אם יש, הוא מגיב. כל הפעולות נעשות בזהות של אותו חשבון, בדיוק כמו בן אדם, אז אין צורך בשום רישום ובשום אישור מנהל. זה עובד גם בלי Workspace עסקי. היתרון: פשוט, חינמי, ועובד בחשבון פרטי. החיסרון: יש עיכוב של עד דקה, כי זו בדיקה מחזורית ולא דחיפה מיידית, והבוט מופיע כמשתמש רגיל ולא עם תווית של אפליקציה. המכשולים שתפגשו, מסודרים מראש לפני הקוד, כדאי לדעת מה מחכה, כי כל אחד מאלה עצר אנשים בדרך: החשבון שמריץ את הסקריפט חייב להיות חבר בקבוצה, אחרת הוא לא רואה כלום. פותחים את הסקריפט מהחשבון הזה, לא מהחשבון הפרטי שלכם. צריך להפעיל ידנית שירות שנקרא Advanced Chat Service, אחרת הפקודות לקריאת הודעות לא קיימות בכלל. בהרצה הראשונה גוגל מציגה מסך מפחיד שהאפליקציה לא מאומתת, וצריך לדעת לעבור אותו. בלי סימון של נקודת התחלה, הבוט יגיב לכל ההיסטוריה הישנה של הקבוצה בבת אחת. אם הבוט לא מזהה את ההודעות של עצמו, הוא נכנס ללולאה ומגיב לעצמו בלי סוף. וכשמגיעים לחלק של ימות, קריאה ישירה מ-Apps Script לשרת של ימות פשוט לא עוברת, וצריך רכיב מגשר באמצע. עכשיו נעבור שלב שלב. חלק א: לחבר את Google Chat ל-Apps Script שלב 1: חשבון בוט ייעודי פותחים או לוקחים חשבון גוגל נפרד שישמש כבוט. לא החשבון האישי שלכם, כי כל מה שהבוט יכתוב יופיע בשם החשבון הזה. נכנסים לחשבון הזה, נכנסים ל-Google Chat, ומוודאים שהוא חבר בקבוצה שבה הבוט אמור לפעול. אם הוא לא חבר, הוא לא יראה הודעות ולא יוכל לכתוב. המכשול הראשון טריוויאלי אבל קורה. שלב 2: פתיחת פרויקט Apps Script נכנסים לכתובת script.google.com. שימו לב היטב: צריך להיות מחוברים לחשבון של הבוט, לא לשלכם. אם יש לכם כמה חשבונות גוגל פתוחים בדפדפן, הכי בטוח לפתוח חלון גלישה פרטית ולהיכנס רק עם חשבון הבוט. זה מונע את הטעות הכי נפוצה, שבה הסקריפט נוצר בטעות תחת החשבון הלא נכון וכל ההרשאות אחר כך מתייחסות לחשבון הלא נכון. לוחצים על פרויקט חדש. קיבלתם עורך קוד שרץ על השרתים של גוגל בחינם, בלי להתקין כלום. שלב 3: הפעלת שירות ה-Chat שלב שאי אפשר לדלג עליו. בצד שמאל של העורך יש רשימה שנקראת Services עם סימן פלוס לידה. לוחצים על הפלוס, בוחרים מהרשימה את Google Chat API, ולוחצים Add. מה שזה עושה: מוסיף לקוד שלכם אובייקט בשם Chat שדרכו קוראים וכותבים הודעות. בלי זה, השורה שקוראת את ההודעות תיתן שגיאה שהמשתנה Chat לא מוגדר. הרבה אנשים מדביקים קוד, מקבלים את השגיאה הזאת, וחושבים שהקוד שבור, כשבעצם הם רק דילגו על השלב הזה. שלב 4: מציאת מזהה הקבוצה לכל קבוצה ב-Chat יש מזהה שנראה כמו spaces/AAAAxxxxxxx. הדרך הכי פשוטה להשיג אותו: פותחים את הקבוצה ב-Google Chat בדפדפן, ומסתכלים על שורת הכתובת למעלה. החלק שאחרי המילה space הוא המזהה. מעתיקים אותו בצד, נצטרך אותו בקוד. שלב 5: הקוד המלא מוחקים את מה שהיה בעורך ומדביקים את הקוד הזה במלואו. משנים רק שתי שורות למעלה: מזהה הקבוצה, ואם רוצים תשובות חכמות גם מפתח של Gemini. אם לא שמים מפתח Gemini, הבוט עדיין עובד ומגיב בתשובה פשוטה, כדי שתראו שהמנגנון חי. // ===== הגדרות - שנו רק את השתיים הראשונות ===== const SPACE = 'spaces/PASTE_SPACE_ID'; // מזהה הקבוצה משלב 4 const GEMINI_API_KEY = 'PASTE_GEMINI_KEY'; // אופציונלי - אפשר להשאיר ריק const GEMINI_MODEL = 'gemini-flash-lite-latest'; const TRIGGER = /בוט/i; // מילת ההפעלה בהודעה // ===== הלולאה הראשית - רצה כל דקה מהטריגר ===== function checkMessages() { const props = PropertiesService.getScriptProperties(); const last = props.getProperty('last'); // הרצה ראשונה: רק לסמן נקודת התחלה, בלי להגיב להיסטוריה if (!last) { props.setProperty('last', new Date().toISOString()); return; } // ההודעות האחרונות, רק חדשות מנקודת ההתחלה const res = Chat.Spaces.Messages.list(SPACE, { pageSize: 15, orderBy: 'createTime desc' }); const fresh = (res.messages || []).filter(m => m.createTime > last); if (!fresh.length) return; // לעדכן את נקודת ההתחלה מיד, לפני שמגיבים props.setProperty('last', fresh[0].createTime); fresh.reverse(); // לטפל מהישן לחדש for (const m of fresh) { if (isSelf(m)) continue; // לא להגיב לעצמו - מונע לולאה const t = (m.text || '').trim(); if (!t || !TRIGGER.test(t)) continue; // מגיב רק כשכתבו את מילת ההפעלה const answer = ask(t); if (answer) post(answer); } } // ===== האם ההודעה היא של הבוט עצמו ===== function isSelf(m) { const me = Session.getActiveUser().getEmail(); // המייל של חשבון הבוט return m.sender && m.sender.email && m.sender.email === me; } // ===== שאלה ל-Gemini, או תשובת ברירת מחדל אם אין מפתח ===== function ask(question) { if (!GEMINI_API_KEY || GEMINI_API_KEY.indexOf('PASTE') === 0) { return 'קיבלתי: ' + question; // מצב בדיקה בלי Gemini } const url = 'https://generativelanguage.googleapis.com/v1beta/models/' + GEMINI_MODEL + ':generateContent?key=' + GEMINI_API_KEY; const body = { contents: [{ role: 'user', parts: [{ text: question }] }] }; const r = UrlFetchApp.fetch(url, { method: 'post', contentType: 'application/json', payload: JSON.stringify(body), muteHttpExceptions: true }); if (r.getResponseCode() !== 200) { console.log('Gemini', r.getContentText()); return null; } try { return JSON.parse(r.getContentText()).candidates[0].content.parts.map(p => p.text).join('').trim(); } catch (e) { return null; } } // ===== כתיבת הודעה לקבוצה, בזהות חשבון הבוט ===== function post(text) { UrlFetchApp.fetch('https://chat.googleapis.com/v1/' + SPACE + '/messages', { method: 'post', contentType: 'application/json', headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }, payload: JSON.stringify({ text: text }), muteHttpExceptions: true }); } הסבר קצר על החלקים החשובים, כי כדאי להבין ולא רק להעתיק. הפונקציה checkMessages היא הלב. היא שומרת בזיכרון של הסקריפט חותמת זמן בשם last, שהיא הזמן של ההודעה האחרונה שכבר טופלה. בכל ריצה היא מבקשת את חמש עשרה ההודעות האחרונות, מסננת רק את אלה שחדשות יותר מ-last, ומטפלת בהן. הסינון הזה מונע מהבוט להגיב שוב ושוב לאותן הודעות. הפונקציה isSelf בודקת אם השולח הוא הבוט עצמו, לפי כתובת המייל, וזה מונע את הלולאה האינסופית שבה הבוט מגיב לתשובות של עצמו. הכתיבה חזרה נעשית עם ScriptApp.getOAuthToken, שזה מפתח הגישה הזמני של החשבון שמריץ את הסקריפט, כלומר הבוט כותב כאילו הוא יושב ומקליד בעצמו. שלב 6: הרצה ראשונה ומעבר במסך ההרשאות בוחרים למעלה בעורך את הפונקציה checkMessages מהרשימה הנפתחת, ולוחצים Run. כאן מגיע מכשול שמבלבל הרבה אנשים. גוגל תעצור ותבקש הרשאות, כי הקוד רוצה לגשת לצ'אט ולאינטרנט. מאשרים. אחר כך יופיע מסך אדום שאומר שהאפליקציה לא מאומתת ו-Google לא בדקה אותה. זה נשמע מפחיד אבל תקין לגמרי, כי זו אפליקציה פרטית שאתם עצמכם כתבתם רק לעצמכם. לוחצים על Advanced או על האפשרויות המתקדמות למטה, ואז על השורה שאומרת Go to project ולהמשיך. מאשרים את ההרשאות עד הסוף. חשוב לדעת שההרצה הראשונה הזאת לא תעשה שום דבר גלוי. היא רק תרשום את חותמת הזמן ההתחלתית ותצא. זה בכוונה, כדי שהבוט לא יריק על הקבוצה תגובות לכל ההיסטוריה הישנה. אם דילגתם על השלב הזה, זה בדיוק המקור לתופעה שבה הבוט פתאום מגיב להמון הודעות ישנות. שלב 7: הגדרת בדיקה אוטומטית כל דקה עד עכשיו הסקריפט רץ רק כשלוחצים Run. כדי שיהפוך לבוט חי, צריך טריגר שמריץ אותו לבד. בצד שמאל בעורך יש אייקון של שעון מעורר, שנקרא Triggers. נכנסים לשם, לוחצים על Add Trigger למטה מימין, ובוחרים: הפונקציה checkMessages, מקור האירוע Time-driven, סוג Minutes timer, ותדירות Every minute. שומרים. מרגע זה גוגל מריצה את הבדיקה לבד כל דקה, גם כשהמחשב שלכם כבוי, כי הכל רץ בענן של גוגל. זה גם המקום להבין למה בכלל פולינג ולא Webhook. Webhook היה נותן תגובה מיידית, אבל הוא חסום בחשבון פרטי כמו שהסברנו. הפולינג, כלומר הבדיקה כל דקה, הוא מה שמאפשר לעקוף את החסימה הזאת לגמרי, במחיר של עד דקה עיכוב. שלב 8: בדיקה שהכל עובד נכנסים לקבוצה מהחשבון האישי שלכם, לא של הבוט, וכותבים הודעה שמכילה את מילת ההפעלה, למשל: בוט מה שלומך. ממתינים עד דקה. הבוט אמור לענות. אם הגדרתם מפתח Gemini תקבלו תשובה חכמה, ואם לא, תקבלו את המילים קיבלתי ואת מה שכתבתם, וזה כבר מוכיח שכל השרשרת עובדת. המכשולים הנפוצים, ואיך פותרים כל אחד הבוט לא עונה בכלל. תסתכלו בעורך על החלק Executions בצד שמאל. אם checkMessages לא רצה, הטריגר לא הוגדר, חזרו לשלב שבע. אם הוא רץ ונתן שגיאה על המשתנה Chat, לא הפעלתם את Advanced Chat Service, חזרו לשלב שלוש. אם הוא רץ בלי שגיאה אבל אין תגובה, כנראה חשבון הבוט לא באמת חבר בקבוצה, או שמזהה הקבוצה לא נכון. הבוט מגיב לעצמו בלולאה. זה קורה כשהבדיקה isSelf לא תופסת. ודאו שאתם מריצים את הסקריפט מחשבון הבוט, כי הבדיקה משווה מול המייל של החשבון שמריץ. אם החשבון לא נכון, ההשוואה נכשלת והלולאה מתחילה. הבוט הגיב להמון הודעות ישנות בבת אחת. דילגתם על ההרצה הראשונה הריקה. כבו את הטריגר, הריצו ידנית פעם אחת את checkMessages כדי לרשום נקודת התחלה טרייה, ואז הפעילו את הטריגר מחדש. תשובות Gemini חוזרות ריקות. או שהמפתח שגוי, או ששם המודל לא נתמך במפתח שלכם. אפשר לבדוק מול רשימת המודלים שהמפתח תומך בהם ולעדכן את שם המודל בהתאם. חלק ב: החיבור לימות, ולמה הוא חייב גישור כאן מגיע החלק שהכי חשוב להבין, ושהכי הרבה אנשים נכשלים בו בלי להבין למה. עד עכשיו הכל היה בתוך העולם של גוגל. הסקריפט קרא לשירותים של גוגל עצמה, ולכן הכל עבד חלק. ברגע שרוצים שהסקריפט יקרא החוצה, לשרת של ימות המשיח, נתקלים בקיר. הקריאה הישירה מ-Apps Script לשרת של ימות פשוט לא עוברת. לפני שסומכים על המילה שלי, זו בדיקה שכל אחד יכול להריץ ולראות במו עיניו. פותחים פונקציה זמנית בעורך, מדביקים את השורות האלה, ומריצים: function testYemotDirect() { const r = UrlFetchApp.fetch('https://www.call2all.co.il/ym/api/GetSession', { muteHttpExceptions: true }); console.log('קוד: ' + r.getResponseCode()); console.log('תשובה: ' + r.getContentText()); } כשמריצים את זה מ-Apps Script, מקבלים כשל ולא תשובה תקינה של ימות. אם תריצו בדיוק את אותה קריאה מהדפדפן או מהמחשב שלכם, היא כן תעבוד. ההבדל הוא לא הכתובת ולא הפקודה, אלא מאיפה הבקשה יוצאת. בקשה שיוצאת מהשרתים של גוגל לא מתקבלת אצל ימות. זו ההוכחה, והיא חוזרת על עצמה בכל פעם. הפתרון הוא לשים רכיב מגשר קטן באמצע, שיושב במקום שכן מורשה לדבר עם ימות. הרכיב מקבל את הבקשה מהסקריפט של גוגל ומעביר אותה הלאה לימות. הכלי הכי נוח לזה הוא Cloudflare Worker, שהוא סקריפט זעיר שרץ בענן של קלאודפלייר בחינם. הסקריפט של גוגל מדבר עם הגשר, והגשר מדבר עם ימות. ככה עוקפים את החסימה בלי לשנות כלום בקוד של הבוט עצמו. קוד הגשר: Cloudflare Worker זה כל הקוד של הגשר. הוא מקבל בקשה, מוודא שהיא מגיעה עם מילת סוד שרק אתם מכירים כדי שאף אחד אקראי לא ישתמש בו, ומעביר את התוכן לימות בפקודת העלאת קובץ: export default { async fetch(request, env) { if (request.method !== 'POST') { return new Response('POST only', { status: 405 }); } // הגנה: רק בקשות עם הסוד הנכון ממשיכות if (request.headers.get('X-Auth') !== env.SHARED_SECRET) { return new Response('forbidden', { status: 403 }); } const data = await request.json(); // { ext, file, contents } // בונים את הבקשה לימות בפורמט שהיא מצפה לו const form = new URLSearchParams(); form.set('token', env.YEMOT_TOKEN); // מספר-המערכת:סיסמה form.set('what', 'ivr2:' + data.ext + '/' + data.file); // יעד הקובץ form.set('contents', data.contents); // תוכן הטקסט const r = await fetch('https://www.call2all.co.il/ym/api/UploadTextFile', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: form }); return new Response(await r.text(), { status: r.status }); } }; מילות הסוד לא יושבות בקוד אלא בהגדרות הסודיות של ה-Worker. במסך של Cloudflare, תחת Settings ואז Variables, מוסיפים שני משתני סוד. הראשון YEMOT_TOKEN, שהערך שלו הוא מספר המערכת שלכם, נקודתיים, והסיסמה. השני SHARED_SECRET, שהוא סתם מחרוזת ארוכה ואקראית שאתם ממציאים, וישמש כמפתח בין הסקריפט לגשר. לאחר הפרסום תקבלו כתובת של ה-Worker, משהו שמסתיים ב-workers.dev, וזאת הכתובת שהסקריפט יפנה אליה. חיבור הסקריפט אל הגשר חוזרים לסקריפט של גוגל ומוסיפים את הפונקציה שמעבירה את ההודעות דרך הגשר. שנו את הכתובת ואת הסוד לאלה שלכם: const BRIDGE_URL = 'https://your-worker.workers.dev'; // כתובת ה-Worker const BRIDGE_SECRET = 'PASTE_YOUR_SHARED_SECRET'; // אותו סוד כמו ב-Worker const YEMOT_EXT = '5'; // מספר השלוחה בקו const YEMOT_FILE = '000.tts'; // הקובץ שהמחייגים ישמעו function syncToYemot() { const msgs = Chat.Spaces.Messages.list(SPACE, { pageSize: 10, orderBy: 'createTime desc' }) .messages || []; const withText = msgs.filter(m => m.text && m.text.trim()).reverse(); if (!withText.length) return; const lines = withText.map(m => { const who = m.sender && m.sender.displayName ? m.sender.displayName : 'בן משפחה'; return who + ' כתב: ' + m.text.trim(); }); const digest = 'ההודעות האחרונות בקבוצה. ' + lines.join('. '); UrlFetchApp.fetch(BRIDGE_URL, { method: 'post', contentType: 'application/json', headers: { 'X-Auth': BRIDGE_SECRET }, payload: JSON.stringify({ ext: YEMOT_EXT, file: YEMOT_FILE, contents: digest }), muteHttpExceptions: true }); } מוסיפים לפונקציה הזאת טריגר משלה, בדיוק כמו בשלב שבע, שירוץ כל דקה או כל שתי דקות. מעכשיו, כל מה שנכתב בקבוצה נאסף, נשלח לגשר, והגשר מעלה אותו לימות כקובץ טקסט שהמערכת מקריאה בקול לכל מי שמחייג לשלוחה. הוכחה שהגישור עובד יש שתי בדיקות פשוטות. הראשונה: הריצו ידנית את syncToYemot מהעורך, ואז בקו ימות היכנסו לשלוחה שהגדרתם, ותראו שהקובץ 000.tts נוצר עם התוכן. אם הוא שם, הגשר העביר בהצלחה. השנייה, שמוכיחה את כל השרשרת ביחד: כתבו הודעה בקבוצה, המתינו דקה או שתיים, וחייגו לקו. אם אתם שומעים את ההודעה מוקראת, הוכחתם שהכל עובד מקצה לקצה, מהצ'אט, דרך הסקריפט, דרך הגשר, ועד הטלפון. סיכום השרשרת כדי לראות את התמונה השלמה, זה מה שקורה בכל מחזור. מישהו כותב בקבוצת Google Chat. הסקריפט של Apps Script, שרץ כחבר רגיל בקבוצה, קורא את ההודעה בבדיקה המחזורית שלו. אם צריך להעביר לימות, הוא לא פונה לימות ישירות, כי זה חסום, אלא שולח את התוכן ל-Cloudflare Worker. ה-Worker, שיושב במקום שמורשה לדבר עם ימות, מעלה את הטקסט כקובץ TTS לשלוחה. מחייגים לקו ושומעים את ההודעות מוקראות. שום חלק בשרשרת לא דורש חשבון עסקי, ושום חלק לא שולח שיחות יוצאות, אז אין שום סיכון של חיוג לא רצוי. בהצלחה רבה!
  • הסבר

    פורום מפתחים API
    7
    1
    0 הצבעות
    7 פוסטים
    83 צפיות
    נ
    @שמעון-אדלר וגם לא במחשב שלך (זה קוד על המחשב)
  • 0 הצבעות
    1 פוסטים
    14 צפיות
    אין תגובות
  • 4 הצבעות
    87 פוסטים
    852 צפיות
    A
    @CUBASE זה טופל
  • 2 הצבעות
    64 פוסטים
    726 צפיות
    י
    @cubase האם תוכל לעשות החלפת ערכים שבמקום סימן ה= שבין הערכים, יוסיף לדוגמה שתי פסיקים?
  • 0 הצבעות
    9 פוסטים
    67 צפיות
    E
    @יעקב-יצחק אתה צודק פשוט חשבתי שזה יעלה כסף אבל @אa האלוף פשוט עזר לי באופן מטורף ממש צדיק
  • שלא יוכלו לענות לצינתוק חינמי

    שאלות ועזרה הדדית
    2
    0 הצבעות
    2 פוסטים
    24 צפיות
    5
    @זעליג בשלוחה שמפעילה את הצינתוק להגדיר: tzintuk_say_system_info_on_answer=no
  • Few people 1 ID

    לא נפתר שאלות ועזרה הדדית
    20
    0 הצבעות
    20 פוסטים
    69 צפיות
    S
    @שלוחה-404 but I want the system should Automatically recognize the phone number.
  • 3 הצבעות
    1 פוסטים
    23 צפיות
    אין תגובות
  • 8 הצבעות
    156 פוסטים
    1k צפיות
    פ
    @שלמה-גולד כתב: א. בעת עריכת קובץ, שיהיה אפשר לעצור באמצע ההשמעה, ולהמשיך לשמוע, בהקשה על מקש הרווח במחשב (בדומה לרוב תוכנות העריכה והשמע). טופל כעת אפשר לעצור באמצע עם הקשה על רווח כמו כן נוספו הקיצורים הבאים [image: 1786279497643-8f8b106d-935f-466d-b3ab-333d56d23e02-image.jpeg]
  • 7 הצבעות
    23 פוסטים
    174 צפיות
    מ
    @lavitoren-הטי-ל כתב: מדהים ביותר ממש ממשק קל נח וכיף לשימוש תודה רבה @lavitoren-הטי-ל כתב: נ. ב. אם יהיה אפשר לכתוב פוסטים דרך הקו זה יהיה מטורף לגמרי אם תוכל לסדר כזה דבר זה פשוט ליגה אחרת לא יודע עד כמה מנהלי הפורום ישמחו מזה
  • זה אמור לעבוד? בהקלטה או תא קולי למייל

    לא נפתר שאלות ועזרה הדדית
    4
    0 הצבעות
    4 פוסטים
    33 צפיות
    0
    @שמול אבל זה כן עובד: folder_up-1-
  • משחק ילדים מהפכני חדש בטלפון הכשר!!!👍✨

    בקשות לפיתוח
    10
    2 הצבעות
    10 פוסטים
    75 צפיות
    ח
    @יהודה-צ.-כ. כנראה שזאת הסיבה שבקו שלנו אוהבים מאוד את המשחקים - כי באמת הקו שלנו מיועד דווקא ללקויי ראייה ועיוורים, שהערוץ החזותי שלהם חלש, אבל הדמיון מאוד חזק. כשיש לי זמן לפתח משחקים אני מייצרת דברים באופן עצמאי, על בסיס שלוחה שבכל פעם, באופן אקראי, מפעילה מתוכה תת שלוחה אחרת. לא עשיתי את זה כבר הרבה זמן, אבל נדמה לי שהשתמשתי ב type=folder_play_random הדוגמה שהכי קל להסביר היא משחק סביבון לחנוכה: כל לחיצה על כפתור גורמת, כביכול לסיבוב של הסביבון, יש השמעה של מוזיקת סביבון ובסיומה המערכת בוחרת באופן אקראי נ. ג. ה או פ. כשכל אחד מהם מוביל למשימה מסוג אחר. המשחק שאני הייתי רוצה שמישהו יפתח נקרא "סיימון" זהו משחק זיכרון אלקטרוני עם 4 סוגי צלילים בהתאמה ל4 צבעים שונים. אני לא חושבת שזה צריך להיות מסובך בכלל, רק צריך לדעת לעבוד עם API (הלוואי עלי... אולי יום אחד) ואם כבר... אז הייתי רוצה שתהיה אפשרות למנהל לשנות כל פעם את סוגי הצלילים: פעם צלילים כמו במשחק המקורי, פעם מספרים, פעם מילים בנושא כלשהו וכן הלאה. וגם להרחיב את מספר הכפתורים- אם במשחק המקורי יש רק 4 כפתורים, הייתי רוצה שהמשתמש (הפעם המשתמש ולא המנהל) יוכל לבחור את כמות המקשים הפעילים, מ4 ועד 9. ודרך אגב,משחקים הם לא רק לילדים...
  • 0 הצבעות
    8 פוסטים
    32 צפיות
    M
    @שמול בסדר
  • בינה מלאכותית בפורום... | דעות ותובנות 🧑‍💻💻

    על הפורום
    18
    11 הצבעות
    18 פוסטים
    482 צפיות
    ש
    @וזכיני-לגדל @פלוס @cubase @שיחה-ממתינה שתדעו הכל תלוי בנוסח השאלה, איך מגדירים לבינה, מה הנקודה המרכזית בשאלה, רק כך תנצלו מטעויות..