Dooratre commited on
Commit
a0bdbd8
·
verified ·
1 Parent(s): 3090b5a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +645 -26
app.py CHANGED
@@ -1,35 +1,654 @@
1
- import requests
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- # Replace 'YOUR_BOT_TOKEN' with your actual bot token
4
- bot_token = '6990801595:AAE79xNVO1D_0SeWZlzYLE57Suwfp9GyKT8'
 
5
 
6
- def send_message(chat_id, text):
7
- url = f'https://api.telegram.org/bot{bot_token}/sendMessage'
8
- params = {'chat_id': chat_id, 'text': text}
9
- response = requests.get(url, params=params)
10
- return response.json()
11
 
12
- def handle_message(message):
13
- chat_id = message['chat']['id']
14
- text = message['text']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
- if text == '/start':
17
- send_message(chat_id, 'Hi')
 
18
 
19
- def main():
20
- offset = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
- while True:
23
- url = f'https://api.telegram.org/bot{bot_token}/getUpdates'
24
- params = {'offset': offset}
25
- response = requests.get(url, params=params)
26
- data = response.json()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
- if data['ok']:
29
- for update in data['result']:
30
- offset = update['update_id'] + 1
31
- if 'message' in update:
32
- handle_message(update['message'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  if __name__ == '__main__':
35
- main()
 
1
+ import os
2
+ import json
3
+ import time
4
+ import threading
5
+ from flask import Flask, render_template, request, redirect, url_for, jsonify, session
6
+ from flask_socketio import SocketIO, emit
7
+ from functools import wraps
8
+ from database.db import fetch_json_from_github as fetch_user_json
9
+ from database.db import update_user_json_file as update_user_json
10
+ from database.db import fetch_authenticity_token_and_commit_oid as fetch_user_tokens
11
+ from database.msg import fetch_json_from_github as fetch_messages_json
12
+ from database.msg import update_user_json_file as update_messages_json
13
+ from database.msg import fetch_authenticity_token_and_commit_oid as fetch_messages_tokens
14
 
15
+ app = Flask(__name__)
16
+ app.secret_key = os.urandom(24)
17
+ socketio = SocketIO(app, cors_allowed_origins="*")
18
 
19
+ # Cache for user data and messages
20
+ user_data_cache = {}
21
+ messages_cache = {}
22
+ last_fetch_time = 0
23
+ CACHE_TIMEOUT = 60 # seconds
24
 
25
+ # Background thread for checking updates
26
+ thread = None
27
+ thread_lock = threading.Lock()
28
+
29
+ def login_required(f):
30
+ @wraps(f)
31
+ def decorated_function(*args, **kwargs):
32
+ if 'logged_in' not in session or not session['logged_in']:
33
+ return redirect(url_for('login'))
34
+ return f(*args, **kwargs)
35
+ return decorated_function
36
+
37
+ def background_thread():
38
+ """Background thread for checking updates in messages"""
39
+ while True:
40
+ with thread_lock:
41
+ # Check for new messages every 10 seconds
42
+ fetch_and_update_messages()
43
+ socketio.sleep(10)
44
+
45
+ def fetch_and_update_messages():
46
+ """Fetch messages and notify clients if there are changes"""
47
+ global messages_cache
48
 
49
+ # Only fetch if we have active users
50
+ if not user_data_cache:
51
+ return
52
 
53
+ for page_id in user_data_cache.get('page_ids', []):
54
+ result = fetch_messages_json()
55
+ if result['success']:
56
+ new_messages = result['data'].get(page_id, [])
57
+ old_messages = messages_cache.get(page_id, [])
58
+
59
+ # Check if there are new messages
60
+ if len(new_messages) > len(old_messages):
61
+ messages_cache[page_id] = new_messages
62
+ # Notify clients about new messages
63
+ socketio.emit('new_messages', {
64
+ 'page_id': page_id,
65
+ 'count': len(new_messages) - len(old_messages)
66
+ })
67
+
68
+ def get_user_data(force_refresh=False):
69
+ """Get user data from GitHub or cache"""
70
+ global user_data_cache, last_fetch_time
71
 
72
+ current_time = time.time()
73
+ if force_refresh or not user_data_cache or (current_time - last_fetch_time) > CACHE_TIMEOUT:
74
+ result = fetch_user_json()
75
+ if result['success']:
76
+ # Process the data to make it easier to work with
77
+ pages = result['data'].get('pages', [])
78
+ page_ids = [page.get('page_id') for page in pages]
79
+
80
+ user_data_cache = {
81
+ 'pages': pages,
82
+ 'page_ids': page_ids,
83
+ 'raw_data': result['data']
84
+ }
85
+ last_fetch_time = current_time
86
+ return user_data_cache
87
+
88
+ return user_data_cache
89
+
90
+ def get_messages(page_id, force_refresh=False):
91
+ """Get messages for a specific page from GitHub or cache"""
92
+ global messages_cache
93
+
94
+ if force_refresh or page_id not in messages_cache:
95
+ result = fetch_messages_json()
96
+ if result['success']:
97
+ messages = result['data'].get(page_id, [])
98
+ messages_cache[page_id] = messages
99
+ return messages
100
+
101
+ return messages_cache.get(page_id, [])
102
+
103
+ @app.route('/')
104
+ def index():
105
+ if 'logged_in' in session and session['logged_in']:
106
+ return redirect(url_for('dashboard'))
107
+ return redirect(url_for('login'))
108
+
109
+ @app.route('/login', methods=['GET', 'POST'])
110
+ def login():
111
+ error = None
112
+ if request.method == 'POST':
113
+ username = request.form['username']
114
+ password = request.form['password']
115
+
116
+ # Get user data
117
+ user_data = get_user_data(force_refresh=True)
118
+
119
+ # Check credentials
120
+ authenticated = False
121
+ for page in user_data.get('pages', []):
122
+ if page.get('username') == username and page.get('password') == password:
123
+ authenticated = True
124
+ session['logged_in'] = True
125
+ session['page_id'] = page.get('page_id')
126
+ session['username'] = username
127
+
128
+ # Start background thread if not already running
129
+ global thread
130
+ with thread_lock:
131
+ if thread is None:
132
+ thread = socketio.start_background_task(background_thread)
133
+
134
+ return redirect(url_for('dashboard'))
135
 
136
+ if not authenticated:
137
+ error = 'اسم المستخدم أو كلمة المرور غير صحيح. الرجاء المحاولة مرة أخرى'
138
+
139
+ return render_template('login.html', error=error)
140
+
141
+ @app.route('/logout')
142
+ def logout():
143
+ session.clear()
144
+ return redirect(url_for('login'))
145
+
146
+ @app.route('/dashboard')
147
+ @login_required
148
+ def dashboard():
149
+ page_id = session.get('page_id')
150
+ user_data = get_user_data()
151
+
152
+ # Find the current page data
153
+ current_page = None
154
+ for page in user_data.get('pages', []):
155
+ if page.get('page_id') == page_id:
156
+ current_page = page
157
+ break
158
+
159
+ if not current_page:
160
+ return redirect(url_for('logout'))
161
+
162
+ # Extract system prompt, style, and products
163
+ system_prompt = current_page.get('system', '')
164
+
165
+ # Extract style if it exists
166
+ style = ""
167
+ style_start = system_prompt.find('<style>')
168
+ style_end = system_prompt.find('</style>')
169
+ if style_start != -1 and style_end != -1:
170
+ style = system_prompt[style_start + 7:style_end]
171
+
172
+ # Extract products if they exist and pre-parse them
173
+ products = []
174
+ product_start = system_prompt.find('<product>')
175
+ while product_start != -1:
176
+ product_end = system_prompt.find('</product>', product_start)
177
+ if product_end != -1:
178
+ product_text = system_prompt[product_start + 9:product_end]
179
+
180
+ # Parse the product text into a dictionary
181
+ product_data = {
182
+ 'name': '',
183
+ 'price': '',
184
+ 'description': '',
185
+ 'info': '',
186
+ 'raw_text': product_text # Keep the raw text for editing/deleting
187
+ }
188
+
189
+ lines = product_text.split('\n')
190
+ for line in lines:
191
+ if 'NAME:' in line:
192
+ product_data['name'] = line.replace('NAME:', '').strip()
193
+ elif 'PRICE (LIBYAN DINNER):' in line:
194
+ product_data['price'] = line.replace('PRICE (LIBYAN DINNER):', '').strip()
195
+ elif 'DESCRIPTION:' in line:
196
+ product_data['description'] = line.replace('DESCRIPTION:', '').strip()
197
+ elif 'ANOTHER INFO:' in line:
198
+ product_data['info'] = line.replace('ANOTHER INFO:', '').strip()
199
+
200
+ products.append(product_data)
201
+ product_start = system_prompt.find('<product>', product_end)
202
+ else:
203
+ break
204
+
205
+ # Get bot status
206
+ bot_status = current_page.get('status', 'OFF')
207
+
208
+ # Get subscription info from the actual JSON structure and translate to Arabic
209
+ subscription_type = current_page.get('subscription', None)
210
+ subscription_message = None
211
+
212
+ if subscription_type == 'Basic':
213
+ subscription_status = 'اشتراك عادي'
214
+ elif subscription_type == 'Plus':
215
+ subscription_status = 'اشتراك +'
216
+ elif subscription_type == 'Premium':
217
+ subscription_status = 'اشتراك مميز'
218
+ elif subscription_type == 'Free':
219
+ subscription_status = 'اشتراك مجاني'
220
+ else:
221
+ subscription_status = 'لا يوجد اشتراك'
222
+ subscription_message = 'يرجى الاشتراك للاستفادة من جميع المميزات'
223
+
224
+ expiration_date = current_page.get('expiration', '2023-12-31')
225
+
226
+ # Calculate days until expiration
227
+ import datetime
228
+ is_expired = False
229
+ expiration_message = None
230
+ try:
231
+ exp_date = datetime.datetime.strptime(expiration_date, '%Y-%m-%d')
232
+ today = datetime.datetime.now()
233
+ days_left = (exp_date - today).days
234
+
235
+ if days_left <= 0:
236
+ is_expired = True
237
+ expiration_message = 'انتهت صلاحية اشتراكك! يرجى التجديد للاستمرار في استخدام الخدمة'
238
+ elif days_left <= 3:
239
+ expiration_message = f'سينتهي اشتراكك خلال {days_left} أيام!'
240
+ except:
241
+ days_left = 0
242
+ is_expired = True
243
+ expiration_message = 'تاريخ انتهاء غير صالح! يرجى التواصل مع الدعم الفني'
244
+
245
+ # Get unread messages count
246
+ messages = get_messages(page_id, force_refresh=True)
247
+ unread_count = sum(1 for msg in messages if not msg.get('seen', False))
248
+
249
+ return render_template(
250
+ 'dashboard.html',
251
+ page=current_page,
252
+ style=style,
253
+ products=products,
254
+ system_prompt=system_prompt,
255
+ bot_status=bot_status,
256
+ subscription_status=subscription_status,
257
+ subscription_message=subscription_message,
258
+ expiration_date=expiration_date,
259
+ days_left=days_left,
260
+ is_expired=is_expired,
261
+ expiration_message=expiration_message,
262
+ unread_count=unread_count
263
+ )
264
+
265
+ @app.route('/messages')
266
+ @login_required
267
+ def messages_page():
268
+ page_id = session.get('page_id')
269
+ messages = get_messages(page_id, force_refresh=True)
270
+
271
+ # Sort messages by timestamp (newest first)
272
+ messages = sorted(messages, key=lambda x: x.get('timestamp', ''), reverse=True)
273
+
274
+ user_data = get_user_data()
275
+ current_page = None
276
+ for page in user_data.get('pages', []):
277
+ if page.get('page_id') == page_id:
278
+ current_page = page
279
+ break
280
+
281
+ if not current_page:
282
+ return redirect(url_for('logout'))
283
+
284
+ return render_template(
285
+ 'messages.html',
286
+ page=current_page,
287
+ messages=messages
288
+ )
289
+
290
+ @app.route('/api/update_status', methods=['POST'])
291
+ @login_required
292
+ def update_status():
293
+ page_id = session.get('page_id')
294
+ status = request.json.get('status')
295
+
296
+ if status not in ['ON', 'OFF']:
297
+ return jsonify({'success': False, 'message': 'Invalid status value'})
298
+
299
+ # Get current data
300
+ user_data = get_user_data(force_refresh=True)
301
+ raw_data = user_data.get('raw_data', {})
302
+
303
+ # Update the status for the current page
304
+ for page in raw_data.get('pages', []):
305
+ if page.get('page_id') == page_id:
306
+ page['status'] = status
307
+ break
308
+
309
+ # Get tokens for updating
310
+ auth_token, commit_oid = fetch_user_tokens()
311
+ if not auth_token or not commit_oid:
312
+ return jsonify({'success': False, 'message': 'Failed to get authentication tokens'})
313
+
314
+ # Update the file
315
+ result = update_user_json(auth_token, commit_oid, json.dumps(raw_data))
316
+
317
+ if result['success']:
318
+ # Update cache
319
+ get_user_data(force_refresh=True)
320
+ # Notify all clients about the status change
321
+ socketio.emit('status_updated', {'page_id': page_id, 'status': status})
322
+ return jsonify({'success': True, 'message': 'Status updated successfully'})
323
+ else:
324
+ return jsonify({'success': False, 'message': 'Failed to update status'})
325
+
326
+ @app.route('/api/update_system', methods=['POST'])
327
+ @login_required
328
+ def update_system():
329
+ page_id = session.get('page_id')
330
+ style = request.json.get('style', '')
331
+
332
+ # Get current data
333
+ user_data = get_user_data(force_refresh=True)
334
+ raw_data = user_data.get('raw_data', {})
335
+
336
+ # Find the current page
337
+ current_page = None
338
+ for page in raw_data.get('pages', []):
339
+ if page.get('page_id') == page_id:
340
+ current_page = page
341
+ break
342
+
343
+ if not current_page:
344
+ return jsonify({'success': False, 'message': 'Page not found'})
345
+
346
+ # Get the current system prompt
347
+ system_prompt = current_page.get('system', '')
348
+
349
+ # Check if style tag already exists
350
+ style_start = system_prompt.find('<style>')
351
+ style_end = system_prompt.find('</style>')
352
+
353
+ if style_start != -1 and style_end != -1:
354
+ # Replace existing style
355
+ new_system = system_prompt[:style_start] + f'<style>{style}</style>' + system_prompt[style_end + 8:]
356
+ else:
357
+ # Add style at the end of the system prompt
358
+ base_prompt_end = system_prompt.find('here how to talk style and products if there : ')
359
+ if base_prompt_end != -1:
360
+ new_system = system_prompt[:base_prompt_end + 46] + f'<style>{style}</style>'
361
+ else:
362
+ new_system = system_prompt + f' <style>{style}</style>'
363
+
364
+ # Update the system prompt
365
+ current_page['system'] = new_system
366
+
367
+ # Get tokens for updating
368
+ auth_token, commit_oid = fetch_user_tokens()
369
+ if not auth_token or not commit_oid:
370
+ return jsonify({'success': False, 'message': 'Failed to get authentication tokens'})
371
+
372
+ # Update the file
373
+ result = update_user_json(auth_token, commit_oid, json.dumps(raw_data))
374
+
375
+ if result['success']:
376
+ # Update cache
377
+ get_user_data(force_refresh=True)
378
+ return jsonify({'success': True, 'message': 'System prompt updated successfully'})
379
+ else:
380
+ return jsonify({'success': False, 'message': 'Failed to update system prompt'})
381
+
382
+ @app.route('/api/add_product', methods=['POST'])
383
+ @login_required
384
+ def add_product():
385
+ page_id = session.get('page_id')
386
+ product_data = request.json.get('product', {})
387
+
388
+ # Format product data
389
+ product_text = f"NAME: {product_data.get('name', '')}\n"
390
+ product_text += f"DESCRIPTION: {product_data.get('description', '')}\n"
391
+ product_text += f"PRICE (LIBYAN DINNER): {product_data.get('price', '')}\n"
392
+ product_text += f"ANOTHER INFO: {product_data.get('info', '')}"
393
+
394
+ # Get current data
395
+ user_data = get_user_data(force_refresh=True)
396
+ raw_data = user_data.get('raw_data', {})
397
+
398
+ # Find the current page
399
+ current_page = None
400
+ for page in raw_data.get('pages', []):
401
+ if page.get('page_id') == page_id:
402
+ current_page = page
403
+ break
404
+
405
+ if not current_page:
406
+ return jsonify({'success': False, 'message': 'Page not found'})
407
+
408
+ # Get the current system prompt
409
+ system_prompt = current_page.get('system', '')
410
+
411
+ # Add product tag at the end
412
+ new_system = system_prompt + f' <product>{product_text}</product>'
413
+
414
+ # Update the system prompt
415
+ current_page['system'] = new_system
416
+
417
+ # Get tokens for updating
418
+ auth_token, commit_oid = fetch_user_tokens()
419
+ if not auth_token or not commit_oid:
420
+ return jsonify({'success': False, 'message': 'Failed to get authentication tokens'})
421
+
422
+ # Update the file
423
+ result = update_user_json(auth_token, commit_oid, json.dumps(raw_data))
424
+
425
+ if result['success']:
426
+ # Update cache
427
+ get_user_data(force_refresh=True)
428
+ return jsonify({'success': True, 'message': 'Product added successfully'})
429
+ else:
430
+ return jsonify({'success': False, 'message': 'Failed to add product'})
431
+
432
+ @app.route('/api/delete_product', methods=['POST'])
433
+ @login_required
434
+ def delete_product():
435
+ page_id = session.get('page_id')
436
+ product_index = request.json.get('index')
437
+
438
+ # Get current data
439
+ user_data = get_user_data(force_refresh=True)
440
+ raw_data = user_data.get('raw_data', {})
441
+
442
+ # Find the current page
443
+ current_page = None
444
+ for page in raw_data.get('pages', []):
445
+ if page.get('page_id') == page_id:
446
+ current_page = page
447
+ break
448
+
449
+ if not current_page:
450
+ return jsonify({'success': False, 'message': 'Page not found'})
451
+
452
+ # Get the current system prompt
453
+ system_prompt = current_page.get('system', '')
454
+
455
+ # Find all products
456
+ products = []
457
+ product_start = system_prompt.find('<product>')
458
+ while product_start != -1:
459
+ product_end = system_prompt.find('</product>', product_start)
460
+ if product_end != -1:
461
+ products.append({
462
+ 'start': product_start,
463
+ 'end': product_end + 10, # Include the closing tag
464
+ 'text': system_prompt[product_start:product_end + 10]
465
+ })
466
+ product_start = system_prompt.find('<product>', product_end)
467
+ else:
468
+ break
469
+
470
+ # Check if the index is valid
471
+ if product_index < 0 or product_index >= len(products):
472
+ return jsonify({'success': False, 'message': 'Invalid product index'})
473
+
474
+ # Remove the product
475
+ product_to_remove = products[product_index]
476
+ new_system = system_prompt[:product_to_remove['start']] + system_prompt[product_to_remove['end']:]
477
+
478
+ # Update the system prompt
479
+ current_page['system'] = new_system
480
+
481
+ # Get tokens for updating
482
+ auth_token, commit_oid = fetch_user_tokens()
483
+ if not auth_token or not commit_oid:
484
+ return jsonify({'success': False, 'message': 'Failed to get authentication tokens'})
485
+
486
+ # Update the file
487
+ result = update_user_json(auth_token, commit_oid, json.dumps(raw_data))
488
+
489
+ if result['success']:
490
+ # Update cache
491
+ get_user_data(force_refresh=True)
492
+ return jsonify({'success': True, 'message': 'Product deleted successfully'})
493
+ else:
494
+ return jsonify({'success': False, 'message': 'Failed to delete product'})
495
+
496
+
497
+ @app.route('/api/refresh_data', methods=['POST'])
498
+ @login_required
499
+ def refresh_data():
500
+ data_type = request.json.get('type', 'all')
501
+
502
+ if data_type == 'messages' or data_type == 'all':
503
+ # Force refresh messages
504
+ page_id = session.get('page_id')
505
+ messages = get_messages(page_id, force_refresh=True)
506
+
507
+ # Notify clients about the refresh
508
+ socketio.emit('data_refreshed', {'type': data_type})
509
+
510
+ return jsonify({'success': True, 'message': 'تم تحديث البيانات بنجاح'})
511
+
512
+ return jsonify({'success': False, 'message': 'نوع البيانات غير صالح'})
513
+
514
+
515
+ @app.route('/api/mark_message_seen', methods=['POST'])
516
+ @login_required
517
+ def mark_message_seen():
518
+ page_id = session.get('page_id')
519
+ message_index = request.json.get('index')
520
+
521
+ # Ensure message_index is an integer
522
+ try:
523
+ message_index = int(message_index)
524
+ except (ValueError, TypeError):
525
+ return jsonify({'success': False, 'message': 'مؤشر الرسالة غير صالح'})
526
+
527
+ # Get current messages
528
+ result = fetch_messages_json()
529
+ if not result['success']:
530
+ return jsonify({'success': False, 'message': 'فشل في جلب الرسائل'})
531
+
532
+ messages_data = result['data']
533
+ page_messages = messages_data.get(page_id, [])
534
+
535
+ # Sort messages by timestamp (newest first) to match the display order
536
+ page_messages = sorted(page_messages, key=lambda x: x.get('timestamp', ''), reverse=True)
537
+
538
+ # Check if the index is valid
539
+ if message_index < 0 or message_index >= len(page_messages):
540
+ return jsonify({'success': False, 'message': 'مؤشر الرسالة غير صالح'})
541
+
542
+ # Mark the message as seen
543
+ page_messages[message_index]['seen'] = True
544
+
545
+ # Re-sort messages back to their original order before saving
546
+ # This is needed because we're working with the sorted list but need to update the original data
547
+ original_messages = messages_data.get(page_id, [])
548
+
549
+ # Find the corresponding message in the original list by matching properties
550
+ message_to_mark = page_messages[message_index]
551
+ for orig_msg in original_messages:
552
+ if (orig_msg.get('message') == message_to_mark.get('message') and
553
+ orig_msg.get('sender_id') == message_to_mark.get('sender_id') and
554
+ orig_msg.get('timestamp') == message_to_mark.get('timestamp')):
555
+ orig_msg['seen'] = True
556
+ break
557
+
558
+ # Update messages data
559
+ messages_data[page_id] = original_messages
560
+
561
+ # Get tokens for updating
562
+ auth_token, commit_oid = fetch_messages_tokens()
563
+ if not auth_token or not commit_oid:
564
+ return jsonify({'success': False, 'message': 'فشل في الحصول على رموز المصادقة'})
565
+
566
+ # Update the file
567
+ result = update_messages_json(auth_token, commit_oid, json.dumps(messages_data))
568
+
569
+ if result['success']:
570
+ # Update cache
571
+ messages_cache[page_id] = original_messages
572
+ # Notify clients about the message being seen
573
+ socketio.emit('message_seen', {'page_id': page_id, 'index': message_index})
574
+ return jsonify({'success': True, 'message': 'تم تعليم الرسالة كمقروءة'})
575
+ else:
576
+ return jsonify({'success': False, 'message': 'فشل في تحديث حالة الرسالة'})
577
+ @app.route('/api/delete_message', methods=['POST'])
578
+ @login_required
579
+ def delete_message():
580
+ page_id = session.get('page_id')
581
+ message_index = request.json.get('index')
582
+
583
+ # Ensure message_index is an integer
584
+ try:
585
+ message_index = int(message_index)
586
+ except (ValueError, TypeError):
587
+ return jsonify({'success': False, 'message': 'مؤشر الرسالة غير صالح'})
588
+
589
+ # Get current messages
590
+ result = fetch_messages_json()
591
+ if not result['success']:
592
+ return jsonify({'success': False, 'message': 'فشل في جلب الرسائل'})
593
+
594
+ messages_data = result['data']
595
+ page_messages = messages_data.get(page_id, [])
596
+
597
+ # Sort messages by timestamp (newest first) to match the display order
598
+ sorted_messages = sorted(page_messages, key=lambda x: x.get('timestamp', ''), reverse=True)
599
+
600
+ # Check if the index is valid
601
+ if message_index < 0 or message_index >= len(sorted_messages):
602
+ return jsonify({'success': False, 'message': 'مؤشر الرسالة غير صالح'})
603
+
604
+ # Get the message to delete
605
+ message_to_delete = sorted_messages[message_index]
606
+
607
+ # Find and remove the message from the original list
608
+ original_messages = messages_data.get(page_id, [])
609
+ for i, msg in enumerate(original_messages):
610
+ if (msg.get('message') == message_to_delete.get('message') and
611
+ msg.get('sender_id') == message_to_delete.get('sender_id') and
612
+ msg.get('timestamp') == message_to_delete.get('timestamp')):
613
+ original_messages.pop(i)
614
+ break
615
+
616
+ # Update messages data
617
+ messages_data[page_id] = original_messages
618
+
619
+ # Get tokens for updating
620
+ auth_token, commit_oid = fetch_messages_tokens()
621
+ if not auth_token or not commit_oid:
622
+ return jsonify({'success': False, 'message': 'فشل في الحصول على رموز المصادقة'})
623
+
624
+ # Update the file
625
+ result = update_messages_json(auth_token, commit_oid, json.dumps(messages_data))
626
+
627
+ if result['success']:
628
+ # Update cache
629
+ messages_cache[page_id] = original_messages
630
+ # Notify all clients about the message deletion
631
+ socketio.emit('message_deleted', {'page_id': page_id, 'index': message_index})
632
+ return jsonify({'success': True, 'message': 'تم حذف الرسالة بنجاح'})
633
+ else:
634
+ return jsonify({'success': False, 'message': 'فشل في حذف الرسالة'})
635
+
636
+ # WebSocket events
637
+ @socketio.on('connect')
638
+ def handle_connect():
639
+ # Start background thread if not already running
640
+ global thread
641
+ with thread_lock:
642
+ if thread is None:
643
+ thread = socketio.start_background_task(background_thread)
644
+ emit('connected', {'data': 'Connected'})
645
+
646
+ @socketio.on('request_messages_update')
647
+ def handle_messages_update(data):
648
+ page_id = data.get('page_id')
649
+ if page_id:
650
+ messages = get_messages(page_id, force_refresh=True)
651
+ emit('messages_updated', {'page_id': page_id, 'messages': messages})
652
 
653
  if __name__ == '__main__':
654
+ socketio.run(host="0.0.0.0", port=7860, debug=True ,app)