Dooratre commited on
Commit
8a420b0
·
verified ·
1 Parent(s): c1f9f48

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +214 -383
app.py CHANGED
@@ -1,416 +1,247 @@
1
- import time
 
 
 
2
  import json
3
- import requests
4
- import re
5
- import logging
6
- from flask import Flask, jsonify
7
- from apscheduler.schedulers.background import BackgroundScheduler
8
- from datetime import datetime, timedelta
9
- from db import deeper, signals
10
- from ai import analyze_forex_pairs
11
-
12
- # Configure logging
13
- logging.basicConfig(
14
- level=logging.INFO,
15
- format='%(asctime)s - %(levelname)s - %(message)s'
16
- )
17
- logger = logging.getLogger(__name__)
18
-
19
- # Initialize Flask app
20
- app = Flask(__name__)
21
 
22
- # Message API configuration
23
- MESSAGE_API_URL = "https://aoamrnuwara.pythonanywhere.com/api/send-message"
24
- MESSAGE_API_KEY = "Seakp0683asppoit"
25
 
26
- def send_message_to_api(message):
27
- """Send a message via the message forwarding API."""
28
- headers = {
29
- "Content-Type": "application/json",
30
- "X-API-Key": MESSAGE_API_KEY
 
 
 
 
 
 
31
  }
32
 
33
- payload = {
34
- "message": message
35
- }
36
 
37
- try:
38
- logger.info("Sending message via API")
39
- response = requests.post(MESSAGE_API_URL, headers=headers, data=json.dumps(payload))
40
- response.raise_for_status()
41
- response_json = response.json()
42
- logger.info(f"Message sent to API successfully. Status Code: {response.status_code}")
43
- return {"success": True, "response": response_json}
44
- except requests.exceptions.RequestException as e:
45
- logger.error(f"API request error: {e}", exc_info=True)
46
- return {"success": False, "error": str(e)}
47
- except Exception as e:
48
- logger.error(f"Unexpected error sending message to API: {e}", exc_info=True)
49
- return {"success": False, "error": str(e)}
50
-
51
- def get_active_signals():
52
- """Get all active signals from the signals database"""
53
- signals_response = signals.fetch_json_from_github()
54
-
55
- if not signals_response["success"]:
56
- logger.error(f"Error fetching signals data: {signals_response['message']}")
57
- return "لا توجد صفقات نشطة حالياً."
58
-
59
- signals_data = signals_response["data"]
60
-
61
- # Defensive check - ensure signals_data is a list
62
- if not isinstance(signals_data, list) or len(signals_data) == 0:
63
- logger.warning("No active signals found in database")
64
- return "لا توجد صفقات نشطة حالياً."
65
-
66
- deals_string = []
67
- for signal in signals_data:
68
- deal = f"الزوج: {signal.get('pair', '')}, "
69
- deal += f"النوع: {signal.get('type', '')}, "
70
- deal += f"سعر الدخول: {signal.get('entry', '')}, "
71
- deal += f"وقف الخسارة: {signal.get('stop_loss', '')}, "
72
- deal += f"الهدف: {signal.get('take_profit', '')}"
73
- deals_string.append(deal)
74
-
75
- if not deals_string:
76
- return "لا توجد صفقات نشطة حالياً."
77
-
78
- return "\n".join(deals_string)
79
-
80
- def extract_signal_from_ai_response(response):
81
- """Extract signal data from AI response if present"""
82
- signal_pattern = r'<signal>(.*?)</signal>'
83
- match = re.search(signal_pattern, response, re.DOTALL)
84
-
85
- if not match:
86
- return None
87
-
88
- signal_text = match.group(1)
89
-
90
- # Extract individual fields from signal - full format
91
- pair_match = re.search(r'<pair>(.*?)</pair>', signal_text, re.DOTALL)
92
- type_match = re.search(r'<type>(.*?)</type>', signal_text, re.DOTALL)
93
- entry_match = re.search(r'<entry>(.*?)</entry>', signal_text, re.DOTALL)
94
- stop_loss_match = re.search(r'<stop_loss>(.*?)</stop_loss>', signal_text, re.DOTALL)
95
- take_profit_match = re.search(r'<take_profit>(.*?)</take_profit>', signal_text, re.DOTALL)
96
- duration_match = re.search(r'<duration>(.*?)</duration>', signal_text, re.DOTALL)
97
- reason_match = re.search(r'<reason>(.*?)</reason>', signal_text, re.DOTALL)
98
-
99
- # Create signal dictionary
100
- signal_data = {
101
- "pair": pair_match.group(1).strip() if pair_match else "",
102
- "timeframe": "15min", # Default timeframe
103
- "type": type_match.group(1).strip() if type_match else "",
104
- "entry": entry_match.group(1).strip() if entry_match else "",
105
- "stop_loss": stop_loss_match.group(1).strip() if stop_loss_match else "",
106
- "take_profit": take_profit_match.group(1).strip() if take_profit_match else "",
107
- "duration": duration_match.group(1).strip() if duration_match else "1-3 ساعات",
108
- "reason": reason_match.group(1).strip() if reason_match else "تم التحليل بواسطة النظام الآلي",
109
- "status": "starting"
110
- }
111
 
