אתר העתקת מערכות מתקדם - העברת רוב סוגי הקבצים
-
@אA
מרשים!
אני חושב שזה אחד הדברים הנחוצים בימות המשיח!
תודה רבה על זה ועל כל פועלך למען הפורום!
-
@אA
אפשר את זה בדף html ??? -
@שואל-שאלה
תודה על המשוב החם! -
בשמחה
הקוד
<!DOCTYPE html> <html lang="he" dir="rtl"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>מערכת העברת מאגר מוזיקה ושלוחות</title> <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; } 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; } .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); } .header { text-align: center; margin-bottom: 35px; } h2 { font-size: 2.2rem; font-weight: 800; margin: 0 0 8px 0; color: #0369a1; letter-spacing: -0.5px; } .subtitle { color: var(--text-secondary); font-size: 1rem; margin: 0; } h3 { color: #0c4a6e; font-size: 1.25rem; margin-top: 0; margin-bottom: 16px; font-weight: 700; display: flex; align-items: center; gap: 8px; } .section { background: #f8fafc; border: 1px solid #e2e8f0; padding: 24px; margin-bottom: 20px; border-radius: 14px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02); } .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: #ffffff; 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; } .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 0%, #b91c1c 100%); box-shadow: 0 6px 16px rgba(239, 68, 68, 0.3); } 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 0%, #1e293b 100%); } button:disabled { background: #cbd5e1 !important; color: #94a3b8 !important; cursor: not-allowed !important; transform: none !important; box-shadow: none !important; } .progress-container { width: 100%; background: #e2e8f0; 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-hover); text-align: center; margin-top: 10px; font-size: 0.95rem; } .info-box { background: #f0f9ff; border: 1px solid #bae6fd; color: #0369a1; padding: 14px 18px; border-radius: 12px; margin-bottom: 25px; font-size: 0.95rem; display: flex; align-items: center; gap: 10px; font-weight: 600; } .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: 6px; display: block; font-weight: 600; } </style> </head> <body onbeforeunload="return 'האם אתה בטוח שברצונך לרענן או לעזוב את הדף? תהליכים פעילים עלולים להיעצר.';"> <div class="container"> <div class="header"> <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="מספר מערכת מקור"> <input type="password" id="srcPassword" placeholder="סיסמת מערכת מקור"> </div> <div style="margin-top: 10px;"> <span class="settings-label">הגדרות סריקת מקור:</span> <div class="input-group"> <input type="text" id="srcStartPath" placeholder="שלוחת התחלה במקור (למשל /1 או /music)" 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> </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> <!-- חלק 2: העברה למערכת יעד --> <div class="section"> <h3>2. העברה למערכת יעד</h3> <div class="input-group"> <input type="text" id="destSystem" placeholder="מספר מערכת יעד"> <input type="password" id="destPassword" placeholder="סיסמת מערכת יעד"> <input type="text" id="destStartPath" placeholder="שלוחת יעד (למשל 2, השאר ריק לשרש)" value=""> </div> <div class="input-group" style="margin-top: 15px;"> <button id="transferBtn" onclick="startTransfer()">🚀 התחל העברה</button> <button id="stopTransferBtn" class="stop-btn" onclick="stopTransferProcess()" disabled>⏹️ עצור העברה</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> <!-- יומן בזמן אמת ומתג הצגה --> <div class="section"> <div style="display: flex; justify-content: space-between; align-items: center;"> <span style="font-weight: 600; color: var(--text-secondary); font-size: 0.95rem;">יומן מעקב מעודכן (Live Log):</span> <button id="toggleLogBtn" class="log-toggle-btn" onclick="toggleLog()">👁️ צפה בלוג</button> </div> <div class="log-box" id="logBox">היומן מוכן...</div> </div> </div> <script> let isScanCancelled = false; let isTransferCancelled = false; let scannedFiles = []; let activeSrcToken = ""; 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 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 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; } 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 getRelativePath(fullPath, startPath) { let cleanFull = fullPath.replace(/\/+/g, '/'); let cleanStart = startPath.replace(/\/+/g, '/'); if (cleanStart !== '/' && cleanFull.startsWith(cleanStart)) { let rel = cleanFull.substring(cleanStart.length); return rel.startsWith('/') ? rel : '/' + rel; } return cleanFull; } function addOrUpdateFile(fileAcc, fileObj) { const existing = fileAcc.find(f => f.fullPath === fileObj.fullPath); if (!existing) { fileAcc.push(fileObj); } } // סריקת עומק רקורסיבית הנכנסת לכל השלוחות והתת-שלוחות async function scanFolderRecursive(token, sPath, rootStartPath, digits, fileAcc, statusElement) { if (isScanCancelled) return; sPath = sPath.replace(/\/+/g, '/'); const maxRange = Math.pow(10, digits) - 1; 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) {} // תחקור אקטיבי לשלוחות מספריות (0 עד maxRange) const subScan = []; for (let i = 0; i <= maxRange; i++) { const n = i.toString(); 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); // מעבר על הפריטים והמשך סריקה רקורסיבית עמוקה 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 || (!isNaN(f.name) && !f.name.includes('.')); if (isDir) { try { const iniPath = `${itemPath}/ext.ini`.replace(/\/+/g, '/'); const iniRes = await fetch(`https://www.call2all.co.il/ym/api/GetTextFile?token=${encodeURIComponent(token)}&what=ivr2:${iniPath}`); const iniData = await iniRes.json(); if (iniData && iniData.contents !== undefined) { addOrUpdateFile(fileAcc, { fullPath: iniPath, relPath: getRelativePath(iniPath, rootStartPath), fileName: 'ext.ini', isIni: true, contents: iniData.contents }); logMessage(`נמצא קובץ הגדרות: ${iniPath}`, 'info'); } } catch(e) {} // כניסה רקורסיבית עמוקה לתוך תת-השלוחה! await scanFolderRecursive(token, itemPath, rootStartPath, digits, fileAcc, statusElement); } else { if (f.name === "ext.ini") continue; logMessage(`נמצא קובץ: ${itemPath}`, 'info'); addOrUpdateFile(fileAcc, { fullPath: itemPath, relPath: getRelativePath(itemPath, rootStartPath), fileName: f.name, isIni: false }); } } } 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; 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'); scanBtn.disabled = true; stopScanBtn.disabled = false; status.innerText = "מתחבר למערכת המקור..."; try { logMessage("--- התחלת סריקת עומק למערכת מקור ---", 'info'); activeSrcToken = await fetchApiToken(srcSys, srcPass); localStorage.setItem('src_token', activeSrcToken); status.innerText = `סורק משלוחת התחלה (${srcStartPath})...`; // הרצת סריקת העומק הרקורסיבית await scanFolderRecursive(activeSrcToken, srcStartPath, srcStartPath, digits, scannedFiles, status); if (isScanCancelled) { status.innerText = "🛑 הסריקה נעצרה על ידי המשתמש."; } else { localStorage.setItem('music_database_files', JSON.stringify(scannedFiles)); status.innerText = `✅ סריקת העומק הושלמה בהצלחה! נמצאו ${scannedFiles.length} קבצים ושלוחות מוכנים להעברה.`; logMessage(`סריקה הושלמה! ${scannedFiles.length} קבצים נשמרו בזיכרון.`, 'success'); } } catch (err) { alert(err.message); status.innerText = "הסריקה הופסקה בשל שגיאה."; } finally { scanBtn.disabled = false; stopScanBtn.disabled = true; } } async function startTransfer() { const destSys = document.getElementById('destSystem').value.trim(); const destPass = document.getElementById('destPassword').value.trim(); let destStartPath = document.getElementById('destStartPath').value.trim(); if (!destSys || !destPass) return alert("נא למלא מספר מערכת יעד וסיסמה."); 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 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 = "מתחבר למערכת היעד..."; try { logMessage("--- התחלת העברה למערכת יעד ---", 'info'); const destToken = await fetchApiToken(destSys, destPass); for (let i = 0; i < scannedFiles.length; i++) { if (isTransferCancelled) { status.innerText = "🛑 ההעברה נעצרה על ידי המשתמש."; break; } const item = scannedFiles[i]; let itemRel = item.relPath || item.fullPath; let targetFullPath = (destStartPath ? `${destStartPath}/${itemRel}` : itemRel).replace(/\/+/g, '/'); status.innerText = `מעביר קובץ (${i + 1}/${scannedFiles.length}): ${targetFullPath}`; logMessage(`מעביר: ${item.fullPath} ➔ ${targetFullPath}`, 'info'); try { let fileBlob; if (item.isIni && item.contents !== undefined) { fileBlob = new Blob([item.contents], { type: 'text/plain;charset=utf-8' }); } else { 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('הורדת קובץ נכשלה'); 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) / scannedFiles.length) * 100); progBar.style.width = percent + '%'; progBar.innerText = percent + '%'; } if (!isTransferCancelled) { status.innerText = '✅ העברת מאגר המוזיקה והשלוחות הושלמה בהצלחה!'; logMessage('ההעברה הושלמה בהצלחה!', 'success'); } } catch (err) { alert(err.message); status.innerText = "ההעברה הופסקה בשל שגיאה."; } finally { transferBtn.disabled = false; stopTransferBtn.disabled = true; } } </script> </body> </html> -
@אA תגיד זה בעצם אומר שאני לוקח את כל ההשמעות משלוחה מסויימת ומעלה אותם חזרה למערכת אחרת שלוחה אחרת או לאותה מערכת?
-
@lavitoren-הטי-ל
אתה יכול למערכת אחרת ואתה יכול גם לאותה המערכת.
תלוי במערכת שאתה מכניס וכן בנתיב -
@אA כי אני רוצה למשל לעשות שלוחה שמשמיעה באופן אקראי מכל ההשמעות במערכת (ומדובר ככל הנראה במאות אלפים בצד יותר של המליון) ולכן אני מחפש קוד שתסרוק את כל המערכת איפה יש השמעות קבצים תשכפל אותם (ולפני תשאל מאיזה שלוחות לא להעתיק) לשלוחה ספציפית שהגדרתי
-
@lavitoren-הטי-ל
יש לי קוד דומה בשירשור של הקבצים.
תחפש שם. -
@אA איך קוראים לה?
-
@lavitoren-הטי-ל
תחפש קבצים ותוכנות בימות המשיח.
או שתיכנס לפרופיל שלי ותראה שם בתוצאות הראשונות -
בשירשור של כל המודולים שלך יש את זה?
כי אם זה לא אתה עשית את השירשור ואולי תפתח שירשור אם כ-ל המודולים שפיתחת
אי פעם כי זכורני שמדובר על מעל עשר ואולי גם שלושים -
@lavitoren-הטי-ל
בינתיים אין לי מודולים שהעלתי לכאן.
אבל ישנם קבצים לניהול המערכת. -
-
@אA יש אולי משהו אחד שב-א-מ-ת מאחד הכל כלומר תוכנה אחת שעושה את העבודה או שאולי אצור כזו שנית ראית מה שיצרתי בימים האחרונים (על אף שעדיין לא גמור לגמרי?)
-
@אA לא מצאתי משהו מתאים
-
@lavitoren-הטי-ל
בהעתקה ממערכת למערכת לא נותן לבחור?!
ובנוגע לתוכנה כוללת, האמת שמאוד רציתי לעשות כזה דבר אבל כהיום אני מתמקד יותר בשרתים ופחות בקבצים כאלו. -
@אA שרתים כלומר? (API וPHP?)
ולגבי התוכנה של סריקת מערכת ומציאת השמעות קבצים ושכפולם לשלוחה ספציפית (שתהא רנדומלית) אמרת שיש משהו כזה אז אמרתי שלא מצאתי -
@lavitoren-הטי-ל
לא אמרתי שזה מה שיש.
ביקשת תוכנה שתיתן לך אפשרות לבחור מתוך מה שמצאה את מה להעתיק ואת זה יש.
אתה יכול לקחת את הקוד שנתתי ולתת לAI לשדרג אותו למה שתרצה.
רוב העבודה כבר עשיתי... -
@אA זה משכפל או מעביר התוכנה הזו כעת התחלתי להשתמש והיא מדהימה לפי איך שנראה כקגע
-
@אA כתוב באופציה התחל העברה (?)
שלום! נראה שהשיחה הזו מעניינת אותך, אבל עדיין אין לך חשבון.
נמאס לכם לגלול בין אותם הפוסטים בכל ביקור? כשנרשמים לחשבון, תמיד תחזרו בדיוק למקום שבו הייתם קודם, ותוכלו לבחור לקבל התראות על תגובות חדשות (בין אם במייל, ובין אם בהתראת פוש). תוכלו גם לשמור סימניות ולפרגן ב-upvote לפוסטים כדי להביע הערכה לחברי קהילה אחרים.
בעזרת התרומה שלך, הפוסט הזה יכול להיות אפילו טוב יותר 💗
הרשמה התחברות