@אA יצרתי קוד PHP לניהול שלוחה ספציפית
כרגע אני מצליח ליצור את ההגבלה רק דרך הקוד לא דרך המפתח לכן הוא לא מתאים לHTML אני ימשיך לנסות לסדר את זה שיעבוד אם מפתח מוגבל בצורה מלאה בינתיים אני מעלה את הקוד אם יהיה לך זמן לבדוק
<?php
// === הגדרות מערכת ===
$token = 'Xh-nVBQis7mP3C58aBaHUOCQfMXxRMj8RQHXZXpbqM'; // החלף בטוקן שלך
$baseUrl = 'https://private.call2all.co.il/ym/api/';
$baseExtension = 'ivr2:/18'; // התחלה מהשלוחה הראשית (Root)
// === טיפול בבקשות הורדה ישירה ===
if (isset($_GET['download'])) {
$path = $_GET['path'];
$url = $baseUrl . "DownloadFile?token=" . $token . "&path=" . urlencode($path);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($path) . '"');
readfile($url);
exit;
}
// === טיפול בבקשות API ===
if (isset($_GET['ajax'])) {
header('Content-Type: application/json');
$action = $_GET['ajax'];
function callApi($endpoint, $postData =[], $isMultipart = false) {
global $baseUrl, $token;
$postData['token'] = $token;
$ch = curl_init($baseUrl . $endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
if ($isMultipart) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
} else {
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
}
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
switch ($action) {
case 'get_dir':
$path = $_POST['path'] ?? $baseExtension;
echo callApi('GetIVR2Dir',['path' => $path]);
break;
case 'delete':
echo callApi('FileAction', ['action' => 'delete', 'what' => $_POST['what']]);
break;
case 'get_text':
echo callApi('GetTextFile',['what' => $_POST['what']]);
break;
case 'save_text':
echo callApi('UploadTextFile',['what' => $_POST['what'], 'contents' => $_POST['contents']]);
break;
case 'upload':
if (isset($_FILES['file'])) {
$cfile = new CURLFile($_FILES['file']['tmp_name'], $_FILES['file']['type'], $_FILES['file']['name']);
echo callApi('UploadFile', ['path' => $_POST['path'], 'file' => $cfile], true);
} else {
echo json_encode(['success' => false, 'message' => 'No file uploaded']);
}
break;
}
exit;
}
?>
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>מערכת תוכן - ימות המשיח</title>
<!-- פונט גוגל ואייקונים -->
<link href="https://fonts.googleapis.com/css2?family=Heebo:wght@300;400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
<style>
:root {
--primary: #2563eb;
--primary-hover: #1d4ed8;
--bg-color: #f8fafc;
--card-bg: #ffffff;
--text-main: #1e293b;
--text-muted: #64748b;
--border: #e2e8f0;
}
body { font-family: 'Heebo', sans-serif; margin: 0; padding: 0; background-color: var(--bg-color); color: var(--text-main); }
/* אזור עליון */
.top-header { background: white; padding: 20px 40px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
.top-header h1 { margin: 0; font-size: 28px; font-weight: 600; }
.actions-bar { display: flex; gap: 15px; }
button { display: flex; align-items: center; gap: 8px; font-family: 'Heebo', sans-serif; font-size: 15px; font-weight: 500; cursor: pointer; border: none; border-radius: 8px; padding: 10px 20px; transition: 0.2s; }
.btn-primary { background: var(--primary); color: white; }
.btn-primary:hover { background: var(--primary-hover); }
.btn-secondary { background: #475569; color: white; }
.btn-secondary:hover { background: #334155; }
.btn-danger { background: #ef4444; color: white; }
.btn-danger:hover { background: #dc2626; }
.btn-warning { background: #f59e0b; color: white; }
.btn-warning:hover { background: #d97706; }
.btn-icon { padding: 8px; font-size: 14px; }
.main-container { max-width: 1400px; margin: 0 auto; padding: 30px; }
/* ניווט / פירורי לחם */
.breadcrumbs { font-size: 16px; color: var(--text-muted); margin-bottom: 20px; display: flex; align-items: center; gap: 10px; }
.breadcrumbs span.clickable { cursor: pointer; transition: 0.2s; font-weight: 600; }
.breadcrumbs span.clickable:hover { color: var(--primary); }
.breadcrumbs .separator { color: #cbd5e1; cursor: default; }
/* כרטיסיות (Tabs) */
.tabs-header { display: flex; gap: 30px; border-bottom: 2px solid var(--border); margin-bottom: 30px; }
.tab-btn { background: none; border: none; color: var(--text-muted); font-size: 18px; font-weight: 600; padding: 10px 5px; cursor: pointer; border-bottom: 3px solid transparent; margin-bottom: -2px; border-radius: 0; }
.tab-btn.active { color: var(--primary); border-bottom-color: var(--primary); }
.tab-content { display: none; }
.tab-content.active { display: block; }
/* גריד תיקיות */
.folders-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; margin-bottom: 40px; }
.folder-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px; padding: 20px; display: flex; align-items: center; gap: 15px; cursor: pointer; transition: box-shadow 0.2s, transform 0.2s; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
.folder-card:hover { box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1); transform: translateY(-2px); border-color: #cbd5e1; }
.folder-icon { color: var(--text-muted); font-size: 40px; }
.folder-details { flex: 1; }
.folder-title { font-size: 20px; font-weight: 700; margin: 0 0 5px 0; }
.folder-subtitle { font-size: 14px; color: var(--text-muted); margin: 0; }
/* טבלאות קבצים */
.files-section { background: white; border-radius: 12px; border: 1px solid var(--border); overflow: hidden; }
.section-title { padding: 15px 20px; background: #f8fafc; border-bottom: 1px solid var(--border); margin: 0; font-size: 16px; color: var(--text-muted); }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 15px 20px; text-align: right; border-bottom: 1px solid var(--border); }
th { color: var(--text-muted); font-weight: 600; font-size: 14px; }
tr:hover { background: #f1f5f9; }
.td-actions { display: flex; gap: 8px; justify-content: flex-end; }
/* עורכי טקסט */
.editor-container { background: white; padding: 20px; border-radius: 12px; border: 1px solid var(--border); }
textarea.code-editor { width: 100%; height: 400px; font-family: monospace; font-size: 16px; direction: ltr; padding: 15px; box-sizing: border-box; border: 1px solid var(--border); border-radius: 8px; background: #1e1e1e; color: #d4d4d4; margin-bottom: 15px; resize: vertical;}
/* Modal לעריכת כל INI */
.modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 1000; justify-content: center; align-items: center; }
.modal-content { background: white; width: 700px; max-width: 90%; border-radius: 12px; padding: 25px; display: flex; flex-direction: column; gap: 15px; box-shadow: 0 10px 25px rgba(0,0,0,0.2); }
.modal-content h3 { margin: 0; font-size: 20px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; }
/* כפתורי העלאה נסתרים */
.hidden-input { display: none; }
</style>
</head>
<body>
<!-- כותרת עליונה -->
<header class="top-header">
<h1>מערכת תוכן</h1>
<div class="actions-bar">
<button class="btn-primary" onclick="document.getElementById('file-upload-new').click()">
<span class="material-symbols-outlined">upload</span> העלה קובץ חדש
</button>
<input type="file" id="file-upload-new" class="hidden-input" onchange="uploadNewFile(this)">
<!-- אינפוט נסתר להחלפת קובץ קיים -->
<input type="file" id="file-replace-input" class="hidden-input" onchange="submitReplaceFile(this)">
</div>
</header>
<div class="main-container">
<!-- ניווט (פירורי לחם) -->
<div class="breadcrumbs" id="breadcrumbs">
<!-- יטען דרך JS -->
</div>
<!-- כרטיסיות ניווט -->
<div class="tabs-header">
<button class="tab-btn active" onclick="switchTab('tab-folders')">תיקיות וקבצים</button>
<button class="tab-btn" onclick="switchTab('tab-messages')">הודעות מערכת</button>
<button class="tab-btn" onclick="switchTab('tab-settings')">הגדרות שלוחה (ext.ini)</button>
</div>
<!-- תוכן 1: תיקיות וקבצים -->
<div id="tab-folders" class="tab-content active">
<div class="folders-grid" id="folders-grid">
<!-- תיקיות יטענו לכאן -->
</div>
<div class="files-section">
<h3 class="section-title">קבצים בשלוחה (כולל קבצי שמע, הגדרות ודוחות)</h3>
<table>
<thead><tr><th>שם קובץ</th><th>סוג</th><th>גודל</th><th>תאריך שינוי</th><th>פעולות</th></tr></thead>
<tbody id="files-list"></tbody>
</table>
</div>
</div>
<!-- תוכן 2: הודעות מערכת -->
<div id="tab-messages" class="tab-content">
<div class="files-section">
<h3 class="section-title">הודעות מערכת מוקלטות (קבצי M)</h3>
<table>
<thead><tr><th>שם קובץ</th><th>תיאור הודעה</th><th>גודל/אורך</th><th>פעולות</th></tr></thead>
<tbody id="messages-list"></tbody>
</table>
</div>
</div>
<!-- תוכן 3: הגדרות שלוחה מהירות -->
<div id="tab-settings" class="tab-content">
<div class="editor-container">
<h3 style="margin-top:0;">עריכת ext.ini (שלוחה נוכחית)</h3>
<p style="color:#64748b; font-size:14px;">כאן תוכל לערוך במהירות את הגדרות התנהגות השלוחה.</p>
<textarea id="ini-editor" class="code-editor" spellcheck="false" placeholder="טוען נתונים..."></textarea>
<div style="text-align: left;">
<button class="btn-primary" onclick="saveExtIniFile(this)">
<span class="material-symbols-outlined">save</span> שמור הגדרות
</button>
</div>
</div>
</div>
</div>
<!-- מודל לעריכת כל קובץ INI/טקסט שאינו ext.ini -->
<div id="file-editor-modal" class="modal-overlay">
<div class="modal-content">
<h3 id="modal-editor-title">עריכת קובץ</h3>
<textarea id="modal-editor-textarea" class="code-editor" spellcheck="false"></textarea>
<div class="modal-actions">
<button class="btn-secondary" onclick="closeEditorModal()">ביטול</button>
<button class="btn-primary" onclick="saveModalFile(this)">
<span class="material-symbols-outlined">save</span> שמור קובץ
</button>
</div>
<input type="hidden" id="modal-editor-path">
</div>
</div>
<script>
const BASE_EXTENSION = '<?php echo $baseExtension; ?>';
let currentPath = BASE_EXTENSION;
let currentReplacePath = '';
document.addEventListener('DOMContentLoaded', () => {
loadDirectory(currentPath);
});
function switchTab(tabId) {
document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
document.querySelectorAll('.tab-btn').forEach(el => el.classList.remove('active'));
document.getElementById(tabId).classList.add('active');
event.currentTarget.classList.add('active');
}
async function loadDirectory(path) {
try {
const formData = new FormData();
formData.append('path', path);
const response = await fetch('?ajax=get_dir', { method: 'POST', body: formData });
const data = await response.json();
if (data.responseStatus === 'ERROR' || data.responseStatus === 'EXCEPTION') {
alert('שגיאה: ' + (data.message || data.exceptionMessage));
return;
}
currentPath = path;
renderBreadcrumbs(path);
renderFolders(data.dirs ||[]);
// איחוד קבצים: שמע, HTML, וגם כל קבצי ה-INI שבשלוחה
renderFiles(data.files ||[], data.html || [], data.ini || []);
renderMessages(data.messages ||[], data.msgDescriptions || {});
loadExtIniEditor(path);
} catch (error) {
console.error('Error:', error);
alert('שגיאת תקשורת');
}
}
// ניווט פירורי לחם (חזרה אחורה) מתוקן
function renderBreadcrumbs(path) {
const container = document.getElementById('breadcrumbs');
container.innerHTML = '';
// כפתור חזרה לראשי (בית)
let rootSpan = document.createElement('span');
rootSpan.className = 'material-symbols-outlined clickable';
rootSpan.style.fontSize = '24px';
rootSpan.innerText = 'home';
rootSpan.onclick = () => loadDirectory(BASE_EXTENSION);
container.appendChild(rootSpan);
// ניקוי הקידומת ivr2: לצורך תצוגה
let cleanPath = path.replace(/^ivr2:/, '');
if (cleanPath === '/' || cleanPath === '') return; // אם אנחנו בראשי, אין צורך להמשיך
let parts = cleanPath.split('/').filter(p => p.trim() !== '');
let buildPath = 'ivr2:';
parts.forEach((part, index) => {
buildPath += (index === 0 ? '' : '/') + part;
let clickPath = buildPath;
let sep = document.createElement('span');
sep.className = 'separator';
sep.innerText = ' / ';
container.appendChild(sep);
let span = document.createElement('span');
span.className = 'clickable';
span.innerText = part;
span.onclick = () => loadDirectory(clickPath);
container.appendChild(span);
});
}
function renderFolders(dirs) {
const grid = document.getElementById('folders-grid');
grid.innerHTML = '';
dirs.forEach(dir => {
const title = dir.extTitle || 'ללא תיאור';
const type = dir.extType || 'תיקייה / תפריט';
grid.innerHTML += `
<div class="folder-card" onclick="loadDirectory('${dir.what}')">
<span class="material-symbols-outlined folder-icon">folder</span>
<div class="folder-details">
<h3 class="folder-title">${dir.name}</h3>
<p class="folder-subtitle">${type} • ${title}</p>
</div>
</div>
`;
});
}
// טבלת קבצים רגילים + INI
function renderFiles(files, htmlFiles, iniFiles) {
const tbody = document.getElementById('files-list');
tbody.innerHTML = '';
let allRegular = [...files, ...htmlFiles, ...iniFiles];
if (allRegular.length === 0) {
tbody.innerHTML = '<tr><td colspan="5" style="text-align:center;">אין קבצים בשלוחה זו</td></tr>';
return;
}
allRegular.forEach(file => {
let sizeInfo = file.size ? (file.size / 1024).toFixed(2) + ' KB' : '-';
let isEditable = file.fileType === 'INI' || file.fileType === 'HTML' || file.name.endsWith('.txt');
let icon = 'description';
if(file.fileType === 'AUDIO' || file.name.endsWith('.wav') || file.name.endsWith('.mp3')) icon = 'audio_file';
if(file.fileType === 'INI') icon = 'settings';
let editBtn = isEditable ?
`<button class="btn-primary btn-icon" onclick="openFileEditorModal('${file.what}', '${file.name}')" title="ערוך קובץ טקסט"><span class="material-symbols-outlined">edit</span></button>` : '';
tbody.innerHTML += `
<tr>
<td><span class="material-symbols-outlined" style="vertical-align: middle; margin-left:5px;">${icon}</span> ${file.name}</td>
<td>${file.fileType || 'FILE'}</td>
<td dir="ltr" style="text-align: right;">${sizeInfo}</td>
<td dir="ltr" style="text-align: right;">${file.mtime || '-'}</td>
<td class="td-actions">
${editBtn}
<button class="btn-warning btn-icon" onclick="triggerReplace('${file.what}')" title="החלף קובץ קיים"><span class="material-symbols-outlined">find_replace</span></button>
<button class="btn-secondary btn-icon" onclick="downloadFile('${file.what}')" title="הורדה"><span class="material-symbols-outlined">download</span></button>
<button class="btn-danger btn-icon" onclick="deleteFile('${file.what}')" title="מחיקה"><span class="material-symbols-outlined">delete</span></button>
</td>
</tr>
`;
});
}
function renderMessages(messages, descriptions) {
const tbody = document.getElementById('messages-list');
tbody.innerHTML = '';
if (messages.length === 0) {
tbody.innerHTML = '<tr><td colspan="4" style="text-align:center;">אין הודעות מערכת (M) בשלוחה זו</td></tr>';
return;
}
messages.forEach(file => {
let desc = descriptions[file.name.replace('.wav','')] || 'ללא תיאור';
let sizeInfo = file.durationStr ? file.durationStr : (file.size ? (file.size / 1024).toFixed(2) + ' KB' : '-');
tbody.innerHTML += `
<tr>
<td style="font-weight:bold; color:var(--primary);">${file.name}</td>
<td>${desc}</td>
<td dir="ltr" style="text-align: right;">${sizeInfo}</td>
<td class="td-actions">
<button class="btn-warning btn-icon" onclick="triggerReplace('${file.what}')" title="החלף קובץ"><span class="material-symbols-outlined">find_replace</span></button>
<button class="btn-secondary btn-icon" onclick="downloadFile('${file.what}')" title="הורדה"><span class="material-symbols-outlined">download</span></button>
<button class="btn-danger btn-icon" onclick="deleteFile('${file.what}')" title="מחיקה"><span class="material-symbols-outlined">delete</span></button>
</td>
</tr>
`;
});
}
// --- מנגנון החלפת קובץ ---
function triggerReplace(targetPath) {
currentReplacePath = targetPath;
document.getElementById('file-replace-input').click();
}
async function submitReplaceFile(inputElement) {
if (inputElement.files.length === 0) return;
const file = inputElement.files[0];
// מציג למשתמש התראת טעינה
alert('הקובץ מועלה כעת, אנא המתן...');
const formData = new FormData();
formData.append('path', currentReplacePath); // שומרים על הנתיב המקורי בדיוק!
formData.append('file', file);
try {
const response = await fetch('?ajax=upload', { method: 'POST', body: formData });
const result = await response.json();
if (result.responseStatus === 'OK' || result.path) {
alert('הקובץ הוחלף בהצלחה!');
loadDirectory(currentPath);
} else {
alert('שגיאה בהחלפה: ' + JSON.stringify(result));
}
} catch (error) {
alert('שגיאת תקשורת בהחלפת הקובץ');
}
inputElement.value = ''; // ניקוי הזיכרון של האינפוט
}
// --- העלאת קובץ חדש רגיל ---
async function uploadNewFile(inputElement) {
if (inputElement.files.length === 0) return;
const file = inputElement.files[0];
// בגלל שזה קובץ חדש, מצרפים את שם הקובץ לנתיב התיקייה הנוכחית
let targetPath = currentPath;
if (targetPath === '/') targetPath = 'ivr2:';
else if (!targetPath.startsWith('ivr2:')) targetPath = 'ivr2:' + targetPath;
targetPath = targetPath + '/' + file.name;
const formData = new FormData();
formData.append('path', targetPath);
formData.append('file', file);
alert('מעלה קובץ חדש, אנא המתן...');
try {
const response = await fetch('?ajax=upload', { method: 'POST', body: formData });
const result = await response.json();
if (result.responseStatus === 'OK' || result.path) {
alert('הקובץ הועלה בהצלחה!');
loadDirectory(currentPath);
} else {
alert('שגיאה: ' + JSON.stringify(result));
}
} catch (error) {
alert('שגיאת תקשורת');
}
inputElement.value = '';
}
function downloadFile(what) { window.location.href = '?download=1&path=' + encodeURIComponent(what); }
async function deleteFile(what) {
if (!confirm('האם למחוק קובץ זה לצמיתות?')) return;
const formData = new FormData();
formData.append('what', what);
await fetch('?ajax=delete', { method: 'POST', body: formData });
loadDirectory(currentPath);
}
// --- מנגנון עריכת קבצי INI (במודל צף) ---
async function openFileEditorModal(what, name) {
document.getElementById('modal-editor-title').innerText = `עורך קובץ: ${name}`;
document.getElementById('modal-editor-path').value = what;
document.getElementById('modal-editor-textarea').value = 'טוען תוכן...';
document.getElementById('file-editor-modal').style.display = 'flex';
const formData = new FormData();
formData.append('what', what);
try {
const response = await fetch('?ajax=get_text', { method: 'POST', body: formData });
const result = await response.json();
document.getElementById('modal-editor-textarea').value = result.contents !== undefined ? result.contents : '';
} catch (e) {
document.getElementById('modal-editor-textarea').value = 'שגיאה בטעינת הקובץ';
}
}
function closeEditorModal() { document.getElementById('file-editor-modal').style.display = 'none'; }
async function saveModalFile(btn) {
const what = document.getElementById('modal-editor-path').value;
const contents = document.getElementById('modal-editor-textarea').value;
btn.innerHTML = '<span class="material-symbols-outlined">hourglass_empty</span> שומר...';
const formData = new FormData();
formData.append('what', what);
formData.append('contents', contents);
try {
const response = await fetch('?ajax=save_text', { method: 'POST', body: formData });
const result = await response.json();
if (result.responseStatus === 'OK') {
alert('הקובץ נשמר!');
closeEditorModal();
loadDirectory(currentPath);
} else {
alert('שגיאה בשמירה');
}
} catch (e) { alert('שגיאת תקשורת'); }
btn.innerHTML = '<span class="material-symbols-outlined">save</span> שמור קובץ';
}
// --- מנגנון עריכת ext.ini המהיר (בכרטיסייה ה-3) ---
async function loadExtIniEditor(path) {
let targetPath = path;
if (targetPath === '/') targetPath = 'ivr2:';
else if (!targetPath.startsWith('ivr2:')) targetPath = 'ivr2:' + targetPath;
const editor = document.getElementById('ini-editor');
editor.value = 'טוען...';
const formData = new FormData();
formData.append('what', targetPath + '/ext.ini');
try {
const response = await fetch('?ajax=get_text', { method: 'POST', body: formData });
const result = await response.json();
editor.value = result.contents !== undefined ? result.contents : '';
} catch (e) { editor.value = ''; }
}
async function saveExtIniFile(btn) {
let targetPath = currentPath;
if (targetPath === '/') targetPath = 'ivr2:';
else if (!targetPath.startsWith('ivr2:')) targetPath = 'ivr2:' + targetPath;
const contents = document.getElementById('ini-editor').value;
btn.innerHTML = '<span class="material-symbols-outlined">hourglass_empty</span> שומר...';
const formData = new FormData();
formData.append('what', targetPath + '/ext.ini');
formData.append('contents', contents);
try {
await fetch('?ajax=save_text', { method: 'POST', body: formData });
alert('הגדרות השלוחה נשמרו בהצלחה!');
loadDirectory(currentPath);
} catch (e) { alert('שגיאת תקשורת'); }
btn.innerHTML = '<span class="material-symbols-outlined">save</span> שמור הגדרות';
}
</script>
</body>
</html>
אולי ההגבלות שעשיתי למפתח לא טובות אני צריך גם לבדוק את זה
{
"tokenNike": "הגבלה לשלוחה 18",
"tokenUser": "pIi0j5kxIJmxCGStG3DNiQ",
"tokenMore": {
"ws_parms_whitelist": [
"wath",
"path",
"what"
],
"ws_parms_mismatch_action": "remove",
"default_acl_policy": "deny",
"acl_rules": [
{
"ip": [],
"name": null,
"active": true,
"params": [
"what=ivr2:/18/**",
"wath=ivr2:/18/**",
"path=ivr/18/**"
],
"policy": "allow",
"endpoint": [],
"set_params": {}
}
]
}
}
Spoiler
ההנחיה שנתתי לגימני היה לנו שיחה ארוכה בסוף הגענו לקוד הזה אם אני מגביל דרך הקוד זה עובד מעולה הבעיה שבHTML כל אחד יכול לשנות
אני צריך קוד PHP משולב HTML לניהול המערכת הטלפונית שלי
אני צריך יכולת להעלות קבצים
להוריד קבצים
להציג את הקבצים הקיימים שאני בוחר שלוחה
מחיקת קבצים
עריכת קבצי EXT
עריכת קבצי INI
החיבור הוא באמצעות מפתח טוקן
אני רוצה להטמיע בקוד מה שלוחה שממנה מתחיל להציג דוגמה משלוחה 8 וכל התיקיות שבתוכה
שאני נכנס מציג לי את עץ התיקיות בצד ימין בחלונית שמה אני יכול לבחור לאיזה תיקייה להיכנס ובצד שמאל אחרי שבחרתי תיקייה מציג את הקבצים שבתוך התיקייה
מצרף תיעוד API של הפעולות הנצרכות
כתובת לשליחת הבקשות
https://private.call2all.co.il/ym/api/
העלאה והורדה
העלאת קובץ
הפקודה היא - UploadFile
מתודת פניה
יש לפנות ב-HTTP POST בפורמט multipart/form-data. (פרמטרים כמו token path וכדומה ניתן לצרף בגוף הפנייה או במחרוזת השאילתה כמו בבקשת GET)
שימו לב! ניתן לעלות קובץ בודד בכל פנייה.
חשוב לשים לב שיש מגבלה על גודל הקובץ שאפשר לעלות בבקשה אחת (נכון לתאריך 28/09/2022 המגבלה היא 50MB) ולכן אם הקובץ שלכם שוקל יותר מזה, צריך לפצל את הקובץ ולהעלות אותו בחלקים נפרדים וכפי שיובא להלן.
הפרמטרים הנדרשים
פרמטר תיאור הערות
token טוקן חובה
path נתיב להעלאה חובה. עבור העלאת קבצים לתיקיות במערכת יש לציין בהתחלה ivr2: ולאחר מכן את הנתיב המלא. למשל לקובץ 000.wav בתיקייה 5 הנתיב יהיה ivr2:5/000.wav. שימו לב שבהעלאה רגילה חובה לציין את שם הקובץ הרצוי, בהעלאה עם מספור אוטומטי (ראה להלן) יש לציין את התיקייה בלבד
convertAudio המרת הקובץ בוליאני (1/0). ברירת המחדל היא ללא המרה. אם convertAudio = 1, הקובץ שהועלה יומר אוטומטית לפורמט wav המתאים לטלפוניה. קובץ המקור יכול להיות בכל אחד מפורמטי האודיו הפופולריים (MP3, OGG, WMA וכו '). הערה: פרמטר הנתיב חייב להיות בשם של קובץ היעד לאחר ההמרה (כך שהוא חייב להיות עם סיומת .wav)
autoNumbering מספור אוטומטי כנ"ל
tts הצהרה על קובץ tts בוליאני (1/0). נצרך במקרה של מספור אוטומטי לקבצי tts כדי שהמערכת לא תתן לקובץ את הסיומת wav אלא tts
פיצול קובץ לחלקים נפרדים והעלאה לשרת
שלב א' - העלאת הקבצים
פרמטר תיאור דוגמה
qquuid ID יש ליצור באופן רנדומלי לפני הבקשה הראשונה 2017390a-60cf-44ea-822f-27017c13de69
qqpartindex אינדקס העלאה 1
qqpartbyteoffset עד כה עלה ללא הבקשה הנוכחית בבתים 4000000
qqchunksize גודל הבקשה הנוכחית בבתים 4000000
qqtotalparts סה"כ חלקים לביצוע (מתחיל ב0 כולל הבקשה האחרונה של החיבור) 8
qqtotalfilesize גודל כולל של הקובץ בבתים 29863882
qqfilename השם המקורי של הקובץ בוקר טוב.mp3
qqfile מקטע של הקובץ שאותו אנחנו מעלים בבקשה הנוכחית (קובץ)
uploader מחלקה שמבצעת את העלאה yemot-admin
שלב ב' - סיום העלאה ובקשת חיבור לקבצים
בסיום העלאה יש לפנות אל - UploadFile?done
הפרמטרים שיש לצרף לבקשה
פרמטר תיאור דוגמה
token טוקן כנ"ל
path נתיב כנ"ל
convertAudio המרת אודיו כנ"ל
autoNumbering מספור אוטומטי כנ"ל
tts קובץ tts כנ"ל
qquuid ID של מזהה הפעולה 2017390a-60cf-44ea-822f-27017c13de69
qqfilename שם מקורי בוקר טוב.mp3
qqtotalfilesize גודל כולל 29863882
qqtotalparts סך הכל חלקים 8
מאפייני תגובת השרת:
מאפיין סוג הסבר
path string נתיב הקובץ שהועלה, כפי שהועבר על ידי פרמטר הנתיב
size long גודל הקובץ שהועלה בבייטים
אם convertAudio = 1, יוחזרו בתגובה מאפיינים נוספים :
מאפיין סוג הסבר
convertedSize long גודל קובץ ה- WAV שהומר בבייטים
duration double משך האודיו בשניות
במקרה של שגיאה בביצוע ההעברה ההודעות והקודים האפשריים הם כדלקמן:
messageCode message הסבר
105 System error שגיאה כללית במהלך הטיפול בהעלאה
107 File upload expected לא נמצאה קובץ להעלאה בבקשה
108 Only single upload per request is supported הועלה יותר מקובץ אחד בבקשה אחת
109 path is required דרוש נתיב
110 path is invalid הנתיב אינו חוקי
על מנת לבדוק העלאות HTTP ניתן להשתמש בטופס פשוט זה:
https://www.call2all.co.il/ym/api_upload_test.php
Eמנותק
eliyahu
ניהול
4 בנוב׳ 2020, 17:33
הורדת קובץ
הפקודה היא - DownloadFile
הפרמטרים הנדרשים:
פרמטר תיאור הערות
token טוקן
path שם הקובץ להורדה בהמשך יפורט איך לציין את הנתיב של כל קובץ
מאפייני תגובת השרת:
במידה והקובץ קיים - התגובה תכיל את את תוכן הקובץ המבוקש.
במידה והקובץ לא קיים או שהתרחשה שגיאה - התגובה תהיה HTTP 404 Not Found.
הערה: שימו לב שהתגובה לבקשה זו אינה JSON (בשונה משאר הבקשות)
הצגת קבצים וניהול הקבצים
הצגת תוכן שלוחה (תיקייה)
הפקודה היא GetIVR2Dir
הפרמטרים הנדרשים
פרמטר תיאור הערות
token טוקן חובה
path נתיב תיקייה חובה. לדוגמה: / עבור שלוחה ראשית. 1 עבור שלוחה 1 ext/1 עבור שלוחה ext/1
filesFrom הצג קבצים מ רשות. 0 יציג מהקובץ הראשון 1 יציג מהקובץ השני וכן הלאה. ברירת מחדל מציג מהקובץ הראשון.
filesLimit הצג קבצים עד רשות. לדוגמה, 5 יציג את הקובץ החמישי (כולל). ברירת מחדל מציג עד הקובץ האחרון
orderBy מיין קבצים לפי ראה להלן "ערכים אפשריים לפרמטר orderBy"
orderDir סדר קבצים asc - סדר עולה. desc - סדר יורד.
ערכים אפשריים לפרמטר orderBy
ערך תיאור
name שם קובץ (ברירת מחדל)
date תאריך יצירה
mtime תאריך שינוי אחרון
customerdid מספר מערכת
uploader מעלה הקובץ
size גודל
source מקור
מאפייני תגובת השרת
מאפיין סוג הסבר
extIni object אובייקט הכולל את הגדרות השלוחה
thisPath string נתיב תיקייה נוכחית
parentPath string נתיב תיקיית אב
dirs Array מערך הכולל את התיקיות והשלוחות שבתיקייה הנוכחית
files Array מערך הכולל את הקבצים שבתיקייה הנוכחית (מלבד קבצי ini ו-html שנמצאים במערך נפרד)
ini Array מערך הכולל את קבצי ההגדרות (ini) שבשלוחה
messages Array מערך הכולל את הודעות המערכת הקשורות לשלוחה
html Array מערך הכולל את קבצי הדוחות (html) שבשלוחה
msgDescriptions object אובייקט הכולל את התיאור של כל הודעות המערכת בשלוחה (למשל M0000=הודעת ברוכים הבאים)
מאפיינים משותפים לאובייקטים במערכים "dirs" "files" "ini" "messages" "html"
מאפיין סוג הסבר
exists boolean האם התיקייה/קובץ קיימים
name string שם התיקייה/קובץ
uniqueId string מזהה ייחודי לתיקייה/קובץ
what string נתיב תיקייה/קובץ
fileType string סוג תיקייה/קובץ
מאפיינים משותפים לאובייקטים במערכים "files" "ini" "messages" "html"
מאפיין סוג הסבר
size int גודל קובץ (בבתים)
mtime string תאריך שינוי אחרון
מאפיינים משותפים לאובייקטים במערכים "files" "messages"
הערה: המאפיינים הבאים הינם עבור קבצי שמע בלבד
מאפיין סוג הסבר
duration אורך (בדקות)
durationStr string אורך בפורמט mm:ss
customerDid string מספר מערכת בה נוצר הקובץ
meta string אובייקט המכיל מידע נוסף על הקובץ
date string זמן יצירת קובץ dd/mm/yyyy hh:mm
source string מקור הקובץ
phone string טלפון יוצר הקובץ
ip string כתובת IP של מעלה הקובץ
מאפייני אובייקטים במערך dirs
הערה: המאפיינים הבאים הינם עבור תיקיות המוגדרות כשלוחה ולא עבור תיקיות רגילות
מאפיין סוג הסבר
extType string סוג שלוחה
extTitle string תיאור שלוחה
Eמנותק
eliyahu
ניהול
4 בנוב׳ 2020, 17:35
קבלת מידע על קובץ בודד
הפקודה היא - GetFile
הפרמטרים הנדרשים
פרמטר תיאור סוג
token טוקן string
what נתיב במערכת string (דוגמה למטה)
דוגמה לנתיב
what=ivr2:2/000.wav /// מידע על קובץ 000 בשלוחה 2
תגובה (במידה והקובץ קיים)
דומה למאפיינים של קובץ כפי שמופיע בGetIVR2Dir
במידה וקובץ לא קיים יחזור שגיאה
{
"responseStatus": "ERROR",
"message": "file does not exist",
"messageCode": null,
"yemotAPIVersion": 6
}
במידה ונתיב לא חוקי יחזור
{
"responseStatus": "EXCEPTION",
"exceptionClass": "IllegalArgumentException",
"exceptionMessage": "bad descriptor format. don't know what is xyz",
"nestedException": null,
"yemotAPIVersion": 6
}
Eמנותק
eliyahu
ניהול
4 בנוב׳ 2020, 17:35
ניהול תיקיות וקבצים
הפקודה היא FileAction
הפרמטרים הנדרשים
פרמטר תיאור הערה
token טוקן
action סוג הפעולה לביצוע ראה להלן
what נתיב ראה להלן
target יעד ראה להלן
בפרמטר action האפשרויות הקיימות הן:
copy - העתקה
move - העברה (לשינוי שם של שלוחה או קובץ יש להשתמש בהעברה)
delete - מחיקה
בפרמטר what האפשרויות הקיימות הן:
ניהול קובץ בודד או שלוחה בודדת.
ניהול קבצים מרובים כאשר בפרמטר what יש לציין כל קובץ או שלוחה בנפרד. לדוגמה:
ניהול קובץ בתבנית קמפיין. ראה כאן
u
r
l
F
i
l
e
A
c
t
i
o
n
?
t
o
k
e
n
=
urlFileAction?token=
{token}&action=${action}&what0=ivr2:1&what1=ivr2:2/ext.ini
בדוגמה: ניהול שלוחה 1 וניהול קובץ ext.ini שבשלוחה 2.
בפעולה מסוג העברה או העתקה חובה לציין פרמטר target. האפשרויות הקיימות הן:
בניהול קבצים מרובים או שלוחות מרובות יש לציין את נתיב היעד הרצוי. לדוגמה, במידה והיעד הוא שלוחה 1 יש לציין את הנתיב כך target=ivr2:1.
הערה: שימו לב! השם המקורי נשמר. במידה ומדובר בהעברת או העתקת קבצים עם שם בעל מספר סידורי שמות הקבצים ישתנו בהתאם לשמות הקבצים בשלוחת היעד. (לדוגמה, אם בוצעה העתקה של קובץ 001 משלוחה 2 לשלוחה 1 ששם קיים קובץ בשם 050 אז השם של הקובץ שהועתק ישתנה ל-051).
בניהול קובץ בודד או שלוחה בודדת ניתן גם לציין נתיב מלא כולל השם הרצוי ביעד.
מאפייני תגובת השרת:
מאפיין סוג הסבר הערה
reports array מערך אובייקטים ראה להלן
success boolean האם הפעולה בוצעה במידה וכן, יופיע הערך true. במידה ולא, יופיע הערך false
action סוג הפעולה שבוצעה
תבנית אובייקט
מאפיין ערך
what נתיב מקור
target נתיב יעד
success האם בוצע (זהה לתיאור לעיל)
Eמנותק
eliyahu
ניהול
4 בנוב׳ 2020, 17:36
קבלת תוכן קובץ טקסט
הפקודה היא - GetTextFile
הפרמטרים הנדרשים:
פרמטר תיאור הערות
token טוקן
what נתיב מלא כולל שם הקובץ והסיומת לדוגמה ivr2:1/ext.ini
מאפייני תגובת השרת:
מאפיין סוג ערך
contents string התוכן הכתוב בקובץ
file array מערך אובייקטים (ראה להלן)
תבנית אובייקט:
מאפיין סוג ערך
exists boolean האם הפעולה בוצעה (במידה וכן, יופיע הערך true. במידה ולא, יופיע הערך false)
name string שם הקובץ
uniqueId string מזהה תנועה ייחודי
fileType string סוג קובץ (למשל: INI)
size int גודל קובץ
mtime string תאריך ושעה שהקובץ השתנה (פורמט: dd/MM/yyyy HH:mm)
what string נתיב מלא
Eמנותק
eliyahu
ניהול
4 בנוב׳ 2020, 17:36
העלאת טקסט לקובץ
הערה: במידה והקובץ לא קיים בשלוחה, ייווצר קובץ חדש.
הפקודה היא - UploadTextFile
הפרמטרים הנדרשים:
פרמטר תיאור הערות
token טוקן
what שם הקובץ והסיומת יש לציין את הנתיב המלא. לדוגמה ivr2:1/ext.ini
contents תוכן הקובץ להעלאה במידה וקיים כבר טקסט בקובץ הוא יימחק
אין מאפיינים מיוחדים בתגובת השרת
Eמנותק
eliyahu
ניהול
4 בנוב׳ 2020, 17:49
עדכון הגדרות שלוחה
שימו לב! בשונה מהפקודה UploadTextFile כאן המערכת לא מוחקת את הקיים בקובץ ext.ini והדבר היחיד שמשתנה הוא מה שאתם שולחים לשרת
הפקודה היא - UpdateExtension
הפרמטרים הנדרשים:
פרמטר תיאור / הערות
token טוקן
path נתיב
בפרמטרים הנוספים תוכלו לצרף ערכים לעדכון בקובץ ext.ini
לדוגמה:
u
r
l
U
p
d
a
t
e
E
x
t
e
n
s
i
o
n
?
t
o
k
e
n
=
urlUpdateExtension?token=
{token}&path=ivr2:1&type=menu&title=בדיקה&enter_id=yes
בדוגמה, עדכון הגדרות לשלוחה 1, סוג השלוחה - תפריט, כינוי השלוחה - בדיקה, תתבצע כניסה לפי מספר אישי.
אין מאפיינים מיוחדים בתגובת השרת
הערה: במידה והשלוחה לא קיימת במערכת, תיווצר שלוחה חדשה.
קבלת מידע כללי על תיקיה (שלוחה)
הפקודה היא GetIVR2DirStats
הפרמטרים הנדרשים
פרמטר תיאור הערות
token טוקן חובה
path נתיב תיקייה חובה. לדוגמה: / עבור שלוחה ראשית. 1 עבור שלוחה 1 ext/1 עבור שלוחה ext/1
מאפייני תגובת השרת
מאפיין סוג הסבר
type string סוג השלוחה
thisPath string נתיב תיקייה נוכחית
parentPath string נתיב תיקיית אב
dirsCount int כמות תיקיות בשלוחה
filesCount int כמות קבצים בשלוחה
contentFilesCount int כמות קבצי שמע בשלוחה
minFile object מידע על קובץ השמע הנמוך בשלוחה
maxFile object מידע על קובץ השמע הגבוה בשלוחה
מאפייני קובץ שמגיעים באובייקטים minFile/maxFile
מאפיין סוג הסבר
exists boolean האם התיקייה/קובץ קיימים
name string שם התיקייה/קובץ
uniqueId string מזהה ייחודי לתיקייה/קובץ
what string נתיב תיקייה/קובץ
fileType string סוג תיקייה/קובץ
size int גודל קובץ (בבתים)
mtime string תאריך שינוי אחרון
duration אורך (בדקות)
durationStr string אורך בפורמט mm:ss
customerDid string מספר מערכת בה נוצר הקובץ
meta string אובייקט המכיל מיגע נוסף על הקובץ
date string זמן יצירת קובץ dd/mm/yyyy hh:mm
source string מקור הקובץ
phone string טלפון יוצר הקובץ
ip string כתובת IP של מעלה הקובץ
אם חסר מידע בתיעוד תכתוב לי אני ישלים