112
- return signal_data
 
113
 
114
- def check_if_pairs_exist_in_signals(pairs_list):
115
- """Check if a list of pairs already exists in the signals database"""
116
- signals_response = signals.fetch_json_from_github()
117
 
118
- if not signals_response["success"]:
119
- logger.error(f"Error fetching signals data: {signals_response['message']}")
120
- return False
 
 
 
 
 
121
 
122
- signals_data = signals_response["data"]
 
 
 
 
 
 
123
 
124
- # Defensive check - ensure signals_data is a list
125
- if not isinstance(signals_data, list):
126
- logger.warning(f"signals_data is not a list (type: {type(signals_data)}), converting to empty list")
127
- signals_data = []
128
 
129
- # Convert pairs_list to a sorted JSON string for consistent comparison
130
- pairs_json = json.dumps(sorted(pairs_list), ensure_ascii=False)
 
 
131
 
132
- # Check if pairs list exists
133
- for signal in signals_data:
134
- if "pairs" in signal and json.dumps(sorted(signal.get("pairs", [])), ensure_ascii=False) == pairs_json:
135
- return True
136
 
137
- return False
 
 
 
 
138
 
139
- def update_signals_file(signal_data, pairs_list):
140
- """Update signals JSON file with new signal data including pairs list"""
141
- # Fetch current signals data
142
- signals_response = signals.fetch_json_from_github()
143
 
144
- if not signals_response["success"]:
145
- logger.error(f"Error fetching signals data: {signals_response['message']}")
146
- return False
147
 
148
- signals_data = signals_response["data"]
 
 
 
149
 
150
- # Defensive check - ensure signals_data is a list
151
- if not isinstance(signals_data, list):
152
- logger.warning(f"signals_data is not a list (type: {type(signals_data)}), converting to empty list")
153
- signals_data = []
154
 
155
- # Add pairs list to the signal data
156
- signal_data["pairs"] = pairs_list
 
 
 
 
 
157
 
158
- # Add new signal
159
- signals_data.append(signal_data)
 
160
 
161
- # Get authenticity token and commit OID for signals file
162
- auth_token, commit_oid = signals.fetch_authenticity_token_and_commit_oid()
163
- if not auth_token or not commit_oid:
164
- logger.error("Failed to get authenticity token or commit OID for signals file")
165
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
- # Update the signals file - using json.dumps with separators to ensure a single line
168
- update_response = signals.update_user_json_file(
169
- auth_token,
170
- commit_oid,
171
- json.dumps(signals_data, ensure_ascii=False, separators=(',', ':'))
172
- )
173
 
174
- return update_response["success"]
 
 
 
175
 
