File manager - Edit - /home/cipherteam/htdocs/cipherteam.in/admin3/scraper_servers.php
Back
<?php // scraper_servers.php session_start(); /* ---------------- LOGIN CHECK ---------------- */ if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) { // If AJAX request → return JSON if (isset($_GET['action'])) { http_response_code(401); header("Content-Type: application/json; charset=utf-8"); echo json_encode([ "ok" => false, "msg" => "Unauthorized. Please login again." ]); exit; } // Normal page request → redirect header("Location: login.php"); exit; } // -------------------- DB CONNECTION (YOUR CODE) -------------------- $con = mysqli_connect("localhost:3306", "marketdatauser", "d7o7A8%s2d7", "marketdataci"); if (mysqli_connect_errno()) { echo "Connection Fail " . mysqli_connect_error(); exit; } mysqli_set_charset($con, "utf8mb4"); // -------------------- HELPERS -------------------- function json_out($arr, $code = 200) { http_response_code($code); header("Content-Type: application/json; charset=utf-8"); echo json_encode($arr); exit; } function post_str($k) { return isset($_POST[$k]) ? trim($_POST[$k]) : ""; } function require_fields($fields) { foreach ($fields as $f) { if (!isset($_POST[$f]) || trim($_POST[$f]) === "") { json_out(["ok" => false, "msg" => "Missing field: " . $f], 422); } } } // -------------------- AJAX ACTIONS -------------------- if (isset($_GET["action"])) { $action = $_GET["action"]; if ($action === "add") { require_fields(["server_name", "url", "cron_timing", "ipo_name"]); $server_name = post_str("server_name"); $url = post_str("url"); // FULL COMMAND allowed $cron_timing = post_str("cron_timing"); $ipo_name = post_str("ipo_name"); $is_enabled = isset($_POST["is_enabled"]) ? 1 : 0; $stmt = mysqli_prepare($con, "INSERT INTO scraper_servers (server_name, url, cron_timing, ipo_name, is_enabled) VALUES (?,?,?,?,?)"); mysqli_stmt_bind_param($stmt, "ssssi", $server_name, $url, $cron_timing, $ipo_name, $is_enabled); mysqli_stmt_execute($stmt); json_out(["ok" => true, "msg" => "Server added successfully."]); } if ($action === "get") { require_fields(["id"]); $id = (int)$_POST["id"]; $stmt = mysqli_prepare($con, "SELECT * FROM scraper_servers WHERE id=?"); mysqli_stmt_bind_param($stmt, "i", $id); mysqli_stmt_execute($stmt); $res = mysqli_stmt_get_result($stmt); if (!$res || mysqli_num_rows($res) === 0) json_out(["ok" => false, "msg" => "Record not found"], 404); json_out(["ok" => true, "data" => mysqli_fetch_assoc($res)]); } if ($action === "update") { require_fields(["id", "server_name", "url", "cron_timing", "ipo_name"]); $id = (int)$_POST["id"]; $server_name = post_str("server_name"); $url = post_str("url"); $cron_timing = post_str("cron_timing"); $ipo_name = post_str("ipo_name"); $is_enabled = isset($_POST["is_enabled"]) ? 1 : 0; $stmt = mysqli_prepare($con, "UPDATE scraper_servers SET server_name=?, url=?, cron_timing=?, ipo_name=?, is_enabled=? WHERE id=?"); mysqli_stmt_bind_param($stmt, "ssssii", $server_name, $url, $cron_timing, $ipo_name, $is_enabled, $id); mysqli_stmt_execute($stmt); json_out(["ok" => true, "msg" => "Server updated successfully."]); } if ($action === "toggle") { require_fields(["id"]); $id = (int)$_POST["id"]; $stmt = mysqli_prepare($con, "SELECT is_enabled FROM scraper_servers WHERE id=?"); mysqli_stmt_bind_param($stmt, "i", $id); mysqli_stmt_execute($stmt); $res = mysqli_stmt_get_result($stmt); if (!$res || mysqli_num_rows($res) === 0) json_out(["ok" => false, "msg" => "Record not found"], 404); $row = mysqli_fetch_assoc($res); $new = ((int)$row["is_enabled"] === 1) ? 0 : 1; $stmt2 = mysqli_prepare($con, "UPDATE scraper_servers SET is_enabled=? WHERE id=?"); mysqli_stmt_bind_param($stmt2, "ii", $new, $id); mysqli_stmt_execute($stmt2); json_out(["ok" => true, "msg" => "Status updated.", "is_enabled" => $new]); } // ✅ RUN NOW (immediate run via master_runner.php?force_id=ID&token=...) if ($action === "run_now") { require_fields(["id"]); $id = (int)$_POST["id"]; $token = "CHANGE_THIS_SECRET_TOKEN"; // <-- CHANGE THIS $runnerUrl = "https://cipherteam.in/APPS/CronJobs/master_runner.php?force_id=".$id."&token=".$token; $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $runnerUrl, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8, CURLOPT_FOLLOWLOCATION => true, ]); $resp = curl_exec($ch); $err = curl_error($ch); curl_close($ch); if ($resp === false) { json_out(["ok"=>false, "msg"=>"Runner call failed: ".$err], 500); } json_out(["ok"=>true, "msg"=>"Run Now triggered.", "runner_response"=>$resp]); } json_out(["ok" => false, "msg" => "Invalid action"], 400); } // -------------------- PAGE LOAD -------------------- $rows = []; $q = mysqli_query($con, "SELECT * FROM scraper_servers ORDER BY id DESC"); while ($r = mysqli_fetch_assoc($q)) $rows[] = $r; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Scraping Site List</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"> <style> :root { --primary: #4f46e5; --primary-light: #e0e7ff; --primary-dark: #3730a3; --surface: #ffffff; --surface-alt: #f8fafc; --border: #e2e8f0; --text: #1e293b; --text-muted: #64748b; --success: #059669; --success-light: #ecfdf5; --warning: #d97706; --warning-light: #fffbeb; --danger: #dc2626; --danger-light: #fef2f2; --info: #0284c7; --info-light: #f0f9ff; --radius: 12px; --radius-sm: 8px; --shadow-sm: 0 1px 2px rgba(0,0,0,0.05); --shadow: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04); --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.08), 0 2px 4px -2px rgba(0,0,0,0.04); } * { box-sizing: border-box; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; background: #f1f5f9; color: var(--text); min-height: 100vh; margin: 0; padding: 0; } .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; } /* ── Top Bar ── */ .top-bar { background: var(--surface); border-bottom: 1px solid var(--border); padding: 16px 0; position: sticky; top: 0; z-index: 100; box-shadow: var(--shadow-sm); } .top-bar .inner { max-width: 1280px; margin: 0 auto; padding: 0 24px; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; } .brand { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 20px; color: var(--primary); } .brand-icon { width: 36px; height: 36px; background: var(--primary); color: #fff; border-radius: 10px; display: grid; place-items: center; font-size: 18px; flex-shrink: 0; } .top-actions { display: flex; align-items: center; gap: 10px; } .btn-back { background: var(--surface-alt); color: var(--text-muted); border: 1px solid var(--border); padding: 8px 18px; border-radius: var(--radius-sm); font-weight: 500; font-size: 13px; text-decoration: none; transition: all 0.2s; display: inline-flex; align-items: center; gap: 6px; } .btn-back:hover { background: var(--primary-light); color: var(--primary); border-color: var(--primary); } .btn-add { background: var(--primary); color: #fff; border: none; padding: 8px 20px; border-radius: var(--radius-sm); font-weight: 600; font-size: 13px; cursor: pointer; transition: all 0.2s; display: inline-flex; align-items: center; gap: 6px; } .btn-add:hover { background: var(--primary-dark); transform: translateY(-1px); box-shadow: var(--shadow-md); } /* ── Main ── */ .main-wrap { max-width: 1280px; margin: 0 auto; padding: 24px; } /* ── Alert ── */ .alert-modern { border-radius: var(--radius-sm); padding: 14px 20px; font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 8px; margin-bottom: 20px; animation: slideDown 0.3s ease; } .alert-modern.alert-success { background: var(--success-light); color: var(--success); border: 1px solid #a7f3d0; } .alert-modern.alert-danger { background: var(--danger-light); color: var(--danger); border: 1px solid #fecaca; } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } /* ── Stats ── */ .stats-line { font-size: 13px; color: var(--text-muted); font-weight: 500; margin-bottom: 16px; display: flex; align-items: center; gap: 8px; } .stats-line .count { background: var(--primary-light); color: var(--primary); padding: 2px 10px; border-radius: 20px; font-weight: 700; font-size: 12px; } /* ── Table Card ── */ .table-card { background: var(--surface); border-radius: var(--radius); border: 1px solid var(--border); box-shadow: var(--shadow); overflow: hidden; } .table-card table { width: 100%; border-collapse: collapse; margin: 0; } .table-card thead th { background: var(--surface-alt); padding: 14px 16px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); border-bottom: 1px solid var(--border); white-space: nowrap; } .table-card tbody td { padding: 14px 16px; font-size: 14px; border-bottom: 1px solid var(--border); vertical-align: middle; } .table-card tbody tr:last-child td { border-bottom: none; } .table-card tbody tr { transition: background 0.15s; } .table-card tbody tr:hover { background: var(--surface-alt); } .server-name { font-weight: 600; color: var(--text); } .server-id { font-size: 12px; color: var(--text-muted); margin-top: 2px; } .cmd-cell { max-width: 400px; } .cmd-text { font-size: 12px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; } .cron-badge { background: var(--surface-alt); padding: 4px 10px; border-radius: 6px; font-size: 12px; font-weight: 600; color: var(--text-muted); border: 1px solid var(--border); } /* ── Status Badges ── */ .status-badge { display: inline-flex; align-items: center; gap: 5px; padding: 4px 12px; border-radius: 20px; font-size: 11px; font-weight: 700; } .status-enabled { background: var(--success-light); color: var(--success); border: 1px solid #a7f3d0; } .status-paused { background: var(--danger-light); color: var(--danger); border: 1px solid #fecaca; } .status-ok { background: var(--info-light); color: var(--info); border: 1px solid #bae6fd; } .status-fail { background: var(--danger-light); color: var(--danger); border: 1px solid #fecaca; } .last-run { font-size: 12px; color: var(--text-muted); } .last-run-ms { font-size: 11px; color: #94a3b8; } /* ── Action Buttons ── */ .act-btn { width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; border: 1px solid transparent; cursor: pointer; transition: all 0.2s; font-size: 13px; background: transparent; } .act-run { color: var(--success); background: var(--success-light); border-color: #a7f3d0; } .act-run:hover { background: var(--success); color: #fff; border-color: var(--success); } .act-toggle { color: var(--text-muted); background: var(--surface-alt); border-color: var(--border); } .act-toggle:hover { background: var(--warning-light); color: var(--warning); border-color: #fed7aa; } .act-edit { color: var(--primary); background: var(--primary-light); border-color: #c7d2fe; } .act-edit:hover { background: var(--primary); color: #fff; border-color: var(--primary); } /* ── Mobile Cards ── */ .mob-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; transition: all 0.2s; } .mob-card:hover { box-shadow: var(--shadow-md); } .mob-card-body { padding: 18px 20px; } .mob-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; } .mob-server-name { font-weight: 700; font-size: 15px; color: var(--text); } .mob-meta { font-size: 12px; color: var(--text-muted); margin-top: 2px; } .mob-section { margin-top: 16px; } .mob-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin-bottom: 4px; } .mob-value { font-size: 14px; font-weight: 500; color: var(--text); } .cmd-box { background: #0f172a; color: #e2e8f0; border-radius: var(--radius-sm); padding: 12px 14px; font-size: 12px; overflow-wrap: anywhere; white-space: pre-wrap; margin-top: 8px; } .mob-actions { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-top: 18px; } .mob-act-btn { padding: 10px; border-radius: var(--radius-sm); font-size: 13px; font-weight: 600; border: 1px solid transparent; cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center; gap: 6px; } .mob-act-run { background: var(--success-light); color: var(--success); border-color: #a7f3d0; } .mob-act-run:hover { background: var(--success); color: #fff; } .mob-act-toggle { background: var(--surface-alt); color: var(--text-muted); border-color: var(--border); } .mob-act-toggle:hover { background: var(--warning-light); color: var(--warning); } .mob-act-edit { background: var(--primary-light); color: var(--primary); border-color: #c7d2fe; } .mob-act-edit:hover { background: var(--primary); color: #fff; } details summary { font-size: 13px; color: var(--primary); cursor: pointer; font-weight: 500; } details summary:hover { text-decoration: underline; } /* ── Empty State ── */ .empty-state { text-align: center; padding: 60px 20px; color: var(--text-muted); } .empty-icon { font-size: 40px; margin-bottom: 12px; } .empty-text { font-size: 15px; font-weight: 500; } /* ── Modals ── */ .modal-content { border: 1px solid var(--border); border-radius: 16px; box-shadow: var(--shadow-md); } .modal-header { border-bottom: 1px solid var(--border); padding: 20px 24px; } .modal-title { font-weight: 700; font-size: 18px; color: var(--text); } .modal-body { padding: 24px; } .modal-body .form-label { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 6px; } .modal-body .form-control { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px 14px; font-size: 14px; transition: border-color 0.2s, box-shadow 0.2s; } .modal-body .form-control:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-light); outline: none; } .modal-footer { border-top: 1px solid var(--border); padding: 16px 24px; gap: 8px; } .modal-footer .btn-cancel { background: var(--surface-alt); color: var(--text-muted); border: 1px solid var(--border); padding: 9px 20px; border-radius: var(--radius-sm); font-weight: 500; font-size: 13px; cursor: pointer; transition: all 0.2s; } .modal-footer .btn-cancel:hover { background: var(--border); color: var(--text); } .modal-footer .btn-save { background: var(--primary); color: #fff; border: none; padding: 9px 20px; border-radius: var(--radius-sm); font-weight: 600; font-size: 13px; cursor: pointer; transition: all 0.2s; display: inline-flex; align-items: center; gap: 6px; } .modal-footer .btn-save:hover { background: var(--primary-dark); } .form-check-input:checked { background-color: var(--primary); border-color: var(--primary); } /* ── Responsive ── */ .desktop-only { display: none; } .mobile-only { display: block; } @media (min-width: 992px) { .desktop-only { display: block; } .mobile-only { display: none; } } @media (max-width: 768px) { .main-wrap { padding: 16px; } } </style> </head> <body> <!-- Top Bar --> <div class="top-bar"> <div class="inner"> <div class="brand"> <div class="brand-icon">⏱️</div> Allotment Cron </div> <div class="top-actions"> <a href="https://cipherteam.in/admin3/index.php" class="btn-back">← Back to List</a> <button class="btn-add" data-bs-toggle="modal" data-bs-target="#addModal"> <i class="fa-solid fa-plus"></i> Add Server </button> </div> </div> </div> <div class="main-wrap"> <!-- Alert --> <div id="alertBox" class="alert-modern d-none" role="alert"></div> <!-- Stats --> <div class="stats-line"> Managing <span class="count"><?= count($rows) ?></span> scraper server<?= count($rows) !== 1 ? 's' : '' ?> </div> <!-- =================== DESKTOP TABLE =================== --> <div class="desktop-only"> <div class="table-card"> <div class="table-responsive"> <table> <thead> <tr> <th style="padding-left:20px;">Server</th> <th>Command</th> <th>Cron</th> <th>Status</th> <th>IPO</th> <th>Last Run</th> <th style="padding-right:20px; text-align:right;">Actions</th> </tr> </thead> <tbody> <?php if (count($rows) === 0): ?> <tr> <td colspan="7"> <div class="empty-state"> <div class="empty-icon">📭</div> <div class="empty-text">No servers added yet.</div> </div> </td> </tr> <?php else: ?> <?php foreach ($rows as $row): ?> <?php $enabled = ((int)$row["is_enabled"] === 1); $lastStatus = $row["last_status"] ?? ""; $lastRunAt = $row["last_run_at"] ?? ""; $lastMs = isset($row["last_exec_ms"]) ? (int)$row["last_exec_ms"] : null; ?> <tr> <td style="padding-left:20px;"> <div class="server-name"><?= htmlspecialchars($row["server_name"]) ?></div> <div class="server-id">#<?= (int)$row["id"] ?></div> </td> <td class="cmd-cell"> <span class="cmd-text mono" title="<?= htmlspecialchars($row["url"]) ?>"> <?= htmlspecialchars($row["url"]) ?> </span> </td> <td><span class="cron-badge mono"><?= htmlspecialchars($row["cron_timing"]) ?></span></td> <td> <div class="d-flex flex-wrap gap-1"> <?php if ($enabled): ?> <span class="status-badge status-enabled">Enabled</span> <?php else: ?> <span class="status-badge status-paused">Paused</span> <?php endif; ?> <?php if ($lastStatus === "SUCCESS"): ?> <span class="status-badge status-ok">OK</span> <?php elseif ($lastStatus === "FAILED" || $lastStatus === "TIMEOUT" || $lastStatus === "LOCKED"): ?> <span class="status-badge status-fail"><?= htmlspecialchars($lastStatus) ?></span> <?php endif; ?> </div> </td> <td><span style="font-weight:500;"><?= htmlspecialchars($row["ipo_name"]) ?></span></td> <td> <?php if ($lastRunAt): ?> <div class="last-run"><?= htmlspecialchars($lastRunAt) ?></div> <?php if (!is_null($lastMs)): ?> <div class="last-run-ms mono"><?= $lastMs ?> ms</div> <?php endif; ?> <?php else: ?> <span class="last-run">—</span> <?php endif; ?> </td> <td style="padding-right:20px; text-align:right;"> <div class="d-flex justify-content-end gap-6" style="gap:6px;"> <button class="act-btn act-run" title="Run Now" onclick="runNow(<?= (int)$row['id'] ?>)"> <i class="fa-solid fa-bolt"></i> </button> <button class="act-btn act-toggle" title="<?= $enabled ? "Pause" : "Start" ?>" onclick="toggleStatus(<?= (int)$row['id'] ?>)"> <i class="fa-solid <?= $enabled ? "fa-pause" : "fa-play" ?>"></i> </button> <button class="act-btn act-edit" title="Edit" onclick="openEdit(<?= (int)$row['id'] ?>)"> <i class="fa-solid fa-pen"></i> </button> </div> </td> </tr> <?php endforeach; ?> <?php endif; ?> </tbody> </table> </div> </div> </div> <!-- =================== MOBILE CARDS =================== --> <div class="mobile-only"> <?php if (count($rows) === 0): ?> <div class="mob-card"> <div class="mob-card-body"> <div class="empty-state"> <div class="empty-icon">📭</div> <div class="empty-text">No servers added yet.</div> </div> </div> </div> <?php else: ?> <div class="d-flex flex-column gap-3"> <?php foreach ($rows as $row): ?> <?php $enabled = ((int)$row["is_enabled"] === 1); $lastStatus = $row["last_status"] ?? ""; $lastRunAt = $row["last_run_at"] ?? ""; $lastMs = isset($row["last_exec_ms"]) ? (int)$row["last_exec_ms"] : null; ?> <div class="mob-card"> <div class="mob-card-body"> <div class="mob-header"> <div> <div class="mob-server-name"><?= htmlspecialchars($row["server_name"]) ?></div> <div class="mob-meta">#<?= (int)$row["id"] ?> · <span class="mono"><?= htmlspecialchars($row["cron_timing"]) ?></span></div> </div> <div class="d-flex flex-wrap gap-1"> <?php if ($enabled): ?> <span class="status-badge status-enabled">Enabled</span> <?php else: ?> <span class="status-badge status-paused">Paused</span> <?php endif; ?> <?php if ($lastStatus === "SUCCESS"): ?> <span class="status-badge status-ok">OK</span> <?php elseif ($lastStatus === "FAILED" || $lastStatus === "TIMEOUT" || $lastStatus === "LOCKED"): ?> <span class="status-badge status-fail"><?= htmlspecialchars($lastStatus) ?></span> <?php endif; ?> </div> </div> <div class="mob-section"> <div class="mob-label">IPO Name</div> <div class="mob-value"><?= htmlspecialchars($row["ipo_name"]) ?></div> </div> <div class="mob-section"> <div class="mob-label">Command</div> <details> <summary>Tap to view command</summary> <div class="cmd-box mono"><?= htmlspecialchars($row["url"]) ?></div> </details> </div> <div class="mob-section"> <div class="mob-label">Last Run</div> <?php if ($lastRunAt): ?> <div class="mob-value" style="font-size:13px;"> <?= htmlspecialchars($lastRunAt) ?> <?php if (!is_null($lastMs)): ?> <span class="mono last-run-ms" style="margin-left:6px;"><?= $lastMs ?> ms</span> <?php endif; ?> </div> <?php else: ?> <div class="last-run">—</div> <?php endif; ?> </div> <div class="mob-actions"> <button class="mob-act-btn mob-act-run" onclick="runNow(<?= (int)$row['id'] ?>)"> <i class="fa-solid fa-bolt"></i> Run </button> <button class="mob-act-btn mob-act-toggle" onclick="toggleStatus(<?= (int)$row['id'] ?>)"> <i class="fa-solid <?= $enabled ? "fa-pause" : "fa-play" ?>"></i> <?= $enabled ? "Pause" : "Start" ?> </button> <button class="mob-act-btn mob-act-edit" onclick="openEdit(<?= (int)$row['id'] ?>)"> <i class="fa-solid fa-pen"></i> Edit </button> </div> </div> </div> <?php endforeach; ?> </div> <?php endif; ?> </div> </div> <!-- ADD MODAL --> <div class="modal fade" id="addModal" tabindex="-1" aria-hidden="true"> <div class="modal-dialog modal-lg modal-dialog-scrollable"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Add Server</h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <form id="addForm"> <div class="modal-body"> <div class="row g-3"> <div class="col-md-6"> <label class="form-label">Server</label> <input type="text" class="form-control" name="server_name" required> </div> <div class="col-md-6"> <label class="form-label">IPO Name</label> <input type="text" class="form-control" name="ipo_name" required> </div> <div class="col-12"> <label class="form-label">Command</label> <input type="text" class="form-control mono" name="url" required placeholder="/usr/bin/php8.2 /home/.../MintIPONews.php"> </div> <div class="col-md-6"> <label class="form-label">Cron Timing</label> <input type="text" class="form-control mono" name="cron_timing" required placeholder="*/5 * * * *"> </div> <div class="col-md-6 d-flex align-items-end"> <div class="form-check form-switch"> <input class="form-check-input" type="checkbox" id="addEnabled" name="is_enabled" checked> <label class="form-check-label" for="addEnabled">Enabled</label> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn-cancel" data-bs-dismiss="modal">Cancel</button> <button type="submit" class="btn-save"> <i class="fa-solid fa-floppy-disk"></i> Save </button> </div> </form> </div> </div> </div> <!-- EDIT MODAL --> <div class="modal fade" id="editModal" tabindex="-1" aria-hidden="true"> <div class="modal-dialog modal-lg modal-dialog-scrollable"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Edit Server</h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <form id="editForm"> <input type="hidden" name="id" id="editId"> <div class="modal-body"> <div class="row g-3"> <div class="col-md-6"> <label class="form-label">Server</label> <input type="text" class="form-control" name="server_name" id="editServer" required> </div> <div class="col-md-6"> <label class="form-label">IPO Name</label> <input type="text" class="form-control" name="ipo_name" id="editIpo" required> </div> <div class="col-12"> <label class="form-label">Command</label> <input type="text" class="form-control mono" name="url" id="editUrl" required> </div> <div class="col-md-6"> <label class="form-label">Cron Timing</label> <input type="text" class="form-control mono" name="cron_timing" id="editCron" required> </div> <div class="col-md-6 d-flex align-items-end"> <div class="form-check form-switch"> <input class="form-check-input" type="checkbox" id="editEnabled" name="is_enabled"> <label class="form-check-label" for="editEnabled">Enabled</label> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn-cancel" data-bs-dismiss="modal">Cancel</button> <button type="submit" class="btn-save"> <i class="fa-solid fa-floppy-disk"></i> Update </button> </div> </form> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> <script> const alertBox = document.getElementById('alertBox'); function showAlert(type, msg){ alertBox.className = 'alert-modern alert-' + type; alertBox.textContent = msg; alertBox.classList.remove('d-none'); window.scrollTo({top: 0, behavior: 'smooth'}); setTimeout(() => alertBox.classList.add('d-none'), 2500); } async function postAction(action, data) { const formData = new FormData(); Object.keys(data).forEach(k => formData.append(k, data[k])); const res = await fetch('scraper_servers.php?action=' + action, { method:'POST', body: formData }); return await res.json(); } document.getElementById('addForm').addEventListener('submit', async (e) => { e.preventDefault(); const f = e.target; const data = { server_name:f.server_name.value, ipo_name:f.ipo_name.value, url:f.url.value, cron_timing:f.cron_timing.value }; if (f.is_enabled.checked) data.is_enabled = 1; const out = await postAction('add', data); if (out.ok) { showAlert('success', out.msg); bootstrap.Modal.getInstance(addModal).hide(); setTimeout(()=>location.reload(), 350); } else showAlert('danger', out.msg || 'Failed'); }); async function openEdit(id) { const out = await postAction('get', {id}); if (!out.ok) return showAlert('danger', out.msg || 'Failed'); const d = out.data; editId.value = d.id; editServer.value = d.server_name; editIpo.value = d.ipo_name; editUrl.value = d.url; editCron.value = d.cron_timing; editEnabled.checked = (parseInt(d.is_enabled) === 1); new bootstrap.Modal(document.getElementById('editModal')).show(); } document.getElementById('editForm').addEventListener('submit', async (e) => { e.preventDefault(); const f = e.target; const data = { id:f.id.value, server_name:f.server_name.value, ipo_name:f.ipo_name.value, url:f.url.value, cron_timing:f.cron_timing.value }; if (f.is_enabled.checked) data.is_enabled = 1; const out = await postAction('update', data); if (out.ok) { showAlert('success', out.msg); bootstrap.Modal.getInstance(editModal).hide(); setTimeout(()=>location.reload(), 350); } else showAlert('danger', out.msg || 'Failed'); }); async function toggleStatus(id) { const out = await postAction('toggle', {id}); if (out.ok) { showAlert('success', out.msg); setTimeout(()=>location.reload(), 200); } else showAlert('danger', out.msg || 'Failed'); } async function runNow(id) { const out = await postAction('run_now', {id}); if (out.ok) { showAlert('success', out.msg); setTimeout(()=>location.reload(), 600); } else showAlert('danger', out.msg || 'Run Now failed'); } </script> </body> </html>
| ver. 1.4 |
Github
|
.
| PHP 8.2.9 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings