maylinejix commited on
Commit
ff0130c
Β·
verified Β·
1 Parent(s): fedec58

Create index.js

Browse files
Files changed (1) hide show
  1. index.js +364 -0
index.js ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // server.js - Node.js Backend with Express and Tesseract OCR
2
+ const express = require('express');
3
+ const multer = require('multer');
4
+ const Tesseract = require('tesseract.js');
5
+ const path = require('path');
6
+ const fs = require('fs');
7
+
8
+ const app = express();
9
+ const PORT = process.env.PORT || 7860;
10
+
11
+ // Multer configuration for file uploads
12
+ const upload = multer({
13
+ dest: 'uploads/',
14
+ limits: { fileSize: 10 * 1024 * 1024 } // 10MB limit
15
+ });
16
+
17
+ // Middleware
18
+ app.use(express.json());
19
+ app.use(express.urlencoded({ extended: true }));
20
+ app.use(express.static('public'));
21
+
22
+ // Database configuration
23
+ const DB_FILE = './database.json';
24
+ const ADMIN_PASSWORD = 'BTXHZ';
25
+ const ADMIN_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6dHJ1ZX0.dummytoken';
26
+
27
+ // Initialize database file if doesn't exist
28
+ if (!fs.existsSync(DB_FILE)) {
29
+ fs.writeFileSync(DB_FILE, JSON.stringify([]));
30
+ console.log('πŸ“ Database file created');
31
+ }
32
+
33
+ // Initialize uploads folder if doesn't exist
34
+ if (!fs.existsSync('uploads')) {
35
+ fs.mkdirSync('uploads');
36
+ console.log('πŸ“ Uploads folder created');
37
+ }
38
+
39
+ // Database helper functions
40
+ const getDB = () => {
41
+ try {
42
+ const data = fs.readFileSync(DB_FILE, 'utf8');
43
+ return JSON.parse(data);
44
+ } catch (error) {
45
+ console.error('Error reading database:', error);
46
+ return [];
47
+ }
48
+ };
49
+
50
+ const saveDB = (data) => {
51
+ try {
52
+ fs.writeFileSync(DB_FILE, JSON.stringify(data, null, 2));
53
+ return true;
54
+ } catch (error) {
55
+ console.error('Error saving database:', error);
56
+ return false;
57
+ }
58
+ };
59
+
60
+ // Authentication middleware
61
+ const authMiddleware = (req, res, next) => {
62
+ const authHeader = req.headers.authorization;
63
+
64
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
65
+ return res.status(401).json({
66
+ success: false,
67
+ error: 'Unauthorized - No token provided'
68
+ });
69
+ }
70
+
71
+ const token = authHeader.replace('Bearer ', '');
72
+
73
+ if (token !== ADMIN_TOKEN) {
74
+ return res.status(401).json({
75
+ success: false,
76
+ error: 'Unauthorized - Invalid token'
77
+ });
78
+ }
79
+
80
+ next();
81
+ };
82
+
83
+ // ============================================
84
+ // HTML ROUTES
85
+ // ============================================
86
+
87
+ // Root route - redirect to home
88
+ app.get('/', (req, res) => {
89
+ res.redirect('/home');
90
+ });
91
+
92
+ // Home page
93
+ app.get('/home', (req, res) => {
94
+ res.sendFile(path.join(__dirname, 'public', 'home.html'));
95
+ });
96
+
97
+ // Admin create page
98
+ app.get('/home/admin/create', (req, res) => {
99
+ res.sendFile(path.join(__dirname, 'public', 'admin.html'));
100
+ });
101
+
102
+ // Verification page
103
+ app.get('/home/url/:name/:id', (req, res) => {
104
+ res.sendFile(path.join(__dirname, 'public', 'verify.html'));
105
+ });
106
+
107
+ // ============================================
108
+ // API ROUTES
109
+ // ============================================
110
+
111
+ // Login endpoint
112
+ app.post('/api/login', (req, res) => {
113
+ const { password } = req.body;
114
+
115
+ if (!password) {
116
+ return res.status(400).json({
117
+ success: false,
118
+ error: 'Password is required'
119
+ });
120
+ }
121
+
122
+ if (password === ADMIN_PASSWORD) {
123
+ res.json({
124
+ success: true,
125
+ token: ADMIN_TOKEN,
126
+ message: 'Login successful'
127
+ });
128
+ } else {
129
+ res.status(401).json({
130
+ success: false,
131
+ error: 'Invalid password'
132
+ });
133
+ }
134
+ });
135
+
136
+ // Create short link endpoint (protected)
137
+ app.post('/api/create', authMiddleware, (req, res) => {
138
+ const { title, redirect, name, verify } = req.body;
139
+
140
+ // Validation
141
+ if (!title || !redirect || !name) {
142
+ return res.status(400).json({
143
+ success: false,
144
+ error: 'Title, redirect, and name are required'
145
+ });
146
+ }
147
+
148
+ // Check if name already exists
149
+ const db = getDB();
150
+ const existingLink = db.find(link => link.name === name);
151
+
152
+ if (existingLink) {
153
+ return res.status(400).json({
154
+ success: false,
155
+ error: 'Short name already exists'
156
+ });
157
+ }
158
+
159
+ // Create new link
160
+ const id = Date.now().toString();
161
+ const newLink = {
162
+ id,
163
+ title,
164
+ redirect,
165
+ name,
166
+ verify: verify === true,
167
+ createdAt: new Date().toISOString()
168
+ };
169
+
170
+ db.push(newLink);
171
+
172
+ if (saveDB(db)) {
173
+ console.log(`βœ… New link created: ${name} (ID: ${id})`);
174
+ res.json({
175
+ success: true,
176
+ link: newLink,
177
+ message: 'Short link created successfully'
178
+ });
179
+ } else {
180
+ res.status(500).json({
181
+ success: false,
182
+ error: 'Failed to save link'
183
+ });
184
+ }
185
+ });
186
+
187
+ // Get all links endpoint
188
+ app.get('/api/links', (req, res) => {
189
+ const db = getDB();
190
+ res.json(db);
191
+ });
192
+
193
+ // Get specific link endpoint
194
+ app.get('/api/link/:name/:id', (req, res) => {
195
+ const { name, id } = req.params;
196
+ const db = getDB();
197
+
198
+ const link = db.find(l => l.name === name && l.id === id);
199
+
200
+ if (link) {
201
+ res.json(link);
202
+ } else {
203
+ res.status(404).json({
204
+ error: 'Link not found',
205
+ message: 'The requested short link does not exist'
206
+ });
207
+ }
208
+ });
209
+
210
+ // OCR Verification endpoint
211
+ app.post('/api/verify', upload.single('image'), async (req, res) => {
212
+ if (!req.file) {
213
+ return res.status(400).json({
214
+ success: false,
215
+ error: 'No image file uploaded'
216
+ });
217
+ }
218
+
219
+ const filePath = req.file.path;
220
+ console.log(`πŸ” Processing OCR for file: ${req.file.originalname}`);
221
+
222
+ try {
223
+ // Perform OCR using Tesseract
224
+ const { data: { text } } = await Tesseract.recognize(
225
+ filePath,
226
+ 'eng',
227
+ {
228
+ logger: info => {
229
+ if (info.status === 'recognizing text') {
230
+ console.log(`OCR Progress: ${Math.round(info.progress * 100)}%`);
231
+ }
232
+ }
233
+ }
234
+ );
235
+
236
+ console.log('πŸ“ OCR Text extracted:', text.substring(0, 100) + '...');
237
+
238
+ // Clean up uploaded file
239
+ fs.unlinkSync(filePath);
240
+
241
+ // Normalize text for better matching
242
+ const normalizedText = text.toLowerCase();
243
+
244
+ // Check for required conditions
245
+ const hasNotmebotz = normalizedText.includes('notmebotz') ||
246
+ normalizedText.includes('notme botz');
247
+
248
+ const hasFollowButton = normalizedText.includes('follow channel') ||
249
+ normalizedText.includes('follow') && normalizedText.includes('channel');
250
+
251
+ const hasPrivacy = normalizedText.includes('added privacy') ||
252
+ normalizedText.includes('this channel has added privacy');
253
+
254
+ // Verification logic
255
+ const verified = hasNotmebotz && !hasFollowButton && !hasPrivacy;
256
+
257
+ console.log(`βœ… Verification result: ${verified ? 'PASSED' : 'FAILED'}`);
258
+ console.log(` - Channel: ${hasNotmebotz ? 'NOTMEBOTZ βœ“' : 'NOT FOUND βœ—'}`);
259
+ console.log(` - Follow Button: ${hasFollowButton ? 'PRESENT βœ—' : 'ABSENT βœ“'}`);
260
+ console.log(` - Privacy Text: ${hasPrivacy ? 'PRESENT βœ—' : 'ABSENT βœ“'}`);
261
+
262
+ res.json({
263
+ success: true,
264
+ verified,
265
+ channelName: hasNotmebotz ? 'NOTMEBOTZ' : 'UNKNOWN',
266
+ hasFollowButton,
267
+ hasPrivacy,
268
+ extractedText: text.substring(0, 200) // Return first 200 chars for debugging
269
+ });
270
+
271
+ } catch (error) {
272
+ console.error('❌ OCR Error:', error);
273
+
274
+ // Clean up file if it still exists
275
+ if (fs.existsSync(filePath)) {
276
+ fs.unlinkSync(filePath);
277
+ }
278
+
279
+ res.status(500).json({
280
+ success: false,
281
+ error: 'OCR processing failed',
282
+ message: error.message
283
+ });
284
+ }
285
+ });
286
+
287
+ // Delete link endpoint (optional - for admin)
288
+ app.delete('/api/link/:id', authMiddleware, (req, res) => {
289
+ const { id } = req.params;
290
+ const db = getDB();
291
+
292
+ const index = db.findIndex(link => link.id === id);
293
+
294
+ if (index !== -1) {
295
+ const deletedLink = db.splice(index, 1)[0];
296
+ saveDB(db);
297
+
298
+ console.log(`πŸ—‘οΈ Link deleted: ${deletedLink.name} (ID: ${id})`);
299
+
300
+ res.json({
301
+ success: true,
302
+ message: 'Link deleted successfully',
303
+ deletedLink
304
+ });
305
+ } else {
306
+ res.status(404).json({
307
+ success: false,
308
+ error: 'Link not found'
309
+ });
310
+ }
311
+ });
312
+
313
+ // Health check endpoint
314
+ app.get('/api/health', (req, res) => {
315
+ res.json({
316
+ status: 'OK',
317
+ uptime: process.uptime(),
318
+ timestamp: new Date().toISOString()
319
+ });
320
+ });
321
+
322
+ // ============================================
323
+ // ERROR HANDLING
324
+ // ============================================
325
+
326
+ // 404 handler
327
+ app.use((req, res) => {
328
+ res.status(404).json({
329
+ error: 'Not Found',
330
+ message: 'The requested endpoint does not exist',
331
+ path: req.path
332
+ });
333
+ });
334
+
335
+ // Global error handler
336
+ app.use((err, req, res, next) => {
337
+ console.error('❌ Server Error:', err);
338
+
339
+ res.status(err.status || 500).json({
340
+ error: 'Internal Server Error',
341
+ message: err.message || 'Something went wrong'
342
+ });
343
+ });
344
+
345
+ // ============================================
346
+ // START SERVER
347
+ // ============================================
348
+
349
+ app.listen(PORT, () => {
350
+ console.log('');
351
+ console.log('╔════════════════════════════════════════╗');
352
+ console.log('β•‘ πŸš€ ShortLink OCR Server Running β•‘');
353
+ console.log('β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•');
354
+ console.log('');
355
+ console.log(`🌐 Server: http://localhost:${PORT}`);
356
+ console.log(`πŸ“Š Admin Panel: http://localhost:${PORT}/home/admin/create`);
357
+ console.log(`πŸ” Admin Password: ${ADMIN_PASSWORD}`);
358
+ console.log('');
359
+ console.log('πŸ“ Database:', DB_FILE);
360
+ console.log('πŸ“‚ Uploads:', path.join(__dirname, 'uploads'));
361
+ console.log('');
362
+ console.log('Press Ctrl+C to stop the server');
363
+ console.log('');
364
+ });