Spaces:
Sleeping
Sleeping
Upload 4 files
Browse files- Dockerfile +26 -0
- README.md +6 -5
- app.js +157 -0
- package.json +29 -0
Dockerfile
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Gunakan image Node.js yang mendukung Playwright
|
2 |
+
FROM mcr.microsoft.com/playwright:focal
|
3 |
+
|
4 |
+
# Set environment variable untuk menghindari dialog pada Playwright
|
5 |
+
ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD 1
|
6 |
+
|
7 |
+
# Tentukan work directory
|
8 |
+
WORKDIR /app
|
9 |
+
|
10 |
+
# Copy file package.json dan package-lock.json
|
11 |
+
COPY package*.json ./
|
12 |
+
|
13 |
+
# Install dependencies
|
14 |
+
RUN npm install
|
15 |
+
|
16 |
+
# Copy semua file ke container
|
17 |
+
COPY . .
|
18 |
+
|
19 |
+
# Install Playwright dependencies dan browser binaries
|
20 |
+
RUN npx playwright install --with-deps
|
21 |
+
|
22 |
+
# Expose port untuk aplikasi
|
23 |
+
EXPOSE 7860
|
24 |
+
|
25 |
+
# Start aplikasi
|
26 |
+
CMD ["npm", "start"]
|
README.md
CHANGED
@@ -1,11 +1,12 @@
|
|
1 |
---
|
2 |
-
title: Playwright
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: docker
|
7 |
pinned: false
|
8 |
-
license:
|
|
|
9 |
---
|
10 |
|
11 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
1 |
---
|
2 |
+
title: Try Playwright
|
3 |
+
emoji: 💽
|
4 |
+
colorFrom: gray
|
5 |
+
colorTo: yellow
|
6 |
sdk: docker
|
7 |
pinned: false
|
8 |
+
license: apache-2.0
|
9 |
+
short_description: bart
|
10 |
---
|
11 |
|
12 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.js
ADDED
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const express = require('express');
|
2 |
+
const cors = require('cors');
|
3 |
+
const dotenv = require('dotenv');
|
4 |
+
const os = require('os');
|
5 |
+
const fs = require('fs');
|
6 |
+
const path = require('path');
|
7 |
+
const axios = require('axios');
|
8 |
+
const FormData = require('form-data');
|
9 |
+
const { fromBuffer } = require('file-type');
|
10 |
+
|
11 |
+
dotenv.config();
|
12 |
+
|
13 |
+
const app = express();
|
14 |
+
app.use(express.json());
|
15 |
+
app.use(cors());
|
16 |
+
app.set('json spaces', 3);
|
17 |
+
|
18 |
+
// Fungsi untuk mengunggah buffer ke API totemp
|
19 |
+
async function totemp(imageBuffer) {
|
20 |
+
const apiUrl = "https://neoxr.my.id/srv";
|
21 |
+
try {
|
22 |
+
const response = await axios.get(apiUrl);
|
23 |
+
const apiPath = response.data.api_path;
|
24 |
+
const { ext } = await fromBuffer(imageBuffer);
|
25 |
+
let formData = new FormData();
|
26 |
+
formData.append("someFiles", imageBuffer, "tmp." + ext);
|
27 |
+
|
28 |
+
const uploadResponse = await axios.post(apiPath, formData, {
|
29 |
+
headers: {
|
30 |
+
...formData.getHeaders(),
|
31 |
+
},
|
32 |
+
});
|
33 |
+
const result = uploadResponse.data;
|
34 |
+
|
35 |
+
// Kembalikan struktur URL dan file yang diinginkan
|
36 |
+
return {
|
37 |
+
status: true,
|
38 |
+
data: {
|
39 |
+
publicURL: result.data.url,
|
40 |
+
fileName: `screenshot.${ext}`,
|
41 |
+
extension: ext,
|
42 |
+
},
|
43 |
+
};
|
44 |
+
} catch (error) {
|
45 |
+
console.error('Error uploading to totemp:', error.message);
|
46 |
+
return {
|
47 |
+
status: false,
|
48 |
+
msg: error.message,
|
49 |
+
};
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
// Endpoint untuk menjalankan kode dari pengguna
|
54 |
+
app.post('/run', async (req, res) => {
|
55 |
+
try {
|
56 |
+
const { code } = req.body;
|
57 |
+
|
58 |
+
if (!code) {
|
59 |
+
return res.status(400).json({
|
60 |
+
success: false,
|
61 |
+
message: 'Parameter "code" diperlukan.',
|
62 |
+
});
|
63 |
+
}
|
64 |
+
|
65 |
+
const startTime = Date.now();
|
66 |
+
const tempFileName = 'brat.png'; // Nama file sementara untuk screenshot
|
67 |
+
|
68 |
+
try {
|
69 |
+
// Buat file script pengguna
|
70 |
+
const scriptPath = path.join(__dirname, 'user-script.js');
|
71 |
+
fs.writeFileSync(scriptPath, code, 'utf8');
|
72 |
+
|
73 |
+
// Jalankan kode pengguna dengan child process
|
74 |
+
const { exec } = require('child_process');
|
75 |
+
await new Promise((resolve, reject) => {
|
76 |
+
exec(`node ${scriptPath}`, (err, stdout, stderr) => {
|
77 |
+
if (err) {
|
78 |
+
reject(stderr || err.message);
|
79 |
+
} else {
|
80 |
+
console.log(stdout);
|
81 |
+
resolve(stdout);
|
82 |
+
}
|
83 |
+
});
|
84 |
+
});
|
85 |
+
|
86 |
+
// Pastikan file screenshot dihasilkan
|
87 |
+
if (!fs.existsSync(tempFileName)) {
|
88 |
+
throw new Error('File screenshot tidak ditemukan.');
|
89 |
+
}
|
90 |
+
|
91 |
+
// Konversi screenshot ke buffer
|
92 |
+
const imageBuffer = fs.readFileSync(tempFileName);
|
93 |
+
|
94 |
+
// Unggah buffer ke API totemp
|
95 |
+
const uploadResult = await totemp(imageBuffer);
|
96 |
+
|
97 |
+
// Hapus file screenshot setelah diunggah
|
98 |
+
fs.unlinkSync(tempFileName);
|
99 |
+
|
100 |
+
const duration = Date.now() - startTime;
|
101 |
+
|
102 |
+
if (uploadResult.status) {
|
103 |
+
res.status(200).json({
|
104 |
+
success: true,
|
105 |
+
error: "",
|
106 |
+
version: "1.47.0", // Versi Playwright yang Anda gunakan
|
107 |
+
duration: `${duration}`, // Durasi eksekusi
|
108 |
+
files: [
|
109 |
+
{
|
110 |
+
publicURL: uploadResult.data.publicURL,
|
111 |
+
fileName: uploadResult.data.fileName,
|
112 |
+
extension: uploadResult.data.extension,
|
113 |
+
},
|
114 |
+
],
|
115 |
+
output: "", // Anda dapat menyertakan output lain jika diperlukan
|
116 |
+
});
|
117 |
+
} else {
|
118 |
+
res.status(500).json({
|
119 |
+
success: false,
|
120 |
+
message: 'Gagal mengunggah hasil ke totemp.',
|
121 |
+
error: uploadResult.msg,
|
122 |
+
});
|
123 |
+
}
|
124 |
+
} catch (error) {
|
125 |
+
throw error;
|
126 |
+
}
|
127 |
+
} catch (error) {
|
128 |
+
console.error('Error:', error.message);
|
129 |
+
res.status(500).json({
|
130 |
+
success: false,
|
131 |
+
message: 'Terjadi kesalahan saat menjalankan kode.',
|
132 |
+
error: process.env.NODE_ENV === 'development' ? error.message : undefined,
|
133 |
+
});
|
134 |
+
}
|
135 |
+
});
|
136 |
+
|
137 |
+
// Endpoint untuk informasi server
|
138 |
+
app.get('/', (req, res) => {
|
139 |
+
res.status(200).json({
|
140 |
+
name: 'Playwright Executor',
|
141 |
+
version: '2.1.0',
|
142 |
+
runtime: {
|
143 |
+
os: os.type(),
|
144 |
+
platform: os.platform(),
|
145 |
+
architecture: os.arch(),
|
146 |
+
cpuCount: os.cpus().length,
|
147 |
+
uptime: `${os.uptime()} seconds`,
|
148 |
+
memoryUsage: `${Math.round((os.totalmem() - os.freemem()) / 1024 / 1024)} MB used of ${Math.round(os.totalmem() / 1024 / 1024)} MB`,
|
149 |
+
},
|
150 |
+
});
|
151 |
+
});
|
152 |
+
|
153 |
+
// Menjalankan server
|
154 |
+
const PORT = process.env.PORT || 7860;
|
155 |
+
app.listen(PORT, () => {
|
156 |
+
console.log(`Server running on port ${PORT}`);
|
157 |
+
});
|
package.json
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "try-playwright",
|
3 |
+
"version": "0.0.1",
|
4 |
+
"description": "API for generating HD Bart images using Playwright",
|
5 |
+
"main": "app.js",
|
6 |
+
"scripts": {
|
7 |
+
"start": "node app.js",
|
8 |
+
"dev": "nodemon app.js"
|
9 |
+
},
|
10 |
+
"keywords": ["playwright", "express", "API"],
|
11 |
+
"author": "@ryukenshiroo – Pratama",
|
12 |
+
"license": "MIT",
|
13 |
+
"dependencies": {
|
14 |
+
"express": "latest",
|
15 |
+
"playwright": "latest",
|
16 |
+
"cors": "latest",
|
17 |
+
"dotenv": "latest",
|
18 |
+
"axios": "*",
|
19 |
+
"fs": "*",
|
20 |
+
"path": "latest",
|
21 |
+
"axios": "*",
|
22 |
+
"form-data": "*",
|
23 |
+
"file-type": "*"
|
24 |
+
|
25 |
+
},
|
26 |
+
"devDependencies": {
|
27 |
+
"nodemon": "latest"
|
28 |
+
}
|
29 |
+
}
|