176
- def remove_group_from_deeper(group_key):
177
- """Remove analyzed group from deeper.json file"""
178
- # Fetch current deeper data
179
- deeper_response = deeper.fetch_json_from_github()
 
180
 
181
- if not deeper_response["success"]:
182
- logger.error(f"Error fetching deeper data: {deeper_response['message']}")
183
- return False
184
 
185
- deeper_data = deeper_response["data"]
 
 
186
 
187
- # Remove the group from forwards if it exists
188
- if group_key in deeper_data.get("forwards", {}):
189
- del deeper_data["forwards"][group_key]
190
 
191
- # Get authenticity token and commit OID for deeper file
192
- auth_token, commit_oid = deeper.fetch_authenticity_token_and_commit_oid()
193
- if not auth_token or not commit_oid:
194
- logger.error("Failed to get authenticity token or commit OID for deeper file")
195
- return False
196
-
197
- # Update the deeper file - using json.dumps with separators to ensure a single line
198
- update_response = deeper.update_user_json_file(
199
- auth_token,
200
- commit_oid,
201
- json.dumps(deeper_data, ensure_ascii=False, separators=(',', ':'))
202
- )
203
-
204
- return update_response["success"]
205
-
206
- def format_telegram_message(signal_data):
207
- """تنسيق إشارة الفوركس للإرسال عبر تيليجرام - بصيغة احترافية"""
208
- message = "🔔 <b>إشارة فوركس جديدة</b> 🔔\n\n"
209
- message += f"<b>🔹 الزوج:</b> {signal_data['pair']}\n"
210
- message += f"<b>📊 النوع:</b> {signal_data['type']}\n"
211
- message += f"<b>🎯 الد��ول:</b> {signal_data['entry']}\n"
212
- message += f"<b>🛡️ وقف الخسارة:</b> {signal_data['stop_loss']}\n"
213
- message += f"<b>💰 الهدف:</b> {signal_data['take_profit']}\n"
214
-
215
- return message
216
-
217
- def analyze_forex_groups():
218
- """Function to analyze forex groups from the deeper.json file"""
219
- logger.info("Starting forex group analysis cycle")
220
-
221
- try:
222
- # Fetch data from deeper.json
223
- deeper_response = deeper.fetch_json_from_github()
224
-
225
- if not deeper_response["success"]:
226
- logger.error(f"Error fetching deeper data: {deeper_response['message']}")
227
- return
228
-
229
- deeper_data = deeper_response["data"]
230
-
231
- # Check if system is enabled
232
- if not deeper_data.get("status", False):
233
- logger.info("System is currently turned OFF. Please turn it ON to continue.")
234
- return
235
-
236
- # Get active signals to pass to AI
237
- active_deals = get_active_signals()
238
- logger.info(f"Active deals: {active_deals}")
239
-
240
- # Process each forex group in the forwards section
241
- for group_key, group_data in deeper_data.get("forwards", {}).items():
242
- pairs = group_data.get("pairs", [])
243
- message = group_data.get("message", "")
244
-
245
- if not pairs:
246
- logger.warning(f"Group {group_key} has no pairs. Skipping.")
247
- continue
248
-
249
- logger.info(f"Analyzing group {group_key} with pairs: {', '.join(pairs)}")
250
-
251
- # Check if this group already exists in signals database
252
- if check_if_pairs_exist_in_signals(pairs):
253
- logger.info(f"Signal for group {group_key} already exists in database. Skipping analysis.")
254
-
255
- # Remove the group from deeper.json since we're not processing it
256
- if remove_group_from_deeper(group_key):
257
- logger.info(f"Group {group_key} removed from deeper.json successfully")
258
- else:
259
- logger.error(f"Failed to remove group {group_key} from deeper.json")
260
-
261
- continue
262
-
263
- # Call AI to analyze the forex pairs with active deals
264
- ai_response = analyze_forex_pairs(pairs, message, active_deals)
265
-
266
- # Check if the AI response contains a signal
267
- signal_data = extract_signal_from_ai_response(ai_response)
268
-
269
- if signal_data:
270
- logger.info(f"Signal detected for group {group_key}")
271
-
272
- # Update signals file with the new signal, including pairs list
273
- if update_signals_file(signal_data, pairs):
274
- logger.info(f"Signal for group {group_key} saved successfully")
275
-
276
- # Format message and send via API instead of directly to Telegram
277
- formatted_message = format_telegram_message(signal_data)
278
- logger.info("Attempting to send message via API...")
279
- api_response = send_message_to_api(formatted_message)
280
-
281
- if api_response["success"]:
282
- logger.info(f"Message for group {group_key} sent successfully via API")
283
- else:
284
- logger.error(f"Failed to send message for group {group_key} via API. Error: {api_response.get('error')}")
285
-
286
- # Remove the group from deeper.json
287
- if remove_group_from_deeper(group_key):
288
- logger.info(f"Group {group_key} removed from deeper.json successfully")
289
- else:
290
- logger.error(f"Failed to remove group {group_key} from deeper.json")
291
- else:
292
- logger.error(f"Failed to save signal for group {group_key}")
293
- else:
294
- logger.info(f"No signal detected in AI response for group {group_key}")
295
 
