קבצים ותוכנות לשימוש במערכות ימות המשיח
-
לאור כך שבתקופה האחרונה הרבה משתמשים יקרים כאן בפורום העלו לטובת כלל המשתמשים קבצי HTML שמקילים מאוד את השימוש במערכות ללא צורך להיכנס למערכת בכל פעם, חשבתי שכדאי לקבץ את כל הקבצים לשירשור אחד, כך יוכלו למצוא אותם בקלות.
אשמח שכל מי שנתקל בקבצים שעדיין לא הועלו כאן שיעדכן בשירשור עם הקרדיט למפתח.שימו לב! עקב בעיה בהעלאת הקבצים לפורום ניתן להורידם כאן.
https://mitmachim.top/assets/uploads/files/1766433643666-0ef717c9-96cf-4412-9005-b17ee5626ab9-downloads.rarבנוסף אני אעדכן את הקודים של הקבצים.
כדי לפותחם כקובץ יש להעתיק את הטקסט לקובץ טקסט פשוט >קובץ>שמור בשם,ולשמור בשם כל שהוא, ובסוף נקודה (.) ואז html. בנוסף בסוג קובץ לבחור All Files ואז שמור, וזהו.
סרטון לדוגמא
סרטון לדוגמארשימת הקבצים: (מתעדכן)
קובץ להוספת והגדרת שלוחות במערכות (מתעדכן)
קובץ להעלאת קבצי שמע למערכת
קובץ להוספת נקודות למאזינים
תוכנה להורדה של רשימת הצינתוקים למחשב
קובץ לצפייה בדוחות של קבלת נתונים
קובץ ליצירת שלוחות API
קובץ להורדת קבצים מהמערכת (קבצי wav, tts, ini, html) כולל אפשרות להמרה + אפשרות להורדת קבצים מרובים
קובץ להעלאה והורדה של כל סוגי הקבצים למערכות כולל קבצי ini - עם אפשרות להפעלת צינתוק בסיום העלאה!
קובץ להפעלת קמפיין - הנכנס לשלוחה במערכת -
קובץ להעלאת קבצי שמע למערכת (הקובץ מוגן מ f12 וללא בעיות אבטחה!)
הקוד המלא
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" lang="he" xml:lang="he" dir="rtl"> <head> <!-- a.c --> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>העלאת קבצי שמע למערכת טלפונית</title> <meta name="description" content="העלאת קבצי שמע למערכת טלפונית"> <meta http-equiv="content-language" content="he"> <style> body { background: #1100ff; color: #000000; } fieldset{ text-align: center; background: #bfffbf; border-radius:20px; width: 90%; height: 480px; margin: 0%; } h1{ color: #d5bfff; text-align: center; } </style> בס"ד </head> <body> <h1>טופס העלאת קבצים</h1> <form action="https://www.call2all.co.il/ym/api/UploadFile" method="POST" enctype="multipart/form-data" target="_blank"> <fieldset> <!-- כאן תכניס שם משתמש וסיסמה [עם נקודותיים ביניהם] --> <label>הכניסו מספר מערכת וסיסמה<br> [עם נקודותיים ביניהם] <strong>דוגמא: <br> 0773137770:123456</strong><br> </label>מספר מערכת וסיסמא:<input type="text" name="token" value="" required style="width:100%; height: 0.3in"> <!-- כאן תכניס את הכתובת אליה אתה רוצה שיעלה הקובץ, כולל שם הקובץ הסופי במערכת --> <label>הכניסו את נתיב השלוחה אליה אתה רוצה שיעלה הקובץ, כולל שם הקובץ הסופי במערכת, כמו בדוגמא, <br> סיומת הקובץ צריכה להיות תואמת לסיומת של הקובץ שאתם מעלים)<br> <strong>בהכנסת נתיב חובה לכתוב בתחילת הנתיב:<br> :ivr2 <br> ואז את נתיב השלוחה והקובץ, דוגמא: <br> (בדוגמא יכניס לשלוחה 4 את קובץ: 000.wev) <br> ivr2:4/000.wav </strong> </label><input type="text" name="path" value="ivr2:" required style="width:100%; height: 0.3in"> <!-- תיבת הכנסת הקובץ על ידי המשתמש --> <p> <input type="file" name="upload" required style="width:100%; "> </p> <p> <!-- המר קובץ שמע = 1 [אם העלאה היא של קובץ שאינו שמע יש להחליף ל0] --> <input id="convert-audio" name="convertAudio" type="hidden" value="0" checked > </p> <!-- לחצן שלח טופס --> <p> <input type="submit" name="submit" style="width: 80%; background: #3115ff; color: #fff;height: 30px;"> </p> </fieldset> </form> </div> <div style="color: #d5f4ff;"> <br>פותח על ידי: <a href="mailto: avrhco770@gmail.com" style="color: #ffffff;">אברהם כהן</a><br><hr> <h2>יחי אדוננו מורנו ורבינו מלך המשיח לעולם ועד!</h2> </div> </html>מקור:https://f2.freeivr.co.il/post/75371
קרדיט: @avrham
-
קובץ להוספת נקודות למאזינים
הקוד המלא
<?php // --- הגדרת משתנים להודעות --- // $success = ''; $error = ''; // --- פונקציות API --- // function downloadFile($token, $filePath) { $apiUrl = 'https://www.call2all.co.il/ym/api/GetTextFile'; $ch = curl_init($apiUrl); $postData = http_build_query([ 'token' => $token, 'what' => $filePath, ]); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postData, ]); $response = curl_exec($ch); curl_close($ch); // ננסה לפרש את התשובה כ-JSON $data = json_decode($response, true); if (is_array($data) && isset($data['responseStatus'])) { if ($data['responseStatus'] !== 'OK') { return [ 'status' => 'error', 'message' => 'שגיאה בהורדת הקובץ: ' . ($data['message'] ?? 'לא ידוע'), ]; } // כאן התוכן האמיתי של הקובץ (השורות digits-1-...) $contents = $data['contents'] ?? ''; return [ 'status' => 'ok', 'content' => $contents, ]; } // אם זו לא תשובת JSON – נחזיר כטקסט גולמי return [ 'status' => 'ok', 'content' => $response, ]; } function uploadFile($token, $filePath, $content) { $apiUrl = 'https://www.call2all.co.il/ym/api/UploadTextFile'; $ch = curl_init($apiUrl); $postData = http_build_query([ 'token' => $token, 'what' => $filePath, 'contents' => $content, // רק הטקסט של הקובץ ]); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postData, ]); $response = curl_exec($ch); curl_close($ch); $data = json_decode($response, true); if (is_array($data) && isset($data['responseStatus']) && $data['responseStatus'] === 'OK') { return ['status' => 'ok']; } $msg = is_array($data) && isset($data['message']) ? $data['message'] : 'תגובה לא תקינה מהשרת'; return ['status' => 'error', 'message' => 'שגיאה בהעלאת הקובץ: ' . $msg]; } // --- לוגיקה ראשית --- // if ($_SERVER['REQUEST_METHOD'] === 'POST' || !empty($_GET)) { do { $source = $_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST : $_GET; // פעולה: בדיקה / עדכון / איפוס נבחרים / איפוס הכל $action = $source['action'] ?? 'update'; // פרמטרים $token = trim($source['token'] ?? ''); $filePath = trim($source['filePath'] ?? ''); $updates = $source['updates'] ?? null; if (empty($token) || empty($filePath)) { $error = 'יש למלא TOKEN ונתיב קובץ.'; break; } // באקשנים שקשורים ל-IDים (update / reset_selected) אנחנו צריכים לפחות מזהה אחד if (in_array($action, ['update', 'reset_selected'], true)) { if (empty($updates) || !is_array($updates['id'])) { $error = 'יש להזין לפחות מזהה אחד.'; break; } } $updateIds = isset($updates['id']) ? $updates['id'] : []; $updatePoints = isset($updates['points']) ? $updates['points'] : []; // ולידציה בסיסית למזהים – רק כשיש IDs if (!empty($updateIds)) { foreach ($updateIds as $id) { $id = trim($id); if ($id === '' || !is_numeric($id)) { $error = 'נמצאו מזהים לא חוקיים. אנא בדוק את כל שדות ה-ID.'; break 2; } } } // לוגיקת עדכון $updatesToProcess = []; if ($action === 'update') { if (!is_array($updatePoints) || count($updateIds) !== count($updatePoints)) { $error = 'שגיאה פנימית: מספר המזהים אינו תואם למספר ערכי הנקודות.'; break; } foreach ($updateIds as $index => $id) { $points = $updatePoints[$index] ?? ''; $id = trim($id); $points = trim($points); if ($points === '' || !is_numeric($points)) { $error = 'נמצאו ערכי נקודות לא חוקיים. אנא בדוק את כל השדות.'; break 2; } $updatesToProcess[$id] = ($updatesToProcess[$id] ?? 0) + (float)$points; } if (empty($updatesToProcess)) { $error = 'לא נמצאו עדכונים חוקיים לעיבוד.'; break; } } // 2. הורדת הקובץ $downloadResult = downloadFile($token, $filePath); if ($downloadResult['status'] === 'error') { $error = $downloadResult['message']; break; } $fileContent = $downloadResult['content']; $lines = preg_split('/\r\n|\n|\r/', $fileContent); $newContentArray = []; $updatedIds = []; // 3. מצבים שונים לפי action if ($action === 'reset_all') { // איפוס כל המזהים לקובץ foreach ($lines as $line) { if (preg_match('/^(digits-\d+-points_total=)([-.0-9]+)$/', $line, $m)) { $prefix = $m[1]; $newContentArray[] = $prefix . '0'; } else { $newContentArray[] = $line; } } $newContent = implode("\n", $newContentArray); $uploadResult = uploadFile($token, $filePath, $newContent); if ($uploadResult['status'] === 'error') { $error = $uploadResult['message']; break; } $success = 'כל המזהים אופסו לנקודות 0.'; break; } if ($action === 'reset_selected') { // איפוס רק למזהים שנבחרו $idsToReset = array_map('trim', $updateIds); $idsToReset = array_values(array_filter($idsToReset, 'strlen')); $resetFound = []; foreach ($lines as $line) { if (preg_match('/^digits-(\d+)-points_total=([-.0-9]+)$/', $line, $m)) { $currentId = $m[1]; $prefix = "digits-{$currentId}-points_total="; if (in_array($currentId, $idsToReset, true)) { $newContentArray[] = $prefix . '0'; $resetFound[] = $currentId; } else { $newContentArray[] = $line; } } else { $newContentArray[] = $line; } } $newContent = implode("\n", $newContentArray); $uploadResult = uploadFile($token, $filePath, $newContent); if ($uploadResult['status'] === 'error') { $error = $uploadResult['message']; break; } if (!empty($resetFound)) { $success = 'המזהים הבאים אופסו לנקודות 0: ' . implode(', ', $resetFound) . '.'; } else { $error = 'אף אחד מהמזהים שבחרת לא נמצא בקובץ.'; } break; } if ($action === 'check') { // בדיקה בלבד – לא משנים את הקובץ $statusMessages = []; // אם לא הוזן אף מזהה – מציגים את כל המזהים מהקובץ $hasAnyId = false; foreach ($updateIds as $rawId) { if (trim($rawId) !== '') { $hasAnyId = true; break; } } if (!$hasAnyId) { // כל המזהים foreach ($lines as $line) { if (preg_match('/^digits-(\d+)-points_total=([-.0-9]+)$/', $line, $m)) { $id = $m[1]; $points = $m[2]; $statusMessages[] = "מזהה {$id}: נקודות נוכחיות = {$points}"; } } if (!empty($statusMessages)) { $success = implode(' | ', $statusMessages); } else { $error = 'לא נמצאו מזהים בקובץ.'; } break; } // יש מזהים מסוימים – מציגים רק אותם foreach ($updateIds as $id) { $id = trim($id); if ($id === '') { continue; } $found = false; $points = null; foreach ($lines as $line) { if (preg_match('/^digits-(' . preg_quote($id, '/') . ')-points_total=([-.0-9]+)$/', $line, $m)) { $found = true; $points = $m[2]; break; } } if ($found) { $statusMessages[] = "מזהה {$id}: נקודות נוכחיות = {$points}"; } else { $statusMessages[] = "מזהה {$id}: לא נמצא בקובץ."; } } if (!empty($statusMessages)) { $success = implode(' | ', $statusMessages); } else { $error = 'לא נמצאו מזהים חוקיים או תואמים בקובץ.'; } break; } // action === 'update' – עדכון נקודות רגיל foreach ($lines as $line) { if (preg_match('/^digits-(\d+)-points_total=/', $line, $matches)) { $currentId = $matches[1]; if (isset($updatesToProcess[$currentId])) { $pointsToAdd = $updatesToProcess[$currentId]; if (preg_match('/^(digits-\d+-points_total=)([-.0-9]+)$/', $line, $valueMatches)) { $prefix = $valueMatches[1]; $currentValue = $valueMatches[2]; $newValue = (float)$currentValue + (float)$pointsToAdd; $newContentArray[] = $prefix . $newValue; $updatedIds[] = $currentId; unset($updatesToProcess[$currentId]); } else { $newContentArray[] = $line; } continue; } } $newContentArray[] = $line; } $newContent = implode("\n", $newContentArray); $uploadResult = uploadFile($token, $filePath, $newContent); if ($uploadResult['status'] === 'error') { $error = $uploadResult['message']; break; } $successMessage = ''; if (!empty($updatedIds)) { $successMessage = 'הקובץ עודכן. מזהים שעודכנו: ' . implode(', ', $updatedIds) . '.'; } $errorMessage = ''; if (!empty($updatesToProcess)) { $notFoundIds = array_keys($updatesToProcess); $errorMessage = 'המזהים הבאים לא נמצאו בקובץ או שהפורמט שלהם שגוי: ' . implode(', ', $notFoundIds) . '.'; } if (!empty($successMessage) && !empty($errorMessage)) { $success = $successMessage . ' ' . $errorMessage; } elseif (!empty($successMessage)) { $success = $successMessage; } else { $error = $errorMessage ?: 'לא בוצעו עדכונים. ייתכן שהמזהים שהוזנו לא קיימים בקובץ.'; } } while (false); } ?> <!DOCTYPE html> <html lang="he"> <head> <meta charset="UTF-8"> <title>ניהול נקודות בקובץ - ימות המשיח</title> <style> body { font-family: Arial, sans-serif; direction: rtl; padding: 20px; max-width: 700px; margin: auto; background-color: #f4f4f4; } h2 { text-align: center; color: #333; } form { background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } label { display: block; margin-top: 15px; font-weight: bold; color: #555; } input[type="text"], input[type="number"] { width: 100%; padding: 10px; margin-top: 5px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; } button[type="submit"], button[type="button"] { padding: 10px 15px; font-size: 14px; border: none; border-radius: 4px; cursor: pointer; } .submit-row { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; } .btn-check { background-color: #6c757d; color: #fff; flex: 1; } .btn-check:hover { background-color: #5a6268; } .btn-update { background-color: #007bff; color: #fff; flex: 1; } .btn-update:hover { background-color: #0056b3; } .btn-reset-selected { background-color: #ffc107; color: #212529; flex: 1; } .btn-reset-selected:hover { background-color: #e0a800; } .btn-reset-all { background-color: #dc3545; color: #fff; flex: 1; } .btn-reset-all:hover { background-color: #c82333; } .msg { margin-top: 20px; padding: 15px; border-radius: 4px; font-weight: bold; text-align: center; } .error { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; } .success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; } .update-pair { display: flex; gap: 10px; margin-bottom: 10px; align-items: center; } .update-pair input { flex: 1; } #add-update-field { width: auto; padding: 8px 15px; font-size: 14px; background-color: #28a745; margin-top: 10px; border: none; border-radius: 4px; color: white; cursor: pointer; } #add-update-field:hover { background-color: #218838; } .remove-field { background-color: #dc3545; color: white; border: none; border-radius: 50%; width: 24px; height: 24px; cursor: pointer; font-weight: bold; line-height: 24px; text-align: center; padding: 0; } .remove-field:hover { background-color: #c82333; } small.hint { color: #777; display: block; margin-top: 4px; } </style> <script> document.addEventListener('DOMContentLoaded', function() { const container = document.getElementById('update-fields-container'); function addField() { const newPair = document.createElement('div'); newPair.className = 'update-pair'; newPair.innerHTML = ` <input type="number" name="updates[id][]" placeholder="מזהה ID"> <input type="number" name="updates[points][]" step="any" placeholder="נקודות (לעדכון בלבד)"> <button type="button" class="remove-field">X</button> `; container.appendChild(newPair); } document.getElementById('add-update-field').addEventListener('click', addField); container.addEventListener('click', function(e) { if (e.target && e.target.classList.contains('remove-field')) { if (container.children.length > 1) { e.target.closest('.update-pair').remove(); } } }); function setRequiredForIdPoints(required) { const idInputs = container.querySelectorAll('input[name="updates[id][]"]'); const pointInputs = container.querySelectorAll('input[name="updates[points][]"]'); idInputs.forEach(inp => inp.required = required); pointInputs.forEach(inp => inp.required = required); } const btnCheck = document.querySelector('button[name="action"][value="check"]'); const btnUpdate = document.querySelector('button[name="action"][value="update"]'); const btnResetSelected = document.querySelector('button[name="action"][value="reset_selected"]'); const btnResetAll = document.querySelector('button[name="action"][value="reset_all"]'); if (btnCheck) { btnCheck.addEventListener('click', function() { // בדיקה בלבד – לא נדרש למלא מזהים setRequiredForIdPoints(false); }); } if (btnUpdate) { btnUpdate.addEventListener('click', function() { setRequiredForIdPoints(true); }); } if (btnResetSelected) { btnResetSelected.addEventListener('click', function() { setRequiredForIdPoints(true); }); } if (btnResetAll) { btnResetAll.addEventListener('click', function() { setRequiredForIdPoints(false); }); } }); </script> </head> <body> <h2>עדכון / בדיקה / איפוס נקודות בימות המשיח</h2> <form method="post"> <label for="token">TOKEN:</label> <input type="text" id="token" name="token" required> <label for="filePath">נתיב קובץ מלא (למשל, ivr2:/Points/Split/points_total.ini):</label> <input type="text" id="filePath" name="filePath" required> <label>מזהים (לבדיקה, עדכון או איפוס נבחרים):</label> <small class="hint">באיפוס כללי (איפוס כל המזהים) או בבדיקת כל המזהים אין חובה למלא מזהים.</small> <div id="update-fields-container"> <div class="update-pair"> <input type="number" name="updates[id][]" placeholder="מזהה ID"> <input type="number" name="updates[points][]" step="any" placeholder="נקודות (לעדכון בלבד)"> </div> </div> <button type="button" id="add-update-field">הוסף שדה מזהה/נקודות</button> <div class="submit-row"> <button type="submit" name="action" value="check" class="btn-check">בדוק מצב נקודות</button> <button type="submit" name="action" value="update" class="btn-update">בצע עדכון נקודות</button> <button type="submit" name="action" value="reset_selected" class="btn-reset-selected">איפוס מזהים נבחרים</button> <button type="submit" name="action" value="reset_all" class="btn-reset-all" onclick="return confirm('למחוק את כל הנקודות לכל המזהים? פעולה זו בלתי הפיכה.');">איפוס כל המזהים</button> </div> </form> <?php if (!empty($error)): ?> <div class="msg error"> <?= htmlspecialchars($error) ?> </div> <?php elseif (!empty($success)): ?> <div class="msg success"> <?= htmlspecialchars($success) ?> </div> <?php endif; ?> </body> </html>מקור: https://f2.freeivr.co.il/post/167538
קרדיט: @זאביק
שימו לב! הקוד במקור הוא קוד php , כך שאני לא בטוח שהוא יעבוד בלי שגיאה.
אך כיוון שכרגע הוא חסום לי בנטפרי אשמח אם יש מי שיוכל לבדוק אותו ולעדכן אם הוא עובד או לא. -
תוכנה להורדה של רשימת הצינתוקים למחשב
להסבר מפורט: https://f2.freeivr.co.il/post/142148
קרדיט: @ivrפון
-
-
-
קובץ להורדת קבצים מהמערכת (קבצי wav, tts, ini, html) כולל אפשרות להמרה + אפשרות להורדת קבצים מרובים
הקוד מצורף בספויילר
<!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;
padding: 20px;
background-color: #e9ecef;
text-align: right;
direction: rtl;
}
.container {
background-color: #ffffff;
padding: 30px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
max-width: 400px;
margin: 40px auto;
}
h2 {
font-size: 24px;
color: #343a40;
margin-bottom: 25px;
text-align: center;
border-bottom: 2px solid #007BFF;
padding-bottom: 10px;
}
label, input, button, select {
display: block;
width: 100%;
margin-bottom: 15px;
box-sizing: border-box;
}
label {
font-weight: 600;
color: #495057;
margin-bottom: 5px;
}
input[type="text"], select {
padding: 12px;
border: 1px solid #ced4da;
border-radius: 6px;
transition: border-color 0.3s;
}
input[type="text"]:focus, select:focus {
border-color: #007BFF;
outline: none;
}
button {
background-color: #007BFF;
color: white;
padding: 12px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 18px;
font-weight: bold;
margin-top: 20px;
transition: background-color 0.3s;
}
button:hover {
background-color: #0056b3;
}
#conversionOptions {
display: none;
margin-top: -5px;
}
#iniWarning {
color: #721c24;
background-color: #f8d7da;
border: 1px solid #f5c6cb;
padding: 10px;
border-radius: 5px;
margin-bottom: 15px;
display: none;
}
/* סגנון הודעת שגיאה כללית */
#generalError {
color: #721c24;
background-color: #f8d7da;
border: 1px solid #f5c6cb;
padding: 10px;
border-radius: 5px;
margin-top: 15px;
font-weight: bold;
display: none;
text-align: center;
}
</style>
</head>
<body><div class="container">
<h2>
ממשק הורדת קובץ</h2><label for="token">טוקן (Token):</label> <input type="text" id="token" placeholder="יש ליצור טוקן בלשונית אבטחה" oninput="saveInputValues()"> <label for="path">נתיב השלוחה (לדוגמה: 1/2):</label> <input type="text" id="path" placeholder="נתיב השלוחה" oninput="saveInputValues()"> <label for="filename">שם הקובץ (לדוגמה: 001):</label> <input type="text" id="filename" placeholder="שם הקובץ" oninput="saveInputValues()"> <label for="filetype">סוג הקובץ:</label> <select id="filetype" onchange="toggleConversion(); saveInputValues();"> <option value="wav">wav</option> <option value="tts">tts</option> <option value="ini">ini</option> <option value="ymgr">ymgr</option> </select> <div id="iniWarning"> ⚠️ **שים לב: קובץ INI** <ul> <li>הקובץ יורד כקובץ **INI**. לאחר ההורדה, ייתכן שתידרש **לשנות את סיומת הקובץ ל-**.txt** באופן ידני** כדי לפתוח אותו כקובץ טקסט רגיל.</li> <li>בשל סוג הקובץ, תוכנת האנטי-וירוס או הדפדפן **עלולים למנוע את הורדת הקובץ** או להציג אזהרה.</li> </ul> </div> <div id="conversionOptions"> <label for="conversionFormat">פורמט המרה (עבור ymgr):</label> <select id="conversionFormat" onchange="saveInputValues()"> <option value="">ללא המרה (ymgr)</option> <option value="csv">אקסל (xlsx)</option> <option value="html">HTML</option> </select> </div> <button onclick="generateAndDownload()">הורד קובץ</button> <div id="generalError"></div></div>
<script>
// פונקציה לשמירת ערכי השדות ב-localStorage
function saveInputValues() {
localStorage.setItem('download_token', document.getElementById('token').value);
localStorage.setItem('download_path', document.getElementById('path').value);
localStorage.setItem('download_filename', document.getElementById('filename').value);
localStorage.setItem('download_filetype', document.getElementById('filetype').value);
localStorage.setItem('download_conversionFormat', document.getElementById('conversionFormat').value);
}// **פונקציה לטעינת ערכי השדות מ-localStorage** function loadInputValues() { document.getElementById('token').value = localStorage.getItem('download_token') || ''; document.getElementById('path').value = localStorage.getItem('download_path') || ''; document.getElementById('filename').value = localStorage.getItem('download_filename') || ''; // טעינת שדות Select const filetype = localStorage.getItem('download_filetype'); if (filetype) { document.getElementById('filetype').value = filetype; } const conversionFormat = localStorage.getItem('download_conversionFormat'); if (conversionFormat) { document.getElementById('conversionFormat').value = conversionFormat; } // נפעיל את toggleConversion כדי לוודא שהתצוגה מתאימה לערכים שנטענו toggleConversion(); } // פונקציה לבניית ה-URL function buildUrl(token, path, filename, filetype, conversionFormat) { const downloadUrlTemplate = "https://www.call2all.co.il/ym/api/DownloadFile?token=טוקן&path=ivr2:נתיב השלוחה/שם הקובץ.סיומת"; const renderUrlTemplate = "https://www.call2all.co.il/ym/api/RenderYMGRFile?token=טוקן&wath=ivr2:נתיב_השלוחה/שם_הקובץ.סיומת&convertType=סוג_ההמרה"; let finalUrl = ""; let downloadFilename = ""; if (filetype === 'ymgr' && conversionFormat !== '') { let conversionType = conversionFormat; finalUrl = renderUrlTemplate .replace("טוקן", encodeURIComponent(token)) .replace("נתיב_השלוחה", encodeURIComponent(path)) .replace("שם_הקובץ", encodeURIComponent(filename)) .replace("סיומת", encodeURIComponent(filetype)) .replace("סוג_ההמרה", encodeURIComponent(conversionType)); downloadFilename = (conversionType === 'csv') ? `${filename}.xlsx` : `${filename}.${conversionType}`; } else { // כולל ini, wav, tts, ו-ymgr ללא המרה finalUrl = downloadUrlTemplate .replace("טוקן", encodeURIComponent(token)) .replace("נתיב השלוחה", encodeURIComponent(path)) .replace("שם הקובץ", encodeURIComponent(filename)) .replace("סיומת", encodeURIComponent(filetype)); downloadFilename = (filetype === 'ini') ? `${filename}.ini` : `${filename}.${filetype}`; } return { finalUrl, downloadFilename }; } // פונקציה להצגה/הסתרה של אזהרות והמרות function toggleConversion() { const fileType = document.getElementById('filetype').value; const conversionOptions = document.getElementById('conversionOptions'); const iniWarning = document.getElementById('iniWarning'); conversionOptions.style.display = (fileType === 'ymgr') ? 'block' : 'none'; iniWarning.style.display = (fileType === 'ini') ? 'block' : 'none'; } // פונקציה להסתרת כל הודעות השגיאה function hideAllErrors() { document.getElementById('generalError').style.display = 'none'; } // הפונקציה הראשית (עכשיו אסינכרונית כדי לאפשר fetch) async function generateAndDownload() { const token = document.getElementById('token').value; const path = document.getElementById('path').value; const filename = document.getElementById('filename').value; const filetype = document.getElementById('filetype').value; const conversionFormat = document.getElementById('conversionFormat').value; const errorElement = document.getElementById('generalError'); // הסתרת שגיאות קודמות hideAllErrors(); if (!token || !path || !filename || !filetype) { alert("אנא מלא את כל השדות הנדרשים."); return; } const { finalUrl, downloadFilename } = buildUrl(token, path, filename, filetype, conversionFormat); try { // 1. נבצע fetch ל-API כדי לבדוק את התוכן const response = await fetch(finalUrl); const content = await response.text(); let errorMessage = ""; // ההודעה המקורית: {"yemotAPIVersion":7,"responseStatus":"EXCEPTION","message":"IllegalStateException(session token is invalid)"} const illegalStateErrorIdentifier = `"IllegalStateException(session token is invalid)"`; // 2. בדיקת שגיאות API ספציפיות // בדיקת שגיאת טוקן ספציפית if (content.includes(illegalStateErrorIdentifier)) { errorMessage = "❌ שגיאת טוקן חמור: הטוקן שהוזן אינו חוקי."; } // בדיקת שגיאת טוקן כללית else if (content.includes("Error: Token not found or wrong")) { errorMessage = "❌ שגיאת טוקן:הטוקן שהוזן אינו נכון."; } // בדיקת קובץ/נתיב לא קיים (הסרת כוביות והדגשה) else if (content.includes("Requested file does not exist")) { errorMessage = "❌ הקובץ אינו קיים: אנא ודא שגם הנתיב (" + path + ") וגם שם הקובץ (" + filename + ") נכונים."; } // 3. טיפול בשגיאות שנמצאו if (errorMessage) { errorElement.innerHTML = errorMessage; errorElement.style.display = 'block'; return; } // 4. אם אין שגיאה בתוכן, מפעילים הורדה const link = document.createElement('a'); link.href = finalUrl; link.download = downloadFilename; document.body.appendChild(link); link.click(); document.body.removeChild(link); } catch (error) { // שגיאת רשת או CORS errorElement.innerHTML = "⚠️ **שגיאה כללית/רשת:** לא ניתן לאמת את קיום הקובץ (יתכן חסימת CORS). אנא ודא את הנתונים."; errorElement.style.display = 'block'; } } document.addEventListener('DOMContentLoaded', () => { // טוען את הערכים השמורים בהתחלה loadInputValues(); // מוודא שהתצוגה נכונה לפי הערכים שנטענו (מופעל גם ב-loadInputValues) // toggleConversion(); });</script>
</body>
</html>קרדיט: @אA
-
קובץ להעלאה והורדה של כל סוגי הקבצים למערכות כולל קבצי ini - עם אפשרות להפעלת צינתוק בסיום העלאה!
הקוד מצורף בספויילר
<!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-color: #f4f7f6; margin: 0; padding: 20px; direction: rtl; }
.card { background: white; max-width: 900px; margin: auto; padding: 30px; border-radius: 15px; box-shadow: 0 10px 25px rgba(0,0,0,0.1); }
h2 { color: #2c3e50; text-align: center; margin-bottom: 25px; border-bottom: 2px solid #007BFF; padding-bottom: 10px; }.type-selector { display: flex; justify-content: center; gap: 15px; margin-bottom: 25px; background: #ecf0f1; padding: 10px; border-radius: 10px; } .type-option { cursor: pointer; padding: 10px 20px; border-radius: 8px; font-weight: bold; transition: 0.3s; flex: 1; text-align: center; } .type-option.active { background: #007BFF; color: white; } .form-group { margin-bottom: 20px; } label { display: block; margin-bottom: 8px; font-weight: 600; color: #495057; } input[type="text"], input[type="number"], input[type="file"], textarea { width: 100%; padding: 12px; border: 1px solid #ced4da; border-radius: 8px; box-sizing: border-box; font-size: 14px; } .ini-container { display: flex; gap: 20px; margin-bottom: 15px; } .ini-box { flex: 1; display: flex; flex-direction: column; } .ini-box textarea { height: 250px; resize: none; } .ini-box span { font-weight: bold; margin-bottom: 5px; color: #2c3e50; display: block; } .path-row { display: flex; gap: 8px; align-items: center; } .prefix { background: #dfe6e9; padding: 12px; border-radius: 8px; border: 1px solid #bdc3c7; font-weight: bold; } .progress-container { width: 100%; background-color: #eee; border-radius: 10px; margin: 20px 0; display: none; overflow: hidden; border: 1px solid #ccc; } .progress-bar { width: 0%; height: 25px; background-color: #28a745; text-align: center; line-height: 25px; color: white; font-weight: bold; transition: width 0.4s ease; } .tzintuk-section { border: 1px solid #ddd; padding: 15px; border-radius: 8px; background: #f9f9f9; margin-bottom: 20px; } .btn-container { display: flex; gap: 10px; margin-top: 10px; } .submit-btn { flex: 2; background-color: #28a745; color: white; border: none; padding: 15px; font-size: 16px; cursor: pointer; border-radius: 8px; font-weight: bold; transition: 0.3s; } .submit-btn:disabled { background-color: #6c757d; cursor: not-allowed; } .list-btn { flex: 1; background-color: #007BFF; color: white; border: none; padding: 15px; font-size: 16px; cursor: pointer; border-radius: 8px; font-weight: bold; } .load-btn-dynamic { background-color: #28a745; color: white; border: none; padding: 8px 20px; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: bold; margin-top: 10px; align-self: flex-start; transition: background-color 0.3s; min-width: 140px; } .load-btn-loading { background-color: #007BFF !important; } .hidden { display: none; } #fileListContainer { margin-top: 25px; border-top: 2px solid #eee; padding-top: 15px; display: none; } table { width: 100%; border-collapse: collapse; margin-top: 10px; background: white; } th, td { border: 1px solid #dee2e6; padding: 12px; text-align: center; } </style></head>
<body><div class="card">
<h2>
ניהול קבצי ימות המשיח</h2><div class="type-selector"> <div id="opt-file" class="type-option active" onclick="switchMode('file')">העלאת קובץ שמע</div> <div id="opt-text" class="type-option" onclick="switchMode('text')">העלאת קובץ טקסט</div> <div id="opt-ini" class="type-option" onclick="switchMode('ini')">העלאת קובץ INI</div> </div> <form id="uploadForm"> <div class="form-group"> <label>טוקן אישי (Token):</label> <input type="text" id="token" required placeholder="הזן טוקן כאן"> </div> <div class="form-group"> <label>שלוחות יעד (הפרד בפסיקים עבור מספר שלוחות):</label> <div class="path-row"> <span class="prefix">ivr2:</span> <input type="text" id="folder" placeholder="למשל: 5, 10, 15/1" required> </div> </div> <div id="progressContainer" class="progress-container"> <div id="progressBar" class="progress-bar">0%</div> </div> <div id="file-section"> <div class="form-group"> <label>בחר קובץ:</label> <input type="file" id="fileInput"> </div> <div class="form-group"> <label>שם קובץ (אופציונלי):</label> <input type="text" id="fileNameAudio" placeholder="למשל 000"> </div> </div> <div id="text-section" class="hidden"> <div class="form-group"> <label>הטקסט להעלאה:</label> <textarea id="textContent" style="height:150px;" placeholder="כתוב טקסט"></textarea> </div> <div class="form-group"> <label>שם קובץ (חובה):</label> <input type="text" id="fileNameText" placeholder="למשל 001.tts"> </div> </div> <div id="ini-section" class="hidden"> <div class="form-group"> <label>שם קובץ (ללא סיומת):</label> <input type="text" id="fileNameIni" value="ext" placeholder="למשל ext"> </div> <div class="ini-container"> <div class="ini-box"> <span>תוכן הקובץ הקיים</span> <textarea id="iniContentExisting" readonly placeholder="התוכן הקיים יופיע כאן"></textarea> <button type="button" id="loadIniBtn" onclick="fetchExistingText()" class="load-btn-dynamic">טען תוכן קיים</button> </div> <div class="ini-box"> <span>טען תוכן להעלאה</span> <textarea id="iniContentNew" placeholder="כתוב טקסט להעלאה..."></textarea> </div> </div> </div> <div id="tzintuk-wrapper" class="tzintuk-section"> <label style="display: flex; align-items: center; gap: 10px; cursor: pointer;"> <input type="checkbox" id="use-tzintuk" style="width: 18px; height: 18px;" onchange="document.getElementById('tz-fields').style.display = this.checked ? 'block' : 'none'"> <span style="font-weight: bold; color: #2c3e50;">הפעל צינתוק בסיום ההעלאה</span> </label> <div id="tz-fields" style="display: none; margin-top: 15px; border-top: 1px solid #eee; padding-top: 10px;"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 10px;"> <div> <label style="font-size: 13px;">זיהוי יוצא (callerId):</label> <input type="text" id="tz-caller" placeholder="הכנס את הזיהוי היוצא"> </div> <div> <label style="font-size: 13px;">זמן (9-16 שניות):</label> <input type="number" id="tz-time" value="9" min="9" max="16"> </div> </div> <div> <label style="font-size: 13px;">מספר רשימת הצינתוקים:</label> <input type="text" id="tz-phones" placeholder="הכנס את מספר רשימת הצינתוקים, למספר רשימות יש להפריד עם פסיק"> </div> </div> </div> <div class="btn-container"> <button type="button" id="mainSubmitBtn" onclick="executeUpload()" class="submit-btn">בצע העלאה</button> <button type="button" onclick="listFiles()" class="list-btn">הצג קבצים בשלוחה</button> </div> </form> <div id="fileListContainer"> <table id="filesTable"> <thead> <tr> <th>שם קובץ</th> <th>פעולות</th> </tr> </thead> <tbody id="filesBody"></tbody> </table> </div></div>
<script>
let currentMode = 'file';function switchMode(mode) { currentMode = mode; document.getElementById('opt-file').classList.toggle('active', mode === 'file'); document.getElementById('opt-text').classList.toggle('active', mode === 'text'); document.getElementById('opt-ini').classList.toggle('active', mode === 'ini'); document.getElementById('file-section').classList.toggle('hidden', mode !== 'file'); document.getElementById('text-section').classList.toggle('hidden', mode !== 'text'); document.getElementById('ini-section').classList.toggle('hidden', mode !== 'ini'); // הסתרת אפשרות הצינתוק אם אנחנו במצב INI const tzWrapper = document.getElementById('tzintuk-wrapper'); if (mode === 'ini') { tzWrapper.style.display = 'none'; } else { tzWrapper.style.display = 'block'; } } async function fetchExistingText() { const token = document.getElementById('token').value; const folder = document.getElementById('folder').value.split(',')[0].trim(); let fileName = document.getElementById('fileNameIni').value.trim() || "ext"; const btn = document.getElementById('loadIniBtn'); if (!token || !folder) { alert("נא למלא טוקן ושלוחה לפני הטעינה"); return; } btn.innerText = "טוען תוכן קובץ..."; btn.classList.add('load-btn-loading'); btn.disabled = true; if (!fileName.toLowerCase().endsWith('.ini')) fileName += ".ini"; const fullPath = `ivr2:${folder}/${fileName}`; try { const url = `https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=${encodeURIComponent(fullPath)}`; const res = await fetch(url); const data = await res.json(); document.getElementById('iniContentExisting').value = data.responseStatus === "OK" ? (data.contents || "קובץ ריק") : "קובץ לא נמצא"; } catch (e) { alert("שגיאת תקשורת"); } finally { btn.innerText = "טען תוכן קיים"; btn.classList.remove('load-btn-loading'); btn.disabled = false; } } async function listFiles() { const token = document.getElementById('token').value; const folder = document.getElementById('folder').value.split(',')[0].trim(); const tbody = document.getElementById('filesBody'); if (!token || !folder) { alert("מלא טוקן ושלוחה (הראשונה)"); return; } try { const url = `https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${token}&path=${folder}`; const res = await fetch(url); const data = await res.json(); if (data.responseStatus === "OK") { tbody.innerHTML = ""; data.files.forEach(f => { tbody.innerHTML += `<tr><td>${f.name}</td><td><button onclick="alert('נתיב: ivr2:${folder}/${f.name}')">פרטים</button></td></tr>`; }); document.getElementById('fileListContainer').style.display = "block"; } } catch (e) { alert("שגיאת תקשורת"); } } async function sendTzintuk() { // אם אנחנו במצב INI, לא לבצע צינתוק בכלל if (currentMode === 'ini') return; const token = document.getElementById('token').value.trim(); const rawPhones = document.getElementById('tz-phones').value.trim(); const callerId = document.getElementById('tz-caller').value.trim() || 'RAND'; const timeout = document.getElementById('tz-time').value; if (!rawPhones) return; const formattedPhones = rawPhones.split(',') .map(p => p.trim()) .filter(p => p !== "") .map(p => p.startsWith('tzl:') ? p : 'tzl:' + p) .join(','); const url = `https://www.call2all.co.il/ym/api/RunTzintuk?token=${token}&phones=${formattedPhones}&callerId=${callerId}&intTzintukTimeOut=${timeout}`; try { const response = await fetch(url); const result = await response.text(); console.log("תגובת צינתוק: " + result); } catch (error) { console.error("שגיאת צינתוק:", error); } } async function executeUpload() { const token = document.getElementById('token').value; const folderInput = document.getElementById('folder').value.trim(); if (!token || !folderInput) { alert("מלא פרטים"); return; } const folders = folderInput.split(',').map(f => f.trim()).filter(f => f !== ""); const submitBtn = document.getElementById('mainSubmitBtn'); const progBar = document.getElementById('progressBar'); const progContainer = document.getElementById('progressContainer'); submitBtn.disabled = true; progContainer.style.display = "block"; let successCount = 0; let failCount = 0; for (let i = 0; i < folders.length; i++) { const folder = folders[i]; submitBtn.innerText = `מעלה לשלוחה ${folder}... (${i+1}/${folders.length})`; const formData = new FormData(); formData.append('token', token); let apiUrl = "https://www.call2all.co.il/ym/api/UploadFile"; if (currentMode === 'file') { const fIn = document.getElementById('fileInput'); if (!fIn.files.length) { alert("בחר קובץ"); break; } formData.append('file', fIn.files[0]); formData.append('convertAudio', '1'); let name = document.getElementById('fileNameAudio').value.trim(); let pathValue = "ivr2:" + folder + "/"; if (name) { if (!name.toLowerCase().endsWith('.wav')) name += ".wav"; pathValue += name; formData.append('autoNumbering', 'false'); } else { formData.append('autoNumbering', 'true'); } formData.append('path', pathValue); } else { apiUrl = "https://www.call2all.co.il/ym/api/UploadTextFile"; let name = currentMode === 'text' ? document.getElementById('fileNameText').value.trim() : document.getElementById('fileNameIni').value.trim(); let content = currentMode === 'text' ? document.getElementById('textContent').value : document.getElementById('iniContentNew').value; if (currentMode === 'ini' && name && !name.toLowerCase().endsWith('.ini')) name += ".ini"; formData.append('what', `ivr2:${folder}/${name}`); formData.append('contents', content); } try { const res = await fetch(apiUrl, { method: "POST", body: formData }); const result = await res.json(); if (result.responseStatus === "OK") successCount++; else failCount++; } catch (e) { failCount++; } const percent = Math.round(((i + 1) / folders.length) * 100); progBar.style.width = percent + "%"; progBar.innerText = percent + "%"; } // ביצוע צינתוק בסיום - רק אם מסומן ורק אם לא במצב INI if (currentMode !== 'ini' && document.getElementById('use-tzintuk').checked) { await sendTzintuk(); } submitBtn.disabled = false; submitBtn.innerText = "בצע העלאה"; alert(`הסתיים. הצלחות: ${successCount}, כשלונות: ${failCount}`); setTimeout(() => { progContainer.style.display = "none"; }, 5000); }</script>
</body>
</html>קרדיט: @אA
-
קובץ להפעלת קמפיין - הנכנס לשלוחה במערכת
הפעלת קמפיין - הנכנס לשלוחה במערכת.html
הקוד מצורף בספויילר
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="UTF-8">
<title>שיגור קמפיין - הנכנס לשלוחה במערכת</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<style>
:root {
--primary-color: #4a90e2;
--success-color: #27ae60;
--error-color: #e74c3c;
--border-radius: 12px;
}body { font-family: 'Segoe UI', Arial, sans-serif; background-color: #f4f7f9; margin: 0; padding: 20px; color: #333; } .container { max-width: 600px; margin: auto; background: white; padding: 30px; border-radius: var(--border-radius); box-shadow: 0 4px 15px rgba(0,0,0,0.1); } h2 { text-align: center; color: var(--primary-color); display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 25px; } .speaker-icon { width: 30px; height: 30px; background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%234a90e2"><path d="M14 3.23v17.54c0 .87-.98 1.34-1.6.84L7.37 15H2c-1.1 0-2-.9-2-2v-2c0-1.1.9-2 2-2h5.37L12.4 2.39c.62-.5 1.6-.03 1.6.84zM16.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM19 12c0 2.97-1.87 5.51-4.5 6.74v-13.48c2.63 1.23 4.5 3.77 4.5 6.74z"/></svg>'); background-repeat: no-repeat; background-position: center; background-size: contain; } .form-group { margin-bottom: 15px; } label { display: block; font-weight: bold; margin-bottom: 5px; } input, textarea { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 8px; box-sizing: border-box; } .type-selector { display: flex; gap: 15px; margin-bottom: 15px; background: #f9f9f9; padding: 10px; border-radius: 8px; } .type-selector label { font-weight: normal; cursor: pointer; display: flex; align-items: center; gap: 5px; margin: 0; } .ivr-input-wrapper { display: flex; direction: ltr; border: 1px solid #ddd; border-radius: 8px; overflow: hidden; } .ivr-prefix { background: #eee; padding: 10px; border-right: 1px solid #ddd; font-weight: bold; } .ivr-input-wrapper input { border: none; flex: 1; outline: none; } button { background-color: var(--success-color); color: white; border: none; padding: 15px; cursor: pointer; border-radius: 8px; width: 100%; font-size: 18px; font-weight: bold; margin-top: 10px; } button:active { transform: scale(0.98); } button:disabled { background-color: #ccc; cursor: not-allowed; } #error-display { margin-top: 15px; padding: 15px; background: #fff5f5; border: 1px solid var(--error-color); border-radius: 8px; color: var(--error-color); display: none; font-size: 14px; } .modal { display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); backdrop-filter: blur(3px); } .modal-content { background: white; margin: 15% auto; padding: 25px; border-radius: var(--border-radius); width: 90%; max-width: 450px; text-align: center; box-shadow: 0 8px 25px rgba(0,0,0,0.2); } table { width: 100%; border-collapse: collapse; margin-top: 15px; direction: rtl; } th, td { border: 1px solid #ddd; padding: 10px; text-align: right; } th { background: #f9f9f9; } .close-btn { background: #666; color: white; padding: 8px 20px; border: none; border-radius: 5px; cursor: pointer; margin-top: 15px; } </style></head>
<body><div class="container">
<h2>
<div class="speaker-icon"></div>
שיגור קמפיין - הנכנס לשלוחה
</h2><div class="form-group"> <label>טוקן (Token):</label> <input type="text" id="token" placeholder="הכנס טוקן API"> </div> <div class="form-group"> <label>סוג יעד:</label> <div class="type-selector"> <label><input type="radio" name="targetType" value="manual" checked onchange="updateUI()"> רשימת מספרים</label> <label><input type="radio" name="targetType" value="tpl" onchange="updateUI()"> רשימת תפוצה</label> <label><input type="radio" name="targetType" value="tzl" onchange="updateUI()"> רשימת צינתוקים</label> </div> </div> <div class="form-group" id="excelGroup"> <label>טעינת אקסל (אופציונלי):</label> <input type="file" id="excelFile" accept=".xlsx, .xls, .csv"> </div> <div class="form-group"> <label id="targetLabel">מספרי טלפון:</label> <textarea id="targetInput" rows="4" placeholder="מספר בכל שורה"></textarea> </div> <div class="form-group"> <label>שלוחה במערכת:</label> <div class="ivr-input-wrapper"> <span class="ivr-prefix">ivr2:</span> <input type="text" id="ivrPath" placeholder="/1/100"> </div> </div> <div class="form-group"> <label>זיהוי שיחה (Caller ID) - אופציונלי:</label> <input type="text" id="callerId" placeholder="ברירת מחדל"> </div> <div class="form-group"> <label>זמן המתנה (30-35 שניות):</label> <input type="number" id="callsTimeOut" value="30" min="30" max="35"> </div> <button id="submitBtn" onclick="sendCampaign()">שיגור קמפיין</button> <div id="error-display"></div></div>
<div id="successModal" class="modal">
<div class="modal-content">
<h3 style="color: var(--success-color);">הקמפיין נוצר בהצלחה!</h3>
<table id="resultTable"></table>
<button class="close-btn" onclick="closeModal()">סגור</button>
</div>
</div><script>
function updateUI() {
const type = document.querySelector('input[name="targetType"]:checked').value;
const inputArea = document.getElementById('targetInput');
const excelGroup = document.getElementById('excelGroup');
const label = document.getElementById('targetLabel');inputArea.value = ''; // ניקוי התיבה במעבר בין סוגים if (type === 'manual') { label.innerText = 'מספרי טלפון:'; inputArea.placeholder = 'מספר בכל שורה'; excelGroup.style.display = 'block'; } else if (type === 'tpl') { label.innerText = 'מזהה רשימת תפוצה:'; inputArea.placeholder = 'הכנס מספר מזהה בלבד'; excelGroup.style.display = 'none'; } else { label.innerText = 'מזהה רשימת צינתוקים:'; inputArea.placeholder = 'הכנס מספר מזהה בלבד'; excelGroup.style.display = 'none'; } } document.getElementById('excelFile').addEventListener('change', function(e) { const file = e.target.files[0]; const reader = new FileReader(); reader.onload = function(event) { try { const data = new Uint8Array(event.target.result); const workbook = XLSX.read(data, { type: 'array' }); const sheet = workbook.Sheets[workbook.SheetNames[0]]; const rows = XLSX.utils.sheet_to_json(sheet, { header: 1 }); const phones = rows.map(r => r[0]).filter(c => c); document.getElementById('targetInput').value = phones.join('\n'); } catch (err) { alert("שגיאה בקריאת הקובץ"); } }; reader.readAsArrayBuffer(file); }); async function sendCampaign() { const btn = document.getElementById('submitBtn'); const errorDiv = document.getElementById('error-display'); errorDiv.style.display = "none"; btn.innerText = "שולח... נא להמתין"; btn.disabled = true; const token = document.getElementById('token').value.trim(); const userInput = document.getElementById('targetInput').value.trim(); let ivrPath = document.getElementById('ivrPath').value.trim(); const timeout = document.getElementById('callsTimeOut').value; const callerId = document.getElementById('callerId').value.trim(); const targetType = document.querySelector('input[name="targetType"]:checked').value; if (!token || !userInput || !ivrPath) { showError("חובה למלא את כל השדות"); resetBtn(); return; } // בניית פרמטר phones עם הקידומת המתאימה מאחורי הקלעים let phonesParam = ""; if (targetType === 'tpl') { phonesParam = `tpl:${userInput}`; } else if (targetType === 'tzl') { phonesParam = `tzl:${userInput}`; } else { phonesParam = userInput.split('\n').map(p => p.trim()).filter(p => p).join(':'); } if (!ivrPath.startsWith('/')) ivrPath = '/' + ivrPath; const finalIvrPath = `ivr2:${ivrPath}`; let url = `https://www.call2all.co.il/ym/api/CallExtensionBridging?token=${token}&phones=${phonesParam}&ivrPath=${finalIvrPath}&callsTimeOut=${timeout}`; if (callerId) url += `&callerId=${callerId}`; try { const response = await fetch(url); const result = await response.json(); if (result.responseStatus === "OK") { showSuccess(result); } else { showError("שגיאת מערכת: " + (result.message || "שגיאה")); } } catch (e) { showError("שגיאת תקשורת."); } finally { resetBtn(); } } function showSuccess(data) { const table = document.getElementById('resultTable'); table.innerHTML = `<tr><td>סטטוס</td><td>${data.responseStatus}</td></tr> <tr><td>מזהה קמפיין</td><td>${data.campaignId || 'אין'}</td></tr> <tr><td>מספרים שנקלטו</td><td>${data.callsCount || '0'}</td></tr>`; document.getElementById('successModal').style.display = "block"; } function showError(msg) { const errorDiv = document.getElementById('error-display'); errorDiv.innerText = msg; errorDiv.style.display = "block"; } function resetBtn() { const btn = document.getElementById('submitBtn'); btn.innerText = "שיגור קמפיין"; btn.disabled = false; } function closeModal() { document.getElementById('successModal').style.display = "none"; }</script>
</body>
</html>קרדיט: @אA
-
פוסט זה נמחק! -
קובץ להוספת והגדרת שלוחות במערכות
הקובץ מתעדכן מידי פעם.
ניתן לעזור בשדרוג הקובץ כאןעידכון אחרון: א' טבת
יצירת והגדרת שלוחות.htmlהקוד מצורף בספויילר
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="UTF-8">
<title>ממשק יצירת והגדרת שלוחות - מתוקן</title>
<style>
:root { --primary: #3498db; --success: #2ecc71; --danger: #e74c3c; --dark: #2c3e50; --bg: #f4f7f6; }
body { font-family: 'Segoe UI', sans-serif; background-color: var(--bg); margin: 0; padding: 20px; direction: rtl; }
.container { max-width: 800px; margin: auto; background: white; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,0.1); overflow: hidden; }
.header { background: var(--dark); color: white; padding: 20px; text-align: center; }
.content { padding: 30px; position: relative; }
.card { border: 1px solid #ddd; padding: 20px; border-radius: 8px; margin-bottom: 20px; background: #fff; position: relative; }
label { display: block; margin-bottom: 6px; font-weight: bold; }
input, select { width: 100%; padding: 12px; border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box; font-size: 16px; margin-bottom: 10px; }.toolbar { display: flex; justify-content: space-between; gap: 10px; margin-bottom: 15px; } .btn-small { padding: 8px 15px; font-size: 14px; cursor: pointer; border-radius: 6px; border: 1px solid var(--dark); background: white; } .btn { padding: 12px; border-radius: 6px; border: none; font-weight: bold; cursor: pointer; width: 100%; transition: 0.2s; font-size: 16px; } .btn-primary { background: var(--primary); color: white; } .btn-success { background: var(--success); color: white; } .btn-danger { background: var(--danger); color: white; } #wizard-box { text-align: center; border: 2px solid var(--primary); display: none; } #display-q { font-size: 22px; font-weight: bold; margin-bottom: 20px; color: var(--dark); min-height: 50px; } .choice-btns { display: flex; gap: 15px; justify-content: center; } .token-dropdown { position: absolute; width: calc(100% - 20px); background: white; border: 1px solid #ddd; border-radius: 6px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); z-index: 100; max-height: 200px; overflow-y: auto; display: none; } .token-item { padding: 10px; cursor: pointer; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; } .token-item:hover { background: #f0f8ff; } </style></head>
<body><div class="container">
<div class="header"><h1>ממשק יצירת והגדרת שלוחות</h1></div><div class="content"> <div class="toolbar"> <button class="btn-small" onclick="exportDatabase()">📥 הורדת גיבוי JSON</button> <button class="btn-small" onclick="document.getElementById('json-upload').click()">📁 ייבוא מאגר JSON</button> <input type="file" id="json-upload" accept=".json" style="display:none" onchange="handleJsonImport(this)"> </div> <div id="setup-card" class="card"> <div style="display:flex; gap:10px;"> <div style="flex:2; position: relative;"> <label>טוקן:</label> <input type="text" id="api-token" placeholder="הזן טוקן או בחר מרשימה" onfocus="showTokenList()"> <div id="token-list" class="token-dropdown"></div> </div> <div style="flex:1;"> <label>מספר שלוחה:</label> <input type="text" id="api-path" placeholder="למשל: 1/5"> </div> </div> <label>בחר סוג שלוחה:</label> <select id="run-main-select"></select> <button id="start-btn" class="btn btn-primary" onclick="initWizard()">התחל שאלון הגדרות</button> </div> <div id="wizard-box" class="card"> <div id="display-q">טוען שאלה...</div> <div id="sub-input-box" style="display:none; margin-bottom:20px;"> <p id="sub-q-label" style="font-weight:bold;"></p> <input type="text" id="user-sub-val" placeholder="הכנס ערך כאן..."> <button class="btn btn-primary" onclick="handleSubInput()">אישור והמשך</button> </div> <div id="choice-btns" class="choice-btns"> <button class="btn btn-success" style="width:120px;" onclick="processChoice(true)">כן</button> <button class="btn btn-danger" style="width:120px;" onclick="processChoice(false)">לא</button> </div> </div> <div id="final-box" class="card" style="display:none; text-align:center;"> <h3>הגדרות מוכנות:</h3> <div id="final-string" style="background:#eee; padding:10px; margin:10px 0; word-break:break-all; font-family:monospace;"></div> <button class="btn btn-success" onclick="sendToYemot()">🚀 שלח לימות המשיח</button> <button class="btn" style="margin-top:10px;" onclick="location.reload()">ביטול</button> </div> </div></div>
<script>
// מאגר ברירת מחדל אם אין כלום בזיכרון
const DEFAULT_DATA = {
"type=menu": [
{ "q": "האם להפעיל השמעת תפריט?", "v": "say_menu=yes", "hasSub": false },
{ "q": "האם להגדיר כותרת לשלוחה?", "v": "title=[VALUE]", "hasSub": true, "subQ": "מה הכותרת?", "subKey": "[VALUE]" }
],
"type=playfile": [
{ "q": "האם לאפשר דילוג על קבצים?", "v": "playfile_control=yes", "hasSub": false }
]
};let DATABASE_CONTENT = JSON.parse(localStorage.getItem('yemot_db')) || DEFAULT_DATA; let currentMainDef = ""; let currentStep = 0; let finalParams = []; window.onload = () => { updateDropdown(); renderTokenList(); }; // --- ייבוא / ייצוא --- function exportDatabase() { const blob = new Blob([JSON.stringify(DATABASE_CONTENT, null, 2)], { type: 'application/json' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'yemot_db.json'; a.click(); } function handleJsonImport(input) { const file = input.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { try { const imported = JSON.parse(e.target.result); DATABASE_CONTENT = imported; localStorage.setItem('yemot_db', JSON.stringify(DATABASE_CONTENT)); updateDropdown(); alert("המאגר עודכן בהצלחה!"); } catch(err) { alert("קובץ לא תקין"); } }; reader.readAsText(file); } // --- לוגיקת שאלון (התיקון כאן) --- function updateDropdown() { const select = document.getElementById('run-main-select'); select.innerHTML = '<option value="">-- בחר --</option>'; Object.keys(DATABASE_CONTENT).forEach(key => { const opt = document.createElement('option'); opt.value = key; opt.innerText = key; select.appendChild(opt); }); } function initWizard() { currentMainDef = document.getElementById('run-main-select').value; if(!currentMainDef) return alert("אנא בחר סוג שלוחה"); currentStep = 0; finalParams = [currentMainDef]; // מתחיל עם סוג השלוחה (למשל type=menu) document.getElementById('setup-card').style.display = 'none'; document.getElementById('wizard-box').style.display = 'block'; renderStep(); } function renderStep() { const questions = DATABASE_CONTENT[currentMainDef]; // בדיקה אם סיימנו את כל השאלות במאגר if(!questions || currentStep >= questions.length) { showFinal(); return; } const currentItem = questions[currentStep]; document.getElementById('display-q').innerText = currentItem.q; document.getElementById('choice-btns').style.display = 'flex'; document.getElementById('sub-input-box').style.display = 'none'; } function processChoice(isYes) { const item = DATABASE_CONTENT[currentMainDef][currentStep]; if(isYes) { if(item.hasSub) { // מעבר להזנת ערך ידני document.getElementById('choice-btns').style.display = 'none'; document.getElementById('sub-input-box').style.display = 'block'; document.getElementById('sub-q-label').innerText = item.subQ; } else { finalParams.push(item.v); currentStep++; renderStep(); } } else { currentStep++; renderStep(); } } function handleSubInput() { const item = DATABASE_CONTENT[currentMainDef][currentStep]; const val = document.getElementById('user-sub-val').value.trim(); if(!val) return alert("חובה להזין ערך"); // החלפת ה-Placeholder בערך שהמשתמש הזין const formattedVal = item.v.replace(item.subKey, val); finalParams.push(formattedVal); document.getElementById('user-sub-val').value = ''; currentStep++; renderStep(); } function showFinal() { document.getElementById('wizard-box').style.display = 'none'; document.getElementById('final-box').style.display = 'block'; document.getElementById('final-string').innerText = finalParams.join('&'); } // --- טוקנים ו-API --- function showTokenList() { document.getElementById('token-list').style.display = 'block'; } function selectToken(t) { document.getElementById('api-token').value = t; document.getElementById('token-list').style.display = 'none'; } function renderTokenList() { const saved = JSON.parse(localStorage.getItem('saved_yemot_tokens')) || []; const list = document.getElementById('token-list'); list.innerHTML = saved.map(i => `<div class="token-item" onclick="selectToken('${i.token}')"><span>${i.alias}</span></div>`).join(''); } async function sendToYemot() { const token = document.getElementById('api-token').value; const path = document.getElementById('api-path').value; const url = `https://www.call2all.co.il/ym/api/UpdateExtension?token=${token}&path=ivr2:${path}&${finalParams.join('&')}`; try { const r = await fetch(url); const txt = await r.text(); alert("תשובה מימות: " + txt); } catch(e) { alert("שגיאת תקשורת"); } }</script>
</body>
</html>קרדיט: @אA
-
@אA במערכת מעלה קבצים יש אפשרות לעלות לכמה שלוחות יחד? למחוק קבצים אפשר?
ואין אפשרות לראות % או משהו כזה עד לסיום הפעולה ? -
פוסט זה נמחק! -
פוסט זה נמחק! -
ממשק ניהול הקבצים במערכת
הקוד מצורף בספויילר
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="UTF-8">
<title>ניהול שלוחות ימות המשיח</title>
<style>
:root {
--primary: #2c3e50; --accent: #3498db; --success: #27ae60;
--danger: #e74c3c; --violet: #8e44ad; --orange: #f39c12;
}
body { font-family: 'Segoe UI', sans-serif; background: #f4f7f6; margin: 0; padding: 20px; }/* סרגל עליון */ .top-bar { background: white; padding: 15px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; } .inputs-row { display: flex; gap: 10px; align-items: center; width: 100%; } input { padding: 8px; border: 1px solid #ddd; border-radius: 5px; flex: 1; } /* עיצוב רכיב הטוקנים */ .token-main { position: relative; flex: 1; display: flex; } /* גודל זהה לשדה הנתיב */ #tokenField { flex: 1; width: 100%; } .token-dropdown { position: absolute; width: 100%; background: white; border: 1px solid #ccc; border-radius: 8px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); z-index: 1000; max-height: 250px; overflow-y: auto; display: none; top: 100%; } .token-item { display: flex; justify-content: space-between; align-items: center; padding: 10px; cursor: pointer; border-bottom: 1px solid #eee; color: #333; } .token-item:hover { background: #f8f9fa; } .delete-item { color: #dc3545; font-weight: bold; padding: 5px 10px; cursor: pointer; border: none; background: none; } .dropdown-footer { padding: 8px; background: #f1f3f5; display: flex; gap: 5px; justify-content: center; border-top: 1px solid #ddd; } .footer-btn { font-size: 11px; padding: 4px 8px; cursor: pointer; border: 1px solid #ccc; background: white; border-radius: 4px; } /* כפתורים וטבלה */ .btn { cursor: pointer; border: none; border-radius: 4px; padding: 4px 8px; font-weight: bold; color: white; transition: 0.2s; font-size: 11px; text-align: center; display: inline-block; width: 100%; max-width: 75px; } .btn:hover { opacity: 0.85; transform: translateY(-1px); } .btn-load { background: var(--primary); padding: 8px 18px; width: auto; max-width: none; font-size: 14px; } .ext-container { background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); margin-bottom: 20px; border-top: 4px solid var(--primary); } .ext-container h4 { margin: 0 0 10px 0; color: var(--primary); display: flex; justify-content: space-between; align-items: center; } #extTextArea { width: 100%; height: 120px; font-family: 'Consolas', monospace; font-size: 13px; padding: 10px; box-sizing: border-box; border: 1px solid #ddd; background: #fcfcfc; border-radius: 5px; } table { width: 100%; background: white; border-collapse: collapse; border-radius: 8px; overflow: hidden; } th { background: #f8f9fa; padding: 10px; font-size: 12px; border-bottom: 2px solid #eee; } td { padding: 5px 8px; border-bottom: 1px solid #eee; text-align: center; font-size: 12px; } .dl { background: var(--success); } .ed { background: var(--orange); } .up { background: var(--accent); } .del { background: var(--danger); } .view { background: var(--violet); } .modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.6); justify-content: center; align-items: center; z-index: 1000; } .modal-content { background: white; padding: 25px; border-radius: 12px; width: 600px; max-width: 95%; } .modal-footer { margin-top: 20px; display: flex; justify-content: flex-start; flex-direction: row-reverse; gap: 10px; } .convert-row { display: flex; gap: 10px; justify-content: center; margin-top: 20px; } </style></head>
<body><div class="top-bar">
<div class="inputs-row">
<div class="token-main">
<input type="text" id="tokenField" placeholder="הזן טוקן או בחר"
onclick="toggleDropdown(true)" oninput="filterDropdown(this.value)" onkeypress="handleEnter(event)" autocomplete="off">
<div id="tokenDropdown" class="token-dropdown"></div>
</div><input type="text" id="pathField" value="" placeholder="נתיב שלוחה" onkeypress="handleEnter(event)"> <button class="btn btn-load" onclick="startProcess()">טען רשימת קבצים</button> </div> <div style="display: flex; align-items: center; gap: 15px; padding-top: 5px;"> <div style="display: flex; align-items: center; gap: 5px;"> <input type="checkbox" id="saveTokenToggle" style="width: auto; cursor: pointer;" onchange="document.getElementById('tokenNameField').style.display = this.checked ? 'block' : 'none'"> <label for="saveTokenToggle" style="font-size: 12px; cursor: pointer; color: #666;">שמור טוקן זה במאגר</label> </div> <div id="tokenNameField" style="display:none;"> <input type="text" id="tokenAlias" placeholder="שם למזהה (למשל: המערכת שלי)" style="font-size: 12px; padding: 5px; width: 200px;"> </div> </div></div>
<div class="ext-container" id="extContainer" style="display:none;">
<h4>
<span>הגדרות שלוחה (ext.ini)</span>
<div style="display:flex; gap:8px;">
<button class="btn" style="background:var(--orange); width:auto; padding:5px 15px;" onclick="renameExtIni()">שנה שם</button>
<button class="btn" style="background:var(--success); width:auto; padding:5px 15px;" onclick="saveExtIni()">שמור שינויים</button>
</div>
</h4>
<textarea id="extTextArea"></textarea>
</div><table>
<thead>
<tr>
<th style="text-align: right; width: 25%;">שם קובץ</th>
<th>גודל</th>
<th>תצוגה</th>
<th>הורדה</th>
<th>שינוי שם</th>
<th>החלפה</th>
<th>מחיקה</th>
</tr>
</thead>
<tbody id="tableBody"></tbody>
</table><div id="mainModal" class="modal">
<div class="modal-content">
<h3 id="modalTitle" style="margin:0 0 15px 0; border-bottom:1px solid #eee; padding-bottom:10px;"></h3>
<div id="modalBody"></div>
<div class="modal-footer" id="modalFooter">
<button id="saveBtn" class="btn btn-load">שמור</button>
<button class="btn" onclick="closeModal()" style="background:#95a5a6;">ביטול</button>
</div>
</div>
</div><script>
const API_BASE = 'https://www.call2all.co.il/ym/api/';
const STORAGE_KEY = 'yemot_permanent_storage';
let savedTokens = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}');document.addEventListener('click', (e) => { if (!e.target.closest('.token-main')) toggleDropdown(false); }); function toggleDropdown(show) { const dropdown = document.getElementById('tokenDropdown'); if (show) { renderDropdown(); dropdown.style.display = 'block'; } else { dropdown.style.display = 'none'; } } function renderDropdown(filter = "") { const dropdown = document.getElementById('tokenDropdown'); dropdown.innerHTML = ''; const filteredKeys = Object.keys(savedTokens).filter(a => a.toLowerCase().includes(filter.toLowerCase())); filteredKeys.forEach(alias => { const item = document.createElement('div'); item.className = 'token-item'; item.innerHTML = `<span>${alias}</span><button type="button" class="delete-item">✖</button>`; item.onclick = () => { document.getElementById('tokenField').value = savedTokens[alias]; toggleDropdown(false); }; item.querySelector('.delete-item').onclick = (e) => { e.stopPropagation(); if(confirm(`למחוק את ${alias}?`)) { delete savedTokens[alias]; localStorage.setItem(STORAGE_KEY, JSON.stringify(savedTokens)); renderDropdown(filter); } }; dropdown.appendChild(item); }); const footer = document.createElement('div'); footer.className = 'dropdown-footer'; footer.innerHTML = `<button type="button" class="footer-btn" style="color:red" onclick="if(confirm('למחוק הכל?')){savedTokens={};localStorage.setItem(STORAGE_KEY,'{}');renderDropdown();}">מחק הכל</button>`; footer.onclick = (e) => e.stopPropagation(); dropdown.appendChild(footer); } function filterDropdown(val) { renderDropdown(val); document.getElementById('tokenDropdown').style.display = 'block'; } function startProcess() { saveCurrentTokenIfRequested(); loadDirectory(); } function saveCurrentTokenIfRequested() { const token = document.getElementById('tokenField').value.trim(); const alias = document.getElementById('tokenAlias').value.trim(); if (document.getElementById('saveTokenToggle').checked && alias && token) { savedTokens[alias] = token; localStorage.setItem(STORAGE_KEY, JSON.stringify(savedTokens)); } } function handleEnter(event) { if (event.key === "Enter") startProcess(); } function getFullPath(fileName = "") { let rawPath = document.getElementById('pathField').value.trim(); if (rawPath && !rawPath.endsWith('/') && fileName !== "") rawPath += '/'; return `ivr2:${rawPath}${fileName}`; } async function callApi(method, params = {}) { const token = document.getElementById('tokenField').value.trim(); if (!token) return; let url = `${API_BASE}${method}?token=${token}`; for (let key in params) url += `&${key}=${encodeURIComponent(params[key])}`; const res = await fetch(url); return await res.json(); } async function loadDirectory() { const data = await callApi('GetIVR2Dir', { path: getFullPath() }); const body = document.getElementById('tableBody'); body.innerHTML = ''; if (data && data.files) { data.files.forEach(file => { const isText = file.name.endsWith('.ini') || file.name.endsWith('.tts'); body.innerHTML += ` <tr> <td style="text-align: right;"><strong>${file.name}</strong></td> <td style="color:#888;">${file.size} B</td> <td>${isText ? `<button class="btn view" onclick="openTextFile('${file.name}')">הצג</button>` : '-'}</td> <td><button class="btn dl" onclick="handleDownloadClick('${file.name}')">הורדה</button></td> <td><button class="btn ed" onclick="renameFile('${file.name}')">שינוי</button></td> <td><button class="btn up" onclick="uploadUI('${file.name}')">החלפה</button></td> <td><button class="btn del" onclick="deleteFile('${file.name}')">מחיקה</button></td> </tr>`; }); loadExtIni(); } } async function loadExtIni() { const data = await callApi('GetTextFile', { what: getFullPath('ext.ini') }); document.getElementById('extContainer').style.display = 'block'; document.getElementById('extTextArea').value = (data && data.exists !== false) ? data.contents || "" : "קובץ ext.ini לא נמצא."; } async function saveExtIni() { const res = await callApi('UploadTextFile', { what: getFullPath('ext.ini'), contents: document.getElementById('extTextArea').value }); if (res && res.responseStatus === "OK") alert("נשמר!"); } async function renameExtIni() { const newName = prompt("שם חדש ל-ext.ini:", "ext.ini"); if (newName) { const res = await callApi('FileAction', { action: 'move', what: getFullPath('ext.ini'), target: getFullPath(newName) }); if (res && res.responseStatus === "OK") loadDirectory(); } } function handleDownloadClick(name) { if (name.toLowerCase().endsWith('.ymgr')) showConvertModal(name); else window.open(`${API_BASE}DownloadFile?token=${document.getElementById('tokenField').value}&path=${getFullPath(name)}`); } function showConvertModal(name) { const html = ` <p style="text-align:center;">בחר פורמט המרה עבור קובץ הנתונים:</p> <div class="convert-row"> <button class="btn" style="background:var(--primary); max-width:none; flex:1; padding:10px;" onclick="executeRender('${name}', '')">ללא המרה</button> <button class="btn" style="background:var(--success); max-width:none; flex:1; padding:10px;" onclick="executeRender('${name}', 'csv')">אקסל (CSV)</button> <button class="btn" style="background:var(--violet); max-width:none; flex:1; padding:10px;" onclick="executeRender('${name}', 'html')">דף HTML</button> </div>`; showModal("המרה והורדה", html); document.getElementById('modalFooter').style.display = 'none'; } function executeRender(name, type) { const token = document.getElementById('tokenField').value; const url = type === "" ? `${API_BASE}DownloadFile?token=${token}&path=${getFullPath(name)}` : `${API_BASE}RenderYMGRFile?token=${token}&wath=${getFullPath(name)}&convertType=${type}`; window.open(url); closeModal(); } function showModal(title, html) { document.getElementById('modalTitle').innerText = title; document.getElementById('modalBody').innerHTML = html; document.getElementById('mainModal').style.display = 'flex'; document.getElementById('modalFooter').style.display = 'flex'; } function closeModal() { document.getElementById('mainModal').style.display = 'none'; } async function deleteFile(name) { if (confirm(`למחוק את ${name}?`)) { const res = await callApi('FileAction', { action: 'delete', what: getFullPath(name) }); if (res.responseStatus === "OK") loadDirectory(); } } function renameFile(name) { const newName = prompt("שם חדש:", name); if (newName) callApi('FileAction', { action: 'move', what: getFullPath(name), target: getFullPath(newName) }).then(loadDirectory); } async function openTextFile(name) { const data = await callApi('GetTextFile', { what: getFullPath(name) }); showModal(`עריכת ${name}`, `<textarea id="modalTextArea" style="width:100%; height:300px; font-family:monospace;">${data.contents || ''}</textarea>`); document.getElementById('saveBtn').onclick = async () => { await callApi('UploadTextFile', { what: getFullPath(name), contents: document.getElementById('modalTextArea').value }); closeModal(); loadDirectory(); }; } function uploadUI(name) { showModal(`החלפת ${name}`, `<input type="file" id="fInp" style="margin-top:10px;">`); document.getElementById('saveBtn').onclick = async () => { const token = document.getElementById('tokenField').value; const file = document.getElementById('fInp').files[0]; if (!file) return; const fd = new FormData(); fd.append('file', file); await fetch(`${API_BASE}UploadFile?token=${token}&path=${getFullPath()}`, { method: 'POST', body: fd }); closeModal(); loadDirectory(); }; }</script>
</body>
</html>קרדיט: @אA
-
פוסט זה נמחק! -
ממשק ליצירת ניהול והפעלת קמפיין
לא בדקתי את הפעולה שלו בזמן אמת, אשמח אם יש מי שהשתמש בזה שיעדכן.
הקוד מצורף בספויילר
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="UTF-8">
<title>מערכת ניהול קמפיינים - Yemot API</title>
<style>
:root {
--primary-color: #2c3e50;
--accent-color: #3498db;
--bg-color: #f8f9fa;
}
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: var(--bg-color); margin: 0; padding: 20px; }
.container { max-width: 1100px; margin: auto; background: white; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); overflow: hidden; }/* תפריט עליון */ .tabs { display: flex; background: var(--primary-color); padding: 0 10px; } .tab-button { padding: 15px 25px; border: none; background: none; color: white; cursor: pointer; font-size: 16px; transition: 0.3s; border-bottom: 3px solid transparent; } .tab-button:hover { background: rgba(255,255,255,0.1); } .tab-button.active { border-bottom: 3px solid var(--accent-color); font-weight: bold; } /* תוכן החלונות */ .tab-content { display: none; padding: 30px; animation: fadeIn 0.4s; } .tab-content.active { display: block; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .form-group { margin-bottom: 20px; } label { display: block; margin-bottom: 8px; font-weight: 600; color: #444; } input, select, textarea { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; box-sizing: border-box; } .btn-row { display: flex; gap: 10px; margin-top: 20px; } button { padding: 12px 24px; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; transition: 0.2s; } .btn-primary { background: var(--accent-color); color: white; } .btn-danger { background: #e74c3c; color: white; } .btn-success { background: #27ae60; color: white; } .response-area { margin-top: 25px; padding: 15px; background: #272c33; color: #61dafb; border-radius: 6px; font-family: monospace; font-size: 13px; white-space: pre-wrap; max-height: 250px; overflow-y: auto; direction: ltr; text-align: left; } .info-box { background: #e8f4fd; padding: 15px; border-radius: 6px; border-right: 4px solid var(--accent-color); margin-bottom: 20px; } </style></head>
<body><div class="container">
<div style="background: #eee; padding: 15px 30px; border-bottom: 1px solid #ddd; display: flex; align-items: center; gap: 15px;">
<label style="margin:0;">טוקן גישה (token):</label>
<input type="text" id="mainToken" placeholder="הכנס טוקן API כאן" style="width: 350px;">
</div><nav class="tabs"> <button class="tab-button active" onclick="openTab(event, 'setup')">הקמה והגדרות</button> <button class="tab-button" onclick="openTab(event, 'run')">הפעלת קמפיין</button> <button class="tab-button" onclick="openTab(event, 'contacts')">ניהול מספרים</button> <button class="tab-button" onclick="openTab(event, 'monitor')">בקרה בזמן אמת</button> <button class="tab-button" onclick="openTab(event, 'schedule')">תזמון</button> </nav> <div id="setup" class="tab-content active"> <h2>הקמת תבנית קמפיין חדשה</h2> <div class="form-group"> <label>שם הקמפיין (תיאור):</label> <input type="text" id="setup_desc" placeholder="לדוגמה: קמפיין התרמה"> </div> <button class="btn-primary" onclick="executeCall('CreateTemplate', {description: 'setup_desc'})">צור תבנית חדשה</button> <div class="response-area" id="res-setup">// ממתין לפעולה...</div> </div> <div id="run" class="tab-content"> <h2>הפעלת קמפיין</h2> <div class="form-group"> <label>מזהה תבנית:</label> <input type="number" id="run_tpl"> </div> <div class="form-group"> <label>רשימת מספרים - הפרדה בנקודותיים:</label> <textarea id="run_phones" rows="3" placeholder="0501234567:0507654321"></textarea> </div> <button class="btn-success" onclick="executeCall('RunCampaign', {templateId: 'run_tpl', phones: 'run_phones'})">שגר קמפיין עכשיו</button> <div class="response-area" id="res-run">// ממתין לפעולה...</div> </div> <div id="contacts" class="tab-content"> <h2>ניהול רשימות תפוצה</h2> <div class="form-group"> <label>מזהה תבנית:</label> <input type="number" id="list_tpl"> </div> <div class="form-group"> <label>נתוני טלפונים:</label> <textarea id="list_data" rows="5" placeholder="0501112233,ישראל ישראלי"></textarea> </div> <div class="btn-row"> <button class="btn-primary" onclick="executeCall('UploadPhoneList', {templateId: 'list_tpl', data: 'list_data'})">העלה רשימה</button> <button class="btn-danger" onclick="executeCall('ClearTemplateEntries', {templateId: 'list_tpl'})">מחק את כל הרשימה</button> </div> <div class="response-area" id="res-contacts">// ממתין לפעולה...</div> </div> <div id="monitor" class="tab-content"> <h2>ניהול קמפיין פעיל</h2> <div class="form-group"> <label>מזהה קמפיין רץ:</label> <input type="text" id="active_id"> </div> <div class="btn-row"> <button class="btn-primary" onclick="executeCall('GetCampaignStatus', {campaignId: 'active_id'})">בדוק סטטוס</button> <button class="btn-danger" onclick="executeCall('CampaignAction', {campaignId: 'active_id', action: 'stop'})">עצור קמפיין</button> <button style="background: #f39c12; color:white;" onclick="executeCall('CampaignAction', {campaignId: 'active_id', action: 'setPaused'})">השהה או המשך</button> </div> <div class="response-area" id="res-monitor">// ממתין לפעולה...</div> </div> <div id="schedule" class="tab-content"> <h2>תזמון קמפיין עתידי</h2> <div class="form-group"> <label>מזהה תבנית:</label> <input type="number" id="sched_tpl"> </div> <div class="form-group"> <label>זמן לביצוע:</label> <input type="text" id="sched_time" placeholder="yyyy-MM-dd HH:mm:ss"> </div> <button class="btn-primary" onclick="executeCall('ScheduleCampaign', {templateId: 'sched_tpl', time: 'sched_time'})">קבע תזמון</button> <div class="response-area" id="res-schedule">// ממתין לפעולה...</div> </div></div>
<script>
const API_BASE = "https://www.call2all.co.il/ym/api/";function openTab(evt, tabName) { var i, tabContent, tabButtons; tabContent = document.getElementsByClassName("tab-content"); for (i = 0; i < tabContent.length; i++) tabContent[i].classList.remove("active"); tabButtons = document.getElementsByClassName("tab-button"); for (i = 0; i < tabButtons.length; i++) tabButtons[i].classList.remove("active"); document.getElementById(tabName).classList.add("active"); evt.currentTarget.classList.add("active"); } function executeCall(command, params) { const token = document.getElementById('mainToken').value; if(!token) { alert("חובה להזין טוקן!"); return; } let url = new URL(API_BASE + command); url.searchParams.append("token", token); for (let key in params) { let val = params[key]; let element = document.getElementById(val); if(element) { url.searchParams.append(key, element.value); } else { url.searchParams.append(key, val); } } const activeResArea = document.querySelector('.tab-content.active .response-area'); activeResArea.innerHTML = "שולח בקשה...\n\nURL:\n" + url.href; }</script>
</body>
</html>קרדיט: @אA
-
הוספת טקסט למספר קבצים במערכת
הקוד מצורף בספויילר
<!DOCTYPE html> <html lang="he" dir="rtl"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ניהול קבצים - ימות המשיח</title> <style> :root { --primary-color: #4a90e2; --secondary-color: #2ecc71; --danger-color: #e74c3c; --bg-color: #f4f7f6; --text-color: #333; --card-bg: #ffffff; --border-radius: 12px; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: var(--bg-color); color: var(--text-color); margin: 0; padding: 20px; display: flex; justify-content: center; } .container { background-color: var(--card-bg); padding: 30px; border-radius: var(--border-radius); box-shadow: 0 10px 25px rgba(0,0,0,0.1); max-width: 650px; width: 100%; } h2 { text-align: center; color: var(--primary-color); margin-bottom: 30px; font-weight: 600; } .input-group { margin-bottom: 20px; } label { display: block; margin-bottom: 8px; font-weight: bold; font-size: 0.9em; } input[type="text"], textarea { width: 100%; padding: 12px; border: 2px solid #eee; border-radius: 8px; box-sizing: border-box; transition: border-color 0.3s; font-size: 16px; } input[type="text"]:focus, textarea:focus { border-color: var(--primary-color); outline: none; } .flex-row { display: flex; gap: 10px; align-items: center; } button { padding: 12px 20px; border: none; border-radius: 8px; cursor: pointer; font-weight: bold; transition: all 0.3s; display: inline-flex; align-items: center; justify-content: center; white-space: nowrap; } .btn-load { background-color: var(--primary-color); color: white; min-width: 120px; } .btn-load:hover { background-color: #357abd; transform: translateY(-1px); } .btn-add { background-color: var(--secondary-color); color: white; font-size: 0.9em; gap: 8px; } .btn-add:hover { background-color: #27ae60; } .btn-delete { background-color: var(--danger-color); color: white; padding: 10px; min-width: 40px; } .btn-delete:hover { background-color: #c0392b; } .file-input-wrapper { display: flex; gap: 8px; margin-bottom: 10px; animation: fadeIn 0.3s ease; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } textarea { height: 180px; resize: vertical; background-color: #fafafa; font-family: monospace; margin-top: 10px; } /* עיצוב חדש לאזור העלאת קובץ מקומי */ .file-upload-zone { margin: 15px 0; padding: 15px; border: 2px dashed #ccc; border-radius: 8px; text-align: center; background-color: #f9f9f9; } .custom-file-upload { display: inline-block; padding: 8px 16px; cursor: pointer; background-color: #fff; border: 1px solid var(--primary-color); color: var(--primary-color); border-radius: 4px; font-weight: bold; transition: 0.3s; } .custom-file-upload:hover { background-color: var(--primary-color); color: white; } #localFileInput { display: none; } .btn-upload { background-color: #e67e22; color: white; width: 100%; font-size: 1.1em; margin-top: 10px; box-shadow: 0 4px 15px rgba(230, 126, 34, 0.3); } .btn-upload:hover { background-color: #d35400; } </style> </head> <body> <div class="container"> <h2>ניהול קבצי מערכת</h2> <div class="input-group"> <label>טוקן אישי</label> <input type="text" id="token" placeholder="הכנס את ה-Token שלך"> </div> <div class="input-group"> <label>מספר שלוחה</label> <div class="flex-row"> <input type="text" id="ext" placeholder="למשל: 1"> <button class="btn-load" onclick="loadFirstFile()">טען תוכן מהשרת</button> </div> </div> <div class="input-group"> <label>שמות קבצים ליעד</label> <div id="file-fields"> <div class="file-input-wrapper"> <input type="text" class="filename-input" placeholder="שם קובץ (למשל ext.ini)"> <button class="btn-add" onclick="addNewFileField()">קובץ נוסף +</button> </div> </div> </div> <div class="input-group"> <label>תוכן הקובץ</label> <textarea id="fileContents" placeholder="כאן יופיע תוכן הקובץ..."></textarea> <div class="file-upload-zone"> <label for="localFileInput" class="custom-file-upload"> 📂 טען טקסט מקובץ במחשב </label> <input type="file" id="localFileInput" accept=".txt,.ini,.csv,.text" onchange="readLocalFile(this)"> <div id="fileNameDisplay" style="margin-top: 8px; font-size: 0.8em; color: #666;"></div> </div> </div> <button class="btn-upload" onclick="uploadAll()">העלה קבצים למערכת</button> </div> <script> const baseUrl = 'https://www.call2all.co.il/ym/api/'; // פונקציה לקריאת קובץ מקומי מהמחשב function readLocalFile(input) { const file = input.files[0]; if (!file) return; const reader = new FileReader(); document.getElementById('fileNameDisplay').innerText = "קובץ שנבחר: " + file.name; reader.onload = function(e) { document.getElementById('fileContents').value = e.target.result; }; reader.readAsText(file); } function addNewFileField() { const container = document.getElementById('file-fields'); const newDiv = document.createElement('div'); newDiv.className = 'file-input-wrapper'; newDiv.innerHTML = ` <input type="text" class="filename-input" placeholder="שם קובץ נוסף"> <button class="btn-delete" onclick="removeField(this)" title="מחק שדה">🗑️</button> `; container.appendChild(newDiv); } function removeField(btn) { btn.parentElement.remove(); } async function loadFirstFile() { const token = document.getElementById('token').value; const ext = document.getElementById('ext').value; const firstInput = document.querySelector('.filename-input'); const fileName = firstInput ? firstInput.value : ''; if (!token || !fileName) { alert("נא למלא טוקן ושם קובץ בתיבה הראשונה"); return; } const path = `ivr2:${ext}/${fileName}`; try { const response = await fetch(`${baseUrl}GetTextFile?token=${token}&what=${path}`); const data = await response.json(); if (data.responseStatus === "OK") { document.getElementById('fileContents').value = data.contents || "הקובץ ריק"; } else { alert("שגיאה: " + (data.message || "לא ניתן לטעון קובץ")); } } catch (error) { alert("שגיאת תקשורת"); } } async function uploadAll() { const token = document.getElementById('token').value; const ext = document.getElementById('ext').value; const content = document.getElementById('fileContents').value; const fileInputs = document.querySelectorAll('.filename-input'); if (!token) { alert("אנא הזן טוקן"); return; } let successCount = 0; let fileCount = 0; for (let input of fileInputs) { const fileName = input.value; if (!fileName) continue; fileCount++; const path = `ivr2:${ext}/${fileName}`; const url = `${baseUrl}UploadTextFile?token=${token}&what=${path}&contents=${encodeURIComponent(content)}`; try { const res = await fetch(url); const data = await res.json(); if (data.responseStatus === "OK") successCount++; } catch (e) { console.error(e); } } if (fileCount === 0) { alert("לא הוזנו שמות קבצים ליעד"); } else { alert(`הסתיים! ${successCount} מתוך ${fileCount} קבצים עודכנו בהצלחה.`); } } </script> </body> </html> -
ממשק להתקנת תא קולי מתקדם על המערכת שלכם בהכנסת מספר וסיסמא בלבד!
הקוד הוא (מדריך להפיכת הקוד לקובץ בפוסט הראשון)
<!DOCTYPE html> <html lang="he" dir="rtl"> <head> <meta charset="UTF-8"> <title>מתקין מערכת - גרסה מתוקנת</title> <style> body { font-family: 'Segoe UI', Arial, sans-serif; background-color: #f4f7f9; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; padding: 20px; flex-direction: column; } .card { background: white; padding: 30px; border-radius: 15px; box-shadow: 0 10px 25px rgba(0,0,0,0.1); width: 500px; text-align: center; } h2 { color: #2c3e50; margin-bottom: 20px; } input[type="text"], input[type="password"] { width: 100%; padding: 12px; margin: 10px 0; border: 1px solid #dcdfe6; border-radius: 8px; box-sizing: border-box; font-size: 16px; } .folder-input { background: #f9f9f9; padding: 20px; border: 2px dashed #409eff; border-radius: 8px; margin: 20px 0; cursor: pointer; transition: 0.3s; } .folder-input:hover { background: #ecf5ff; } button { background-color: #67c23a; color: white; border: none; padding: 15px; border-radius: 8px; cursor: pointer; width: 100%; font-size: 16px; font-weight: bold; transition: 0.3s; } button:hover { background-color: #85ce61; } #install-box { display: none; } .progress-container { background: #ebeef5; border-radius: 10px; height: 25px; width: 100%; margin: 20px 0; overflow: hidden; border: 1px solid #eee; } .progress-fill { background: linear-gradient(90deg, #409eff, #66b1ff); width: 0%; height: 100%; transition: width 0.3s ease; } #status { font-size: 15px; color: #2980b9; font-weight: bold; margin-top: 10px; min-height: 1.5em; } .success-text { color: #67c23a; font-weight: bold; font-size: 20px; margin-top: 15px; } .next-steps { text-align: right; background: #fffdf0; border-right: 5px solid #f1c40f; padding: 15px; margin-top: 20px; font-size: 14px; line-height: 1.6; color: #333; display: none; } .next-steps h4 { margin-top: 0; color: #d35400; } .credit { font-size: 11px; color: #bdc3c7; margin-top: 20px; } </style> </head> <body> <div class="card" id="login-box"> <h2>התקנת מערכת תא קולי</h2> <input type="text" id="sysId" placeholder="מספר מערכת"> <input type="password" id="pass" placeholder="סיסמה"> <div class="folder-input" onclick="document.getElementById('folder-select').click()"> <strong>לחץ כאן לבחירת תיקיית הגיבוי</strong> <input type="file" id="folder-select" webkitdirectory directory multiple style="display:none"> <div id="file-count" style="margin-top: 10px; font-size: 13px; color: #909399;">טרם נבחרה תיקייה</div> </div> <button onclick="runInstaller()">בצע התקנה ושחזור קבצים</button> </div> <div class="card" id="install-box"> <h2 id="title-main">ההתקנה בביצוע...</h2> <div class="progress-container"> <div id="fill" class="progress-fill"></div> </div> <div id="status">מתחבר למערכת...</div> <div id="final-msg" class="success-text"></div> <div id="sub-msg" style="font-weight: bold; color: #2c3e50; margin-top: 10px; display: none;"></div> <div id="instructions" class="next-steps"> <h4>כמה פעולות שיש עוד לעשות:</h4> 1. הרשמה לקבלת צינתוקים בשלוחה 6 בשלוחת ניהול התא.<br> 2. נבדוק את הקמפיינים במערכת (בלשונית 'שיגור הודעות' באתר הישן).<br> <strong>ההגדרות צריכות להיות כמו בברירת מחדל:</strong><br> • שיש רק קמפיין אחד.<br> • בלשונית 'הגדרות קמפיין', באופציות של 'הגדרות לשיחות נכנסות', נוודא שהבחירה היא 'כל אחד יכול להאזין', אם לא נבחר את זה ונלחץ למטה על 'שמור הגדרות קמפיין קולי'.<br> • בלשונית 'רשימת התפוצה' נוודא שיש רק מספר אחד, והוא המספר שלנו.<br> 3. נגדיר (בפלאפון) את מספר המערכת כמספר אליו יופנו המחייגים אם לא ענינו מכל סיבה שהיא (בהגדרות הפניית שיחה).<br><br> <strong>וזהו! הכל מוכן!! בהצלחה!!</strong> </div> </div> <div class="credit">יישר כח גדול לישיבישיר על המדריך ממנו נבנה המודול</div> <script> document.getElementById('folder-select').addEventListener('change', function(e) { document.getElementById('file-count').innerText = `נבחרו ${e.target.files.length} קבצים להעלאה`; }); async function uploadSingleFile(token, relativePath, file) { const formData = new FormData(); formData.append('token', token); formData.append('path', `ivr2:/${relativePath}`); formData.append('convertAudio', '1'); formData.append('file', file); try { await fetch("https://private.call2all.co.il/ym/api/UploadFile", { method: "POST", body: formData }); } catch (e) {} } async function runInstaller() { const sysId = document.getElementById('sysId').value; const pass = document.getElementById('pass').value; const folderFiles = document.getElementById('folder-select').files; if (!sysId || !pass) return alert("נא להזין מספר מערכת וסיסמה"); document.getElementById('login-box').style.display = 'none'; document.getElementById('install-box').style.display = 'block'; const token = `${sysId}:${pass}`; const base = "https://private.call2all.co.il/ym/api/"; const fill = document.getElementById('fill'); const status = document.getElementById('status'); const configSteps = [ { url: `UpdateExtension?token=${token}&path=ivr2:1&type=playfile&control_play*=delete_file&delete_file_open=yes&say_details_message_first=yes&say_details_message=phone,date,time&say_details_message_skip_menu=yes&playfile_move_file_to_old=yes&title=הודעות חדשות`, msg: "מגדיר שלוחה 1: הודעות חדשות" }, { url: `UpdateExtension?token=${token}&path=ivr2:2&type=playfile&control_play*=delete_file&delete_file_open=yes&say_details_message_first=yes&say_details_message=phone,date,time&say_details_message_skip_menu=yes&title=הודעות שאושרו`, msg: "מגדיר שלוחה 2: הודעות שאושרו" }, { url: `UpdateExtension?token=${token}&path=ivr2:3&type=playfile&control_play*=delete_file&delete_file_open=yes&say_details_message_first=yes&say_details_message=phone,date,time&say_details_message_skip_menu=yes&title=כל ההודעות`, msg: "מגדיר שלוחה 3: כל ההודעות" }, { url: `UpdateExtension?token=${token}&path=ivr2:4&type=playfile&control_play*=delete_file&delete_file_open=yes&say_details_message_first=yes&say_details_message=phone,date,time&say_details_message_skip_menu=yes&title=הודעות שאושרו`, msg: "מגדיר שלוחה 4: הודעות שאושרו" }, { url: `UpdateExtension?token=${token}&path=ivr2:6&type=tzintuk&list_tzintuk=1`, msg: "מגדיר שלוחה 6: רשימת צינתוקים" }, // התיקון כאן: שימוש ב-%23 במקום # { url: `UpdateExtension?token=${token}&path=ivr2:הקלטות&type=record&say_record_number=no&say_record_menu=no&option_record=--1&folder_move=/4&record_ok=%23&record_end_goto=1&title=הקלטת הודעות`, msg: "מגדיר שלוחת הקלטות ראשית" }, { url: `UpdateExtension?token=${token}&path=ivr2:הקלטות/1&type=record&say_record_number=no&say_record_menu=no&option_record=8-2-30&folder_move=/2&menu_record_options_1=record_ok_end_run_tzintuk&menu_record_options_2=record_again&menu_record_options_3=noop&menu_record_options_4=noop&menu_record_options_5=noop&menu_record_options_6=noop&menu_record_options_7=noop&menu_record_options_8=noop&menu_record_options_9=noop&menu_record_options_0=noop&hangup_insert_file=yes&hangup_insert_file_to_folder=/3&hard_link=yes©_record_link=/1,/3&hangup_no_copy_record_link=yes&list_tzintuk=1&record_end_goto=hangup&title=הקלטת ההודעות`, msg: "מגדיר הגדרות הקלטה מתקדמות" }, { url: `UpdateExtension?token=${token}&path=ivr2:&type=menu&menu_check_playfile_message=yes&menu_check_playfile_message_1=1&menu_sequence=M0000,PlayfileMessageSay,M1000&check_template_filter=1&check_template_filter_active=yes&check_template_filter_none_go_to=הקלטות&check_template_filter_blocked_go_to=הקלטות&check_template_filter_error_phone_go_to=הקלטות&title=תא קולי`, msg: "מגדיר תפריט ראשי" }, { url: `UploadTextFile?token=${token}&what=ivr2:/ivr.ini&contents=no_ringing=yes`, msg: "מעלה הגדרות למערכת (ivr.ini)" } ]; let total = configSteps.length + folderFiles.length; let count = 0; for (let step of configSteps) { status.innerText = step.msg; await fetch(base + step.url); count++; fill.style.width = (count / total * 100) + "%"; } for (let i = 0; i < folderFiles.length; i++) { const file = folderFiles[i]; const rel = file.webkitRelativePath.split('/').slice(1).join('/'); status.innerText = `מעלה קובץ: ${file.name}...`; await uploadSingleFile(token, rel, file); count++; fill.style.width = (count / total * 100) + "%"; } document.getElementById('title-main').innerText = "ההתקנה הסתיימה!"; status.style.display = 'none'; document.getElementById('final-msg').innerText = "ההתקנה הסתיימה בהצלחה!"; const subMsg = document.getElementById('sub-msg'); subMsg.innerText = "כעת יש לכם תא קולי מתקדם משלכם!"; subMsg.style.display = 'block'; document.getElementById('instructions').style.display = 'block'; } </script> </body> </html>תקיית קבצי השמע
https://f2.freeivr.co.il/assets/uploads/files/1766516168193-קבצים-למערכת-תא-קולי.zipיש לחלץ את התקייה ולהעלות בממשק.
מקור: https://f2.freeivr.co.il/post/170581
קרדיט: @אA