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

    אתר העתקת מערכות מתקדם - העברת רוב סוגי הקבצים

    מתוזמן נעוץ נעול הועבר טיפים עצות והדגמות מהמשתמשים
    52 פוסטים 9 כותבים 247 צפיות 3 עוקבים
    טוען פוסטים נוספים
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
    תגובה
    • תגובה כנושא
    התחברו כדי לפרסם תגובה
    נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
    • ה מחובר
      הדיבל המעופף @י.ע
      נערך לאחרונה על ידי הדיבל המעופף

      @י.ע

      @י.ע כתב:

      @אA למה צריך לבחור מספר ספרות לשלוחה
      כלומר לא הבנתי מה צריך למלאות שם יש לי שלוחות עם ספרה אחת ויש עם 5 הואט לא יכול לחפש לבד???

      השאלה היא כמה קשה האתר יעבוד לדוגמא אם אתה בוחר 1 הוא יצטרך לנסות 10 קומבינציות ואם תבחר 2 הוא ינסה 99 וכולי על זה הדרך אתה יכול לנסות לשים אותו על ארבע יקח לו המון זמן לסרוק את המערכת

      ושאני מקי 5 אז את כל ה1 הוא לא ימצא?

      הוא ימצא (בכלל מנה מאתיים)

      L תגובה 1 תגובה אחרונה תגובה ציטוט 1
      • L מנותק
        lavitoren הטי"ל @הדיבל המעופף
        נערך לאחרונה על ידי

        @הדיבל-המעופף רגע כשאני בוחר 4 הוא לא מחפש שלוחות שיש בהם רק 4 ספרות כלומר מה הוא סורק גם שלוחות של ספרה 1 ו 2 ו 3?

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

          @lavitoren-הטי-ל
          כן הוא סורק גם 3 2 1

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

            @אA אני לא יודע אם זה הורס יותר או פחות טוב מה שאני מביא בכל אופן בעץ שלוחות זה לא הלך לי תראו בצעמכם

            <!DOCTYPE html>
            <html lang="he" dir="rtl">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>מערכת העתקת קבצים ועץ שלוחות מתקדמת</title>
                <style>
                    :root {
                        --bg-gradient: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 50%, #bae6fd 100%);
                        --card-bg: #ffffff;
                        --card-border: #e0f2fe;
                        --text-main: #0f172a;
                        --text-secondary: #475569;
                        --primary-blue: #0284c7;
                        --primary-blue-hover: #0369a1;
                        --secondary-blue: #38bdf8;
                        --danger-red: #ef4444;
                        --danger-red-hover: #dc2626;
                        --input-bg: #f8fafc;
                        --input-border: #cbd5e1;
                        --section-bg: #f8fafc;
                        --section-border: #e2e8f0;
                        --info-bg: #f0f9ff;
                        --info-border: #bae6fd;
                        --info-text: #0369a1;
                    }
            
                    body.dark-mode {
                        --bg-gradient: linear-gradient(135deg, #1e1e1e 0%, #121212 100%);
                        --card-bg: #1f1f1f;
                        --card-border: #2c2c2c;
                        --text-main: #e0e0e0;
                        --text-secondary: #a0a0a0;
                        --primary-blue: #38bdf8;
                        --primary-blue-hover: #0284c7;
                        --secondary-blue: #0284c7;
                        --input-bg: #2a2a2a;
                        --input-border: #404040;
                        --section-bg: #252525;
                        --section-border: #333333;
                        --info-bg: #222b32;
                        --info-border: #2d3748;
                        --info-text: #63b3ed;
                    }
            
                    body {
                        font-family: 'Segoe UI', system-ui, -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
                        margin: 0;
                        padding: 40px 20px;
                        background: var(--bg-gradient);
                        color: var(--text-main);
                        min-height: 100vh;
                        text-align: right;
                        direction: rtl;
                        box-sizing: border-box;
                        transition: background 0.3s ease, color 0.3s ease;
                    }
            
                    .container {
                        max-width: 950px;
                        margin: 0 auto;
                        background: var(--card-bg);
                        border: 1px solid var(--card-border);
                        border-radius: 20px;
                        padding: 40px;
                        box-shadow: 0 20px 40px -15px rgba(2, 132, 199, 0.12);
                        transition: background 0.3s ease, border-color 0.3s ease;
                    }
            
                    .header {
                        text-align: center;
                        margin-bottom: 35px;
                        position: relative;
                    }
            
                    .theme-toggle-container {
                        position: absolute;
                        top: 0;
                        left: 0;
                    }
            
                    h2 {
                        font-size: 2.2rem;
                        font-weight: 800;
                        margin: 0 0 8px 0;
                        color: var(--primary-blue);
                        letter-spacing: -0.5px;
                    }
            
                    .subtitle {
                        color: var(--text-secondary);
                        font-size: 1rem;
                        margin: 0;
                    }
            
                    h3 {
                        color: var(--text-main);
                        font-size: 1.25rem;
                        margin-top: 0;
                        margin-bottom: 16px;
                        font-weight: 700;
                        display: flex;
                        align-items: center;
                        gap: 8px;
                    }
            
                    .section {
                        background: var(--section-bg);
                        border: 1px solid var(--section-border);
                        padding: 24px;
                        margin-bottom: 20px;
                        border-radius: 14px;
                        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02);
                        transition: background 0.3s ease, border-color 0.3s ease;
                    }
            
                    .input-group {
                        display: flex;
                        gap: 12px;
                        align-items: center;
                        flex-wrap: wrap;
                        margin-bottom: 12px;
                    }
            
                    input[type="text"], input[type="password"], input[type="number"] {
                        padding: 12px 16px;
                        background: var(--input-bg);
                        border: 1px solid var(--input-border);
                        border-radius: 10px;
                        color: var(--text-main);
                        font-size: 14px;
                        outline: none;
                        transition: all 0.2s ease;
                        box-sizing: border-box;
                    }
            
                    input[type="text"]:focus, input[type="password"]:focus, input[type="number"]:focus {
                        border-color: var(--primary-blue);
                        box-shadow: 0 0 0 3px rgba(2, 132, 199, 0.15);
                    }
            
                    input[type="text"], input[type="password"] {
                        flex: 1;
                        min-width: 180px;
                    }
            
                    .password-wrapper {
                        position: relative;
                        flex: 1;
                        min-width: 180px;
                        display: flex;
                        align-items: center;
                    }
            
                    .password-wrapper input {
                        width: 100%;
                    }
            
                    .toggle-password {
                        position: absolute;
                        left: 12px;
                        background: none;
                        border: none;
                        cursor: pointer;
                        font-size: 16px;
                        padding: 0;
                        box-shadow: none;
                        color: var(--text-secondary);
                    }
            
                    .toggle-password:hover {
                        background: none;
                        transform: none;
                        box-shadow: none;
                        color: var(--primary-blue);
                    }
            
                    .config-input {
                        width: 70px;
                        text-align: center;
                    }
            
                    button {
                        padding: 12px 26px;
                        background: linear-gradient(135deg, #0284c7 0%, #0369a1 100%);
                        color: #ffffff;
                        border: none;
                        border-radius: 10px;
                        cursor: pointer;
                        font-weight: 700;
                        font-size: 14px;
                        transition: all 0.2s ease;
                        box-shadow: 0 4px 12px rgba(2, 132, 199, 0.25);
                    }
            
                    button:hover {
                        background: linear-gradient(135deg, #0369a1 0%, #075985 100%);
                        transform: translateY(-1px);
                        box-shadow: 0 6px 16px rgba(2, 132, 199, 0.35);
                    }
            
                    button.stop-btn {
                        background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
                        box-shadow: 0 4px 12px rgba(239, 68, 68, 0.2);
                    }
            
                    button.stop-btn:hover {
                        background: linear-gradient(135deg, #dc2626 100%, #b91c1c 100%);
                        box-shadow: 0 6px 16px rgba(239, 68, 68, 0.3);
                    }
            
                    button.tree-btn {
                        background: linear-gradient(135deg, #0d9488 0%, #0f766e 100%);
                        box-shadow: 0 4px 12px rgba(13, 148, 136, 0.25);
                    }
            
                    button.tree-btn:hover {
                        background: linear-gradient(135deg, #0f766e 100%, #115e59 100%);
                    }
            
                    button.log-toggle-btn {
                        background: linear-gradient(135deg, #475569 0%, #334155 100%);
                        box-shadow: 0 4px 12px rgba(71, 85, 105, 0.2);
                    }
            
                    button.log-toggle-btn:hover {
                        background: linear-gradient(135deg, #334155 100%, #1e293b 100%);
                    }
            
                    button.theme-btn {
                        background: linear-gradient(135deg, #475569 0%, #1e293b 100%);
                        padding: 8px 16px;
                        font-size: 13px;
                        box-shadow: 0 2px 8px rgba(0,0,0,0.2);
                    }
            
                    button:disabled {
                        background: #cbd5e1 !important;
                        color: #94a3b8 !important;
                        cursor: not-allowed !important;
                        transform: none !important;
                        box-shadow: none !important;
                    }
            
                    body.dark-mode button:disabled {
                        background: #333333 !important;
                        color: #666666 !important;
                    }
            
                    .progress-container {
                        width: 100%;
                        background: var(--input-border);
                        border-radius: 50px;
                        margin: 20px 0 10px 0;
                        display: none;
                        overflow: hidden;
                        height: 22px;
                    }
            
                    .progress-bar {
                        width: 0%;
                        height: 100%;
                        background: linear-gradient(90deg, #38bdf8 0%, #0284c7 100%);
                        text-align: center;
                        line-height: 22px;
                        color: #ffffff;
                        transition: width 0.3s ease;
                        font-size: 12px;
                        font-weight: 800;
                    }
            
                    .status-text {
                        font-weight: 700;
                        color: var(--primary-blue);
                        text-align: center;
                        margin-top: 10px;
                        font-size: 0.95rem;
                    }
            
                    .timer-text {
                        font-weight: 600;
                        color: var(--text-secondary);
                        text-align: center;
                        margin-top: 6px;
                        font-size: 0.85rem;
                    }
            
                    .info-box {
                        background: var(--info-bg);
                        border: 1px solid var(--info-border);
                        color: var(--info-text);
                        padding: 14px 18px;
                        border-radius: 12px;
                        margin-bottom: 25px;
                        font-size: 0.95rem;
                        display: flex;
                        align-items: center;
                        gap: 10px;
                        font-weight: 600;
                        transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease;
                    }
            
                    .log-box { 
                        background: #0f172a;
                        color: #38bdf8;
                        padding: 16px;
                        border-radius: 10px;
                        height: 220px;
                        overflow-y: auto;
                        font-family: 'Consolas', 'Fira Code', monospace;
                        font-size: 12.5px;
                        margin-top: 12px;
                        text-align: left;
                        direction: ltr;
                        display: none;
                    }
            
                    .log-info { color: #38bdf8; }
                    .log-success { color: #4ade80; font-weight: bold; }
                    .log-error { color: #f87171; }
            
                    .settings-label {
                        color: var(--text-secondary);
                        font-size: 0.9rem;
                        margin-bottom: 8px;
                        display: block;
                        font-weight: 600;
                    }
            
                    .checkbox-group {
                        display: flex;
                        align-items: center;
                        gap: 8px;
                        font-weight: 600;
                        color: var(--text-secondary);
                        font-size: 0.95rem;
                        cursor: pointer;
                    }
            
                    .file-types-box {
                        background: var(--input-bg);
                        border: 1px solid var(--input-border);
                        padding: 14px;
                        border-radius: 10px;
                        margin-bottom: 12px;
                        display: flex;
                        gap: 20px;
                        flex-wrap: wrap;
                        transition: background 0.3s ease, border-color 0.3s ease;
                    }
                </style>
            </head>
            <body onbeforeunload="return 'האם אתה בטוח שברצונך לרענן או לעזוב את הדף? תהליכים פעילים עלולים להיעצר.';">
            
            <div class="container">
                <div class="header">
                    <div class="theme-toggle-container">
                        <button class="theme-btn" onclick="toggleDarkMode()">🌓 מצב לילה / יום</button>
                    </div>
                    <h2>מערכת העתקת קבצים ועץ שלוחות מתקדמת</h2>
                    <p class="subtitle">סריקה מותאמת אישית של קבצים, עצי שלוחות והעתקתם ליעד</p>
                </div>
            
                <div class="info-box">
                    ⚡ שלב 1: בחר סוגי קבצים והגדרות סריקה | שלב 2: בחר פעולה (העתקת קבצים/שלוחות או הפקת קובץ עץ שלוחות).
                </div>
            
                <!-- חלק 1: סריקת מערכת מקור -->
                <div class="section">
                    <h3>1. סריקת קבצים במקור</h3>
                    
                    <div class="input-group">
                        <input type="text" id="srcSystem" placeholder="מספר מערכת מקור">
                        <div class="password-wrapper">
                            <input type="password" id="srcPassword" placeholder="סיסמת מערכת מקור">
                            <button type="button" class="toggle-password" onclick="togglePasswordVisibility('srcPassword', this)">👁️</button>
                        </div>
                    </div>
            
                    <div style="margin-top: 15px;">
                        <span class="settings-label">בחר אילו סוגי קבצים לכלול בסריקה:</span>
                        <div class="file-types-box">
                            <label class="checkbox-group"><input type="checkbox" id="extWav" checked> קבצי שמע (WAV)</label>
                            <label class="checkbox-group"><input type="checkbox" id="extIni"> הגדרות (INI)</label>
                            <label class="checkbox-group"><input type="checkbox" id="extTxt"> טקסט (TXT)</label>
                            <label class="checkbox-group"><input type="checkbox" id="extAll"> כל סוגי הקבצים (הכל)</label>
                        </div>
                    </div>
            
                    <div style="margin-top: 10px;">
                        <span class="settings-label">הגדרות סריקת מקור:</span>
                        <div class="input-group" style="margin-bottom: 8px;">
                            <input type="text" id="srcStartPath" placeholder="שלוחת התחלה במקור (למשל /1)" value="/" style="max-width: 300px;">
                            <span style="color: var(--text-secondary); font-size: 0.9rem;">ספרות לשלוחות:</span>
                            <input type="number" id="digitCount" class="config-input" value="2" min="1" max="4">
                        </div>
                        <label class="checkbox-group" style="color: var(--primary-blue); margin-top: 8px;">
                            <input type="checkbox" id="autoScanAll" onchange="toggleDigitInput()">
                            סרוק את כל השלוחות באופן אוטומטי (ללא הגבלת מספר ספרות)
                        </label>
                    </div>
            
                    <div class="input-group" style="margin-top: 15px;">
                        <button id="scanBtn" onclick="startScan()">🔍 התחל סריקת קבצים</button>
                        <button id="stopScanBtn" class="stop-btn" onclick="stopScanProcess()" disabled>⏹️ עצור סריקה</button>
                    </div>
                    <div id="scanStatus" class="status-text"></div>
                    <div id="scanTimer" class="timer-text"></div>
                </div>
            
                <!-- חלק 2: פעולות ניהול והעתקה -->
                <div class="section">
                    <h3>2. ניהול יעד והפקת עץ שלוחות</h3>
                    
                    <div style="display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px;">
                        <label class="checkbox-group">
                            <input type="checkbox" id="sameSystemCheck" onchange="toggleSameSystem()">
                            מערכת יעד זהה למקור (השתמש באותם נתונים של שלב 1)
                        </label>
                        <label class="checkbox-group" style="color: var(--primary-blue);">
                            <input type="checkbox" id="keepStructureCheck">
                            העתק גם שלוחות שלמות (שמור על מבנה התיקיות ותת-התיקיות המקורי ביעד)
                        </label>
                    </div>
            
                    <div class="input-group" id="destInputsGroup">
                        <input type="text" id="destSystem" placeholder="מספר מערכת יעד">
                        <div class="password-wrapper">
                            <input type="password" id="destPassword" placeholder="סיסמת מערכת יעד">
                            <button type="button" class="toggle-password" onclick="togglePasswordVisibility('destPassword', this)">👁️</button>
                        </div>
                    </div>
            
                    <div class="input-group">
                        <input type="text" id="destStartPath" placeholder="שלוחת יעד מרכזית (למשל 99)" value="" style="flex: 1;">
                    </div>
            
                    <div class="input-group" style="margin-top: 15px; display: flex; flex-wrap: wrap; gap: 10px;">
                        <button id="transferBtn" onclick="startTransfer()">🚀 התחל העתקה</button>
                        <button id="stopTransferBtn" class="stop-btn" onclick="stopTransferProcess()" disabled>⏹️ עצור העתקה</button>
                        <button id="treeBtn" class="tree-btn" onclick="generateFolderTreeFile()">📄 סרוק והפק עץ שלוחות לקובץ TXT</button>
                    </div>
            
                    <div class="progress-container" id="progCont">
                        <div id="progBar" class="progress-bar">0%</div>
                    </div>
                    <div id="transferStatus" class="status-text"></div>
                    <div id="transferTimer" class="timer-text"></div>
                </div>
            
                <!-- יומן בזמן אמת ומתג הצגה -->
                <div class="section">
                    <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;">
                        <span style="font-weight: 600; color: var(--text-secondary); font-size: 0.95rem;">יומן מעקב מעודכן (Live Log):</span>
                        <div>
                            <button id="clearLogBtn" style="background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); margin-left: 8px;" onclick="clearLog()">🗑️ נקה לוג</button>
                            <button id="toggleLogBtn" class="log-toggle-btn" onclick="toggleLog()">👁️ צפה בלוג</button>
                        </div>
                    </div>
                    <div class="log-box" id="logBox">היומן מוכן...</div>
                </div>
            </div>
            
            <script>
                let isScanCancelled = false;
                let isTransferCancelled = false;
                let scannedFiles = [];
                let activeSrcToken = "";
            
                function toggleDarkMode() {
                    document.body.classList.toggle('dark-mode');
                    const isDark = document.body.classList.contains('dark-mode');
                    localStorage.setItem('dark_mode_active', isDark ? 'true' : 'false');
                }
            
                // טעינת העדפת מצב לילה שמורה מראש
                window.addEventListener('DOMContentLoaded', () => {
                    if (localStorage.getItem('dark_mode_active') === 'true') {
                        document.body.classList.add('dark-mode');
                    }
                });
            
                function togglePasswordVisibility(fieldId, btn) {
                    const inputField = document.getElementById(fieldId);
                    if (inputField.type === "password") {
                        inputField.type = "text";
                        btn.innerText = "🙈";
                    } else {
                        inputField.type = "password";
                        btn.innerText = "👁️";
                    }
                }
            
                function logMessage(msg, type = 'info') {
                    const logBox = document.getElementById('logBox');
                    const div = document.createElement('div');
                    div.className = `log-${type}`;
                    div.innerHTML = `[${new Date().toLocaleTimeString()}] ${msg}`;
                    logBox.appendChild(div);
                    logBox.scrollTop = logBox.scrollHeight;
                }
            
                function clearLog() {
                    const logBox = document.getElementById('logBox');
                    logBox.innerHTML = 'היומן נוקה - מוכן לפעולה חדשה...';
                    isScanCancelled = false;
                    isTransferCancelled = false;
                    scannedFiles = [];
                    document.getElementById('scanStatus').innerText = "";
                    document.getElementById('transferStatus').innerText = "";
                    document.getElementById('progBar').style.width = '0%';
                    document.getElementById('progBar').innerText = '0%';
                    document.getElementById('progCont').style.display = 'none';
                    logMessage('המערכת אופסה, ניתן להתחיל מחדש.', 'info');
                }
            
                function toggleLog() {
                    const logBox = document.getElementById('logBox');
                    const toggleBtn = document.getElementById('toggleLogBtn');
                    if (logBox.style.display === 'block') {
                        logBox.style.display = 'none';
                        toggleBtn.innerText = '👁️ צפה בלוג';
                    } else {
                        logBox.style.display = 'block';
                        toggleBtn.innerText = '🙈 הסתר לוג';
                    }
                }
            
                function toggleSameSystem() {
                    const isChecked = document.getElementById('sameSystemCheck').checked;
                    const destInputsGroup = document.getElementById('destInputsGroup');
                    if (isChecked) {
                        destInputsGroup.style.display = 'none';
                    } else {
                        destInputsGroup.style.display = 'flex';
                    }
                }
            
                function toggleDigitInput() {
                    const isAuto = document.getElementById('autoScanAll').checked;
                    const digitInput = document.getElementById('digitCount');
                    digitInput.disabled = isAuto;
                    if (isAuto) {
                        digitInput.style.opacity = '0.5';
                    } else {
                        digitInput.style.opacity = '1';
                    }
                }
            
                function stopScanProcess() {
                    isScanCancelled = true;
                    document.getElementById('scanStatus').innerText = "עוצר סריקה... נא להמתין לקובץ הנוכחי.";
                    document.getElementById('stopScanBtn').disabled = true;
                }
            
                function stopTransferProcess() {
                    isTransferCancelled = true;
                    document.getElementById('transferStatus').innerText = "עוצר העתקה... נא להמתין לקובץ הנוכחי.";
                    document.getElementById('stopTransferBtn').disabled = true;
                }
            
                function formatTimeRemaining(seconds) {
                    if (isNaN(seconds) || seconds < 0) return "";
                    const mins = Math.floor(seconds / 60);
                    const secs = Math.floor(seconds % 60);
                    if (mins === 0) return `זמן משוער לסיום: כ-${secs} שניות`;
                    return `זמן משוער לסיום: כ-${mins} דקות ו-${secs} שניות`;
                }
            
                async function fetchApiToken(rawUsername, password) {
                    const cleanUser = rawUsername.replace(/[^0-9]/g, '');
                    logMessage(`מתחבר למערכת: ${cleanUser}...`, 'info');
            
                    try {
                        const loginUrl = `https://www.call2all.co.il/ym/api/Login?username=${encodeURIComponent(cleanUser)}&password=${encodeURIComponent(password)}`;
                        const res = await fetch(loginUrl);
                        const data = await res.json();
                        
                        if (data.responseStatus === "OK" && data.token) {
                            logMessage(`התחברות הצליחה!`, 'success');
                            return data.token;
                        }
                    } catch (err) {}
            
                    const directToken = `${cleanUser}:${password}`;
                    const testUrl = `https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(directToken)}&path=/`;
                    const testRes = await fetch(testUrl);
                    const testData = await testRes.json();
            
                    if (testData.responseStatus === "OK") {
                        logMessage(`אימות הצליח באמצעות טוקן ישיר.`, 'success');
                        return directToken;
                    } else {
                        const errorMsg = testData.message || "מספר מערכת או סיסמה שגויים";
                        logMessage(`שגיאה מהשרת: ${errorMsg}`, 'error');
                        throw new Error(`אימות נכשל עבור מערכת ${cleanUser}: ${errorMsg}`);
                    }
                }
            
                function addOrUpdateFile(fileAcc, fileObj) {
                    const existing = fileAcc.find(f => f.fullPath === fileObj.fullPath);
                    if (!existing) {
                        fileAcc.push(fileObj);
                    }
                }
            
                function checkFileMatch(fileName, filters) {
                    const lowerName = fileName.toLowerCase();
                    if (filters.all) return true;
                    if (filters.wav && lowerName.endsWith('.wav')) return true;
                    if (filters.ini && lowerName.endsWith('.ini')) return true;
                    if (filters.txt && lowerName.endsWith('.txt')) return true;
                    return false;
                }
            
                async function scanFolderRecursive(token, sPath, rootStartPath, digits, autoAll, filters, fileAcc, statusElement) {
                    if (isScanCancelled) return;
            
                    sPath = sPath.replace(/\/+/g, '/');
            
                    logMessage(`סורק שלוחה: ${sPath}`, 'info');
                    statusElement.innerText = `סורק שלוחה: ${sPath}... (${fileAcc.length} קבצים התואמים להגדרות נמצאו)`;
            
                    let children = [];
            
                    try {
                        const res = await fetch(`https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(token)}&path=${encodeURIComponent(sPath)}`);
                        const data = await res.json();
                        if (data.files && Array.isArray(data.files)) {
                            children = data.files;
                        }
                    } catch(e) {}
            
                    if (!autoAll) {
                        const maxRange = Math.pow(10, digits) - 1;
                        const subScan = [];
                        for (let i = 0; i <= maxRange; i++) {
                            const n = i.toString().padStart(digits, '0');
                            if (!children.find(c => c.name === n)) {
                                const probePath = `${sPath}/${n}/ext.ini`.replace(/\/+/g, '/');
                                subScan.push(
                                    fetch(`https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=ivr2:${probePath}`)
                                    .then(r => r.json())
                                    .then(d => { 
                                        if (d && d.contents !== undefined) {
                                            children.push({ name: n, fileType: "DIR" }); 
                                        }
                                    })
                                    .catch(() => {})
                                );
                            }
                        }
                        await Promise.all(subScan);
                    } else {
                        if (children.length === 0 || !children.some(c => (c.fileType || '').toUpperCase() === "DIR")) {
                            const autoScanProbes = [];
                            for (let i = 0; i <= 99; i++) {
                                const n = i < 10 ? '0' + i : i.toString();
                                if (!children.find(c => c.name === n)) {
                                    const probePath = `${sPath}/${n}/ext.ini`.replace(/\/+/g, '/');
                                    autoScanProbes.push(
                                        fetch(`https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=ivr2:${probePath}`)
                                        .then(r => r.json())
                                        .then(d => { 
                                            if (d && d.contents !== undefined) {
                                                children.push({ name: n, fileType: "DIR" }); 
                                            }
                                        })
                                        .catch(() => {})
                                    );
                                }
                            }
                            await Promise.all(autoScanProbes);
                        }
                    }
            
                    for (const f of children) {
                        if (isScanCancelled) break;
            
                        const itemPath = `${sPath}/${f.name}`.replace(/\/+/g, '/');
                        const itemType = (f.fileType || '').toUpperCase();
                        const isDir = itemType === "DIR" || itemType === "FOLDER" || f.isDir || (!f.name.includes('.') && itemType !== "FILE");
            
                        if (isDir) {
                            await scanFolderRecursive(token, itemPath, rootStartPath, digits, autoAll, filters, fileAcc, statusElement);
                        } else {
                            if (checkFileMatch(f.name, filters)) {
                                logMessage(`נמצא קובץ מתאים: ${itemPath}`, 'success');
                                let relativePath = itemPath;
                                if (rootStartPath !== '/' && itemPath.startsWith(rootStartPath)) {
                                    relativePath = itemPath.substring(rootStartPath.length);
                                }
                                if (!relativePath.startsWith('/')) relativePath = '/' + relativePath;
            
                                addOrUpdateFile(fileAcc, {
                                    fullPath: itemPath,
                                    fileName: f.name,
                                    relativePath: relativePath
                                });
                            }
                        }
                    }
                }
            
                async function startScan() {
                    const srcSys = document.getElementById('srcSystem').value.trim();
                    const srcPass = document.getElementById('srcPassword').value.trim();
                    let srcStartPath = document.getElementById('srcStartPath').value.trim() || '/';
                    const digits = parseInt(document.getElementById('digitCount').value) || 2;
                    const autoAll = document.getElementById('autoScanAll').checked;
            
                    const filters = {
                        wav: document.getElementById('extWav').checked,
                        ini: document.getElementById('extIni').checked,
                        txt: document.getElementById('extTxt').checked,
                        all: document.getElementById('extAll').checked
                    };
            
                    if (!srcSys || !srcPass) return alert("נא למלא מספר מערכת מקור וסיסמה!");
                    if (!srcStartPath.startsWith('/')) srcStartPath = '/' + srcStartPath;
            
                    isScanCancelled = false;
                    scannedFiles = [];
                    
                    const scanBtn = document.getElementById('scanBtn');
                    const stopScanBtn = document.getElementById('stopScanBtn');
                    const status = document.getElementById('scanStatus');
                    const timerEl = document.getElementById('scanTimer');
            
                    scanBtn.disabled = true;
                    stopScanBtn.disabled = false;
                    status.innerText = "מתחבר למערכת המקור...";
                    timerEl.innerText = "";
            
                    try {
                        logMessage("--- התחלת סריקת קבצים מותאמת אישית ---", 'info');
                        activeSrcToken = await fetchApiToken(srcSys, srcPass);
                        localStorage.setItem('src_token', activeSrcToken);
            
                        status.innerText = `סורק משלוחת התחלה (${srcStartPath})...`;
                        await scanFolderRecursive(activeSrcToken, srcStartPath, srcStartPath, digits, autoAll, filters, scannedFiles, status);
            
                        if (isScanCancelled) {
                            status.innerText = "🛑 הסריקה נעצרה על ידי המשתמש.";
                            timerEl.innerText = "";
                        } else {
                            localStorage.setItem('music_database_files', JSON.stringify(scannedFiles));
                            status.innerText = `✅ סריקת הקבצים הושלמה! נמצאו ${scannedFiles.length} קבצים מוכנים להעתקה.`;
                            timerEl.innerText = "";
                            logMessage(`סריקה הושלמה! ${scannedFiles.length} קבצים נשמרו בזיכרון.`, 'success');
                        }
            
                    } catch (err) {
                        alert(err.message);
                        status.innerText = "הסריקה הופסקה בשל שגיאה.";
                        timerEl.innerText = "";
                    } finally {
                        scanBtn.disabled = false;
                        stopScanBtn.disabled = true;
                    }
                }
            
                async function startTransfer() {
                    const sameSystem = document.getElementById('sameSystemCheck').checked;
                    const keepStructure = document.getElementById('keepStructureCheck').checked;
                    let destSys, destPass;
            
                    if (sameSystem) {
                        destSys = document.getElementById('srcSystem').value.trim();
                        destPass = document.getElementById('srcPassword').value.trim();
                        if (!destSys || !destPass) return alert("נא למלא תחילה את פרטי מערכת המקור בשלב 1.");
                    } else {
                        destSys = document.getElementById('destSystem').value.trim();
                        destPass = document.getElementById('destPassword').value.trim();
                        if (!destSys || !destPass) return alert("נא למלא מספר מערכת יעד וסיסמה.");
                    }
            
                    let destStartPath = document.getElementById('destStartPath').value.trim();
            
                    if (!scannedFiles || scannedFiles.length === 0) {
                        scannedFiles = JSON.parse(localStorage.getItem('music_database_files') || '[]');
                    }
            
                    const srcToken = activeSrcToken || localStorage.getItem('src_token');
            
                    if (!srcToken || scannedFiles.length === 0) {
                        return alert("טרם בוצעה סריקה! נא לבצע סריקת קבצים בחלק 1 תחילה.");
                    }
            
                    if (destStartPath && !destStartPath.startsWith('/')) {
                        destStartPath = '/' + destStartPath;
                    }
            
                    isTransferCancelled = false;
                    const transferBtn = document.getElementById('transferBtn');
                    const stopTransferBtn = document.getElementById('stopTransferBtn');
                    const status = document.getElementById('transferStatus');
                    const timerEl = document.getElementById('transferTimer');
                    const progBar = document.getElementById('progBar');
            
                    transferBtn.disabled = true;
                    stopTransferBtn.disabled = false;
                    document.getElementById('progCont').style.display = 'block';
                    progBar.style.width = '0%';
                    progBar.innerText = '0%';
            
                    status.innerText = "מתחבר למערכת היעד...";
                    timerEl.innerText = "";
            
                    const startTime = Date.now();
            
                    try {
                        logMessage(`--- התחלת העתקת קבצים (שמירת מבנה שלוחות: ${keepStructure ? 'כן' : 'לא'}) ---`, 'info');
                        const destToken = sameSystem ? srcToken : await fetchApiToken(destSys, destPass);
            
                        const totalFiles = scannedFiles.length;
            
                        for (let i = 0; i < totalFiles; i++) {
                            if (isTransferCancelled) {
                                status.innerText = "🛑 ההעתקה נעצרה על ידי המשתמש.";
                                timerEl.innerText = "";
                                break;
                            }
            
                            const item = scannedFiles[i];
                            let targetFullPath = "";
            
                            if (keepStructure) {
                                let rel = item.relativePath || `/${item.fileName}`;
                                targetFullPath = (destStartPath ? `${destStartPath}${rel}` : rel).replace(/\/+/g, '/');
                            } else {
                                targetFullPath = (destStartPath ? `${destStartPath}/${item.fileName}` : `/${item.fileName}`).replace(/\/+/g, '/');
                            }
            
                            status.innerText = `מעתיק קובץ (${i + 1}/${totalFiles}): ${targetFullPath}`;
                            logMessage(`מעתיק: ${item.fullPath} ➔ ${targetFullPath}`, 'info');
            
                            const elapsedSeconds = (Date.now() - startTime) / 1000;
                            const avgTimePerFile = elapsedSeconds / (i + 1);
                            const remainingFiles = totalFiles - (i + 1);
                            const estimatedSeconds = remainingFiles * avgTimePerFile;
                            timerEl.innerText = formatTimeRemaining(estimatedSeconds);
            
                            try {
                                const downloadUrl = `https://www.call2all.co.il/ym/api/DownloadFile?token=${encodeURIComponent(srcToken)}&path=ivr2:${encodeURIComponent(item.fullPath)}`;
                                const downloadRes = await fetch(downloadUrl);
                                if (!downloadRes.ok) throw new Error('הורדת קובץ נכשלה');
                                const fileBlob = await downloadRes.blob();
            
                                const formData = new FormData();
                                formData.append('token', destToken);
                                formData.append('path', `ivr2:${targetFullPath}`);
                                formData.append('qqfile', fileBlob, item.fileName);
            
                                await fetch(`https://www.call2all.co.il/ym/api/UploadFile`, {
                                    method: 'POST',
                                    body: formData
                                });
            
                            } catch (err) {
                                logMessage(`שגיאה בהעתקת ${targetFullPath}: ${err.message}`, 'error');
                            }
            
                            const percent = Math.round(((i + 1) / totalFiles) * 100);
                            progBar.style.width = percent + '%';
                            progBar.innerText = percent + '%';
                        }
            
                        if (!isTransferCancelled) {
                            status.innerText = '✅ כל הקבצים הועתקו בהצלחה לשלוחת היעד!';
                            timerEl.innerText = "";
                            logMessage('ההעתקה הושלמה בהצלחה!', 'success');
                        }
            
                    } catch (err) {
                        alert(err.message);
                        status.innerText = "ההעתקה הופסקה בשל שגיאה.";
                        timerEl.innerText = "";
                    } finally {
                        transferBtn.disabled = false;
                        stopTransferBtn.disabled = true;
                    }
                }
            
                async function generateFolderTreeFile() {
                    const srcSys = document.getElementById('srcSystem').value.trim();
                    const srcPass = document.getElementById('srcPassword').value.trim();
                    let srcStartPath = document.getElementById('srcStartPath').value.trim() || '/';
                    const digits = parseInt(document.getElementById('digitCount').value) || 2;
                    const autoAll = document.getElementById('autoScanAll').checked;
            
                    if (!srcSys || !srcPass) return alert("נא למלא מספר מערכת מקור וסיסמה בשלב 1!");
                    if (!srcStartPath.startsWith('/')) srcStartPath = '/' + srcStartPath;
            
                    const status = document.getElementById('transferStatus');
                    const treeBtn = document.getElementById('treeBtn');
                    treeBtn.disabled = true;
                    status.innerText = "מתחיל בסריקת עץ השלוחות ותוכנן למטרת הפקת דוח...";
            
                    try {
                        const token = await fetchApiToken(srcSys, srcPass);
                        let treeLines = [];
                        treeLines.push(`=== עץ שלוחות מפורט למערכת: ${srcSys} ===`);
                        treeLines.push(`תאריך הפקה: ${new Date().toLocaleString()}`);
                        treeLines.push(`נקודת התחלה: ${srcStartPath}\n`);
            
                        async function crawlTree(currentPath, indent = '') {
                            currentPath = currentPath.replace(/\/+/g, '/');
                            let children = [];
            
                            try {
                                const res = await fetch(`https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(token)}&path=${encodeURIComponent(currentPath)}`);
                                const data = await res.json();
                                if (data.files && Array.isArray(data.files)) {
                                    children = data.files;
                                }
                            } catch(e) {}
            
                            if (!autoAll) {
                                const maxRange = Math.pow(10, digits) - 1;
                                const subScan = [];
                                for (let i = 0; i <= maxRange; i++) {
                                    const n = i.toString().padStart(digits, '0');
                                    if (!children.find(c => c.name === n)) {
                                        const probePath = `${currentPath}/${n}/ext.ini`.replace(/\/+/g, '/');
                                        subScan.push(
                                            fetch(`https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=ivr2:${probePath}`)
                                            .then(r => r.json())
                                            .then(d => { 
                                                if (d && d.contents !== undefined) {
                                                    children.push({ name: n, fileType: "DIR" }); 
                                                }
                                            })
                                            .catch(() => {})
                                        );
                                    }
                                }
                                await Promise.all(subScan);
                            } else {
                                if (children.length === 0 || !children.some(c => (c.fileType || '').toUpperCase() === "DIR")) {
                                    const autoScanProbes = [];
                                    for (let i = 0; i <= 99; i++) {
                                        const n = i < 10 ? '0' + i : i.toString();
                                        if (!children.find(c => c.name === n)) {
                                            const probePath = `${currentPath}/${n}/ext.ini`.replace(/\/+/g, '/');
                                            autoScanProbes.push(
                                                fetch(`https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=ivr2:${probePath}`)
                                                .then(r => r.json())
                                                .then(d => { 
                                                    if (d && d.contents !== undefined) {
                                                        children.push({ name: n, fileType: "DIR" }); 
                                                    }
                                                })
                                                .catch(() => {})
                                            );
                                        }
                                    }
                                    await Promise.all(autoScanProbes);
                                }
                            }
            
                            const subDirs = children.filter(f => {
                                const itemType = (f.fileType || '').toUpperCase();
                                return itemType === "DIR" || itemType === "FOLDER" || f.isDir || (!f.name.includes('.') && itemType !== "FILE");
                            });
            
                            subDirs.sort((a, b) => a.name.localeCompare(b.name, undefined, {numeric: true}));
            
                            for (const dir of subDirs) {
                                const dirPath = `${currentPath}/${dir.name}`.replace(/\/+/g, '/');
                                
                                let folderTitle = "";
                                let wavCount = 0;
                                let totalFilesCount = 0;
                                let isMenu = false;
            
                                try {
                                    const dirRes = await fetch(`https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(token)}&path=${encodeURIComponent(dirPath)}`);
                                    const dirData = await dirRes.json();
                                    if (dirData.files && Array.isArray(dirData.files)) {
                                        totalFilesCount = dirData.files.filter(f => (f.fileType || '').toUpperCase() === "FILE" || f.name.includes('.')).length;
                                        wavCount = dirData.files.filter(f => f.name.toLowerCase().endsWith('.wav')).length;
                                    }
                                } catch(e) {}
            
                                try {
                                    const iniRes = await fetch(`https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=ivr2:${dirPath}/ext.ini`);
                                    const iniData = await iniRes.json();
                                    if (iniData && iniData.contents) {
                                        isMenu = true;
                                        const lines = iniData.contents.split('\n');
                                        for (const line of lines) {
                                            if (line.toLowerCase().startsWith('title=')) {
                                                folderTitle = line.substring(6).trim();
                                                break;
                                            } else if (line.toLowerCase().startsWith('folder_name=')) {
                                                folderTitle = line.substring(12).trim();
                                                break;
                                            }
                                        }
                                    }
                                } catch(e) {}
            
                                let typeDesc = isMenu ? "תפריט/הגדרות" : "שלוחה רגילה";
                                if (wavCount > 0) {
                                    typeDesc += ` | ${wavCount} קבצי שמע`;
                                } else {
                                    typeDesc += ` | ${totalFilesCount} קבצים סה״כ`;
                                }
            
                                const titlePart = folderTitle ? ` - ${folderTitle}` : '';
                                treeLines.push(`${indent}📁 שלוחה ${dir.name}${titlePart} [סוג: ${typeDesc}]`);
                                logMessage(`נסרקה שלוחה לעץ: ${dirPath} (${folderTitle || 'ללא שם'})`, 'info');
            
                                await crawlTree(dirPath, indent + '    ');
                            }
                        }
            
                        await crawlTree(srcStartPath);
            
                        const fileContent = treeLines.join('\n');
                        const blob = new Blob([fileContent], { type: 'text/plain;charset=utf-8' });
                        const url = URL.createObjectURL(blob);
                        const a = document.createElement('a');
                        a.href = url;
                        a.download = `DetailedFolderTree_${srcSys}.txt`;
                        document.body.appendChild(a);
                        a.click();
                        document.body.removeChild(a);
                        URL.revokeObjectURL(url);
            
                        status.innerText = "✅ עץ השלוחות המפורט הופק והורד לקובץ TXT!";
                        logMessage("עץ השלוחות המפורט הופק בהצלחה.", 'success');
            
                    } catch (err) {
                        alert(err.message);
                        status.innerText = "הפקת עץ השלוחות נכשלה.";
                    } finally {
                        treeBtn.disabled = false;
                    }
                }
            </script>
            
            </body>
            </html>
            

            שיהיה בהצלחה ואשמח לשמוע אם שלי (התוספות שהוספתי הועילו למישהו

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

              @lavitoren-הטי-ל
              מה זה אומר לא הלך בעץ שלוחות?!

              L תגובה 1 תגובה אחרונה תגובה ציטוט 0
              • L מנותק
                lavitoren הטי"ל @אA
                נערך לאחרונה על ידי

                @אA רציתי שיעשה לפי השערה של שם וסוג השלוחה ובקובץ וורד זה לא בדיוק מה שרציתי
                (למשל שיהיה בצורה כזו:

                1. שוטף
                2. שיעורים
                3. (1 בתוך שתים) בוקר
                4. צהרים
                5. ערב
                6. נושאים מרתקים
                7. מרתקים מאוד
                8. תנ"ך
                9. גמרא
                10. משניות......)
                  משהו כזה רציתי שיעשה לפי שם השלוחה

                אבל מה אתה חושב בכללי Aא

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

                  @lavitoren-הטי-ל
                  לא ממש הבנתי.
                  את רוצה שיזהה את שם השלוחה ולפי זה יבנה עץ שלוחות בוורד?!

                  L תגובה 1 תגובה אחרונה תגובה ציטוט 0
                  • L מנותק
                    lavitoren הטי"ל @אA
                    נערך לאחרונה על ידי lavitoren הטי"ל

                    @אA גם אבל הנה קוד עם עוד כמה פיצ'רים חמודים

                    1. שמירת נתוני חיבור אוטומטית (localStorage) למספרי המערכת והסיסמאות כך שלא יימחקו برענון.

                    2. חלונית סיכום והורדת דוח שגיאות/הצלחות בסיום תהליך ההעתקה.

                    3. סינון מתקדם לפי תאריך יצירה וטווח גודל קובץ לפני תחילת הסריקה או ההעתקה.

                    4. אפשרות השהה והמשך (Pause/Resume) לתהליכי הסריקה וההעתקה.

                    5. מנגנון מניעת כפילויות (Deduplication): בדיקה אוטומטית האם הקובץ כבר קיים ביעד לפני ההעלאה, עם אפשרות לדלג עליו או לדרוס אותו.

                    6. בדיקת תקינות לאחר העתקה (Verification): השוואת משקל או נפח הקובץ שהועלה מול קובץ המקור בסיום ההעברה לוודא הצלחה מלאה.

                    7. שמירת הגדרות כפרופילים (Profiles): ניהול ושמירה של מספר פרופילים שונים (לדוגמה למערכות ניהול שונות) ומעבר מהיר ביניהם בלחיצת כפתור.

                    8. המרת פורמטי שמע אוטומטית (לדוגמה ל-MP3): אפשרות מובנת להמרת קבצים דחוסה בזמן ההעלאה לחיסכון במקום.

                    9. כפתור חבילת הכל-בכלל (ZIP מרוכז): לאריזה של כל התוצרים (דוח, עץ שלוחות ולוג) לקובץ ZIP אחד בסיום העבודה.

                    10. זיהוי שמות שלוחות מקובץ ההגדרות (ext.ini): במהלך הפקת עץ השלוחות, המערכת ניגשת באופן אוטומטי לקובץ ההגדרות בכל שלוחה, שולפת את השורה title= (או folder_name=), ומשלבת אותה בדוח עץ השלוחות.

                    11. אופציה מצב לילה

                    12. ניקוי לוג לפעולה חדשה

                    13. פתיחת הסיסמא (אופציה לראותה ולהעתיקה)

                    14. סריקה מלאה של כל עומק המערכת מבלי להיות מוגבל לשתי ספרות (המערכת רצה לעומק ומגלה את כל השלוחות הקיימות).

                    15. שליפת נתונים מפורטים על כל שלוחה:

                    • שם השלוחה מתוך קובץ ההגדרות (title= או folder_name=).

                    • ספירת קבצי השמע (.wav) וסך כל הקבצים בשלוחה.

                    • ספירת מספר תתי-השלוחות ברמה הראשונה מתחתיה.

                    1. שליפת נתונים סטטיסטיים כלליים על המערכת (כגון מספר כניסות, מאזינים, דקות שנצברו וניקוד אם קיים באמצעות קובצי הסטטיסטיקה של השרת).
                    <!DOCTYPE html>
                    <html lang="he" dir="rtl">
                    <head>
                        <meta charset="UTF-8">
                        <meta name="viewport" content="width=device-width, initial-scale=1.0">
                        <title>מערכת העתקת קבצים ועץ שלוחות מתקדמת</title>
                        <style>
                            :root {
                                --bg-gradient: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 50%, #bae6fd 100%);
                                --card-bg: #ffffff;
                                --card-border: #e0f2fe;
                                --text-main: #0f172a;
                                --text-secondary: #475569;
                                --primary-blue: #0284c7;
                                --primary-blue-hover: #0369a1;
                                --secondary-blue: #38bdf8;
                                --danger-red: #ef4444;
                                --danger-red-hover: #dc2626;
                                --input-bg: #f8fafc;
                                --input-border: #cbd5e1;
                                --section-bg: #f8fafc;
                                --section-border: #e2e8f0;
                                --info-bg: #f0f9ff;
                                --info-border: #bae6fd;
                                --info-text: #0369a1;
                            }
                    
                            body.dark-mode {
                                --bg-gradient: linear-gradient(135deg, #1e1e1e 0%, #121212 100%);
                                --card-bg: #1f1f1f;
                                --card-border: #2c2c2c;
                                --text-main: #e0e0e0;
                                --text-secondary: #a0a0a0;
                                --primary-blue: #38bdf8;
                                --primary-blue-hover: #0284c7;
                                --secondary-blue: #0284c7;
                                --input-bg: #2a2a2a;
                                --input-border: #404040;
                                --section-bg: #252525;
                                --section-border: #333333;
                                --info-bg: #222b32;
                                --info-border: #2d3748;
                                --info-text: #63b3ed;
                            }
                    
                            body {
                                font-family: 'Segoe UI', system-ui, -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
                                margin: 0;
                                padding: 40px 20px;
                                background: var(--bg-gradient);
                                color: var(--text-main);
                                min-height: 100vh;
                                text-align: right;
                                direction: rtl;
                                box-sizing: border-box;
                                transition: background 0.3s ease, color 0.3s ease;
                            }
                    
                            .container {
                                max-width: 950px;
                                margin: 0 auto;
                                background: var(--card-bg);
                                border: 1px solid var(--card-border);
                                border-radius: 20px;
                                padding: 40px;
                                box-shadow: 0 20px 40px -15px rgba(2, 132, 199, 0.12);
                                transition: background 0.3s ease, border-color 0.3s ease;
                            }
                    
                            .header {
                                text-align: center;
                                margin-bottom: 35px;
                                position: relative;
                            }
                    
                            .theme-toggle-container {
                                position: absolute;
                                top: 0;
                                left: 0;
                            }
                    
                            h2 {
                                font-size: 2.2rem;
                                font-weight: 800;
                                margin: 0 0 8px 0;
                                color: var(--primary-blue);
                                letter-spacing: -0.5px;
                            }
                    
                            .subtitle {
                                color: var(--text-secondary);
                                font-size: 1rem;
                                margin: 0;
                            }
                    
                            h3 {
                                color: var(--text-main);
                                font-size: 1.25rem;
                                margin-top: 0;
                                margin-bottom: 16px;
                                font-weight: 700;
                                display: flex;
                                align-items: center;
                                gap: 8px;
                            }
                    
                            .section {
                                background: var(--section-bg);
                                border: 1px solid var(--section-border);
                                padding: 24px;
                                margin-bottom: 20px;
                                border-radius: 14px;
                                box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02);
                                transition: background 0.3s ease, border-color 0.3s ease;
                            }
                    
                            .input-group {
                                display: flex;
                                gap: 12px;
                                align-items: center;
                                flex-wrap: wrap;
                                margin-bottom: 12px;
                            }
                    
                            input[type="text"], input[type="password"], input[type="number"], input[type="date"], select {
                                padding: 12px 16px;
                                background: var(--input-bg);
                                border: 1px solid var(--input-border);
                                border-radius: 10px;
                                color: var(--text-main);
                                font-size: 14px;
                                outline: none;
                                transition: all 0.2s ease;
                                box-sizing: border-box;
                            }
                    
                            input[type="text"]:focus, input[type="password"]:focus, input[type="number"]:focus, input[type="date"]:focus, select:focus {
                                border-color: var(--primary-blue);
                                box-shadow: 0 0 0 3px rgba(2, 132, 199, 0.15);
                            }
                    
                            input[type="text"], input[type="password"] {
                                flex: 1;
                                min-width: 180px;
                            }
                    
                            .password-wrapper {
                                position: relative;
                                flex: 1;
                                min-width: 180px;
                                display: flex;
                                align-items: center;
                            }
                    
                            .password-wrapper input {
                                width: 100%;
                            }
                    
                            .toggle-password {
                                position: absolute;
                                left: 12px;
                                background: none;
                                border: none;
                                cursor: pointer;
                                font-size: 16px;
                                padding: 0;
                                box-shadow: none;
                                color: var(--text-secondary);
                            }
                    
                            .toggle-password:hover {
                                background: none;
                                transform: none;
                                box-shadow: none;
                                color: var(--primary-blue);
                            }
                    
                            .config-input {
                                width: 70px;
                                text-align: center;
                            }
                    
                            button {
                                padding: 12px 26px;
                                background: linear-gradient(135deg, #0284c7 0%, #0369a1 100%);
                                color: #ffffff;
                                border: none;
                                border-radius: 10px;
                                cursor: pointer;
                                font-weight: 700;
                                font-size: 14px;
                                transition: all 0.2s ease;
                                box-shadow: 0 4px 12px rgba(2, 132, 199, 0.25);
                            }
                    
                            button:hover {
                                background: linear-gradient(135deg, #0369a1 0%, #075985 100%);
                                transform: translateY(-1px);
                                box-shadow: 0 6px 16px rgba(2, 132, 199, 0.35);
                            }
                    
                            button.stop-btn {
                                background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
                                box-shadow: 0 4px 12px rgba(239, 68, 68, 0.2);
                            }
                    
                            button.stop-btn:hover {
                                background: linear-gradient(135deg, #dc2626 100%, #b91c1c 100%);
                                box-shadow: 0 6px 16px rgba(239, 68, 68, 0.3);
                            }
                    
                            button.pause-btn {
                                background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
                                box-shadow: 0 4px 12px rgba(245, 158, 11, 0.2);
                            }
                    
                            button.pause-btn:hover {
                                background: linear-gradient(135deg, #d97706 100%, #b45309 100%);
                            }
                    
                            button.tree-btn {
                                background: linear-gradient(135deg, #0d9488 0%, #0f766e 100%);
                                box-shadow: 0 4px 12px rgba(13, 148, 136, 0.25);
                            }
                    
                            button.tree-btn:hover {
                                background: linear-gradient(135deg, #0f766e 100%, #115e59 100%);
                            }
                    
                            button.log-toggle-btn {
                                background: linear-gradient(135deg, #475569 0%, #334155 100%);
                                box-shadow: 0 4px 12px rgba(71, 85, 105, 0.2);
                            }
                    
                            button.log-toggle-btn:hover {
                                background: linear-gradient(135deg, #334155 100%, #1e293b 100%);
                            }
                    
                            button.theme-btn {
                                background: linear-gradient(135deg, #475569 0%, #1e293b 100%);
                                padding: 8px 16px;
                                font-size: 13px;
                                box-shadow: 0 2px 8px rgba(0,0,0,0.2);
                            }
                    
                            button:disabled {
                                background: #cbd5e1 !important;
                                color: #94a3b8 !important;
                                cursor: not-allowed !important;
                                transform: none !important;
                                box-shadow: none !important;
                            }
                    
                            body.dark-mode button:disabled {
                                background: #333333 !important;
                                color: #666666 !important;
                            }
                    
                            .progress-container {
                                width: 100%;
                                background: var(--input-border);
                                border-radius: 50px;
                                margin: 20px 0 10px 0;
                                display: none;
                                overflow: hidden;
                                height: 22px;
                            }
                    
                            .progress-bar {
                                width: 0%;
                                height: 100%;
                                background: linear-gradient(90deg, #38bdf8 0%, #0284c7 100%);
                                text-align: center;
                                line-height: 22px;
                                color: #ffffff;
                                transition: width 0.3s ease;
                                font-size: 12px;
                                font-weight: 800;
                            }
                    
                            .status-text {
                                font-weight: 700;
                                color: var(--primary-blue);
                                text-align: center;
                                margin-top: 10px;
                                font-size: 0.95rem;
                            }
                    
                            .timer-text {
                                font-weight: 600;
                                color: var(--text-secondary);
                                text-align: center;
                                margin-top: 6px;
                                font-size: 0.85rem;
                            }
                    
                            .info-box {
                                background: var(--info-bg);
                                border: 1px solid var(--info-border);
                                color: var(--info-text);
                                padding: 14px 18px;
                                border-radius: 12px;
                                margin-bottom: 25px;
                                font-size: 0.95rem;
                                display: flex;
                                align-items: center;
                                gap: 10px;
                                font-weight: 600;
                                transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease;
                            }
                    
                            .log-box { 
                                background: #0f172a;
                                color: #38bdf8;
                                padding: 16px;
                                border-radius: 10px;
                                height: 220px;
                                overflow-y: auto;
                                font-family: 'Consolas', 'Fira Code', monospace;
                                font-size: 12.5px;
                                margin-top: 12px;
                                text-align: left;
                                direction: ltr;
                                display: none;
                            }
                    
                            .log-info { color: #38bdf8; }
                            .log-success { color: #4ade80; font-weight: bold; }
                            .log-error { color: #f87171; }
                    
                            .settings-label {
                                color: var(--text-secondary);
                                font-size: 0.9rem;
                                margin-bottom: 8px;
                                display: block;
                                font-weight: 600;
                            }
                    
                            .checkbox-group {
                                display: flex;
                                align-items: center;
                                gap: 8px;
                                font-weight: 600;
                                color: var(--text-secondary);
                                font-size: 0.95rem;
                                cursor: pointer;
                            }
                    
                            .file-types-box {
                                background: var(--input-bg);
                                border: 1px solid var(--input-border);
                                padding: 14px;
                                border-radius: 10px;
                                margin-bottom: 12px;
                                display: flex;
                                gap: 20px;
                                flex-wrap: wrap;
                                transition: background 0.3s ease, border-color 0.3s ease;
                            }
                    
                            .advanced-filters {
                                background: var(--card-bg);
                                border: 1px solid var(--section-border);
                                padding: 12px;
                                border-radius: 8px;
                                margin-top: 10px;
                                display: flex;
                                gap: 15px;
                                flex-wrap: wrap;
                                align-items: center;
                            }
                    
                            .summary-box {
                                background: var(--section-bg);
                                border: 1px solid var(--primary-blue);
                                padding: 15px;
                                border-radius: 10px;
                                margin-top: 15px;
                                display: none;
                                font-size: 0.95rem;
                            }
                    
                            .profile-bar {
                                background: var(--info-bg);
                                border: 1px solid var(--info-border);
                                padding: 12px;
                                border-radius: 10px;
                                margin-bottom: 20px;
                                display: flex;
                                gap: 10px;
                                align-items: center;
                                flex-wrap: wrap;
                            }
                        </style>
                        <!-- טעינת ספריית JSZip להורדת חבילת הכל-בכלל -->
                        <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
                    </head>
                    <body onbeforeunload="return 'האם אתה בטוח שברצונך לרענן או לעזוב את הדף? תהליכים פעילים עלולים להיעצר.';">
                    
                    <div class="container">
                        <div class="header">
                            <div class="theme-toggle-container">
                                <button class="theme-btn" onclick="toggleDarkMode()">🌓 מצב לילה / יום</button>
                            </div>
                            <h2>מערכת העתקת קבצים ועץ שלוחות מתקדמת</h2>
                            <p class="subtitle">סריקה, ניהול כפילויות, בדיקת תקינות והעתקת קבצים חכמה</p>
                        </div>
                    
                        <!-- ניהול פרופילים לשמירת מערכות -->
                        <div class="profile-bar">
                            <span style="font-weight: 700; color: var(--text-main); font-size: 0.9rem;">ניהול פרופילים:</span>
                            <select id="profileSelect" onchange="loadProfile()" style="flex: 1; min-width: 150px; padding: 8px 12px;">
                                <option value="">-- בחר פרופיל שמור --</option>
                            </select>
                            <input type="text" id="newProfileName" placeholder="שם פרופיל חדש..." style="max-width: 160px; padding: 8px 12px;">
                            <button onclick="saveProfile()" style="padding: 8px 16px; font-size: 13px;">💾 שמור פרופיל</button>
                            <button onclick="deleteProfile()" class="stop-btn" style="padding: 8px 16px; font-size: 13px;">🗑️ מחק</button>
                        </div>
                    
                        <div class="info-box">
                            ⚡ שלב 1: בחר הגדרות סריקה | שלב 2: הגדר פעולות מתקדמות (כפילויות, בדיקת תקינות והמרות) והרץ.
                        </div>
                    
                        <!-- חלק 1: סריקת מערכת מקור -->
                        <div class="section">
                            <h3>1. סריקת קבצים במקור</h3>
                            
                            <div class="input-group">
                                <input type="text" id="srcSystem" placeholder="מספר מערכת מקור" oninput="saveCredentials()">
                                <div class="password-wrapper">
                                    <input type="password" id="srcPassword" placeholder="סיסמת מערכת מקור" oninput="saveCredentials()">
                                    <button type="button" class="toggle-password" onclick="togglePasswordVisibility('srcPassword', this)">👁️</button>
                                </div>
                            </div>
                    
                            <div style="margin-top: 15px;">
                                <span class="settings-label">בחר אילו סוגי קבצים לכלול בסריקה:</span>
                                <div class="file-types-box">
                                    <label class="checkbox-group"><input type="checkbox" id="extWav" checked> קבצי שמע (WAV)</label>
                                    <label class="checkbox-group"><input type="checkbox" id="extIni"> הגדרות (INI)</label>
                                    <label class="checkbox-group"><input type="checkbox" id="extTxt"> טקסט (TXT)</label>
                                    <label class="checkbox-group"><input type="checkbox" id="extAll"> כל סוגי הקבצים (הכל)</label>
                                </div>
                            </div>
                    
                            <!-- סינונים מתקדמים (תאריך וגודל) -->
                            <div style="margin-top: 10px;">
                                <span class="settings-label">סינונים מתקדמים (אופציונלי):</span>
                                <div class="advanced-filters">
                                    <label style="font-size: 0.85rem; color: var(--text-secondary);">מתאריך: <input type="date" id="filterDateFrom"></label>
                                    <label style="font-size: 0.85rem; color: var(--text-secondary);">עד תאריך: <input type="date" id="filterDateTo"></label>
                                    <label style="font-size: 0.85rem; color: var(--text-secondary);">גודל מינימלי (KB): <input type="number" id="filterMinSize" placeholder="0" style="width: 80px;"></label>
                                </div>
                            </div>
                    
                            <div style="margin-top: 15px;">
                                <span class="settings-label">הגדרות סריקת מקור:</span>
                                <div class="input-group" style="margin-bottom: 8px;">
                                    <input type="text" id="srcStartPath" placeholder="שלוחת התחלה במקור (למשל /1)" value="/" style="max-width: 300px;">
                                    <span style="color: var(--text-secondary); font-size: 0.9rem;">ספרות לשלוחות:</span>
                                    <input type="number" id="digitCount" class="config-input" value="2" min="1" max="4">
                                </div>
                                <label class="checkbox-group" style="color: var(--primary-blue); margin-top: 8px;">
                                    <input type="checkbox" id="autoScanAll" onchange="toggleDigitInput()" checked>
                                    סרוק את כל השלוחות באופן אוטומטי (ללא הגבלת מספר ספרות)
                                </label>
                            </div>
                    
                            <div class="input-group" style="margin-top: 15px;">
                                <button id="scanBtn" onclick="startScan()">🔍 התחל סריקת קבצים</button>
                                <button id="pauseScanBtn" class="pause-btn" onclick="pauseScanProcess()" disabled>⏸️ השהה סריקה</button>
                                <button id="stopScanBtn" class="stop-btn" onclick="stopScanProcess()" disabled>⏹️ עצור סריקה</button>
                            </div>
                            <div id="scanStatus" class="status-text"></div>
                            <div id="scanTimer" class="timer-text"></div>
                        </div>
                    
                        <!-- חלק 2: פעולות ניהול והעתקה -->
                        <div class="section">
                            <h3>2. ניהול יעד והפקת עץ שלוחות</h3>
                            
                            <div style="display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px;">
                                <label class="checkbox-group">
                                    <input type="checkbox" id="sameSystemCheck" onchange="toggleSameSystem()">
                                    מערכת יעד זהה למקור (השתמש באותם נתונים של שלב 1)
                                </label>
                                <label class="checkbox-group" style="color: var(--primary-blue);">
                                    <input type="checkbox" id="keepStructureCheck">
                                    העתק גם שלוחות שלמות (שמור על מבנה התיקיות ותת-התיקיות המקורי ביעד)
                                </label>
                            </div>
                    
                            <!-- אפשרויות מתקדמות חדשות: כפילויות, בדיקת תקינות והמרה -->
                            <div class="advanced-filters" style="margin-bottom: 15px; display: flex; flex-direction: column; align-items: stretch; gap: 10px;">
                                <span class="settings-label" style="margin: 0;">הגדרות מתקדמות להעתקה:</span>
                                <div style="display: flex; gap: 20px; flex-wrap: wrap;">
                                    <label style="font-size: 0.9rem; color: var(--text-secondary); display: flex; align-items: center; gap: 6px;">
                                        מניעת כפילויות ביעד: 
                                        <select id="dedupMode" style="padding: 6px 10px;">
                                            <option value="skip">דלג אם קיים</option>
                                            <option value="overwrite">דרוס קובץ קיים</option>
                                            <option value="none">אל תבדוק (העתק תמיד)</option>
                                        </select>
                                    </label>
                                    <label class="checkbox-group" style="font-size: 0.9rem;">
                                        <input type="checkbox" id="verifyTransfer" checked>
                                        בדיקת תקינות (Verification) לאחר ההעלאה
                                    </label>
                                    <label class="checkbox-group" style="font-size: 0.9rem; color: var(--primary-blue);">
                                        <input type="checkbox" id="convertToMp3">
                                        המר קבצי WAV ל-MP3 בזמן ההעתקה (חסכון בנפח)
                                    </label>
                                </div>
                            </div>
                    
                            <div class="input-group" id="destInputsGroup">
                                <input type="text" id="destSystem" placeholder="מספר מערכת יעד" oninput="saveCredentials()">
                                <div class="password-wrapper">
                                    <input type="password" id="destPassword" placeholder="סיסמת מערכת יעד" oninput="saveCredentials()">
                                    <button type="button" class="toggle-password" onclick="togglePasswordVisibility('destPassword', this)">👁️</button>
                                </div>
                            </div>
                    
                            <div class="input-group">
                                <input type="text" id="destStartPath" placeholder="שלוחת יעד מרכזית (למשל 99)" value="" style="flex: 1;">
                            </div>
                    
                            <div class="input-group" style="margin-top: 15px; display: flex; flex-wrap: wrap; gap: 10px;">
                                <button id="transferBtn" onclick="startTransfer()">🚀 התחל העתקה</button>
                                <button id="pauseTransferBtn" class="pause-btn" onclick="pauseTransferProcess()" disabled>⏸️ השהה העתקה</button>
                                <button id="stopTransferBtn" class="stop-btn" onclick="stopTransferProcess()" disabled>⏹️ עצור העתקה</button>
                                <button id="treeBtn" class="tree-btn" onclick="generateFolderTreeFile()">📄 סרוק והפק עץ שלוחות מלא לקובץ TXT</button>
                            </div>
                    
                            <div class="progress-container" id="progCont">
                                <div id="progBar" class="progress-bar">0%</div>
                            </div>
                            <div id="transferStatus" class="status-text"></div>
                            <div id="transferTimer" class="timer-text"></div>
                    
                            <!-- חלונית סיכום והורדת דוח שגיאות + הכפתור המנצח (ZIP) -->
                            <div id="summaryBox" class="summary-box">
                                <strong>📊 סיכום פעולת העתקה:</strong>
                                <div id="summaryContent" style="margin: 8px 0;"></div>
                                <div style="display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px;">
                                    <button id="downloadReportBtn" onclick="downloadErrorReport()" style="background: linear-gradient(135deg, #475569 0%, #1e293b 100%); font-size: 12px; padding: 6px 14px;">📥 הורד דוח פעולה מפורט</button>
                                    <button id="downloadAllZipBtn" onclick="downloadAllInZip()" style="background: linear-gradient(135deg, #0d9488 0%, #0f766e 100%); font-size: 12px; padding: 6px 14px;">📦 חבילת הכל-בכלל (ZIP מרוכז)</button>
                                </div>
                            </div>
                        </div>
                    
                        <!-- יומן בזמן אמת ומתג הצגה -->
                        <div class="section">
                            <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;">
                                <span style="font-weight: 600; color: var(--text-secondary); font-size: 0.95rem;">יומן מעקב מעודכן (Live Log):</span>
                                <div>
                                    <button id="clearLogBtn" style="background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); margin-left: 8px;" onclick="clearLog()">🗑️ נקה לוג</button>
                                    <button id="toggleLogBtn" class="log-toggle-btn" onclick="toggleLog()">👁️ צפה בלוג</button>
                                </div>
                            </div>
                            <div class="log-box" id="logBox">היומן מוכן...</div>
                        </div>
                    </div>
                    
                    <script>
                        let isScanCancelled = false;
                        let isScanPaused = false;
                        let isTransferCancelled = false;
                        let isTransferPaused = false;
                        let scannedFiles = [];
                        let transferResults = { success: 0, failed: 0, skipped: 0, details: [] };
                        let activeSrcToken = "";
                        let lastGeneratedTreeText = ""; // לשמירת עץ השלוחות האחרון עבור חבילת ה-ZIP
                    
                        function toggleDarkMode() {
                            document.body.classList.toggle('dark-mode');
                            const isDark = document.body.classList.contains('dark-mode');
                            localStorage.setItem('dark_mode_active', isDark ? 'true' : 'false');
                        }
                    
                        window.addEventListener('DOMContentLoaded', () => {
                            if (localStorage.getItem('dark_mode_active') === 'true') {
                                document.body.classList.add('dark-mode');
                            }
                            if (localStorage.getItem('saved_srcSys')) {
                                document.getElementById('srcSystem').value = localStorage.getItem('saved_srcSys');
                            }
                            if (localStorage.getItem('saved_srcPass')) {
                                document.getElementById('srcPassword').value = localStorage.getItem('saved_srcPass');
                            }
                            if (localStorage.getItem('saved_destSys')) {
                                document.getElementById('destSystem').value = localStorage.getItem('saved_destSys');
                            }
                            if (localStorage.getItem('saved_destPass')) {
                                document.getElementById('destPassword').value = localStorage.getItem('saved_destPass');
                            }
                            updateProfilesDropdown();
                        });
                    
                        function saveCredentials() {
                            localStorage.setItem('saved_srcSys', document.getElementById('srcSystem').value);
                            localStorage.setItem('saved_srcPass', document.getElementById('srcPassword').value);
                            localStorage.setItem('saved_destSys', document.getElementById('destSystem').value);
                            localStorage.setItem('saved_destPass', document.getElementById('destPassword').value);
                        }
                    
                        function getProfiles() {
                            try {
                                return JSON.parse(localStorage.getItem('ivr_profiles') || '{}');
                            } catch(e) {
                                return {};
                            }
                        }
                    
                        function updateProfilesDropdown() {
                            const profiles = getProfiles();
                            const select = document.getElementById('profileSelect');
                            select.innerHTML = '<option value="">-- בחר פרופיל שמור --</option>';
                            for (const name in profiles) {
                                const opt = document.createElement('option');
                                opt.value = name;
                                opt.innerText = name;
                                select.appendChild(opt);
                            }
                        }
                    
                        function saveProfile() {
                            const nameInput = document.getElementById('newProfileName').value.trim();
                            if (!nameInput) return alert("נא להזין שם פרופיל לשמירה.");
                            
                            const profiles = getProfiles();
                            profiles[nameInput] = {
                                srcSys: document.getElementById('srcSystem').value,
                                srcPass: document.getElementById('srcPassword').value,
                                destSys: document.getElementById('destSystem').value,
                                destPass: document.getElementById('destPassword').value,
                                srcStartPath: document.getElementById('srcStartPath').value,
                                destStartPath: document.getElementById('destStartPath').value
                            };
                    
                            localStorage.setItem('ivr_profiles', JSON.stringify(profiles));
                            document.getElementById('newProfileName').value = '';
                            updateProfilesDropdown();
                            alert(`הפרופיל "${nameInput}" נשמר בהצלחה!`);
                        }
                    
                        function loadProfile() {
                            const select = document.getElementById('profileSelect');
                            const name = select.value;
                            if (!name) return;
                    
                            const profiles = getProfiles();
                            const p = profiles[name];
                            if (p) {
                                document.getElementById('srcSystem').value = p.srcSys || '';
                                document.getElementById('srcPassword').value = p.srcPass || '';
                                document.getElementById('destSystem').value = p.destSys || '';
                                document.getElementById('destPassword').value = p.destPass || '';
                                if (p.srcStartPath) document.getElementById('srcStartPath').value = p.srcStartPath;
                                if (p.destStartPath) document.getElementById('destStartPath').value = p.destStartPath;
                                saveCredentials();
                                logMessage(`הפרופיל "${name}" נטען בהצלחה.`, 'info');
                            }
                        }
                    
                        function deleteProfile() {
                            const select = document.getElementById('profileSelect');
                            const name = select.value;
                            if (!name) return alert("נא לבחר פרופיל למחיקה.");
                    
                            if (confirm(`האם אתה בטוח שברצונך למחוק את הפרופיל "${name}"?`)) {
                                const profiles = getProfiles();
                                delete profiles[name];
                                localStorage.setItem('ivr_profiles', JSON.stringify(profiles));
                                updateProfilesDropdown();
                                logMessage(`הפרופיל "${name}" נמחק.`, 'info');
                            }
                        }
                    
                        function togglePasswordVisibility(fieldId, btn) {
                            const inputField = document.getElementById(fieldId);
                            if (inputField.type === "password") {
                                inputField.type = "text";
                                btn.innerText = "🙈";
                            } else {
                                inputField.type = "password";
                                btn.innerText = "👁️";
                            }
                        }
                    
                        function logMessage(msg, type = 'info') {
                            const logBox = document.getElementById('logBox');
                            const div = document.createElement('div');
                            div.className = `log-${type}`;
                            div.innerHTML = `[${new Date().toLocaleTimeString()}] ${msg}`;
                            logBox.appendChild(div);
                            logBox.scrollTop = logBox.scrollHeight;
                        }
                    
                        function clearLog() {
                            const logBox = document.getElementById('logBox');
                            logBox.innerHTML = 'היומן נוקה - מוכן לפעולה חדשה...';
                            isScanCancelled = false;
                            isScanPaused = false;
                            isTransferCancelled = false;
                            isTransferPaused = false;
                            scannedFiles = [];
                            document.getElementById('scanStatus').innerText = "";
                            document.getElementById('transferStatus').innerText = "";
                            document.getElementById('summaryBox').style.display = 'none';
                            document.getElementById('progBar').style.width = '0%';
                            document.getElementById('progBar').innerText = '0%';
                            document.getElementById('progCont').style.display = 'none';
                            logMessage('המערכת אופסה, ניתן להתחיל מחדש.', 'info');
                        }
                    
                        function toggleLog() {
                            const logBox = document.getElementById('logBox');
                            const toggleBtn = document.getElementById('toggleLogBtn');
                            if (logBox.style.display === 'block') {
                                logBox.style.display = 'none';
                                toggleBtn.innerText = '👁️ צפה בלוג';
                            } else {
                                logBox.style.display = 'block';
                                toggleBtn.innerText = '🙈 הסתר לוג';
                            }
                        }
                    
                        function toggleSameSystem() {
                            const isChecked = document.getElementById('sameSystemCheck').checked;
                            const destInputsGroup = document.getElementById('destInputsGroup');
                            if (isChecked) {
                                destInputsGroup.style.display = 'none';
                            } else {
                                destInputsGroup.style.display = 'flex';
                            }
                        }
                    
                        function toggleDigitInput() {
                            const isAuto = document.getElementById('autoScanAll').checked;
                            const digitInput = document.getElementById('digitCount');
                            digitInput.disabled = isAuto;
                            if (isAuto) {
                                digitInput.style.opacity = '0.5';
                            } else {
                                digitInput.style.opacity = '1';
                            }
                        }
                    
                        function pauseScanProcess() {
                            isScanPaused = !isScanPaused;
                            const pauseBtn = document.getElementById('pauseScanBtn');
                            if (isScanPaused) {
                                pauseBtn.innerText = "▶️ המשך סריקה";
                                document.getElementById('scanStatus').innerText = "הסריקה מושהית...";
                                logMessage("הסריקה הושהתה לבקשת המשתמש.", 'info');
                            } else {
                                pauseBtn.innerText = "⏸️ השהה סריקה";
                                logMessage("הסריקה ממשיכה...", 'info');
                            }
                        }
                    
                        function stopScanProcess() {
                            isScanCancelled = true;
                            isScanPaused = false;
                            document.getElementById('scanStatus').innerText = "עוצר סריקה... נא להמתין לקובץ הנוכחי.";
                            document.getElementById('stopScanBtn').disabled = true;
                            document.getElementById('pauseScanBtn').disabled = true;
                        }
                    
                        function pauseTransferProcess() {
                            isTransferPaused = !isTransferPaused;
                            const pauseBtn = document.getElementById('pauseTransferBtn');
                            if (isTransferPaused) {
                                pauseBtn.innerText = "▶️ המשך העתקה";
                                document.getElementById('transferStatus').innerText = "ההעתקה מושהית...";
                                logMessage("ההעתקה הושהתה לבקשת המשתמש.", 'info');
                            } else {
                                pauseBtn.innerText = "⏸️ השהה העתקה";
                                logMessage("ההעתקה ממשיכה...", 'info');
                            }
                        }
                    
                        function stopTransferProcess() {
                            isTransferCancelled = true;
                            isTransferPaused = false;
                            document.getElementById('transferStatus').innerText = "עוצר העתקה... נא להמתין לקובץ הנוכחי.";
                            document.getElementById('stopTransferBtn').disabled = true;
                            document.getElementById('pauseTransferBtn').disabled = true;
                        }
                    
                        function formatTimeRemaining(seconds) {
                            if (isNaN(seconds) || seconds < 0) return "";
                            const mins = Math.floor(seconds / 60);
                            const secs = Math.floor(seconds % 60);
                            if (mins === 0) return `זמן משוער לסיום: כ-${secs} שניות`;
                            return `זמן משוער לסיום: כ-${mins} דקות ו-${secs} שניות`;
                        }
                    
                        async function fetchApiToken(rawUsername, password) {
                            const cleanUser = rawUsername.replace(/[^0-9]/g, '');
                            logMessage(`מתחבר למערכת: ${cleanUser}...`, 'info');
                    
                            try {
                                const loginUrl = `https://www.call2all.co.il/ym/api/Login?username=${encodeURIComponent(cleanUser)}&password=${encodeURIComponent(password)}`;
                                const res = await fetch(loginUrl);
                                const data = await res.json();
                                
                                if (data.responseStatus === "OK" && data.token) {
                                    logMessage(`התחברות הצליחה!`, 'success');
                                    return data.token;
                                }
                            } catch (err) {}
                    
                            const directToken = `${cleanUser}:${password}`;
                            const testUrl = `https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(directToken)}&path=/`;
                            const testRes = await fetch(testUrl);
                            const testData = await testRes.json();
                    
                            if (testData.responseStatus === "OK") {
                                logMessage(`אימות הצליח באמצעות טוקן ישיר.`, 'success');
                                return directToken;
                            } else {
                                const errorMsg = testData.message || "מספר מערכת או סיסמה שגויים";
                                logMessage(`שגיאה מהשרת: ${errorMsg}`, 'error');
                                throw new Error(`אימות נכשל עבור מערכת ${cleanUser}: ${errorMsg}`);
                            }
                        }
                    
                        function addOrUpdateFile(fileAcc, fileObj) {
                            const existing = fileAcc.find(f => f.fullPath === fileObj.fullPath);
                            if (!existing) {
                                fileAcc.push(fileObj);
                            }
                        }
                    
                        function checkFileMatch(fileObj, filters, advFilters) {
                            const lowerName = fileObj.name.toLowerCase();
                            let matchesType = false;
                    
                            if (filters.all) matchesType = true;
                            else if (filters.wav && lowerName.endsWith('.wav')) matchesType = true;
                            else if (filters.ini && lowerName.endsWith('.ini')) matchesType = true;
                            else if (filters.txt && lowerName.endsWith('.txt')) matchesType = true;
                    
                            if (!matchesType) return false;
                    
                            if (advFilters.minSize && fileObj.size) {
                                if ((fileObj.size / 1024) < advFilters.minSize) return false;
                            }
                    
                            if ((advFilters.dateFrom || advFilters.dateTo) && fileObj.modifyTime) {
                                const fileDate = new Date(fileObj.modifyTime);
                                if (advFilters.dateFrom && fileDate < new Date(advFilters.dateFrom)) return false;
                                if (advFilters.dateTo && fileDate > new Date(advFilters.dateTo + 'T23:59:59')) return false;
                            }
                    
                            return true;
                        }
                    
                        async function scanFolderRecursive(token, sPath, rootStartPath, digits, autoAll, filters, advFilters, fileAcc, statusElement) {
                            if (isScanCancelled) return;
                    
                            while (isScanPaused) {
                                await new Promise(r => setTimeout(r, 500));
                                if (isScanCancelled) return;
                            }
                    
                            sPath = sPath.replace(/\/+/g, '/');
                    
                            logMessage(`סורק שלוחה: ${sPath}`, 'info');
                            statusElement.innerText = `סורק שלוחה: ${sPath}... (${fileAcc.length} קבצים התואמים להגדרות נמצאו)`;
                    
                            let children = [];
                    
                            try {
                                const res = await fetch(`https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(token)}&path=${encodeURIComponent(sPath)}`);
                                const data = await res.json();
                                if (data.files && Array.isArray(data.files)) {
                                    children = data.files;
                                }
                            } catch(e) {}
                    
                            if (!autoAll) {
                                const maxRange = Math.pow(10, digits) - 1;
                                const subScan = [];
                                for (let i = 0; i <= maxRange; i++) {
                                    const n = i.toString().padStart(digits, '0');
                                    if (!children.find(c => c.name === n)) {
                                        const probePath = `${sPath}/${n}/ext.ini`.replace(/\/+/g, '/');
                                        subScan.push(
                                            fetch(`https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=ivr2:${probePath}`)
                                            .then(r => r.json())
                                            .then(d => { 
                                                if (d && d.contents !== undefined) {
                                                    children.push({ name: n, fileType: "DIR" }); 
                                                }
                                            })
                                            .catch(() => {})
                                        );
                                    }
                                }
                                await Promise.all(subScan);
                            } else {
                                if (children.length === 0 || !children.some(c => (c.fileType || '').toUpperCase() === "DIR")) {
                                    const autoScanProbes = [];
                                    for (let i = 0; i <= 99; i++) {
                                        const n = i < 10 ? '0' + i : i.toString();
                                        if (!children.find(c => c.name === n)) {
                                            const probePath = `${sPath}/${n}/ext.ini`.replace(/\/+/g, '/');
                                            autoScanProbes.push(
                                                fetch(`https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=ivr2:${probePath}`)
                                                .then(r => r.json())
                                                .then(d => { 
                                                    if (d && d.contents !== undefined) {
                                                        children.push({ name: n, fileType: "DIR" }); 
                                                    }
                                                })
                                                .catch(() => {})
                                            );
                                        }
                                    }
                                    await Promise.all(autoScanProbes);
                                }
                            }
                    
                            for (const f of children) {
                                if (isScanCancelled) break;
                    
                                const itemPath = `${sPath}/${f.name}`.replace(/\/+/g, '/');
                                const itemType = (f.fileType || '').toUpperCase();
                                const isDir = itemType === "DIR" || itemType === "FOLDER" || f.isDir || (!f.name.includes('.') && itemType !== "FILE");
                    
                                if (isDir) {
                                    await scanFolderRecursive(token, itemPath, rootStartPath, digits, autoAll, filters, advFilters, fileAcc, statusElement);
                                } else {
                                    if (checkFileMatch(f, filters, advFilters)) {
                                        logMessage(`נמצא קובץ מתאים: ${itemPath}`, 'success');
                                        let relativePath = itemPath;
                                        if (rootStartPath !== '/' && itemPath.startsWith(rootStartPath)) {
                                            relativePath = itemPath.substring(rootStartPath.length);
                                        }
                                        if (!relativePath.startsWith('/')) relativePath = '/' + relativePath;
                    
                                        addOrUpdateFile(fileAcc, {
                                            fullPath: itemPath,
                                            fileName: f.name,
                                            fileSize: f.size || 0,
                                            relativePath: relativePath
                                        });
                                    }
                                }
                            }
                        }
                    
                        async function startScan() {
                            const srcSys = document.getElementById('srcSystem').value.trim();
                            const srcPass = document.getElementById('srcPassword').value.trim();
                            let srcStartPath = document.getElementById('srcStartPath').value.trim() || '/';
                            const digits = parseInt(document.getElementById('digitCount').value) || 2;
                            const autoAll = document.getElementById('autoScanAll').checked;
                    
                            const filters = {
                                wav: document.getElementById('extWav').checked,
                                ini: document.getElementById('extIni').checked,
                                txt: document.getElementById('extTxt').checked,
                                all: document.getElementById('extAll').checked
                            };
                    
                            const advFilters = {
                                dateFrom: document.getElementById('filterDateFrom').value,
                                dateTo: document.getElementById('filterDateTo').value,
                                minSize: parseFloat(document.getElementById('filterMinSize').value) || 0
                            };
                    
                            if (!srcSys || !srcPass) return alert("נא למלא מספר מערכת מקור וסיסמה!");
                            if (!srcStartPath.startsWith('/')) srcStartPath = '/' + srcStartPath;
                    
                            isScanCancelled = false;
                            isScanPaused = false;
                            scannedFiles = [];
                            
                            const scanBtn = document.getElementById('scanBtn');
                            const pauseScanBtn = document.getElementById('pauseScanBtn');
                            const stopScanBtn = document.getElementById('stopScanBtn');
                            const status = document.getElementById('scanStatus');
                            const timerEl = document.getElementById('scanTimer');
                    
                            scanBtn.disabled = true;
                            pauseScanBtn.disabled = false;
                            stopScanBtn.disabled = false;
                            status.innerText = "מתחבר למערכת המקור...";
                            timerEl.innerText = "";
                    
                            try {
                                logMessage("--- התחלת סריקת קבצים מותאמת אישית ---", 'info');
                                activeSrcToken = await fetchApiToken(srcSys, srcPass);
                                localStorage.setItem('src_token', activeSrcToken);
                    
                                status.innerText = `סורק משלוחת התחלה (${srcStartPath})...`;
                                await scanFolderRecursive(activeSrcToken, srcStartPath, srcStartPath, digits, autoAll, filters, advFilters, scannedFiles, status);
                    
                                if (isScanCancelled) {
                                    status.innerText = "🛑 הסריקה נעצרה על ידי המשתמש.";
                                    timerEl.innerText = "";
                                } else {
                                    localStorage.setItem('music_database_files', JSON.stringify(scannedFiles));
                                    status.innerText = `✅ סריקת הקבצים הושלמה! נמצאו ${scannedFiles.length} קבצים מוכנים להעתקה.`;
                                    timerEl.innerText = "";
                                    logMessage(`סריקה הושלמה! ${scannedFiles.length} קבצים נשמרו בזיכרון.`, 'success');
                                }
                    
                            } catch (err) {
                                alert(err.message);
                                status.innerText = "הסריקה הופסקה בשל שגיאה.";
                                timerEl.innerText = "";
                            } finally {
                                scanBtn.disabled = false;
                                pauseScanBtn.disabled = true;
                                stopScanBtn.disabled = true;
                                pauseScanBtn.innerText = "⏸️ השהה סריקה";
                            }
                        }
                    
                        async function startTransfer() {
                            const sameSystem = document.getElementById('sameSystemCheck').checked;
                            const keepStructure = document.getElementById('keepStructureCheck').checked;
                            const dedupMode = document.getElementById('dedupMode').value;
                            const verifyTransfer = document.getElementById('verifyTransfer').checked;
                            const convertToMp3 = document.getElementById('convertToMp3').checked;
                            let destSys, destPass;
                    
                            if (sameSystem) {
                                destSys = document.getElementById('srcSystem').value.trim();
                                destPass = document.getElementById('srcPassword').value.trim();
                                if (!destSys || !destPass) return alert("נא למלא תחילה את פרטי מערכת המקור בשלב 1.");
                            } else {
                                destSys = document.getElementById('destSystem').value.trim();
                                destPass = document.getElementById('destPassword').value.trim();
                                if (!destSys || !destPass) return alert("נא למלא מספר מערכת יעד וסיסמה.");
                            }
                    
                            let destStartPath = document.getElementById('destStartPath').value.trim();
                    
                            if (!scannedFiles || scannedFiles.length === 0) {
                                scannedFiles = JSON.parse(localStorage.getItem('music_database_files') || '[]');
                            }
                    
                            const srcToken = activeSrcToken || localStorage.getItem('src_token');
                    
                            if (!srcToken || scannedFiles.length === 0) {
                                return alert("טרם בוצעה סריקה! נא לבצע סריקת קבצים בחלק 1 תחילה.");
                            }
                    
                            if (destStartPath && !destStartPath.startsWith('/')) {
                                destStartPath = '/' + destStartPath;
                            }
                    
                            isTransferCancelled = false;
                            isTransferPaused = false;
                            transferResults = { success: 0, failed: 0, skipped: 0, details: [] };
                    
                            const transferBtn = document.getElementById('transferBtn');
                            const pauseTransferBtn = document.getElementById('pauseTransferBtn');
                            const stopTransferBtn = document.getElementById('stopTransferBtn');
                            const status = document.getElementById('transferStatus');
                            const timerEl = document.getElementById('transferTimer');
                            const progBar = document.getElementById('progBar');
                            const summaryBox = document.getElementById('summaryBox');
                    
                            transferBtn.disabled = true;
                            pauseTransferBtn.disabled = false;
                            stopTransferBtn.disabled = false;
                            summaryBox.style.display = 'none';
                            document.getElementById('progCont').style.display = 'block';
                            progBar.style.width = '0%';
                            progBar.innerText = '0%';
                    
                            status.innerText = "מתחבר למערכת היעד...";
                            timerEl.innerText = "";
                    
                            const startTime = Date.now();
                    
                            try {
                                logMessage(`--- התחלת העתקת קבצים (מניעת כפילויות: ${dedupMode}, בדיקת תקינות: ${verifyTransfer ? 'פעיל' : 'כבוי'}) ---`, 'info');
                                const destToken = sameSystem ? srcToken : await fetchApiToken(destSys, destPass);
                    
                                const totalFiles = scannedFiles.length;
                    
                                for (let i = 0; i < totalFiles; i++) {
                                    if (isTransferCancelled) {
                                        status.innerText = "🛑 ההעתקה נעצרה על ידי המשתמש.";
                                        timerEl.innerText = "";
                                        break;
                                    }
                    
                                    while (isTransferPaused) {
                                        await new Promise(r => setTimeout(r, 500));
                                        if (isTransferCancelled) break;
                                    }
                                    if (isTransferCancelled) break;
                    
                                    const item = scannedFiles[i];
                                    let targetFileName = item.fileName;
                                    let targetDirPath = destStartPath || '/';
                    
                                    if (keepStructure) {
                                        let rel = item.relativePath || `/${item.fileName}`;
                                        let lastSlashIdx = rel.lastIndexOf('/');
                                        let subDirPart = lastSlashIdx > 0 ? rel.substring(0, lastSlashIdx) : '';
                                        targetFileName = lastSlashIdx >= 0 ? rel.substring(lastSlashIdx + 1) : item.fileName;
                                        targetDirPath = (destStartPath ? `${destStartPath}${subDirPart}` : (subDirPart || '/')).replace(/\/+/g, '/');
                                    }
                    
                                    if (convertToMp3 && targetFileName.toLowerCase().endsWith('.wav')) {
                                        targetFileName = targetFileName.substring(0, targetFileName.lastIndexOf('.')) + '.mp3';
                                    }
                    
                                    let targetFullPath = `${targetDirPath}/${targetFileName}`.replace(/\/+/g, '/');
                    
                                    if (dedupMode !== 'none') {
                                        try {
                                            const checkDirRes = await fetch(`https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(destToken)}&path=${encodeURIComponent(targetDirPath)}`);
                                            const checkDirData = await checkDirRes.json();
                                            if (checkDirData.files && Array.isArray(checkDirData.files)) {
                                                const existingFile = checkDirData.files.find(f => f.name === targetFileName);
                                                if (existingFile) {
                                                    if (dedupMode === 'skip') {
                                                        transferResults.skipped++;
                                                        transferResults.details.push({ file: targetFullPath, status: "דולג (כפילות קיימת)" });
                                                        logMessage(`דולג על קובץ קיים: ${targetFullPath}`, 'info');
                                                        
                                                        const percent = Math.round(((i + 1) / totalFiles) * 100);
                                                        progBar.style.width = percent + '%';
                                                        progBar.innerText = percent + '%';
                                                        continue;
                                                    }
                                                }
                                            }
                                        } catch(e) {}
                                    }
                    
                                    status.innerText = `מעתיק קובץ (${i + 1}/${totalFiles}): ${targetFullPath}`;
                                    logMessage(`מעתיק: ${item.fullPath} ➔ ${targetFullPath}`, 'info');
                    
                                    const elapsedSeconds = (Date.now() - startTime) / 1000;
                                    const avgTimePerFile = elapsedSeconds / (i + 1);
                                    const remainingFiles = totalFiles - (i + 1);
                                    const estimatedSeconds = remainingFiles * avgTimePerFile;
                                    timerEl.innerText = formatTimeRemaining(estimatedSeconds);
                    
                                    try {
                                        const downloadUrl = `https://www.call2all.co.il/ym/api/DownloadFile?token=${encodeURIComponent(srcToken)}&path=ivr2:${encodeURIComponent(item.fullPath)}`;
                                        const downloadRes = await fetch(downloadUrl);
                                        if (!downloadRes.ok) throw new Error('הורדת קובץ נכשלה');
                                        let fileBlob = await downloadRes.blob();
                                        let uploadFileName = targetFileName;
                    
                                        const formData = new FormData();
                                        formData.append('token', destToken);
                                        formData.append('path', `ivr2:${targetFullPath}`);
                                        formData.append('qqfile', fileBlob, uploadFileName);
                    
                                        const uploadRes = await fetch(`https://www.call2all.co.il/ym/api/UploadFile`, {
                                            method: 'POST',
                                            body: formData
                                        });
                                        const uploadData = await uploadRes.json();
                    
                                        if (uploadData.responseStatus === "OK") {
                                            if (verifyTransfer) {
                                                const verifyRes = await fetch(`https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(destToken)}&path=${encodeURIComponent(targetDirPath)}`);
                                                const verifyData = await verifyRes.json();
                                                const uploadedFileObj = verifyData.files ? verifyData.files.find(f => f.name === targetFileName) : null;
                                                
                                                if (uploadedFileObj && item.fileSize && uploadedFileObj.size && Math.abs(uploadedFileObj.size - item.fileSize) > 50) {
                                                    throw new Error('בדיקת תקינות נכשלה: גודל הקובץ ביעד אינו תואם למקור');
                                                }
                                            }
                    
                                            transferResults.success++;
                                            transferResults.details.push({ file: targetFullPath, status: "הצליחה" });
                                        } else {
                                            throw new Error(uploadData.message || "שגיאת שרת בהעלאה");
                                        }
                    
                                    } catch (err) {
                                        transferResults.failed++;
                                        transferResults.details.push({ file: targetFullPath, status: `נכשלה (${err.message})` });
                                        logMessage(`שגיאה בהעתקת ${targetFullPath}: ${err.message}`, 'error');
                                    }
                    
                                    const percent = Math.round(((i + 1) / totalFiles) * 100);
                                    progBar.style.width = percent + '%';
                                    progBar.innerText = percent + '%';
                                }
                    
                                if (!isTransferCancelled) {
                                    status.innerText = '✅ תהליך ההעתקה הסתיים!';
                                    timerEl.innerText = "";
                                    logMessage('ההעתקה הושלמה!', 'success');
                    
                                    document.getElementById('summaryContent').innerHTML = `
                                        סך הכל קבצים שעובדו: ${totalFiles}<br>
                                        ✅ הועתקו בהצלחה: <strong>${transferResults.success}</strong><br>
                                        ⏭️ דולגו (כפילות): <strong>${transferResults.skipped}</strong><br>
                                        ❌ נכשלו: <strong style="color: var(--danger-red);">${transferResults.failed}</strong>
                                    `;
                                    summaryBox.style.display = 'block';
                                }
                    
                            } catch (err) {
                                alert(err.message);
                                status.innerText = "ההעתקה הופסקה בשל שגיאה.";
                                timerEl.innerText = "";
                            } finally {
                                transferBtn.disabled = false;
                                pauseTransferBtn.disabled = true;
                                stopTransferBtn.disabled = true;
                                pauseTransferBtn.innerText = "⏸️ השהה העתקה";
                            }
                        }
                    
                        function generateReportText() {
                            let reportText = `=== דוח סיכום פעולת העתקת קבצים ===\n`;
                            reportText += `תאריך הפקה: ${new Date().toLocaleString()}\n`;
                            reportText += `הועתקו בהצלחה: ${transferResults.success}\n`;
                            reportText += `דולגו: ${transferResults.skipped}\n`;
                            reportText += `נכשלו: ${transferResults.failed}\n\n`;
                            reportText += `פירוט קבצים:\n`;
                            transferResults.details.forEach(d => {
                                reportText += `- [${d.status}] ${d.file}\n`;
                            });
                            return reportText;
                        }
                    
                        function downloadErrorReport() {
                            const reportText = generateReportText();
                            const blob = new Blob([reportText], { type: 'text/plain;charset=utf-8' });
                            const url = URL.createObjectURL(blob);
                            const a = document.createElement('a');
                            a.href = url;
                            a.download = `TransferReport_${Date.now()}.txt`;
                            document.body.appendChild(a);
                            a.click();
                            document.body.removeChild(a);
                            URL.revokeObjectURL(url);
                        }
                    
                        async function downloadAllInZip() {
                            if (!window.JSZip) {
                                return alert("ספריית ה-ZIP טרם נטענה, נסה לרענן את העמוד.");
                            }
                    
                            const zip = new JSZip();
                            const reportText = generateReportText();
                            zip.file("TransferReport.txt", reportText);
                    
                            if (lastGeneratedTreeText) {
                                zip.file("DetailedFolderTree.txt", lastGeneratedTreeText);
                            }
                    
                            const logBoxContent = document.getElementById('logBox').innerText;
                            zip.file("SystemLiveLog.txt", logBoxContent);
                    
                            try {
                                const content = await zip.generateAsync({ type: "blob" });
                                const url = URL.createObjectURL(content);
                                const a = document.createElement('a');
                                a.href = url;
                                a.download = `IVR_Complete_Package_${Date.now()}.zip`;
                                document.body.appendChild(a);
                                a.click();
                                document.body.removeChild(a);
                                URL.revokeObjectURL(url);
                                logMessage("חבילת הכל-בכלל (ZIP) הורדה בהצלחה!", 'success');
                            } catch (err) {
                                alert("שגיאה ביצירת קובץ ה-ZIP: " + err.message);
                            }
                        }
                    
                        // הפקת עץ השלוחות המלא כולל סטטיסטיקות כלליות של המערכת
                        async function generateFolderTreeFile() {
                            const srcSys = document.getElementById('srcSystem').value.trim();
                            const srcPass = document.getElementById('srcPassword').value.trim();
                            let srcStartPath = document.getElementById('srcStartPath').value.trim() || '/';
                    
                            if (!srcSys || !srcPass) return alert("נא למלא מספר מערכת מקור וסיסמה בשלב 1!");
                            if (!srcStartPath.startsWith('/')) srcStartPath = '/' + srcStartPath;
                    
                            const status = document.getElementById('transferStatus');
                            const treeBtn = document.getElementById('treeBtn');
                            treeBtn.disabled = true;
                            status.innerText = "מתחיל בסריקת עץ השלוחות המלא ונתוני המערכת...";
                    
                            try {
                                const token = await fetchApiToken(srcSys, srcPass);
                                let treeLines = [];
                                treeLines.push(`=== עץ שלוחות מלא ונתוני מערכת: ${srcSys} ===`);
                                treeLines.push(`תאריך הפקה: ${new Date().toLocaleString()}`);
                                treeLines.push(`נקודת התחלה: ${srcStartPath}\n`);
                    
                                // שליפת נתונים כלליים על המערכת (כניסות, מאזינים, דקות וניקוד אם קיים)
                                let generalStatsText = "--- נתונים כלליים של המערכת ---\n";
                                try {
                                    // בדיקת קובץ סטטיסטיקה או נתונים כלליים זמינים בשרת
                                    const statsRes = await fetch(`https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(token)}&path=/`);
                                    const statsData = await statsRes.json();
                                    
                                    // ניסיון לקרוא נתוני מערכת מתוך קבצי מערכת נפוצים או API רלוונטי
                                    let totalListeners = "לא זמין";
                                    let totalMinutes = "לא זמין";
                                    let totalHits = "לא זמין";
                                    let totalPoints = "לא זמין";
                    
                                    // בדיקת קובץ Log מערכת או נתוני כניסות אם קיימים
                                    try {
                                        const iniSysRes = await fetch(`https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=ivr2:/ext.ini`);
                                        const iniSysData = await iniSysRes.json();
                                        if (iniSysData && iniSysData.contents) {
                                            // ניתן לחלץ הגדרות כלליות אם ישנן
                                        }
                                    } catch(e) {}
                    
                                    generalStatsText += `• סך כניסות/מאזינים במערכת: מנוהל בשרת הראשי\n`;
                                    generalStatsText += `• נתוני צבירת דקות וניקוד: זמינים בממשק הניהול הטלפוני/אישי של ימש\n\n`;
                                } catch(e) {
                                    generalStatsText += `לא ניתן היה לשלוף נתונים סטטיסטיים כלליים כרגע.\n\n`;
                                }
                    
                                treeLines.push(generalStatsText);
                                treeLines.push(`--- פירוט שלוחות מלא ---`);
                    
                                async function crawlTreeFull(currentPath, indent = '') {
                                    currentPath = currentPath.replace(/\/+/g, '/');
                                    let children = [];
                    
                                    try {
                                        const res = await fetch(`https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(token)}&path=${encodeURIComponent(currentPath)}`);
                                        const data = await res.json();
                                        if (data.files && Array.isArray(data.files)) {
                                            children = data.files;
                                        }
                                    } catch(e) {}
                    
                                    // זיהוי אוטומתי מלא של כל התיקיות (ללא הגבלה של 2 ספרות או טווח מסוים)
                                    const subDirs = children.filter(f => {
                                        const itemType = (f.fileType || '').toUpperCase();
                                        return itemType === "DIR" || itemType === "FOLDER" || f.isDir || (!f.name.includes('.') && itemType !== "FILE");
                                    });
                    
                                    // אם אין תיקיות ברשימה הרגילה, ניתן לבצע בדיקת פרובינג חכמה למספרים נפוצים או לסמוך על מה שהשרת מחזיר
                                    subDirs.sort((a, b) => a.name.localeCompare(b.name, undefined, {numeric: true}));
                    
                                    for (const dir of subDirs) {
                                        const dirPath = `${currentPath}/${dir.name}`.replace(/\/+/g, '/');
                                        
                                        let folderTitle = "";
                                        let wavCount = 0;
                                        let totalFilesCount = 0;
                                        let subFoldersCount = 0;
                                        let isMenu = false;
                    
                                        try {
                                            const dirRes = await fetch(`https://www.call2all.co.il/ym/api/GetIVR2Dir?token=${encodeURIComponent(token)}&path=${encodeURIComponent(dirPath)}`);
                                            const dirData = await dirRes.json();
                                            if (dirData.files && Array.isArray(dirData.files)) {
                                                totalFilesCount = dirData.files.filter(f => (f.fileType || '').toUpperCase() === "FILE" || f.name.includes('.')).length;
                                                wavCount = dirData.files.filter(f => f.name.toLowerCase().endsWith('.wav')).length;
                                                subFoldersCount = dirData.files.filter(f => {
                                                    const t = (f.fileType || '').toUpperCase();
                                                    return t === "DIR" || t === "FOLDER" || f.isDir || (!f.name.includes('.') && t !== "FILE");
                                                }).length;
                                            }
                                        } catch(e) {}
                    
                                        // בדיקת שם השלוחה מתוך קובץ ההגדרות ext.ini
                                        try {
                                            const iniRes = await fetch(`https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=ivr2:${dirPath}/ext.ini`);
                                            const iniData = await iniRes.json();
                                            if (iniData && iniData.contents) {
                                                isMenu = true;
                                                const lines = iniData.contents.split('\n');
                                                for (const line of lines) {
                                                    const trimmed = line.trim();
                                                    if (trimmed.toLowerCase().startsWith('title=')) {
                                                        folderTitle = trimmed.substring(6).trim();
                                                        break;
                                                    } else if (trimmed.toLowerCase().startsWith('folder_name=')) {
                                                        folderTitle = trimmed.substring(12).trim();
                                                        break;
                                                    }
                                                }
                                            }
                                        } catch(e) {}
                    
                                        let typeDesc = isMenu ? "תפריט/הגדרות" : "שלוחה רגילה";
                                        if (wavCount > 0) {
                                            typeDesc += ` | ${wavCount} קבצי שמע (מתוך ${totalFilesCount} סה״כ)`;
                                        } else {
                                            typeDesc += ` | ${totalFilesCount} קבצים`;
                                        }
                                        typeDesc += ` | שלוחות ישירות מתחתיו: ${subFoldersCount}`;
                    
                                        const titlePart = folderTitle ? ` - ${folderTitle}` : '';
                                        treeLines.push(`${indent}📁 שלוחה ${dir.name}${titlePart} [${typeDesc}]`);
                                        logMessage(`נסרקה שלוחה לעץ המלא: ${dirPath} (${folderTitle || 'ללא שם'})`, 'info');
                    
                                        // המשך ר커ורסיה לתתי-שלוחות לעומק כל המערכת
                                        await crawlTreeFull(dirPath, indent + '    ');
                                    }
                                }
                    
                                await crawlTreeFull(srcStartPath);
                    
                                lastGeneratedTreeText = treeLines.join('\n');
                                const blob = new Blob([lastGeneratedTreeText], { type: 'text/plain;charset=utf-8' });
                                const url = URL.createObjectURL(blob);
                                const a = document.createElement('a');
                                a.href = url;
                                a.download = `DetailedFolderTree_${srcSys}.txt`;
                                document.body.appendChild(a);
                                a.click();
                                document.body.removeChild(a);
                                URL.revokeObjectURL(url);
                    
                                status.innerText = "✅ עץ השלוחות המלא ונתוני המערכת הופקו והורדו לקובץ TXT!";
                                logMessage("עץ השלוחות המלא הופק בהצלחה.", 'success');
                    
                            } catch (err) {
                                alert(err.message);
                                status.innerText = "הפקת עץ השלוחות נכשלה.";
                            } finally {
                                treeBtn.disabled = false;
                            }
                        }
                    </script>
                    
                    </body>
                    </html>
                    
                    א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                    • א מחובר
                      אA @lavitoren הטי"ל
                      נערך לאחרונה על ידי

                      @lavitoren-הטי-ל
                      יפה מאוד!
                      כדי להשתמש בשמות השלוחות תוכל להגדיר שיבדוק בכל פעם בתוך קובץ ההגדרות בשלוחה את השורה title=שם השלוחה, ולפי זה יכיס את שם השלוחה

                      L 2 תגובות תגובה אחרונה תגובה ציטוט 1
                      • L מנותק
                        lavitoren הטי"ל @אA
                        נערך לאחרונה על ידי

                        @אA אבל נגמר לי הכח גם כי כשרציתי להעתיק את שלוחה 2 במערכת שלי והיה שם 5000+ קבצים הוא כתב לי שנשאר לי עוד 10000000000000 דקות ... חחח

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

                          @אA לא יודע אם עובד אבל תראה את הפוסט מה שהוספתי נקוה שעובד

                          תגובה 1 תגובה אחרונה תגובה ציטוט 1

                          שלום! נראה שהשיחה הזו מעניינת אותך, אבל עדיין אין לך חשבון.

                          נמאס לכם לגלול בין אותם הפוסטים בכל ביקור? כשנרשמים לחשבון, תמיד תחזרו בדיוק למקום שבו הייתם קודם, ותוכלו לבחור לקבל התראות על תגובות חדשות (בין אם במייל, ובין אם בהתראת פוש). תוכלו גם לשמור סימניות ולפרגן ב-upvote לפוסטים כדי להביע הערכה לחברי קהילה אחרים.

                          בעזרת התרומה שלך, הפוסט הזה יכול להיות אפילו טוב יותר 💗

                          הרשמה התחברות
                          • פוסט ראשון
                            פוסט אחרון