296
- logger.info("Analysis cycle completed successfully")
297
-
298
- except Exception as e:
299
- logger.error(f"Error in analyze_forex_groups: {e}", exc_info=True)
 
300
 
301
- # Flask routes
302
- @app.route('/')
303
- def health_check():
304
- """Health check endpoint to verify the service is running"""
305
- return jsonify({
306
- "status": "running",
307
- "message": "Forex Analysis System is active"
308
- })
309
-
310
- @app.route('/analyze/now')
311
- def trigger_analysis():
312
- """Endpoint to manually trigger analysis"""
313
- try:
314
- analyze_forex_groups()
315
- return jsonify({
316
- "status": "success",
317
- "message": "Analysis triggered successfully"
318
- })
319
- except Exception as e:
320
- logger.error(f"Error triggering analysis: {e}", exc_info=True)
321
- return jsonify({
322
- "status": "error",
323
- "message": f"Error triggering analysis: {str(e)}"
324
- }), 500
325
-
326
- @app.route('/status')
327
- def get_status():
328
- """Endpoint to get system status"""
329
- try:
330
- deeper_response = deeper.fetch_json_from_github()
331
- if deeper_response["success"]:
332
- system_status = deeper_response["data"].get("status", False)
333
- return jsonify({
334
- "system_enabled": system_status,
335
- "service_status": "running"
336
- })
337
- else:
338
- return jsonify({
339
- "service_status": "running",
340
- "error": deeper_response["message"]
341
- })
342
- except Exception as e:
343
- logger.error(f"Error getting status: {e}", exc_info=True)
344
- return jsonify({
345
- "service_status": "running",
346
- "error": str(e)
347
- })
348
-
349
- def schedule_candle_analysis():
350
- """Schedule analysis at candle close times (00, 15, 30, 45)"""
351
- now = datetime.now()
352
- current_minute = now.minute
353
-
354
- # Calculate the next 15-minute mark
355
- if current_minute < 17:
356
- next_minute = 17
357
- elif current_minute < 32:
358
- next_minute = 32
359
- elif current_minute < 47:
360
- next_minute = 47
361
- else:
362
- next_minute = 0 # Next hour
363
 
364
- # Calculate the target time
365
- if next_minute == 0:
366
- target_time = datetime(now.year, now.month, now.day, now.hour, 0, 0) + timedelta(hours=1)
367
  else:
