Spaces:
Paused
Paused
| import { Hono } from "hono"; | |
| import puppeteer from "puppeteer-core"; | |
| import { default as GoLogin } from "gologin"; | |
| import { serve } from "@hono/node-server"; | |
| const app = new Hono(); | |
| const PORT = process.env.PORT || 3000; | |
| // Tạo một instance GoLogin để quản lý profile | |
| const GL = new GoLogin({ | |
| token: | |
| process.env.GOLOGIN_TOKEN || | |
| "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2N2VlYWJmOGJkODY2YjdjM2Y2NmIzZjEiLCJ0eXBlIjoiZGV2Iiwiand0aWQiOiI2N2VlYWMyNjcwZTM0MDBhNWY2YjdkZmUifQ.tUvpgtJL0swAUinAx1XIeWt4OQMjBqszIciDPKoE9Nk", // Token từ GoLogin để xác thực | |
| tmpdir: "/tmp", // Thư mục lưu trữ tạm thời | |
| profile_id: "67eeaf4dc3162f03167f4570", | |
| remote_debugging_port: 3500, | |
| executablePath: "/usr/bin/orbita-browser/chrome", | |
| extra_params: [ | |
| "--start-maximized", | |
| "--disable-dev-shm-usage", | |
| "--no-sandbox", | |
| "--no-zygote", | |
| "--window-position=0,0", | |
| ], | |
| remote: false, | |
| }); | |
| app.get("/api/ping", (c) => { | |
| return c.json({ | |
| message: "Hello", | |
| }); | |
| }); | |
| // API endpoint để khởi tạo trình duyệt | |
| app.get("/api/start", async (c) => { | |
| try { | |
| // Tạo profile mới | |
| // Khởi động trình duyệt với profile đã tạo | |
| const wsUrl = await GL.createStartupAndSpawnBrowser(); | |
| return c.json({ | |
| success: true, | |
| profileId, | |
| wsUrl, | |
| }); | |
| } catch (error) { | |
| console.error("Error starting browser:", error); | |
| return c.json( | |
| { | |
| success: false, | |
| error: error.message, | |
| }, | |
| 500 | |
| ); | |
| } | |
| }); | |
| // API endpoint để điều hướng trình duyệt | |
| app.post("/api/navigate", async (c) => { | |
| try { | |
| const { profileId, url } = await c.req.json(); | |
| if (!profileId || !url) { | |
| return c.json( | |
| { | |
| success: false, | |
| error: "Profile ID and URL are required", | |
| }, | |
| 400 | |
| ); | |
| } | |
| const wsUrl = await GL.getProfileStartupInfo(profileId); | |
| // Kết nối đến trình duyệt đang chạy | |
| const browser = await puppeteer.connect({ | |
| browserWSEndpoint: wsUrl.wsUrl, | |
| ignoreHTTPSErrors: true, | |
| }); | |
| // Mở tab mới | |
| const page = await browser.newPage(); | |
| // Điều hướng đến URL | |
| await page.goto(url, { waitUntil: "networkidle2" }); | |
| // Chụp ảnh màn hình | |
| const screenshot = await page.screenshot({ encoding: "base64" }); | |
| return c.json({ | |
| success: true, | |
| screenshot, | |
| }); | |
| } catch (error) { | |
| console.error("Error navigating browser:", error); | |
| return c.json( | |
| { | |
| success: false, | |
| error: error.message, | |
| }, | |
| 500 | |
| ); | |
| } | |
| }); | |
| // API endpoint để đóng trình duyệt | |
| app.post("/api/stop", async (c) => { | |
| try { | |
| const { profileId } = await c.req.json(); | |
| if (!profileId) { | |
| return c.json( | |
| { | |
| success: false, | |
| error: "Profile ID is required", | |
| }, | |
| 400 | |
| ); | |
| } | |
| // Dừng trình duyệt từ xa | |
| await GL.stopRemote(profileId); | |
| return c.json({ | |
| success: true, | |
| message: "Browser stopped successfully", | |
| }); | |
| } catch (error) { | |
| console.error("Error stopping browser:", error); | |
| return c.json( | |
| { | |
| success: false, | |
| error: error.message, | |
| }, | |
| 500 | |
| ); | |
| } | |
| }); | |
| // Trang chủ | |
| app.get("/api", (c) => { | |
| return c.html(` | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Cloud Browser API</title> | |
| <style> | |
| body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } | |
| h1 { color: #333; } | |
| .endpoint { background: #f5f5f5; padding: 15px; margin: 20px 0; border-radius: 5px; } | |
| code { background: #e0e0e0; padding: 2px 5px; border-radius: 3px; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>Cloud Browser API</h1> | |
| <p>Sử dụng API này để khởi tạo và điều khiển trình duyệt từ xa.</p> | |
| <div class="endpoint"> | |
| <h2>POST /browser/start</h2> | |
| <p>Khởi động một trình duyệt mới và trả về profile ID và WebSocket URL.</p> | |
| </div> | |
| <div class="endpoint"> | |
| <h2>POST /browser/navigate</h2> | |
| <p>Điều hướng trình duyệt đến URL xác định và trả về ảnh chụp màn hình.</p> | |
| <p>Body: <code>{ "profileId": "...", "url": "https://example.com" }</code></p> | |
| </div> | |
| <div class="endpoint"> | |
| <h2>POST /browser/stop</h2> | |
| <p>Đóng trình duyệt.</p> | |
| <p>Body: <code>{ "profileId": "..." }</code></p> | |
| </div> | |
| </body> | |
| </html> | |
| `); | |
| }); | |
| // Khởi động server | |
| console.log(`Server is starting on port ${PORT}...`); | |
| // Bắt đầu lắng nghe kết nối | |
| serve({ | |
| fetch: app.fetch, | |
| port: 3000, | |
| }); | |