Showing
3 changed files
with
121 additions
and
1 deletions
docker-compose.prod.yml
0 → 100644
| 1 | +services: | |
| 2 | + relay: | |
| 3 | + image: moltbot-relay:latest | |
| 4 | + container_name: moltbot-relay | |
| 5 | + ports: | |
| 6 | + - "8888:8888" | |
| 7 | + - "8889:8889" | |
| 8 | + env_file: | |
| 9 | + - .env | |
| 10 | + environment: | |
| 11 | + - REDIS_HOST=redis | |
| 12 | + - REDIS_PORT=6379 | |
| 13 | + | |
| 14 | + redis: | |
| 15 | + image: redis:alpine | |
| 16 | + container_name: moltbot-redis | |
| 17 | + ports: | |
| 18 | + - "6379:6379" | ... | ... |
| 1 | 1 | <?php |
| 2 | 2 | use Workerman\Worker; |
| 3 | 3 | use Workerman\Timer; |
| 4 | +use Tos\TosClient; | |
| 5 | +use Tos\Exception\TosClientException; | |
| 6 | +use Tos\Exception\TosServerException; | |
| 7 | +use Tos\Model\PutObjectInput; | |
| 4 | 8 | |
| 5 | 9 | require_once __DIR__ . '/vendor/autoload.php'; |
| 6 | 10 | |
| ... | ... | @@ -146,4 +150,101 @@ $ws_worker->onClose = function ($connection) use (&$clients, &$devices) { |
| 146 | 150 | } |
| 147 | 151 | }; |
| 148 | 152 | |
| 153 | +// --------------------------------------------------------- | |
| 154 | +// [New] HTTP Server for file uploads and static serving | |
| 155 | +// --------------------------------------------------------- | |
| 156 | +$http_worker = new Worker("http://0.0.0.0:8889"); | |
| 157 | +$http_worker->count = 1; // Single process for uploads | |
| 158 | +$http_worker->onMessage = function ($connection, $request) { | |
| 159 | + // 1. Static File Serving (Simple implementation) | |
| 160 | + $path = $request->path(); | |
| 161 | + if (strpos($path, '/uploads/') === 0) { | |
| 162 | + $file = __DIR__ . $path; | |
| 163 | + if (is_file($file)) { | |
| 164 | + $connection->send(new \Workerman\Protocols\Http\Response( | |
| 165 | + 200, | |
| 166 | + ['Content-Type' => mime_content_type($file)], | |
| 167 | + file_get_contents($file) | |
| 168 | + )); | |
| 169 | + return; | |
| 170 | + } | |
| 171 | + } | |
| 172 | + | |
| 173 | + // 2. Upload Handler | |
| 174 | + if ($path === '/upload') { | |
| 175 | + $files = $request->file(); | |
| 176 | + | |
| 177 | + if (empty($files['file'])) { | |
| 178 | + $connection->send(new \Workerman\Protocols\Http\Response(400, [], json_encode(['ok' => false, 'error' => 'No file']))); | |
| 179 | + return; | |
| 180 | + } | |
| 181 | + | |
| 182 | + $file = $files['file']; | |
| 183 | + | |
| 184 | + // Validate Size (50MB) | |
| 185 | + if ($file['size'] > 50 * 1024 * 1024) { | |
| 186 | + $connection->send(new \Workerman\Protocols\Http\Response(400, [], json_encode(['ok' => false, 'error' => 'File too large (Max 50MB)']))); | |
| 187 | + return; | |
| 188 | + } | |
| 189 | + | |
| 190 | + // Validate Extension | |
| 191 | + $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); | |
| 192 | + // Supported: PDF, Excel, Image, Video | |
| 193 | + $allowed = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'mp4', 'pdf', 'xls', 'xlsx']; | |
| 194 | + if (!in_array($ext, $allowed)) { | |
| 195 | + $connection->send(new \Workerman\Protocols\Http\Response(400, [], json_encode(['ok' => false, 'error' => 'File type not allowed']))); | |
| 196 | + return; | |
| 197 | + } | |
| 198 | + | |
| 199 | + // TOS Configuration (Keys from hsobs.php) | |
| 200 | + $ak = 'AKLTZjkyMzliYjQ5N2IyNDFjNDliMTBiY2E2ZmU5ODhjNTM'; | |
| 201 | + $sk = 'WldKbE5XUmpPRGxqWmpZM05EUTBObUpqTTJSa01qVTNNMkprWmpsbU9Uaw=='; | |
| 202 | + $endpoint = 'tos-cn-shanghai.volces.com'; | |
| 203 | + $region = 'cn-shanghai'; | |
| 204 | + $bucket = 'ocxun'; | |
| 205 | + | |
| 206 | + try { | |
| 207 | + $client = new TosClient([ | |
| 208 | + 'region' => $region, | |
| 209 | + 'endpoint' => $endpoint, | |
| 210 | + 'ak' => $ak, | |
| 211 | + 'sk' => $sk, | |
| 212 | + ]); | |
| 213 | + | |
| 214 | + // Generate Key | |
| 215 | + $uuid = bin2hex(random_bytes(8)); | |
| 216 | + // TODO: 暂时使用 'guest',等待后续对接用户手机号功能 | |
| 217 | + $userPhone = 'guest'; | |
| 218 | + $objectKey = "clawdbot/{$userPhone}/{$uuid}.{$ext}"; | |
| 219 | + | |
| 220 | + // Read file content | |
| 221 | + $contentFn = fopen($file['tmp_name'], 'r'); | |
| 222 | + | |
| 223 | + // Upload using Object Input | |
| 224 | + $input = new PutObjectInput($bucket, $objectKey, $contentFn); | |
| 225 | + $input->setACL('public-read'); | |
| 226 | + | |
| 227 | + $client->putObject($input); | |
| 228 | + | |
| 229 | + if (is_resource($contentFn)) { | |
| 230 | + fclose($contentFn); | |
| 231 | + } | |
| 232 | + | |
| 233 | + // Generate URL | |
| 234 | + $url = "https://{$bucket}.{$endpoint}/{$objectKey}"; | |
| 235 | + | |
| 236 | + $connection->send(json_encode([ | |
| 237 | + 'ok' => true, | |
| 238 | + 'url' => $url | |
| 239 | + ])); | |
| 240 | + | |
| 241 | + } catch (Exception $e) { | |
| 242 | + $connection->send(new \Workerman\Protocols\Http\Response(500, [], json_encode(['ok' => false, 'error' => 'Upload failed: ' . $e->getMessage()]))); | |
| 243 | + } | |
| 244 | + return; | |
| 245 | + } | |
| 246 | + | |
| 247 | + $connection->send("Moltbot Relay HTTP Server"); | |
| 248 | +}; | |
| 249 | + | |
| 149 | 250 | Worker::runAll(); | ... | ... |
Please
register
or
login
to post a comment