368
- target_time = datetime(now.year, now.month, now.day, now.hour, next_minute, 0)
369
-
370
- # Calculate seconds until next run
371
- time_diff = (target_time - now).total_seconds()
372
-
373
- logger.info(f"Scheduling analysis to run at {target_time.strftime('%H:%M:%S')} (in {time_diff:.1f} seconds)")
374
-
375
- # Schedule the job
376
- scheduler.add_job(
377
- run_analysis_and_reschedule,
378
- 'date',
379
- run_date=target_time,
380
- id='candle_analysis'
381
- )
382
-
383
- def run_analysis_and_reschedule():
384
- """Run the analysis and schedule the next run"""
385
- logger.info("Running scheduled analysis at candle close")
386
- try:
387
- analyze_forex_groups()
388
- except Exception as e:
389
- logger.error(f"Error in scheduled analysis: {e}", exc_info=True)
390
- finally:
391
- # Always reschedule the next run
392
- schedule_candle_analysis()
393
-
394
- # Initialize scheduler
395
- scheduler = BackgroundScheduler()
396
-
397
- def start_scheduler():
398
- """Start the scheduler with the analysis job at candle close times"""
399
- logger.info("Starting scheduler for forex analysis at candle close times (00, 15, 30, 45)")
400
-
401
- # Schedule the first analysis
402
- schedule_candle_analysis()
403
-
404
- # Start the scheduler if it's not already running
405
- if not scheduler.running:
406
- scheduler.start()
407
- logger.info("Scheduler started successfully")
408
-
409
- if __name__ == "__main__":
410
- logger.info("Starting Forex Analysis System...")
411
-
412
- # Start the scheduler
413
- start_scheduler()
414
-
415
- # Start the Flask application
416
  app.run(host='0.0.0.0', port=7860, debug=False)
 
1
+ from flask import Flask, render_template, request, redirect, url_for, jsonify, flash
2
+ from db import signals as signals_module
3
+ from db import deeper as deeper_module
4
+ from db import paires as paires_module
5
  import json
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ app = Flask(__name__)
8
+ app.secret_key = 'trading_signals_secret_key'
 
9
 
10
+ @app.route('/')
11
+ def index():
12
+ # Fetch signals from GitHub
13
+ signals_response = signals_module.fetch_json_from_github()
14
+ deeper_response = deeper_module.fetch_json_from_github()
15
+ paires_response = paires_module.fetch_json_from_github()
16
+
17
+ signals_data = []
18
+ system_status = {
19
+ 'deeper': False,
20
+ 'paires': False
21
  }
22
 
23
+ if signals_response['success']:
24
+ signals_data = signals_response['data']
 
25
 
