|
3 | 3 | require_once __DIR__ . '/../function.php'; |
4 | 4 | require_once __DIR__ . '/../botapi.php'; |
5 | 5 |
|
6 | | -function addPathToZip(ZipArchive $zip, $path, $basePath) |
7 | | -{ |
8 | | - $normalizedBase = rtrim($basePath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; |
9 | | - |
10 | | - if (is_dir($path)) { |
11 | | - $files = new RecursiveIteratorIterator( |
12 | | - new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), |
13 | | - RecursiveIteratorIterator::SELF_FIRST |
14 | | - ); |
15 | | - |
16 | | - foreach ($files as $file) { |
17 | | - $filePath = (string) $file; |
18 | | - $relativePath = ltrim(str_replace($normalizedBase, '', $filePath), DIRECTORY_SEPARATOR); |
19 | | - |
20 | | - if ($file->isDir()) { |
21 | | - $zip->addEmptyDir($relativePath); |
22 | | - } elseif ($file->isFile()) { |
23 | | - $zip->addFile($filePath, $relativePath); |
| 6 | +function manualDbBackup($host, $user, $pass, $dbname, $filename) { |
| 7 | + $mysqli = new mysqli($host, $user, $pass, $dbname); |
| 8 | + if ($mysqli->connect_error) { |
| 9 | + throw new Exception("اتصال به دیتابیس شکست خورد: " . $mysqli->connect_error); |
| 10 | + } |
| 11 | + $mysqli->set_charset("utf8mb4"); |
| 12 | + |
| 13 | + $tables = []; |
| 14 | + $result = $mysqli->query("SHOW TABLES"); |
| 15 | + while ($row = $result->fetch_row()) { |
| 16 | + $tables[] = $row[0]; |
| 17 | + } |
| 18 | + |
| 19 | + $sql = "SET SQL_MODE = \"NO_AUTO_VALUE_ON_ZERO\";\n"; |
| 20 | + $sql .= "START TRANSACTION;\n"; |
| 21 | + $sql .= "SET time_zone = \"+00:00\";\n\n"; |
| 22 | + |
| 23 | + foreach ($tables as $table) { |
| 24 | + $sql .= "DROP TABLE IF EXISTS `$table`;\n"; |
| 25 | + $create = $mysqli->query("SHOW CREATE TABLE `$table`"); |
| 26 | + $createRow = $create->fetch_row(); |
| 27 | + $sql .= $createRow[1] . ";\n\n"; |
| 28 | + |
| 29 | + $data = $mysqli->query("SELECT * FROM `$table`"); |
| 30 | + $numFields = $data->field_count; |
| 31 | + |
| 32 | + for ($i = 0; $i < $data->num_rows; $i++) { |
| 33 | + $row = $data->fetch_row(); |
| 34 | + $sql .= "INSERT INTO `$table` VALUES("; |
| 35 | + for ($j = 0; $j < $numFields; $j++) { |
| 36 | + $row[$j] = isset($row[$j]) ? addslashes($row[$j]) : 'NULL'; |
| 37 | + $row[$j] = str_replace("\n", "\\n", $row[$j]); |
| 38 | + if (!isset($row[$j]) || $row[$j] == 'NULL') { |
| 39 | + $sql .= "NULL"; |
| 40 | + } else { |
| 41 | + $sql .= "'" . $row[$j] . "'"; |
| 42 | + } |
| 43 | + if ($j < ($numFields - 1)) { |
| 44 | + $sql .= ','; |
| 45 | + } |
24 | 46 | } |
| 47 | + $sql .= ");\n"; |
| 48 | + } |
| 49 | + $sql .= "\n\n"; |
| 50 | + } |
| 51 | + |
| 52 | + $sql .= "COMMIT;\n"; |
| 53 | + |
| 54 | + if (file_put_contents($filename, $sql) === false) { |
| 55 | + throw new Exception("خطا در ذخیره فایل بکاپ: $filename"); |
| 56 | + } |
| 57 | + |
| 58 | + $mysqli->close(); |
| 59 | + return true; |
| 60 | +} |
| 61 | + |
| 62 | +function createAndSendZip($filePath, $caption, $chatId, $threadId) { |
| 63 | + if (!file_exists($filePath)) return false; |
| 64 | + |
| 65 | + $zipPath = $filePath . '.zip'; |
| 66 | + |
| 67 | + if (class_exists('ZipArchive')) { |
| 68 | + $zip = new ZipArchive(); |
| 69 | + if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) { |
| 70 | + $zip->addFile($filePath, basename($filePath)); |
| 71 | + $zip->close(); |
| 72 | + $sendFile = $zipPath; |
| 73 | + } else { |
| 74 | + $sendFile = $filePath; |
25 | 75 | } |
26 | | - } elseif (is_file($path)) { |
27 | | - $relativePath = ltrim(str_replace($normalizedBase, '', $path), DIRECTORY_SEPARATOR); |
28 | | - $zip->addFile($path, $relativePath); |
| 76 | + } else { |
| 77 | + $sendFile = $filePath; |
| 78 | + } |
| 79 | + |
| 80 | + try { |
| 81 | + telegram('sendDocument', [ |
| 82 | + 'chat_id' => $chatId, |
| 83 | + 'message_thread_id' => $threadId, |
| 84 | + 'document' => new CURLFile(realpath($sendFile)), |
| 85 | + 'caption' => $caption, |
| 86 | + ]); |
| 87 | + |
| 88 | + if (file_exists($sendFile)) unlink($sendFile); |
| 89 | + if (file_exists($filePath)) unlink($filePath); |
| 90 | + } catch (Exception $e) { |
| 91 | + error_log("خطا در ارسال فایل: " . $e->getMessage()); |
| 92 | + return false; |
29 | 93 | } |
| 94 | + |
| 95 | + return true; |
30 | 96 | } |
31 | 97 |
|
32 | | -$reportbackup = select("topicid","idreport","report","backupfile","select")['idreport']; |
| 98 | + |
| 99 | +$reportbackup = select("topicid", "idreport", "report", "backupfile", "select")['idreport']; |
33 | 100 | $destination = getcwd(); |
34 | 101 | $setting = select("setting", "*"); |
35 | 102 | $sourcefir = dirname($destination); |
36 | | -$botlist = select("botsaz","*",null,null,"fetchAll"); |
| 103 | +$botlist = select("botsaz", "*", null, null, "fetchAll"); |
| 104 | + |
| 105 | + |
37 | 106 | if ($botlist) { |
38 | 107 | foreach ($botlist as $bot) { |
39 | 108 | $folderName = $bot['id_user'] . $bot['username']; |
40 | 109 | $botBasePath = $sourcefir . '/vpnbot/' . $folderName; |
41 | 110 | $zipFilePath = $destination . '/file_' . $folderName . '.zip'; |
42 | | - $zip = new ZipArchive(); |
43 | 111 |
|
44 | | - if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) { |
45 | | - $pathsToBackup = [ |
46 | | - $botBasePath . '/data', |
47 | | - $botBasePath . '/product.json', |
48 | | - $botBasePath . '/product_name.json', |
49 | | - ]; |
| 112 | + if (!is_dir($botBasePath)) continue; |
50 | 113 |
|
51 | | - foreach ($pathsToBackup as $path) { |
52 | | - if (file_exists($path)) { |
53 | | - addPathToZip($zip, $path, $botBasePath . '/'); |
54 | | - } else { |
55 | | - error_log('Backup path not found for bot archive: ' . $path); |
56 | | - } |
| 114 | + $filesToZip = []; |
| 115 | + foreach (['data', 'product.json', 'product_name.json'] as $item) { |
| 116 | + $fullPath = $botBasePath . '/' . $item; |
| 117 | + if (file_exists($fullPath)) { |
| 118 | + $filesToZip[] = $fullPath; |
57 | 119 | } |
58 | | - $zip->close(); |
| 120 | + } |
59 | 121 |
|
60 | | - telegram('sendDocument', [ |
61 | | - 'chat_id' => $setting['Channel_Report'], |
62 | | - 'message_thread_id' => $reportbackup, |
63 | | - 'document' => new CURLFile($zipFilePath), |
64 | | - 'caption' => "@{$bot['username']} | {$bot['id_user']}", |
65 | | - ]); |
| 122 | + if (empty($filesToZip)) continue; |
| 123 | + |
| 124 | + if (class_exists('ZipArchive')) { |
| 125 | + $zip = new ZipArchive(); |
| 126 | + if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) { |
| 127 | + foreach ($filesToZip as $path) { |
| 128 | + if (is_dir($path)) { |
| 129 | + $iterator = new RecursiveIteratorIterator( |
| 130 | + new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), |
| 131 | + RecursiveIteratorIterator::SELF_FIRST |
| 132 | + ); |
| 133 | + foreach ($iterator as $file) { |
| 134 | + $relative = str_replace($botBasePath . DIRECTORY_SEPARATOR, '', $file); |
| 135 | + if ($file->isDir()) { |
| 136 | + $zip->addEmptyDir($relative); |
| 137 | + } else { |
| 138 | + $zip->addFile($file, $relative); |
| 139 | + } |
| 140 | + } |
| 141 | + } else { |
| 142 | + $relative = basename($path); |
| 143 | + $zip->addFile($path, $relative); |
| 144 | + } |
| 145 | + } |
| 146 | + $zip->close(); |
| 147 | + |
| 148 | + telegram('sendDocument', [ |
| 149 | + 'chat_id' => $setting['Channel_Report'], |
| 150 | + 'message_thread_id' => $reportbackup, |
| 151 | + 'document' => new CURLFile(realpath($zipFilePath)), |
| 152 | + 'caption' => "@{$bot['username']} | {$bot['id_user']}", |
| 153 | + ]); |
66 | 154 |
|
67 | | - if (file_exists($zipFilePath)) { |
68 | | - unlink($zipFilePath); |
| 155 | + if (file_exists($zipFilePath)) unlink($zipFilePath); |
69 | 156 | } |
70 | 157 | } else { |
71 | | - error_log('Unable to create zip archive for bot directory: ' . $botBasePath); |
| 158 | + telegram('sendMessage', [ |
| 159 | + 'chat_id' => $setting['Channel_Report'], |
| 160 | + 'message_thread_id' => $reportbackup, |
| 161 | + 'text' => "⚠️ نمیتوان بکاپ ربات @{$bot['username']} را فشردهسازی کرد (ZipArchive غیرفعال است).", |
| 162 | + ]); |
72 | 163 | } |
73 | 164 | } |
74 | 165 | } |
75 | 166 |
|
76 | 167 |
|
| 168 | +$backup_file_name = 'backup_' . date("Y-m-d") . '.sql'; |
| 169 | +$success = false; |
77 | 170 |
|
| 171 | +$db_host = 'localhost'; |
78 | 172 |
|
79 | | -$backup_file_name = 'backup_' . date("Y-m-d") . '.sql'; |
80 | | -$zip_file_name = 'backup_' . date("Y-m-d") . '.zip'; |
81 | | - |
82 | | -$command = "mysqldump -h localhost -u $usernamedb -p'$passworddb' --no-tablespaces $dbname > $backup_file_name"; |
83 | | - |
84 | | -$output = []; |
85 | | -$return_var = 0; |
86 | | -exec($command, $output, $return_var); |
87 | | -if ($return_var !== 0) { |
88 | | - telegram('sendmessage', [ |
89 | | - 'chat_id' => $setting['Channel_Report'], |
90 | | - 'message_thread_id' => $reportbackup, |
91 | | - 'text' => "❌❌❌❌❌❌خطا در بکاپ گرفتن لطفا به پشتیبانی اطلاع دهید", |
92 | | - ]); |
93 | | -} else { |
94 | | -$zip = new ZipArchive(); |
95 | | -if ($zip->open($zip_file_name, ZipArchive::CREATE) === TRUE) { |
96 | | - $zip->addFile($backup_file_name, basename($backup_file_name)); |
97 | | - $zip->close(); |
98 | | - |
99 | | - telegram('sendDocument', [ |
100 | | - 'chat_id' => $setting['Channel_Report'], |
101 | | - 'message_thread_id' => $reportbackup, |
102 | | - 'document' => new CURLFile($zip_file_name), |
103 | | - 'caption' => "📌 خروجی دیتابیس ربات اصلی", |
104 | | - ]); |
105 | | - unlink($zip_file_name); |
106 | | - unlink($backup_file_name); |
| 173 | + |
| 174 | +if (function_exists('exec') && !ini_get('safe_mode')) { |
| 175 | + $command = "mysqldump -h " . escapeshellarg($db_host) . |
| 176 | + " -u " . escapeshellarg($usernamedb) . |
| 177 | + " -p" . escapeshellarg($passworddb) . |
| 178 | + " --no-tablespaces " . escapeshellarg($dbname) . |
| 179 | + " > " . escapeshellarg($backup_file_name); |
| 180 | + |
| 181 | + $output = []; |
| 182 | + $return_var = 0; |
| 183 | + @exec($command, $output, $return_var); |
| 184 | + if ($return_var === 0 && file_exists($backup_file_name)) { |
| 185 | + $success = true; |
| 186 | + } |
| 187 | +} |
| 188 | + |
| 189 | +if (!$success) { |
| 190 | + try { |
| 191 | + manualDbBackup($db_host, $usernamedb, $passworddb, $dbname, $backup_file_name); |
| 192 | + $success = true; |
| 193 | + } catch (Exception $e) { |
| 194 | + error_log("خطا در بکاپ دستی: " . $e->getMessage()); |
| 195 | + telegram('sendMessage', [ |
| 196 | + 'chat_id' => $setting['Channel_Report'], |
| 197 | + 'message_thread_id' => $reportbackup, |
| 198 | + 'text' => "❌❌❌❌❌❌\nخطا در بکاپ دیتابیس:\n" . $e->getMessage(), |
| 199 | + ]); |
| 200 | + $success = false; |
| 201 | + } |
107 | 202 | } |
| 203 | + |
| 204 | +if ($success) { |
| 205 | + createAndSendZip( |
| 206 | + $backup_file_name, |
| 207 | + "📌 خروجی دیتابیس ربات اصلی", |
| 208 | + $setting['Channel_Report'], |
| 209 | + $reportbackup |
| 210 | + ); |
108 | 211 | } |
0 commit comments