Vo Hoang Minh commited on
Commit
2661273
·
1 Parent(s): 7a2c594
Files changed (9) hide show
  1. .gitignore +2 -0
  2. Dockerfile +81 -0
  3. README.md +1 -0
  4. entrypoint.sh +15 -0
  5. orbita.conf +25 -0
  6. package.json +23 -0
  7. pnpm-workspace.yaml +3 -0
  8. src/server.mjs +173 -0
  9. tsconfig.json +9 -0
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ node_modules/
2
+ pnpm-lock.yaml
Dockerfile ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Sử dụng Debian Slim để giảm kích thước image nhưng vẫn giữ sự tương thích
2
+ FROM node:22
3
+
4
+ RUN corepack enable && \
5
+ corepack prepare pnpm@latest --activate && \
6
+ apk add --no-cache curl && \
7
+ curl -fsSL https://bun.sh/install | bash && \
8
+ ln -s /root/.bun/bin/bun /usr/local/bin/bun
9
+
10
+ # Thiết lập môi trường
11
+ ENV DEBIAN_FRONTEND=noninteractive \
12
+ DISPLAY=:0
13
+
14
+ # Cài đặt dependencies cần thiết trong một lệnh duy nhất để giảm số lượng layer
15
+ RUN ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime && \
16
+ apt-get update && \
17
+ apt-get install -y --no-install-recommends \
18
+ tzdata x11vnc xvfb zip wget curl psmisc \
19
+ gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 \
20
+ libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 \
21
+ libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 \
22
+ libgtk-3-bin libnspr4 libpango-1.0-0 libpangocairo-1.0-0 \
23
+ libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \
24
+ libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 \
25
+ libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates \
26
+ fonts-liberation libappindicator1 libnss3 lsb-release \
27
+ xdg-utils libgbm-dev nginx libcurl3-gnutls && \
28
+ apt-get clean && rm -rf /var/lib/apt/lists/*
29
+
30
+
31
+ RUN mkdir -p /home/orbita/.gologin/browser
32
+
33
+
34
+ # Tải và cài đặt Orbita Browser
35
+ RUN wget https://orbita-browser-linux.gologin.com/orbita-browser-latest.tar.gz -O /tmp/orbita-browser.tar.gz && \
36
+ tar -xzf /tmp/orbita-browser.tar.gz -C /home/orbita/.gologin && \
37
+ mv /home/orbita/.gologin/orbita-browser /home/orbita/.gologin/browser && \
38
+ rm -f /tmp/orbita-browser.tar.gz
39
+
40
+
41
+ # Cài đặt Node.js dependencies
42
+ WORKDIR /opt/orbita
43
+
44
+ COPY ./ /opt/orbita/
45
+
46
+
47
+ # Cấu hình Nginx
48
+ COPY orbita.conf /etc/nginx/conf.d/orbita.conf
49
+ RUN rm /etc/nginx/sites-enabled/default
50
+
51
+ # Cấp quyền truy cập cho nginx và các thư mục cần thiết
52
+ RUN chmod 777 /var/lib/nginx -R && \
53
+ chmod 777 /var/log -R && \
54
+ chmod 777 /run -R
55
+
56
+ # Cấu hình X11
57
+ RUN mkdir /tmp/.X11-unix && chmod 1777 /tmp/.X11-unix
58
+
59
+ # Copy các file ứng dụng
60
+ COPY entrypoint.sh /entrypoint.sh
61
+ # COPY fonts /home/orbita/.gologin/browser/fonts
62
+
63
+ RUN groupadd -r orbita && \
64
+ useradd -r -g orbita -s /bin/bash -G audio,video,sudo -p $(echo 1 | openssl passwd -1 -stdin) orbita && \
65
+ mkdir -p /home/orbita/Downloads /home/orbita/.gologin/browser/fonts && \
66
+ chown -R orbita:orbita /home/orbita && \
67
+ echo 'orbita ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
68
+
69
+ # Cấp quyền cho entrypoint.sh
70
+ RUN chmod 777 /entrypoint.sh
71
+
72
+ RUN pip install --no-cache-dir -r requirements.txt
73
+
74
+ # bun install package.json
75
+ RUN bun install
76
+
77
+ # Chạy container với user orbita
78
+ USER root
79
+
80
+ # Mở cổng dịch vụ
81
+ EXPOSE 3000
README.md CHANGED
@@ -5,6 +5,7 @@ colorFrom: green
5
  colorTo: red
6
  sdk: docker
7
  pinned: false
 
8
  ---
9
 
10
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
5
  colorTo: red
6
  sdk: docker
7
  pinned: false
8
+ app_port: 3000
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
entrypoint.sh ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ mkdir ~/.vnc
4
+ DISPLAY=:0
5
+ export DISPLAY=:0
6
+ echo $SCREEN_WIDTH
7
+ echo $SCREEN_HEIGHT
8
+ echo `echo $SCREEN_WIDTH`x`echo $SCREEN_HEIGHT`x16
9
+
10
+ cd /opt/orbita
11
+ Xvfb $DISPLAY -screen 0 `echo $SCREEN_WIDTH`x`echo $SCREEN_HEIGHT`x16 &
12
+ sleep 3
13
+ x11vnc -storepasswd 12345678 ~/.vnc/passwd
14
+ x11vnc -display $DISPLAY -bg -forever -usepw -quiet -rfbport 5901 -xkb
15
+ /usr/sbin/nginx -c /etc/nginx/nginx.conf
orbita.conf ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ server {
2
+ listen 3000 default_server;
3
+
4
+ server_name _;
5
+
6
+ location /json {
7
+ proxy_pass http://127.0.0.1:3500;
8
+ proxy_http_version 1.1;
9
+ proxy_set_header X-Real-IP $server_addr;
10
+ proxy_set_header X-Forwarded-for $server_addr;
11
+ proxy_set_header Host '127.0.0.1';
12
+ }
13
+
14
+
15
+
16
+ location /devtools {
17
+ proxy_pass http://127.0.0.1:3500;
18
+ proxy_http_version 1.1;
19
+ proxy_set_header Upgrade $http_upgrade;
20
+ proxy_set_header Connection "upgrade";
21
+ proxy_set_header X-Real-IP $server_addr;
22
+ proxy_set_header X-Forwarded-for $server_addr;
23
+ proxy_set_header Host '127.0.0.1';
24
+ }
25
+ }
package.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "cloudbrowser",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "src/app.mjs",
6
+ "type": "module",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1",
9
+ "dev": "bun run --hot src/server.mjs"
10
+ },
11
+ "keywords": [],
12
+ "author": "",
13
+ "license": "ISC",
14
+ "packageManager": "pnpm@10.10.0",
15
+ "dependencies": {
16
+ "hono": "^4.7.10",
17
+ "puppeteer-core": "^21.0.0",
18
+ "gologin": "^1.0.51"
19
+
20
+ },
21
+ "devDependencies": {
22
+ }
23
+ }
pnpm-workspace.yaml ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ onlyBuiltDependencies:
2
+ - better-sqlite3
3
+ - sqlite3
src/server.mjs ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Hono } from "hono";
2
+ import puppeteer from "puppeteer-core";
3
+ import { default as GoLogin } from "gologin";
4
+
5
+ const app = new Hono();
6
+ const PORT = process.env.PORT || 3000;
7
+
8
+ // Tạo một instance GoLogin để quản lý profile
9
+ const GL = new GoLogin({
10
+ token:
11
+ process.env.GOLOGIN_TOKEN ||
12
+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2N2VlYWJmOGJkODY2YjdjM2Y2NmIzZjEiLCJ0eXBlIjoiZGV2Iiwiand0aWQiOiI2N2VlYWMyNjcwZTM0MDBhNWY2YjdkZmUifQ.tUvpgtJL0swAUinAx1XIeWt4OQMjBqszIciDPKoE9Nk", // Token từ GoLogin để xác thực
13
+ tmpdir: "./tmp", // Thư mục lưu trữ tạm thời
14
+ profileId: "67eeac2670e340a5f67b7c3f66b3f1",
15
+ });
16
+
17
+ // API endpoint để khởi tạo trình duyệt
18
+ app.post("/browser/start", async (c) => {
19
+ try {
20
+ // Tạo profile mới
21
+
22
+ // Khởi động trình duyệt với profile đã tạo
23
+ const wsUrl = await GL.start({
24
+ uploadCookiesToServer: true,
25
+ autoUpdateBrowser: false,
26
+ });
27
+
28
+ return c.json({
29
+ success: true,
30
+ profileId,
31
+ wsUrl,
32
+ });
33
+ } catch (error) {
34
+ console.error("Error starting browser:", error);
35
+ return c.json(
36
+ {
37
+ success: false,
38
+ error: error.message,
39
+ },
40
+ 500
41
+ );
42
+ }
43
+ });
44
+
45
+ // API endpoint để điều hướng trình duyệt
46
+ app.post("/browser/navigate", async (c) => {
47
+ try {
48
+ const { profileId, url } = await c.req.json();
49
+
50
+ if (!profileId || !url) {
51
+ return c.json(
52
+ {
53
+ success: false,
54
+ error: "Profile ID and URL are required",
55
+ },
56
+ 400
57
+ );
58
+ }
59
+
60
+ const wsUrl = await GL.getProfileStartupInfo(profileId);
61
+
62
+ // Kết nối đến trình duyệt đang chạy
63
+ const browser = await puppeteer.connect({
64
+ browserWSEndpoint: wsUrl.wsUrl,
65
+ ignoreHTTPSErrors: true,
66
+ });
67
+
68
+ // Mở tab mới
69
+ const page = await browser.newPage();
70
+
71
+ // Điều hướng đến URL
72
+ await page.goto(url, { waitUntil: "networkidle2" });
73
+
74
+ // Chụp ảnh màn hình
75
+ const screenshot = await page.screenshot({ encoding: "base64" });
76
+
77
+ return c.json({
78
+ success: true,
79
+ screenshot,
80
+ });
81
+ } catch (error) {
82
+ console.error("Error navigating browser:", error);
83
+ return c.json(
84
+ {
85
+ success: false,
86
+ error: error.message,
87
+ },
88
+ 500
89
+ );
90
+ }
91
+ });
92
+
93
+ // API endpoint để đóng trình duyệt
94
+ app.post("/browser/stop", async (c) => {
95
+ try {
96
+ const { profileId } = await c.req.json();
97
+
98
+ if (!profileId) {
99
+ return c.json(
100
+ {
101
+ success: false,
102
+ error: "Profile ID is required",
103
+ },
104
+ 400
105
+ );
106
+ }
107
+
108
+ // Dừng trình duyệt từ xa
109
+ await GL.stopRemote(profileId);
110
+
111
+ return c.json({
112
+ success: true,
113
+ message: "Browser stopped successfully",
114
+ });
115
+ } catch (error) {
116
+ console.error("Error stopping browser:", error);
117
+ return c.json(
118
+ {
119
+ success: false,
120
+ error: error.message,
121
+ },
122
+ 500
123
+ );
124
+ }
125
+ });
126
+
127
+ // Trang chủ
128
+ app.get("/", (c) => {
129
+ return c.html(`
130
+ <!DOCTYPE html>
131
+ <html lang="en">
132
+ <head>
133
+ <meta charset="UTF-8">
134
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
135
+ <title>Cloud Browser API</title>
136
+ <style>
137
+ body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
138
+ h1 { color: #333; }
139
+ .endpoint { background: #f5f5f5; padding: 15px; margin: 20px 0; border-radius: 5px; }
140
+ code { background: #e0e0e0; padding: 2px 5px; border-radius: 3px; }
141
+ </style>
142
+ </head>
143
+ <body>
144
+ <h1>Cloud Browser API</h1>
145
+ <p>Sử dụng API này để khởi tạo và điều khiển trình duyệt từ xa.</p>
146
+
147
+ <div class="endpoint">
148
+ <h2>POST /browser/start</h2>
149
+ <p>Khởi động một trình duyệt mới và trả về profile ID và WebSocket URL.</p>
150
+ </div>
151
+
152
+ <div class="endpoint">
153
+ <h2>POST /browser/navigate</h2>
154
+ <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>
155
+ <p>Body: <code>{ "profileId": "...", "url": "https://example.com" }</code></p>
156
+ </div>
157
+
158
+ <div class="endpoint">
159
+ <h2>POST /browser/stop</h2>
160
+ <p>Đóng trình duyệt.</p>
161
+ <p>Body: <code>{ "profileId": "..." }</code></p>
162
+ </div>
163
+ </body>
164
+ </html>
165
+ `);
166
+ });
167
+
168
+ // Khởi động server
169
+ console.log(`Server is starting on port ${PORT}...`);
170
+
171
+ console.log(`Server running at http://localhost:${PORT}`);
172
+
173
+ export default app;
tsconfig.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "esModuleInterop": true,
7
+ "strict": true
8
+ }
9
+ }