• הרשמה
    • התחברות
    • חיפוש
    • דף הבית
    • אינדקס קישורים
    • פוסטים אחרונים
    • קבלת התראות מהדפדפן
    • משתמשים
    • חיפוש בהגדרות המתקדמות
    • חיפוש גוגל בפורום
    • ניהול המערכת
    • ניהול המערכת - שרת private

    קבצים ותוכנות לשימוש במערכות ימות המשיח

    עזרה הדדית למשתמשים מתקדמים
    5
    16
    251
    טוען פוסטים נוספים
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
    תגובה
    • הגיבו כנושא
    התחברו בכדי לפרסם תגובה
    נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
    • א
      אA נערך לאחרונה על ידי אA

      קובץ להורדת קבצים מהמערכת (קבצי wav, tts, ini, html) כולל אפשרות להמרה + אפשרות להורדת קבצים מרובים

      הורדת קבצים.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

      תגובה 1 תגובה אחרונה תגובה ציטוט 0
      • א
        אA נערך לאחרונה על ידי אA

        קובץ להעלאה והורדה של כל סוגי הקבצים למערכות כולל קבצי 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; 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

        H תגובה 1 תגובה אחרונה תגובה ציטוט 0
        • א
          אA נערך לאחרונה על ידי א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

          א תגובה 1 תגובה אחרונה תגובה ציטוט 1
          • א
            אאא יוני @אA נערך לאחרונה על ידי

            @אA כתב בקבצי HTML לשימוש במערכות ימות המשיח:

            הפעלת קמפיין - הנכנס לשלוחה במערכת.html

            מה הכוונה?
            "הנכנס לשולחה במערכת"?שליחת קמפיין רגיל? משהו אחר?
            (סליחה על ההתערבות בשירשור בלנ"ד אח"כ אמחק )

            תגובה 1 תגובה אחרונה תגובה ציטוט 0
            • א
              אA נערך לאחרונה על ידי א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

              פ תגובה 1 תגובה אחרונה תגובה ציטוט 0
              • H
                haiims @אA נערך לאחרונה על ידי haiims

                @אA במערכת מעלה קבצים יש אפשרות לעלות לכמה שלוחות יחד? למחוק קבצים אפשר?
                ואין אפשרות לראות % או משהו כזה עד לסיום הפעולה ?

                תגובה 1 תגובה אחרונה תגובה ציטוט 0
                • פ
                  פיתה @אA נערך לאחרונה על ידי

                  פוסט זה נמחק!
                  א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                  • א
                    אA @פיתה נערך לאחרונה על ידי

                    פוסט זה נמחק!
                    תגובה 1 תגובה אחרונה תגובה ציטוט 0
                    • א
                      אA נערך לאחרונה על ידי אA

                      ממשק ניהול הקבצים במערכת

                      ממשק ניהול קבצים במערכת.html

                      הקוד מצורף בספויילר

                      <!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

                      תגובה 1 תגובה אחרונה תגובה ציטוט 1
                      • ע
                        עידו נערך לאחרונה על ידי

                        פוסט זה נמחק!
                        תגובה 1 תגובה אחרונה תגובה ציטוט 0
                        • פוסט ראשון
                          פוסט אחרון