@איל-משולש כתב במודל פרסומות:
הוא מקיש משהו ואז אתה מקבל דקות
ולכן זה יצטרך להיות בתשלום, כדי שלא יחלק דקות לכל
השטיבל
@איל-משולש כתב במודל פרסומות:
הוא מקיש משהו ואז אתה מקבל דקות
ולכן זה יצטרך להיות בתשלום, כדי שלא יחלק דקות לכל
השטיבל
|-@הדיבל-המעופף פרסם מחדש כאן כולל קוד-|
ההגדרה בשלוחה:
type=api
api_link=https://listener-management.a775529301.workers.dev
api_add_0=token=טוקן
api_url_post=yes
שימו לב שמספר המאזין שיש להקיש כדי לנתב הוא מספר סידורי ולא מספר טלפון
נראה לי שאין כזה דבר עדיין, אז אני מתחיל:
ממשק להגדרת "מספר אישי" (Routing Yemot) בקליק אחד
העלאת קבצי שמע פלוס כותרת
ממשק לצפייה בדו"חות
ממשק לאקסס פילטר
מציג לוגים מתקדם
ממשק ליצירת שלוחות API
קובץ להגדרת שלוחת קבלת נתונים
העלאת קובץ tts בAPI
קובץ ליצירת מהירה של תשובת API
פורום ימות המשיח
קריינות VoiceMaster
פאנל ניהול מותאם אישית
העלאת שמע למקום מסויים
אינדקס המודלים
תוכנה ליצירת קבצי html
צפייה במאזינים כעת
ממשק ניהול מודל הגדרות דרך הטלפון
מחיקת כל ההודעות שבשלוחת השמעת קבצים
@isi
תודה אם היה לי איך לעשות לך לייק הייתי עושה
ואם אני מעביר למערכת אחרת ואז קונה יחידות למערכת החדשה זה גם יוסיף לו זמן
@עידו
רבנו אמר אין ייאוש בעולם כלל
בס"ד נפתחה קבוצה בגוגל צ'אט בנושא ימות המשיח, API ומה שביניהם.
הקבוצה כוללת הדרכות מקצועיות (לא אני כותב) בעיקר בנושאים הבאים: תקשורת של API ויצירת קוד לימות המשיח באמצעות בינה.
להצטרפות ניתן לפנות במייל.
כרגע הקבוצה פתוחה בנטפרי, נקווה שכך יהיה גם בהמשך.
@הדיבל-המעופף כדאי להוסיף אפשרות ליציאה מהשלוחה ב# (בינתיים אני מנתב את עצמי לשלוחה אחרת)
@פיתה הכנסת טוקן?
שימו לב שזה מוגדר למחיקת הודעות שהושארו לפני שלושה ימים - כי כתבתי את זה בשביל מה ש @י-ש-ל ביקש כאן, אפשר לשנות את מספר הדקות בשורה 10.
/**
* ==========================================
* הגדרות קבועות
* ==========================================
*/
const YEMOT_TOKEN_FALLBACK = 'טוקן'; // הכנס כאן את הטוקן שלך
const YEMOT_PATH = 'ivr2:נתיב'; // הכנס כאן את הנתיב לשלוחה (למשל: ivr2:1 או ivr2:1/2)
const MINUTES_TO_KEEP = 4320; // מספר הדקות לשמירה (4320 דקות = 3 ימים)
function getYemotToken() {
const fromProps = PropertiesService.getScriptProperties().getProperty('YEMOT_TOKEN');
return fromProps || YEMOT_TOKEN_FALLBACK;
}
/**
* ==========================================
* הפונקציה הראשית - בודקת את השלוחה ומוחקת קבצים ישנים
* ==========================================
*/
function deleteOldFiles() {
const token = getYemotToken();
var urlGet = 'https://www.call2all.co.il/ym/api/GetIVR2Dir?token=' + encodeURIComponent(token) + '&path=' + encodeURIComponent(YEMOT_PATH);
var stats = { checked: 0, deleted: 0, skippedSystem: 0, skippedFolder: 0, failed: 0 };
try {
var response = UrlFetchApp.fetch(urlGet, { muteHttpExceptions: true });
var data = JSON.parse(response.getContentText());
if (data.responseStatus !== 'OK' || !data.files) {
Logger.log('שגיאה בקבלת נתוני השלוחה (בדוק טוקן ונתיב): ' + JSON.stringify(data));
return;
}
var now = new Date();
// חישוב זמן התפוגה לפי MINUTES_TO_KEEP (המרת דקות למילישניות)
var expirationDate = new Date(now.getTime() - (MINUTES_TO_KEEP * 60 * 1000));
for (var i = 0; i < data.files.length; i++) {
var file = data.files[i];
var fileName = file.name;
var fileType = file.fileType;
stats.checked++;
// 0. דילוג על תיקיות
if (fileType === 'FOLDER' || fileType === 'DIR' || file.isFolder === true) {
stats.skippedFolder++;
continue;
}
// 1. דילוג על קבצי INI
if (fileType === 'INI' || fileName.toLowerCase().endsWith('.ini')) {
stats.skippedSystem++;
continue;
}
// 2. דילוג על הודעות מערכת של המשתמש (כגון M1000.wav)
if (/^[Mm]\d{4}\.(wav|mp3|ogg|wma)$/.test(fileName)) {
stats.skippedSystem++;
continue;
}
// 3. בדיקת תאריך הקובץ
if (file.mtime) {
var parts = file.mtime.split(/[- :]/);
if (parts.length === 6) {
var fileDate = new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]);
if (isNaN(fileDate.getTime())) {
Logger.log('תאריך לא תקין לקובץ ' + fileName + ': "' + file.mtime + '" - מדלג.');
continue;
}
if (fileDate < expirationDate) {
Logger.log('הקובץ ' + fileName + ' הועלה בתאריך ' + file.mtime + ' והתיישן. מתחיל מחיקה...');
var ok = deleteFileFromYemot(token, YEMOT_PATH + '/' + fileName);
if (ok) stats.deleted++; else stats.failed++;
}
}
}
}
Logger.log('סיכום ריצה: נבדקו ' + stats.checked + ', נמחקו ' + stats.deleted +
', דולגו (מערכת) ' + stats.skippedSystem + ', דולגו (תיקיות) ' + stats.skippedFolder +
', כשלונות מחיקה ' + stats.failed);
} catch (e) {
Logger.log('שגיאה כללית בתהליך: ' + e.toString());
}
}
/**
* ==========================================
* פונקציית עזר למחיקת הקובץ בפועל
* ==========================================
*/
function deleteFileFromYemot(token, filePath) {
var urlDelete = 'https://www.call2all.co.il/ym/api/FileAction';
var payload = {
'token': token,
'action': 'delete',
'what': filePath
};
var options = {
'method': 'post',
'payload': payload,
'muteHttpExceptions': true
};
try {
var response = UrlFetchApp.fetch(urlDelete, options);
var text = response.getContentText();
var result;
try {
result = JSON.parse(text);
} catch (parseErr) {
Logger.log('תגובה לא תקינה (לא JSON) למחיקת ' + filePath + ' -> ' + text);
return false;
}
if (result.responseStatus === 'OK') {
Logger.log('נמחק בהצלחה: ' + filePath);
return true;
}
Logger.log('מחיקה נכשלה עבור ' + filePath + ' -> ' + text);
return false;
} catch (e) {
Logger.log('שגיאה במחיקת ' + filePath + ': ' + e.toString());
return false;
}
}
/**
* ==========================================
* הגדרת הטריגר (להרצה פעם אחת בלבד מהעורך)
* ==========================================
*/
function setupTrigger() {
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() === 'deleteOldFiles') {
ScriptApp.deleteTrigger(triggers[i]);
}
}
ScriptApp.newTrigger('deleteOldFiles')
.timeBased()
.everyMinutes(1)
.create();
Logger.log('הטריגר הוגדר בהצלחה! הפונקציה deleteOldFiles תרוץ כעת אוטומטית פעם בדקה.');
}
@לימוד-בתורת-מרן הוספתי אפשרות אישור באנטר (במקום דווקא בכפתור "הגדר על שלוחה ראשית"):
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="UTF-8">
<title>הגדרת מספר אישי</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(45deg, #0f2027, #203a43, #2c5364);
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
margin: 0;
color: #fff;
}
.container {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(15px);
padding: 40px;
border-radius: 25px;
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
width: 380px;
border: 1px solid rgba(255, 255, 255, 0.1);
text-align: center;
}
h2 { margin-bottom: 30px; font-weight: 300; letter-spacing: 1px; }
label {
display: block;
text-align: right;
font-size: 13px;
opacity: 0.8;
margin: 10px 2px 2px;
}
input {
width: 100%;
padding: 14px;
margin: 4px 0;
border: none;
border-radius: 12px;
background: rgba(255, 255, 255, 0.05);
color: #fff;
font-size: 16px;
border: 1px solid rgba(255, 255, 255, 0.2);
transition: 0.3s;
box-sizing: border-box;
}
input:focus {
outline: none;
background: rgba(255, 255, 255, 0.15);
border-color: #00d2ff;
}
button {
width: 100%;
padding: 15px;
margin-top: 25px;
border: none;
border-radius: 12px;
background: linear-gradient(to right, #00d2ff, #3a7bd5);
color: white;
font-size: 18px;
font-weight: bold;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.3s, opacity 0.2s;
}
button:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(0, 210, 255, 0.4);
}
button:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
#status {
margin-top: 25px;
font-size: 14px;
font-weight: bold;
min-height: 20px;
}
.success { color: #00ffcc; }
.error { color: #ff6666; }
</style>
</head>
<body>
<div class="container">
<h2>הגדרת מספר אישי</h2>
<label for="systemNum">מספר מערכת</label>
<input type="text" id="systemNum" placeholder="מספר מערכת" inputmode="numeric" autocomplete="off">
<label for="password">סיסמת ניהול</label>
<input type="password" id="password" placeholder="סיסמת ניהול" autocomplete="current-password">
<button id="submitBtn" onclick="setupRouting()">הגדר על שלוחה ראשית</button>
<div id="status" role="status" aria-live="polite"></div>
</div>
<script>
const numInput = document.getElementById('systemNum');
const passInput = document.getElementById('password');
const submitBtn = document.getElementById('submitBtn');
const statusDiv = document.getElementById('status');
// אפשר גם לשלוח עם Enter מתוך שדה הסיסמה, לא רק בלחיצה על הכפתור
passInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') setupRouting();
});
async function setupRouting() {
const num = numInput.value.trim();
const pass = passInput.value;
if (!num || !pass) {
statusDiv.className = 'error';
statusDiv.innerText = 'אנא הזן מספר מערכת וסיסמה';
return;
}
submitBtn.disabled = true;
statusDiv.className = '';
statusDiv.innerText = 'מבצע הגדרה, נא להמתין...';
// קידוד תקין של כל פרמטר בנפרד - מונע שבירת הכתובת אם הסיסמה/המספר
// מכילים תווים מיוחדים כמו & # % + : וכד'.
const params = new URLSearchParams({
token: `${num}:${pass}`,
path: 'ivr2:/',
type: 'routing_yemot',
routing_yemot_number: num
});
const url = `https://www.call2all.co.il/ym/api/UpdateExtension?${params.toString()}`;
try {
const response = await fetch(url);
let data;
try {
data = await response.json();
} catch (parseErr) {
statusDiv.className = 'error';
statusDiv.innerText = 'התקבלה תשובה לא תקינה מהשרת';
return;
}
if (response.ok && data.responseStatus === 'OK') {
statusDiv.className = 'success';
statusDiv.innerText = `הוגדר בהצלחה מספר אישי למערכת ומספר המערכת: ${num}`;
} else {
statusDiv.className = 'error';
statusDiv.innerText = `לא ניתן להגדיר מספר אישי למערכת ${num}: סיסמה או מספר שגויים`;
}
} catch (error) {
statusDiv.className = 'error';
statusDiv.innerText = 'שגיאת תקשורת: ודא שיש חיבור אינטרנט תקין';
} finally {
submitBtn.disabled = false;
}
}
</script>
</body>
</html>
זה רעיון גאוני (אם הייתי יכול הייתי נותן לייק) אבל קצת מורכב כי אם הנתונים יגיעו אוטומטית ממי שיקישו * למעבר למפרסם - אנשים יעשו את זה וינתקו מייד, אבל לתת דקות טוקארד למפרסמים (זה בעצם סחר בברטר) כדי שיחלקו ללקוחות מעצמם - יכול להצליח מאד, רק שצריך כח אדם בשביל המערך הזה של דיווח לימות.
||אם כי קו המומלצים כן הצליח כמדומני||
@קו-המוסיקה
אני מצטרף זה גם קרה לי כמה וכמה פעמים
@מוטי-מוטי-מוטי בל"נ כשיהיה שם ממש תוכן מחוץ למדריכים אני אעלה אותו כאן.
@אריה-AI התוכן של הפוסט הראשון לא כ"כ קשור לנושא (רשימה מסודרת), שגם הוא חשוב.
@לימוד-בתורת-מרן כלומר ככה?
; הפעלת שמירת נתוני האזנה מתקדמים
log_playback_play_stop=yes
log_playback_play_stop_year_save_folder=yes
; חיבור למודול הנתונים
api_link=https://moduls.smartel.workers.dev/playfileListeningData.php
; api_add_0=token=הטוקן שלי
control_play6=send_api
api_add_1=offset=3000
api_add_2=say_listening_data=tfr
@שלוחה-404 מה ש @פישל כתב לפני 6 שנים זה הלכה למשה מסיני?
@איל-משולש אשמח אם תיצור איתי קשר במייל H4152280@GMAIL.COM - גם כדי שתסייע לי במשהו וגם בקשר לפוסט הזה
חשבתי שכדאי ליצור מייל שיקבל הודעות כתובות ויחזיר אותן כקובץ שמע, לתועלת מי שכל האתרים הסטנדרטים של הקראת טקסטים חסומים להם.
מה שצריך לעשות זה ככה(ע"פ גמיני):
א. להקדיש לעניין כתובת מייל (ולכן אני לא עושה את זה בעצמי).
ב. להיכנס לאתר Make.com ולהירשם (המסלול החינמי מאפשר עד 1,000 פעולות בחודש).
בלוח הבקרה (Dashboard), ללחוץ על הכפתור הסגול "+ Create a new scenario" בפינה העליונה.
ללחוץ על העיגול הגדול עם הפלוס במרכז המסך.
לחפש את האפליקציה "Gmail" ולבחור בה.
לבחור בפעולה "Watch Emails".
ג. ללחוץ על "Add" ולחבר את חשבון הג'ימייל שהוקדש לעניין. לבחור ב-"Inbox".
ללחוץ על OK. הוא ישאל מאיפה להתחיל – יש לבחור ב-"From now on".
ד. כעת צריך כלי שיקרא את הטקסט. נשתמש ב-Google Cloud Text-to-Speech (הוא הכי איכותי ותומך בעברית מצוין, לפי גמיני, ליידיש מומלץ להשתמש בOPENAI, כמו שיפורט בספוילר הקרוב):
tts-1-hd
או לחפש שירות בשם VoiceRSS שמציע API פשוט בחינם עד רמה מסוימת ללא צורך בהגדרות מורכבות.||
5. הגדרות:
he-IL
בפורמט הקובץ יש לבחור MP3.
ד. כעת יש לדאוג לשליחת הקובץ במייל חוזר:
פתרון אפשרי הוא להגדיר בשלוחה ששולחת את הצינתוקים
tzintuk_say_system_info_on_answer=no
ואז נשלחים צינתוקים ולא שיחות
אבל אני מחפש פתרון למי שכן רוצים לשלוח שיחה נכנסת כשיש הודעה חדשה.