• שדרוג אתר הניהול - חוו"ד המשתמשים

    נעוץ נעול
    1
    36 הצבעות
    1 פוסטים
    1k צפיות
    אין תגובות
  • תקנון קטגוריית עזרה הדדית

    נעוץ נעול הועבר
    1
    16 הצבעות
    1 פוסטים
    2k צפיות
    אין תגובות
  • תגובות | פיתוח פרטי | לייק ודיסלייק בהשמעת קבצים 👍/👎

    48
    3 הצבעות
    48 פוסטים
    185 צפיות
    1
    @CUBASE זה יאמר לפני כל קובץ כמה לייקים יש להודעה אחרי הטיפול
  • הפניית שיחות בזמן שהשלוחה סגורה

    1
    0 הצבעות
    1 פוסטים
    10 צפיות
    אין תגובות
  • השמעת הודעה לפני הפילטר לפי רשימת הצינתוקים

    לא נפתר
    20
    1
    0 הצבעות
    20 פוסטים
    94 צפיות
    ש
    @sh0548534047 איזה הגדרה? תסתכל פה ותגיד לי למה אתה מתכון?
  • פאנל ניהול מותאם אישית

    38
    0 הצבעות
    38 פוסטים
    105 צפיות
    B
    @R.E.T-מערכות @אa תירגמתי את הקוד לHTML הצלחתי ליצור את ההגבלה בטוקן צריך להזין את הטוקן המוגבל לבחור לאיזה שלוחה הוא מוגבל הוא מציג את כל השלוחות ממנה עד בפנים כולל קבצים ייתכן וישנם באגים עדיין לא בדקתי 100 אחוז אשמח לקבל הערות הארות קוד HTML <!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> <!-- פונט גוגל ואייקונים --> <link href="https://fonts.googleapis.com/css2?family=Heebo:wght@300;400;600;700&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" /> <style> :root { --primary: #2563eb; --primary-hover: #1d4ed8; --bg-color: #f8fafc; --card-bg: #ffffff; --text-main: #1e293b; --text-muted: #64748b; --border: #e2e8f0; --success: #10b981; --error: #ef4444; } body { font-family: 'Heebo', sans-serif; margin: 0; padding: 0; background-color: var(--bg-color); color: var(--text-main); } /* === מסך התחברות === */ #login-screen { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: var(--bg-color); z-index: 9999; display: flex; justify-content: center; align-items: center; } .login-card { background: white; padding: 40px; border-radius: 12px; box-shadow: 0 10px 25px rgba(0,0,0,0.05); width: 400px; max-width: 90%; text-align: center; border: 1px solid var(--border); } .login-card h2 { margin-top: 0; color: var(--text-main); font-size: 24px; margin-bottom: 5px; } .login-card p { color: var(--text-muted); font-size: 14px; margin-bottom: 25px; } .form-group { text-align: right; margin-bottom: 20px; } .form-group label { display: block; font-weight: 600; margin-bottom: 8px; font-size: 14px; color: var(--text-main); } .form-group input { width: 100%; padding: 12px; border: 1px solid var(--border); border-radius: 8px; box-sizing: border-box; font-family: 'Heebo', sans-serif; font-size: 15px; transition: 0.2s; direction: ltr; text-align: left; } .form-group input:focus { border-color: var(--primary); outline: none; box-shadow: 0 0 0 3px rgba(37,99,235,0.1); } /* === המערכת המרכזית === */ #app-container { display: none; } .top-header { background: white; padding: 20px 40px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); box-shadow: 0 1px 3px rgba(0,0,0,0.05); } .top-header h1 { margin: 0; font-size: 28px; font-weight: 600; } .actions-bar { display: flex; gap: 15px; } button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; font-family: 'Heebo', sans-serif; font-size: 15px; font-weight: 500; cursor: pointer; border: none; border-radius: 8px; padding: 10px 20px; transition: 0.2s; } .btn-primary { background: var(--primary); color: white; } .btn-primary:hover { background: var(--primary-hover); } .btn-secondary { background: #475569; color: white; } .btn-secondary:hover { background: #334155; } .btn-danger { background: var(--error); color: white; } .btn-danger:hover { background: #dc2626; } .btn-warning { background: #f59e0b; color: white; } .btn-warning:hover { background: #d97706; } .btn-icon { padding: 8px; font-size: 14px; } .btn-full { width: 100%; padding: 12px; font-size: 16px; margin-top: 10px; } .main-container { max-width: 1400px; margin: 0 auto; padding: 30px; } .breadcrumbs { font-size: 16px; color: var(--text-muted); margin-bottom: 20px; display: flex; align-items: center; gap: 10px; } .breadcrumbs span.clickable { cursor: pointer; transition: 0.2s; font-weight: 600; } .breadcrumbs span.clickable:hover { color: var(--primary); } .breadcrumbs .separator { color: #cbd5e1; cursor: default; } .tabs-header { display: flex; gap: 30px; border-bottom: 2px solid var(--border); margin-bottom: 30px; } .tab-btn { background: none; border: none; color: var(--text-muted); font-size: 18px; font-weight: 600; padding: 10px 5px; cursor: pointer; border-bottom: 3px solid transparent; margin-bottom: -2px; border-radius: 0; } .tab-btn.active { color: var(--primary); border-bottom-color: var(--primary); } .tab-content { display: none; } .tab-content.active { display: block; } .folders-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; margin-bottom: 40px; } .folder-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px; padding: 20px; display: flex; align-items: center; gap: 15px; cursor: pointer; transition: box-shadow 0.2s, transform 0.2s; box-shadow: 0 1px 3px rgba(0,0,0,0.05); } .folder-card:hover { box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1); transform: translateY(-2px); border-color: #cbd5e1; } .folder-icon { color: var(--text-muted); font-size: 40px; } .folder-details { flex: 1; } .folder-title { font-size: 20px; font-weight: 700; margin: 0 0 5px 0; } .folder-subtitle { font-size: 14px; color: var(--text-muted); margin: 0; } .files-section { background: white; border-radius: 12px; border: 1px solid var(--border); overflow: hidden; } .section-title { padding: 15px 20px; background: #f8fafc; border-bottom: 1px solid var(--border); margin: 0; font-size: 16px; color: var(--text-muted); } table { width: 100%; border-collapse: collapse; } th, td { padding: 15px 20px; text-align: right; border-bottom: 1px solid var(--border); } th { color: var(--text-muted); font-weight: 600; font-size: 14px; } tr:hover { background: #f1f5f9; } .td-actions { display: flex; gap: 8px; justify-content: flex-end; } .editor-container { background: white; padding: 20px; border-radius: 12px; border: 1px solid var(--border); } textarea.code-editor { width: 100%; height: 400px; font-family: monospace; font-size: 16px; direction: ltr; padding: 15px; box-sizing: border-box; border: 1px solid var(--border); border-radius: 8px; background: #1e1e1e; color: #d4d4d4; margin-bottom: 15px; resize: vertical;} .modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 1000; justify-content: center; align-items: center; } .modal-content { background: white; width: 700px; max-width: 90%; border-radius: 12px; padding: 25px; display: flex; flex-direction: column; gap: 15px; box-shadow: 0 10px 25px rgba(0,0,0,0.2); } .modal-content h3 { margin: 0; font-size: 20px; } .modal-actions { display: flex; justify-content: flex-end; gap: 10px; } .hidden-input { display: none; } /* === הודעות צפות (Toasts) === */ #toast-container { position: fixed; bottom: 20px; left: 20px; z-index: 10000; display: flex; flex-direction: column; gap: 10px; } .toast { background: var(--success); color: white; padding: 12px 24px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: flex; align-items: center; gap: 8px; font-size: 15px; opacity: 0; transform: translateY(20px); transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); } .toast.show { opacity: 1; transform: translateY(0); } .toast.error { background: var(--error); } </style> </head> <body> <!-- קונטיינר להודעות צxxx --> <div id="toast-container"></div> <!-- מסך התחברות --> <div id="login-screen"> <div class="login-card"> <span class="material-symbols-outlined" style="font-size: 48px; color: var(--primary); margin-bottom: 10px;">cloud_sync</span> <h2>התחברות למערכת</h2> <p>הזן את מפתח ה-API (טוקן) שלך כדי להמשיך</p> <div class="form-group"> <label>מפתח API (Token)</label> <input type="password" id="login-token" placeholder="הדבק את הטוקן כאן..." autocomplete="off"> </div> <div class="form-group"> <label>הגבלת שלוחה (אופציונלי)</label> <input type="text" id="login-ext" placeholder="לדוגמה: 18 (השאר ריק אם אין הגבלה)" autocomplete="off"> </div> <button class="btn-primary btn-full" id="login-btn" onclick="attemptLogin()"> <span class="material-symbols-outlined">login</span> התחבר למערכת </button> </div> </div> <!-- המערכת עצמה --> <div id="app-container"> <header class="top-header"> <h1 id="main-title">ניהול קבצים</h1> <div class="actions-bar"> <button class="btn-primary" onclick="document.getElementById('file-upload-new').click()"> <span class="material-symbols-outlined">upload</span> העלה קובץ חדש </button> <button class="btn-secondary" onclick="logout()"> <span class="material-symbols-outlined">logout</span> התנתק </button> <input type="file" id="file-upload-new" class="hidden-input" onchange="uploadNewFile(this)"> <input type="file" id="file-replace-input" class="hidden-input" onchange="submitReplaceFile(this)"> </div> </header> <div class="main-container"> <div class="breadcrumbs" id="breadcrumbs"></div> <div class="tabs-header"> <button class="tab-btn active" onclick="switchTab('tab-folders')">תיקיות וקבצים</button> <button class="tab-btn" onclick="switchTab('tab-messages')">הודעות מערכת</button> <button class="tab-btn" onclick="switchTab('tab-settings')">הגדרות שלוחה (ext.ini)</button> </div> <div id="tab-folders" class="tab-content active"> <div class="folders-grid" id="folders-grid"></div> <div class="files-section"> <h3 class="section-title">קבצים בשלוחה (כולל קבצי שמע, הגדרות ודוחות)</h3> <table> <thead><tr><th>שם קובץ</th><th>סוג</th><th>גודל</th><th>תאריך שינוי</th><th>פעולות</th></tr></thead> <tbody id="files-list"></tbody> </table> </div> </div> <div id="tab-messages" class="tab-content"> <div class="files-section"> <h3 class="section-title">הודעות מערכת מוקלטות (קבצי M)</h3> <table> <thead><tr><th>שם קובץ</th><th>תיאור הודעה</th><th>גודל/אורך</th><th>פעולות</th></tr></thead> <tbody id="messages-list"></tbody> </table> </div> </div> <div id="tab-settings" class="tab-content"> <div class="editor-container"> <h3 style="margin-top:0;">עריכת ext.ini (שלוחה נוכחית)</h3> <textarea id="ini-editor" class="code-editor" spellcheck="false" placeholder="טוען נתונים..."></textarea> <div style="text-align: left;"> <button class="btn-primary" onclick="saveExtIniFile(this)"> <span class="material-symbols-outlined">save</span> שמור הגדרות </button> </div> </div> </div> </div> </div> <!-- מודל עריכה --> <div id="file-editor-modal" class="modal-overlay"> <div class="modal-content"> <h3 id="modal-editor-title">עריכת קובץ</h3> <textarea id="modal-editor-textarea" class="code-editor" spellcheck="false"></textarea> <div class="modal-actions"> <button class="btn-secondary" onclick="closeEditorModal()">ביטול</button> <button class="btn-primary" onclick="saveModalFile(this)"> <span class="material-symbols-outlined">save</span> שמור קובץ </button> </div> <input type="hidden" id="modal-editor-path"> </div> </div> <script> let TOKEN = ''; let BASE_EXTENSION = ''; let currentPath = ''; let currentReplacePath = ''; const API_URL = 'https://private.call2all.co.il/ym/api/'; document.addEventListener('DOMContentLoaded', () => { const savedToken = localStorage.getItem('ym_token'); const savedExt = localStorage.getItem('ym_ext'); if (savedToken) { document.getElementById('login-token').value = savedToken; if (savedExt) document.getElementById('login-ext').value = savedExt; attemptLogin(); } }); function showToast(message, isError = false) { const container = document.getElementById('toast-container'); const toast = document.createElement('div'); toast.className = `toast ${isError ? 'error' : ''}`; toast.innerHTML = `<span class="material-symbols-outlined">${isError ? 'error' : 'check_circle'}</span> ${message}`; container.appendChild(toast); setTimeout(() => toast.classList.add('show'), 10); setTimeout(() => { toast.classList.remove('show'); setTimeout(() => toast.remove(), 300); }, 3000); } function normalizePath(p) { if (!p || p === '/' || p === 'ivr2:') return 'ivr2:/'; if (p.startsWith('ivr2:')) { if (!p.startsWith('ivr2:/')) p = p.replace('ivr2:', 'ivr2:/'); } else if (p.startsWith('/')) { p = 'ivr2:' + p; } else { p = 'ivr2:/' + p; } if (p.endsWith('/') && p.length > 6) p = p.slice(0, -1); return p; } async function attemptLogin() { const tokenInput = document.getElementById('login-token').value.trim(); const extInput = document.getElementById('login-ext').value.trim(); const btn = document.getElementById('login-btn'); if (!tokenInput) { alert('חובה להזין מפתח API (טוקן).'); return; } TOKEN = tokenInput; BASE_EXTENSION = extInput ? normalizePath(extInput) : 'ivr2:/'; currentPath = BASE_EXTENSION; btn.innerHTML = '<span class="material-symbols-outlined">hourglass_empty</span> מתחבר...'; btn.disabled = true; try { const data = await apiRequest('GetIVR2Dir', { path: currentPath }); if (data && (data.responseStatus === 'ERROR' || data.responseStatus === 'EXCEPTION')) { alert("שגיאת גישה: " + (data.message || data.exceptionMessage)); resetLoginBtn(btn); return; } localStorage.setItem('ym_token', TOKEN); localStorage.setItem('ym_ext', extInput); document.getElementById('login-screen').style.display = 'none'; document.getElementById('app-container').style.display = 'block'; let displayTitle = BASE_EXTENSION === 'ivr2:/' ? 'הראשית' : BASE_EXTENSION.replace(/^ivr2:\//, ''); document.getElementById('main-title').innerText = 'ניהול קבצים - שלוחה ' + displayTitle; document.title = 'ניהול תוכן - שלוחה ' + displayTitle; renderBreadcrumbs(currentPath); renderFolders(data.dirs ||[]); renderFiles(data.files ||[], data.html || [], data.ini ||[]); renderMessages(data.messages ||[], data.msgDescriptions || {}); loadExtIniEditor(currentPath); } catch (error) { alert('שגיאת תקשורת מול שרתי ימות המשיח.'); resetLoginBtn(btn); } } function resetLoginBtn(btn) { btn.innerHTML = '<span class="material-symbols-outlined">login</span> התחבר למערכת'; btn.disabled = false; } function logout() { if(!confirm('האם אתה בטוח שברצונך להתנתק?')) return; localStorage.removeItem('ym_token'); localStorage.removeItem('ym_ext'); location.reload(); } // פונקציית תקשורת כללית ללא קבצים - שולחת מידע כפרמטרים כדי לרצות את חומת האש async function apiRequest(endpoint, params = {}) { const urlParams = new URLSearchParams(); urlParams.append('token', TOKEN); for (const key in params) { urlParams.append(key, params[key]); } try { const response = await fetch(API_URL + endpoint, { method: 'POST', body: urlParams }); return await response.json(); } catch (error) { throw error; } } function switchTab(tabId) { document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active')); document.querySelectorAll('.tab-btn').forEach(el => el.classList.remove('active')); document.getElementById(tabId).classList.add('active'); event.currentTarget.classList.add('active'); } async function loadDirectory(path) { let normalizedPath = normalizePath(path); try { const data = await apiRequest('GetIVR2Dir', { path: normalizedPath }); if (!data || data.responseStatus === 'ERROR' || data.responseStatus === 'EXCEPTION') { showToast('שגיאה מול השרת: ' + (data.message || data.exceptionMessage), true); return; } currentPath = normalizedPath; renderBreadcrumbs(normalizedPath); renderFolders(data.dirs ||[]); renderFiles(data.files || [], data.html ||[], data.ini ||[]); renderMessages(data.messages ||[], data.msgDescriptions || {}); loadExtIniEditor(normalizedPath); } catch (error) { showToast('שגיאת תקשורת במשיכת נתוני התיקייה.', true); } } function renderBreadcrumbs(path) { const container = document.getElementById('breadcrumbs'); container.innerHTML = ''; let normPath = normalizePath(path); let normBase = normalizePath(BASE_EXTENSION); let rootSpan = document.createElement('span'); rootSpan.className = 'material-symbols-outlined clickable'; rootSpan.style.fontSize = '24px'; rootSpan.innerText = 'home'; rootSpan.title = 'ראשי'; rootSpan.onclick = () => loadDirectory(normBase); container.appendChild(rootSpan); if (normPath === normBase) return; let relativePath = ''; let prefix = normBase === 'ivr2:/' ? 'ivr2:/' : normBase + '/'; if (normPath.startsWith(prefix)) { relativePath = normPath.substring(prefix.length); } else { relativePath = normPath.replace(/^ivr2:\//, ''); } if(!relativePath) return; let parts = relativePath.split('/'); let buildPath = normBase; parts.forEach((part) => { buildPath += (buildPath === 'ivr2:/' ? '' : '/') + part; let clickPath = buildPath; let sep = document.createElement('span'); sep.className = 'separator'; sep.innerText = ' / '; container.appendChild(sep); let span = document.createElement('span'); span.className = 'clickable'; span.innerText = part; span.onclick = () => loadDirectory(clickPath); container.appendChild(span); }); } function renderFolders(dirs) { const grid = document.getElementById('folders-grid'); grid.innerHTML = ''; if(!dirs || dirs.length === 0) return; dirs.forEach(dir => { const title = dir.extTitle || 'ללא תיאור'; const type = dir.extType || 'תיקייה / תפריט'; grid.innerHTML += ` <div class="folder-card" onclick="loadDirectory('${dir.what}')"> <span class="material-symbols-outlined folder-icon">folder</span> <div class="folder-details"> <h3 class="folder-title">${dir.name}</h3> <p class="folder-subtitle">${type} • ${title}</p> </div> </div> `; }); } function renderFiles(files, htmlFiles, iniFiles) { const tbody = document.getElementById('files-list'); tbody.innerHTML = ''; let allRegular =[...(files||[]), ...(htmlFiles||[]), ...(iniFiles||[])]; if (allRegular.length === 0) { tbody.innerHTML = '<tr><td colspan="5" style="text-align:center;">אין קבצים בשלוחה זו</td></tr>'; return; } allRegular.forEach(file => { let sizeInfo = file.size ? (file.size / 1024).toFixed(2) + ' KB' : '-'; let isEditable = file.fileType === 'INI' || file.fileType === 'HTML' || file.name.endsWith('.txt'); let icon = (file.fileType === 'AUDIO' || file.name.endsWith('.wav') || file.name.endsWith('.mp3')) ? 'audio_file' : (file.fileType === 'INI' ? 'settings' : 'description'); let editBtn = isEditable ? `<button class="btn-primary btn-icon" onclick="openFileEditorModal('${file.what}', '${file.name}')" title="ערוך קובץ"><span class="material-symbols-outlined">edit</span></button>` : ''; tbody.innerHTML += ` <tr> <td><span class="material-symbols-outlined" style="vertical-align: middle; margin-left:5px;">${icon}</span> ${file.name}</td> <td>${file.fileType || 'FILE'}</td> <td dir="ltr" style="text-align: right;">${sizeInfo}</td> <td dir="ltr" style="text-align: right;">${file.mtime || '-'}</td> <td class="td-actions"> ${editBtn} <button class="btn-warning btn-icon" onclick="triggerReplace('${file.what}')" title="החלף קובץ קיים"><span class="material-symbols-outlined">find_replace</span></button> <button class="btn-secondary btn-icon" onclick="downloadFile('${file.what}')" title="הורדה"><span class="material-symbols-outlined">download</span></button> <button class="btn-danger btn-icon" onclick="deleteFile('${file.what}')" title="מחיקה"><span class="material-symbols-outlined">delete</span></button> </td> </tr> `; }); } function renderMessages(messages, descriptions) { const tbody = document.getElementById('messages-list'); tbody.innerHTML = ''; if (!messages || messages.length === 0) { tbody.innerHTML = '<tr><td colspan="4" style="text-align:center;">אין הודעות מערכת (M) בשלוחה זו</td></tr>'; return; } messages.forEach(file => { let desc = (descriptions && descriptions[file.name.replace('.wav','')]) ? descriptions[file.name.replace('.wav','')] : 'ללא תיאור'; let sizeInfo = file.durationStr ? file.durationStr : (file.size ? (file.size / 1024).toFixed(2) + ' KB' : '-'); tbody.innerHTML += ` <tr> <td style="font-weight:bold; color:var(--primary);">${file.name}</td> <td>${desc}</td> <td dir="ltr" style="text-align: right;">${sizeInfo}</td> <td class="td-actions"> <button class="btn-warning btn-icon" onclick="triggerReplace('${file.what}')" title="החלף קובץ"><span class="material-symbols-outlined">find_replace</span></button> <button class="btn-secondary btn-icon" onclick="downloadFile('${file.what}')" title="הורדה"><span class="material-symbols-outlined">download</span></button> <button class="btn-danger btn-icon" onclick="deleteFile('${file.what}')" title="מחיקה"><span class="material-symbols-outlined">delete</span></button> </td> </tr> `; }); } function triggerReplace(targetPath) { currentReplacePath = targetPath; document.getElementById('file-replace-input').click(); } async function submitReplaceFile(inputElement) { if (inputElement.files.length === 0) return; const file = inputElement.files[0]; showToast('הקובץ עולה לשרת, אנא המתן...'); try { const formData = new FormData(); formData.append('token', TOKEN); formData.append('path', normalizePath(currentReplacePath)); formData.append('file', file); const response = await fetch(API_URL + 'UploadFile', { method: 'POST', body: formData }); const result = await response.json(); if (result.responseStatus === 'OK' || result.path) { showToast('הקובץ הוחלף בהצלחה!'); loadDirectory(currentPath); } else { showToast('שגיאה: ' + (result.message || 'חסום'), true); } } catch (error) { showToast('שגיאת תקשורת בהחלפת הקובץ', true); } inputElement.value = ''; } async function uploadNewFile(inputElement) { if (inputElement.files.length === 0) return; const file = inputElement.files[0]; let targetPath = currentPath === 'ivr2:/' ? 'ivr2:/' + file.name : currentPath + '/' + file.name; showToast('מעלה קובץ חדש, אנא המתן...'); try { const formData = new FormData(); formData.append('token', TOKEN); formData.append('path', normalizePath(targetPath)); formData.append('file', file); const response = await fetch(API_URL + 'UploadFile', { method: 'POST', body: formData }); const result = await response.json(); if (result.responseStatus === 'OK' || result.path) { showToast('הקובץ הועלה בהצלחה!'); loadDirectory(currentPath); } else { showToast('שגיאה: ' + (result.message || 'חסום ע"י השרת'), true); } } catch (error) { showToast('שגיאת תקשורת', true); } inputElement.value = ''; } function downloadFile(what) { window.location.href = API_URL + 'DownloadFile?token=' + TOKEN + '&path=' + encodeURIComponent(normalizePath(what)); } async function deleteFile(what) { if (!confirm('האם למחוק קובץ זה לצמיתות?')) return; try { const result = await apiRequest('FileAction', { action: 'delete', what: normalizePath(what) }); if (result.success || result.responseStatus === 'OK') { showToast('הקובץ נמחק בהצלחה!'); loadDirectory(currentPath); } else { showToast('שגיאה במחיקה (ייתכן שחסום ע"י הפיירוול).', true); } } catch(e) { showToast('שגיאת תקשורת במחיקה', true); } } async function openFileEditorModal(what, name) { document.getElementById('modal-editor-title').innerText = `עורך קובץ: ${name}`; document.getElementById('modal-editor-path').value = normalizePath(what); document.getElementById('modal-editor-textarea').value = 'טוען תוכן...'; document.getElementById('file-editor-modal').style.display = 'flex'; try { const result = await apiRequest('GetTextFile', { what: normalizePath(what) }); document.getElementById('modal-editor-textarea').value = result.contents !== undefined ? result.contents : ''; } catch (e) { document.getElementById('modal-editor-textarea').value = 'שגיאה בטעינת הקובץ'; } } function closeEditorModal() { document.getElementById('file-editor-modal').style.display = 'none'; } // הטריק לשמירת כל קובץ INI / TXT (הפיכתו לקובץ וירטואלי) async function saveModalFile(btn) { const what = document.getElementById('modal-editor-path').value; const contents = document.getElementById('modal-editor-textarea').value; const originalHTML = btn.innerHTML; btn.innerHTML = '<span class="material-symbols-outlined">hourglass_empty</span> שומר...'; btn.disabled = true; try { // חילוץ שם הקובץ מתוך הנתיב (למשל file.txt או settings.ini) const filename = what.split('/').pop() || 'file.txt'; // הפיכת הטקסט לקובץ ממשי כדי לעקוף את הפיירוול (כמו העלאת שמע) const blob = new Blob([contents], { type: 'text/plain;charset=utf-8' }); const file = new File([blob], filename, { type: 'text/plain' }); const formData = new FormData(); formData.append('token', TOKEN); formData.append('path', normalizePath(what)); formData.append('file', file); const response = await fetch(API_URL + 'UploadFile', { method: 'POST', body: formData }); const result = await response.json(); if (result.responseStatus === 'OK' || result.path) { btn.innerHTML = '<span class="material-symbols-outlined">check</span> נשמר בהצלחה!'; btn.style.backgroundColor = 'var(--success)'; setTimeout(() => { btn.innerHTML = originalHTML; btn.style.backgroundColor = ''; btn.disabled = false; closeEditorModal(); loadDirectory(currentPath); }, 1500); } else { showToast('שגיאה בשמירה: ' + (result.message || 'חסום'), true); btn.innerHTML = originalHTML; btn.disabled = false; } } catch (e) { showToast('שגיאת תקשורת', true); btn.innerHTML = originalHTML; btn.disabled = false; } } async function loadExtIniEditor(path) { let targetPath = path === 'ivr2:/' ? 'ivr2:/ext.ini' : path + '/ext.ini'; const editor = document.getElementById('ini-editor'); editor.value = 'טוען...'; try { const result = await apiRequest('GetTextFile', { what: targetPath }); editor.value = result.contents !== undefined ? result.contents : ''; } catch (e) { editor.value = ''; } } // הטריק לשמירת ה-ext.ini הראשי בכרטיסיה ה-3 async function saveExtIniFile(btn) { let targetPath = currentPath === 'ivr2:/' ? 'ivr2:/ext.ini' : currentPath + '/ext.ini'; const contents = document.getElementById('ini-editor').value; const originalHTML = btn.innerHTML; btn.innerHTML = '<span class="material-symbols-outlined">hourglass_empty</span> שומר...'; btn.disabled = true; try { // אריזת הטקסט לקובץ וירטואלי const blob = new Blob([contents], { type: 'text/plain;charset=utf-8' }); const file = new File([blob], 'ext.ini', { type: 'text/plain' }); const formData = new FormData(); formData.append('token', TOKEN); formData.append('path', normalizePath(targetPath)); formData.append('file', file); const response = await fetch(API_URL + 'UploadFile', { method: 'POST', body: formData }); const result = await response.json(); if (result.responseStatus === 'OK' || result.path) { btn.innerHTML = '<span class="material-symbols-outlined">check</span> הגדרות נשמרו!'; btn.style.backgroundColor = 'var(--success)'; setTimeout(() => { btn.innerHTML = originalHTML; btn.style.backgroundColor = ''; btn.disabled = false; }, 2500); } else { showToast('שגיאה בשמירה: ' + (result.message || 'בדוק חומת אש'), true); btn.innerHTML = originalHTML; btn.disabled = false; } } catch (e) { showToast('שגיאת תקשורת', true); btn.innerHTML = originalHTML; btn.disabled = false; } } </script> </body> </html> הגסון ששמתי במפתח { "tokenNike": "הגבלה לשלוחה 1", "tokenUser": "pIi0j5kxIJmxCGStG3DNiQ", "tokenMore": { "ws_parms_whitelist": [ "wath", "path", "what", "action", "contents", "target", "file" ], "ws_parms_mismatch_action": "remove", "default_acl_policy": "deny", "acl_rules": [ { "ip": [], "name": "Allow Extension 18 and Sub-folders", "active": true, "params": [ "what=ivr2:/18/**", "what=ivr2:/18", "what=ivr2:18/**", "what=ivr2:18", "wath=ivr2:/18/**", "wath=ivr2:/18", "wath=ivr2:18/**", "wath=ivr2:18", "path=ivr2:/18/**", "path=ivr2:/18", "path=ivr2:18/**", "path=ivr2:18", "path=/18/**", "path=/18", "path=18/**", "path=18", "target=ivr2:/18/**", "target=ivr2:/18", "target=ivr2:18/**", "target=ivr2:18" ], "policy": "allow", "endpoint": [], "set_params": {} } ] } } Spoiler אני לא מבין במפתחות API גם אין כלכך הסבר ברור זה הגדרות שגימיני כתב אז אולי הוא חרטט כמה הגדרות תכלס זה עובד רק לשלוחה השאתי וזה מה שחשוב לי אם יש פה מישהו שמבין בזה אשמח אם יעבור על זה ויתן לי גסון תקין לניהול וביצוע כל הפעולות שתחת שלוחה 18 כולל תתי שלוחות
  • תגובה לקבצי HTML לשימוש במערכות ימות המשיח

    39
    2 הצבעות
    39 פוסטים
    1k צפיות
    א
    שימו לב! השירשור הקודם ננעל, וכעת השירשור של הקבצים נמצא בקישור הבא https://f2.freeivr.co.il/topic/20552/קבצים-ותוכנות-לשימוש-במערכות-ימות-המשיח?_=1776284093577 שירשור התגובות ממשיך כאן בהצלחה!
  • SMS במערכת

    2
    0 הצבעות
    2 פוסטים
    38 צפיות
    B
    איך אני יודע איזה מספרים יכולים לקבל SMS ניסיתי אם הפקודה הזו וזה אומר לי שאף מספר לא מאושר בפועל לפעמים עובד לי על מספר נייח ולפעמים לא
  • הודעה פרטית + הקשת מספר פלאפון

    4
    0 הצבעות
    4 פוסטים
    45 צפיות
    S
    @המיוחס ישלח צינתוק לרשימה של שמעון. אם אתה רוצה חיוג זה עוד הגדרות
  • דוח מקיף על השמעות במערכת, איך עושים?

    11
    0 הצבעות
    11 פוסטים
    38 צפיות
    א
    @anti-malware https://f2.freeivr.co.il/post/84092
  • דחוף - ניהול חדרי ועידה חסומה זמנית - שימו לב לתמונה

    7
    1
    0 הצבעות
    7 פוסטים
    20 צפיות
    י
    @CUBASE תודה על הרצון הטוב. מעריך.
  • בדיקת מספר אם פתוח לכשרים 📶⚖️

    14
    2 הצבעות
    14 פוסטים
    84 צפיות
    C
    יש גם לרמי לוי https://mobile.rami-levy.co.il/Page.aspx/96 כמובן ככל שיש ליותר חברות - זה יותר טוב, אפשר לעשות קו שבו ניתן לבדוק על מספר אם הוא חסום לפי חברה @sumone ה-API של רמי לוי חוזר ב-JSON - הרבה יותר פשוט: https://mobile.rami-levy.co.il/api/List/kosher_block_numbers/ListData?limit=50&ascending=0&page=1&byColumn=1&orderBy=תאריך+חסימה&query[טלפון]=0799193000 { "data": [ { "מס": "2513008", "טלפון": "0799193000", "תאריך חסימה": "27/08/2020", "גורם": "ועדת רבנים", "class": "", "orig": { "k_id": 2513008, "k_dialed_num": "0799193000", "k_block_date": "2020-08-27T00:00:00", "k_block_user": "ועדת רבנים", "k_type_num": "", "block_date": "27/08/2020" } } ], "count": 1 }
  • 07 לא נכנס

    נפתר
    8
    0 הצבעות
    8 פוסטים
    37 צפיות
    ל
    @נועם-אלימלך תסדוק אם עןבד הסרה מרשימה שחורה
  • נושא זה נמחק!

    1
    0 הצבעות
    1 פוסטים
    6 צפיות
    אין תגובות
  • עידכונים

    11
    0 הצבעות
    11 פוסטים
    55 צפיות
    נ
    @R.E.T-מערכות כתב בעידכונים: לא באמת חשוב לך ומילא לא נראה לי שמישהו ייתנדב לעשות לך את זה הדבר הזה בפרט שזה לא נצרך לאף אחד צודק הבל זה כן חשוב
  • הסרת מספר מרשימה שחורה בשלוחה (מודול הסרת ערך)

    9
    0 הצבעות
    9 פוסטים
    32 צפיות
    א
    @יהודה-צ.-כ. יישר כח!
  • משחק קליקר לקו -- אפשרי?

    4
    0 הצבעות
    4 פוסטים
    26 צפיות
    S
    @R.E.T-מערכות כתב במשחק קליקר לקו -- אפשרי?: והכי טוב להשתמש בקליקי בעיקרון הוא לא יציב.
  • שלוחת API

    5
    0 הצבעות
    5 פוסטים
    34 צפיות
    י
    @BEN-ZION תנסה לשלוח לשרת השני, במקום private תשנה ל www
  • איך אני משנה את תפריט שלוחה כוכבית?

    13
    0 הצבעות
    13 פוסטים
    21 צפיות
    ל
    @anti-malware שלחנ כוכסית נקראת בקו Star
  • איך אני מוריד את השלום ל...

    נפתר
    3
    0 הצבעות
    3 פוסטים
    17 צפיות
    S
    תסמן כנפתר