26
+ if deeper_response['success']:
27
+ system_status['deeper'] = deeper_response['data'].get('status', False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
+ if paires_response['success']:
30
+ system_status['paires'] = paires_response['data'].get('status', False)
31
 
32
+ return render_template('index.html',
33
+ signals=signals_data,
34
+ system_status=system_status)
35
 
36
+ @app.route('/signals', methods=['GET'])
37
+ def get_signals():
38
+ # Fetch signals from GitHub
39
+ response = signals_module.fetch_json_from_github()
40
+ if response['success']:
41
+ return jsonify(response['data'])
42
+ else:
43
+ return jsonify({"error": response['message']}), 500
44
 
45
+ @app.route('/signals/delete/<int:signal_id>', methods=['POST'])
46
+ def delete_signal(signal_id):
47
+ # Get current signals
48
+ response = signals_module.fetch_json_from_github()
49
+ if not response['success']:
50
+ flash('Failed to fetch signals data', 'error')
51
+ return redirect(url_for('index'))
52
 
53
+ signals_data = response['data']
 
 
 
54
 
55
+ # Check if signal_id is valid
56
+ if signal_id < 0 or signal_id >= len(signals_data):
57
+ flash('Invalid signal ID', 'error')
58
+ return redirect(url_for('index'))
59
 
60
+ # Remove the signal
61
+ signals_data.pop(signal_id)
 
 
62
 
63
+ # Update the signals.json file
64
+ auth_token, commit_oid = signals_module.fetch_authenticity_token_and_commit_oid()
65
+ if not auth_token or not commit_oid:
66
+ flash('Failed to get authentication tokens', 'error')
67
+ return redirect(url_for('index'))
68
 
69
+ # Convert the updated signals data to JSON string
70
+ new_content = json.dumps(signals_data, ensure_ascii=False)
 
 
71
 
72
+ # Update the signals.json file
73
+ update_response = signals_module.update_user_json_file(auth_token, commit_oid, new_content)
 
74
 
75
+ if update_response['success']:
76
+ flash('Signal deleted successfully', 'success')
77
+ else:
78
+ flash(f'Failed to delete signal: {update_response["message"]}', 'error')
79
 
80
+ return redirect(url_for('index'))
 
 
 
81
 
82
+ @app.route('/signals/delete_all', methods=['POST'])
83
+ def delete_all_signals():
84
+ # Get authentication tokens
85
+ auth_token, commit_oid = signals_module.fetch_authenticity_token_and_commit_oid()
86
+ if not auth_token or not commit_oid:
87
+ flash('Failed to get authentication tokens', 'error')
88
+ return redirect(url_for('index'))
89
 
90
+ # Create an empty array for signals
91
+ empty_signals = []
92
+ new_content = json.dumps(empty_signals, ensure_ascii=False)
93
 
94
+ # Update the signals.json file
95
+ update_response = signals_module.update_user_json_file(auth_token, commit_oid, new_content)
96
+
97
+ if update_response['success']:
98
+ flash('All signals deleted successfully', 'success')
99
+ else:
100
+ flash(f'Failed to delete all signals: {update_response["message"]}', 'error')
101
+
102
+ return redirect(url_for('index'))
103
+
104
+ @app.route('/signals/edit/<int:signal_id>', methods=['GET', 'POST'])
105
+ def edit_signal(signal_id):
106
+ # Get current signals
107
+ response = signals_module.fetch_json_from_github()
108
+ if not response['success']:
109
+ flash('Failed to fetch signals data', 'error')
110
+ return redirect(url_for('index'))
111
+
112
+ signals_data = response['data']
113
+
114
+ # Check if signal_id is valid
115
+ if signal_id < 0 or signal_id >= len(signals_data):
116
+ flash('Invalid signal ID', 'error')
117
+ return redirect(url_for('index'))
118
+
119
+ if request.method == 'POST':
120
+ # Update signal with form data
121
+ signals_data[signal_id]['pair'] = request.form['pair']
122
+ signals_data[signal_id]['timeframe'] = request.form['timeframe']
123
+ signals_data[signal_id]['type'] = request.form['type']
124
+ signals_data[signal_id]['entry'] = request.form['entry']
125
+ signals_data[signal_id]['stop_loss'] = request.form['stop_loss']
126
+ signals_data[signal_id]['take_profit'] = request.form['take_profit']
127
+ signals_data[signal_id]['duration'] = request.form['duration']
128
+ signals_data[signal_id]['reason'] = request.form['reason']
129
+ signals_data[signal_id]['status'] = request.form['status']
130
+
131
+ # Get authentication tokens
132
+ auth_token, commit_oid = signals_module.fetch_authenticity_token_and_commit_oid()
133
+ if not auth_token or not commit_oid:
134
+ flash('Failed to get authentication tokens', 'error')
135
+ return redirect(url_for('index'))
136
+
137
+ # Convert the updated signals data to JSON string
138
+ new_content = json.dumps(signals_data, ensure_ascii=False)
139
+
140
+ # Update the signals.json file
141
+ update_response = signals_module.update_user_json_file(auth_token, commit_oid, new_content)
142
+
143
+ if update_response['success']:
144
+ flash('Signal updated successfully', 'success')
145
+ return redirect(url_for('index'))
146
+ else:
147
+ flash(f'Failed to update signal: {update_response["message"]}', 'error')
148
+ return redirect(url_for('index'))
149
+
150
+ # GET request - display edit form with current signal data
151
+ return render_template('edit_signal.html', signal=signals_data[signal_id], signal_id=signal_id)
152
+
153
+ @app.route('/signals/add', methods=['GET', 'POST'])
154
+ def add_signal():
155
+ if request.method == 'POST':
156
+ # Get current signals
157
+ response = signals_module.fetch_json_from_github()
158
+ if not response['success']:
159
+ flash('Failed to fetch signals data', 'error')
160
+ return redirect(url_for('index'))
161
+
162
+ signals_data = response['data']
163
+
164
+ # Create new signal from form data
165
+ new_signal = {
166
+ 'pair': request.form['pair'],
167
+ 'timeframe': request.form['timeframe'],
168
+ 'type': request.form['type'],
169
+ 'entry': request.form['entry'],
170
+ 'stop_loss': request.form['stop_loss'],
171
+ 'take_profit': request.form['take_profit'],
172
+ 'duration': request.form['duration'],
173
+ 'reason': request.form['reason'],
174
+ 'status': request.form['status']
175
+ }
176
+
177
+ # Add new signal to the beginning of the list
178
+ signals_data.insert(0, new_signal)
179
+
180
+ # Get authentication tokens
181
+ auth_token, commit_oid = signals_module.fetch_authenticity_token_and_commit_oid()
182
+ if not auth_token or not commit_oid:
183
+ flash('Failed to get authentication tokens', 'error')
184
+ return redirect(url_for('index'))
185
+
186
+ # Convert the updated signals data to JSON string
187
+ new_content = json.dumps(signals_data, ensure_ascii=False)
188
+
189
+ # Update the signals.json file
190
+ update_response = signals_module.update_user_json_file(auth_token, commit_oid, new_content)
191
+
192
+ if update_response['success']:
193
+ flash('Signal added successfully', 'success')
194
+ return redirect(url_for('index'))
195
+ else:
196
+ flash(f'Failed to add signal: {update_response["message"]}', 'error')
197
+ return redirect(url_for('index'))
198
 
199
+ # GET request - display add form
200
+ return render_template('add_signal.html')
 
 
 
 
201
 
202
+ @app.route('/system/toggle', methods=['POST'])
203
+ def toggle_system():
204
+ system_type = request.form.get('system_type')
205
+ new_status = request.form.get('status') == 'true'
206
 
207
+ if system_type == 'deeper':
208
+ # Update deeper.json
209
+ response = deeper_module.fetch_json_from_github()
210
+ if not response['success']:
211
+ return jsonify({"success": False, "message": "Failed to fetch deeper.json data"}), 500
212
 
213
+ deeper_data = response['data']
214
+ deeper_data['status'] = new_status
 
215
 
216
+ auth_token, commit_oid = deeper_module.fetch_authenticity_token_and_commit_oid()
217
+ if not auth_token or not commit_oid:
218
+ return jsonify({"success": False, "message": "Failed to get authentication tokens"}), 500
219
 
220
+ new_content = json.dumps(deeper_data, ensure_ascii=False)
221
+ update_response = deeper_module.update_user_json_file(auth_token, commit_oid, new_content)
 
222
 
223
+ return jsonify(update_response)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
+ elif system_type == 'paires':
226
+ # Update paires.json
227
+ response = paires_module.fetch_json_from_github()
228
+ if not response['success']:
229
+ return jsonify({"success": False, "message": "Failed to fetch paires.json data"}), 500
230
 
231
+ paires_data = response['data']
232
+ paires_data['status'] = new_status
233
+
234
+ auth_token, commit_oid = paires_module.fetch_authenticity_token_and_commit_oid()
235
+ if not auth_token or not commit_oid:
236
+ return jsonify({"success": False, "message": "Failed to get authentication tokens"}), 500
237
+
238
+ new_content = json.dumps(paires_data, ensure_ascii=False)
239
+ update_response = paires_module.update_user_json_file(auth_token, commit_oid, new_content)
240
+
241
+ return jsonify(update_response)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
 
 
 
243
  else:
244
+ return jsonify({"success": False, "message": "Invalid system type"}), 400
245
+
246
+ if __name__ == '__main__':
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  app.run(host='0.0.0.0', port=7860, debug=False)