AstraOS commited on
Commit
8147bba
·
verified ·
1 Parent(s): 4a0b1c1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +35 -34
app.py CHANGED
@@ -16,9 +16,9 @@ app = FastAPI()
16
  # (No token or outgoing HTTP calls are used in this version.)
17
  # Conversation state
18
  user_inputs = {}
19
- # The conversation fields will depend on the mode.
20
- # Simple mode (default): Only "input_url" and "output_url" are required.
21
- # Advanced mode (if user sends /setting): Additional fields are required.
22
  conversation_fields = []
23
  current_step = None
24
  advanced_mode = False
@@ -32,7 +32,7 @@ default_settings = {
32
  }
33
 
34
  # Streaming state & statistics
35
- streaming_state = "idle" # "idle", "streaming", "paused", "stopped"
36
  stream_chat_id = None # Chat ID for periodic updates
37
  stream_start_time = None
38
  frames_encoded = 0
@@ -48,9 +48,8 @@ stream_thread = None
48
  live_log_thread = None
49
 
50
  # Live logging globals
51
- live_log_lines = [] # Rolling list (max 50 log lines)
52
- live_log_display = "" # Global variable updated every second by live_log_updater
53
- error_notification = "" # Global variable to hold error details if any
54
 
55
  # -------------------------------------------------------------------
56
  # Enhanced Logging Setup
@@ -81,11 +80,11 @@ logger.addHandler(list_handler)
81
  # Utility Functions & UI Helpers
82
  # -------------------------------------------------------------------
83
  def create_html_message(text: str):
84
- # Wrap text in <pre> tags for monospaced output using HTML parse mode
85
  return {"parse_mode": "HTML", "text": f"<pre>{text}</pre>"}
86
 
87
  def get_inline_keyboard_for_stream():
88
- # Inline keyboard for streaming controls that remain visible in the message
89
  keyboard = {
90
  "inline_keyboard": [
91
  [
@@ -101,7 +100,7 @@ def get_inline_keyboard_for_stream():
101
  return keyboard
102
 
103
  def get_inline_keyboard_for_start():
104
- # Inline keyboard with a start button for when setup is complete.
105
  keyboard = {
106
  "inline_keyboard": [
107
  [
@@ -127,7 +126,7 @@ def help_text():
127
  )
128
 
129
  def send_guide_message(chat_id, message):
130
- # Returns a response dictionary (Markdown format) to be sent as the webhook reply
131
  logging.info(f"Sending message to chat {chat_id}: {message}")
132
  return {
133
  "method": "sendMessage",
@@ -137,7 +136,7 @@ def send_guide_message(chat_id, message):
137
  }
138
 
139
  def send_guide_message_html(chat_id, message):
140
- # Returns a response dictionary (HTML format) to be sent as the webhook reply
141
  logging.info(f"Sending HTML message to chat {chat_id}: {message}")
142
  return {
143
  "method": "sendMessage",
@@ -159,15 +158,14 @@ def get_uptime():
159
  return "0"
160
 
161
  def validate_inputs():
162
- # Ensure all fields in conversation_fields have been provided
163
  missing = [field for field in conversation_fields if field not in user_inputs or not user_inputs[field]]
164
  if missing:
165
  return False, f"Missing fields: {', '.join(missing)}"
166
  return True, ""
167
 
168
  def get_streaming_display_message(prefix=""):
169
- # Build an HTML message with a prefix, current streaming status, and live logs.
170
- global live_log_display, streaming_state, frames_encoded, bytes_sent
171
  status = (
172
  f"<b>Stream Status:</b>\n"
173
  f"State: {streaming_state}\n"
@@ -175,7 +173,14 @@ def get_streaming_display_message(prefix=""):
175
  f"Frames Encoded: {frames_encoded}\n"
176
  f"Bytes Sent: {bytes_sent}\n"
177
  )
178
- logs = live_log_display if live_log_display else "<pre>No logs available yet.</pre>"
 
 
 
 
 
 
 
179
  return f"{prefix}\n{status}\n\nLive Logs:\n{logs}"
180
 
181
  # -------------------------------------------------------------------
@@ -190,11 +195,11 @@ def notify_error(chat_id, error_message):
190
  # Live Log Updater (Background Thread)
191
  # -------------------------------------------------------------------
192
  def live_log_updater():
193
- global live_log_display, streaming_state
194
  try:
195
- while streaming_state in ["streaming", "paused"]:
196
- # Update live_log_display with the last 15 log lines in HTML format
197
- live_log_display = "<pre>" + "\n".join(live_log_lines[-15:]) + "</pre>"
198
  time.sleep(1)
199
  except Exception as e:
200
  logging.error(f"Error in live log updater: {e}")
@@ -203,10 +208,13 @@ def live_log_updater():
203
  # Logs History Handler (/logs)
204
  # -------------------------------------------------------------------
205
  def logs_history(chat_id):
206
- global live_log_display, error_notification
207
- # Use live_log_display if available; otherwise, show a default message.
208
- log_text = live_log_display if live_log_display else "<pre>No logs available yet.</pre>"
209
- # Prepend any error notification if present.
 
 
 
210
  if error_notification:
211
  if log_text.startswith("<pre>"):
212
  log_text = f"<pre>ERROR: {error_notification}\n\n" + log_text[5:]
@@ -224,7 +232,7 @@ def logs_history(chat_id):
224
  # -------------------------------------------------------------------
225
  def handle_start(chat_id):
226
  global current_step, user_inputs, conversation_fields, advanced_mode
227
- # Use simple mode by default (unless advanced_mode was set via /setting)
228
  user_inputs = {}
229
  if not advanced_mode:
230
  conversation_fields = ["input_url", "output_url"]
@@ -337,14 +345,14 @@ def stream_to_youtube(input_url, quality_settings, video_codec, audio_codec, out
337
  out_audio_stream.layout = "stereo"
338
  video_stream.codec_context.time_base = fractions.Fraction(1, video_stream.rate)
339
  logging.info("Streaming started successfully.")
340
- # Start live log updater if not already running
341
  global live_log_thread
342
  if live_log_thread is None or not live_log_thread.is_alive():
343
  live_log_thread = threading.Thread(target=live_log_updater)
344
  live_log_thread.daemon = True
345
  live_log_thread.start()
346
  logging.info("Live log updater thread started.")
347
- # Stream loop
348
  while streaming_state in ["streaming", "paused"]:
349
  for packet in input_stream.demux():
350
  if streaming_state == "stopped":
@@ -484,8 +492,6 @@ def stream_status(chat_id):
484
  async def telegram_webhook(request: Request):
485
  update = await request.json()
486
  logging.debug(f"Received update: {update}")
487
-
488
- # Process messages from users
489
  if "message" in update:
490
  chat_id = update["message"]["chat"]["id"]
491
  text = update["message"].get("text", "").strip()
@@ -507,13 +513,10 @@ async def telegram_webhook(request: Request):
507
  return stream_status(chat_id)
508
  else:
509
  return handle_conversation(chat_id, text)
510
-
511
- # Process inline keyboard callback queries
512
  elif "callback_query" in update:
513
  callback_data = update["callback_query"]["data"]
514
  chat_id = update["callback_query"]["message"]["chat"]["id"]
515
  message_id = update["callback_query"]["message"]["message_id"]
516
-
517
  if callback_data == "pause":
518
  response = pause_stream(chat_id)
519
  elif callback_data == "resume":
@@ -526,10 +529,8 @@ async def telegram_webhook(request: Request):
526
  response = start_streaming(chat_id)
527
  else:
528
  response = send_guide_message_html(chat_id, "❓ Unknown callback command.")
529
- # Update the original message while preserving inline keyboard
530
  response["method"] = "editMessageText"
531
  response["message_id"] = message_id
532
  response["reply_markup"] = get_inline_keyboard_for_stream()
533
  return response
534
-
535
  return {"status": "ok"}
 
16
  # (No token or outgoing HTTP calls are used in this version.)
17
  # Conversation state
18
  user_inputs = {}
19
+ # Conversation fields depend on the mode:
20
+ # Simple mode (default): only "input_url" and "output_url" are required.
21
+ # Advanced mode (if user sends /setting): additional fields are required.
22
  conversation_fields = []
23
  current_step = None
24
  advanced_mode = False
 
32
  }
33
 
34
  # Streaming state & statistics
35
+ streaming_state = "idle" # Can be "idle", "streaming", "paused", or "stopped"
36
  stream_chat_id = None # Chat ID for periodic updates
37
  stream_start_time = None
38
  frames_encoded = 0
 
48
  live_log_thread = None
49
 
50
  # Live logging globals
51
+ live_log_lines = [] # A rolling list of log lines (max 50 lines)
52
+ error_notification = "" # Holds error details (if any)
 
53
 
54
  # -------------------------------------------------------------------
55
  # Enhanced Logging Setup
 
80
  # Utility Functions & UI Helpers
81
  # -------------------------------------------------------------------
82
  def create_html_message(text: str):
83
+ # Return an HTML-formatted message wrapped in <pre> tags for monospaced output.
84
  return {"parse_mode": "HTML", "text": f"<pre>{text}</pre>"}
85
 
86
  def get_inline_keyboard_for_stream():
87
+ # Inline keyboard for stream controls; this keyboard is always returned along with status messages.
88
  keyboard = {
89
  "inline_keyboard": [
90
  [
 
100
  return keyboard
101
 
102
  def get_inline_keyboard_for_start():
103
+ # Inline keyboard with a "Start Streaming" button.
104
  keyboard = {
105
  "inline_keyboard": [
106
  [
 
126
  )
127
 
128
  def send_guide_message(chat_id, message):
129
+ # Return a response dictionary (Markdown format) for webhook replies.
130
  logging.info(f"Sending message to chat {chat_id}: {message}")
131
  return {
132
  "method": "sendMessage",
 
136
  }
137
 
138
  def send_guide_message_html(chat_id, message):
139
+ # Return a response dictionary (HTML format) for webhook replies.
140
  logging.info(f"Sending HTML message to chat {chat_id}: {message}")
141
  return {
142
  "method": "sendMessage",
 
158
  return "0"
159
 
160
  def validate_inputs():
161
+ # Check that all required fields have been provided.
162
  missing = [field for field in conversation_fields if field not in user_inputs or not user_inputs[field]]
163
  if missing:
164
  return False, f"Missing fields: {', '.join(missing)}"
165
  return True, ""
166
 
167
  def get_streaming_display_message(prefix=""):
168
+ # Build an HTML message that combines an optional prefix, current streaming status, and the last 15 log lines.
 
169
  status = (
170
  f"<b>Stream Status:</b>\n"
171
  f"State: {streaming_state}\n"
 
173
  f"Frames Encoded: {frames_encoded}\n"
174
  f"Bytes Sent: {bytes_sent}\n"
175
  )
176
+ if live_log_lines:
177
+ logs = "<pre>" + "\n".join(live_log_lines[-15:]) + "</pre>"
178
+ else:
179
+ logs = "<pre>No logs available yet.</pre>"
180
+ # Prepend any error notification if it exists.
181
+ global error_notification
182
+ if error_notification:
183
+ logs = f"<pre>ERROR: {error_notification}\n\n" + logs[5:]
184
  return f"{prefix}\n{status}\n\nLive Logs:\n{logs}"
185
 
186
  # -------------------------------------------------------------------
 
195
  # Live Log Updater (Background Thread)
196
  # -------------------------------------------------------------------
197
  def live_log_updater():
198
+ # This thread continuously (every 1 second) updates the global log display.
199
  try:
200
+ while True:
201
+ # (We no longer store the result in a separate variable;
202
+ # get_streaming_display_message computes the logs directly from live_log_lines.)
203
  time.sleep(1)
204
  except Exception as e:
205
  logging.error(f"Error in live log updater: {e}")
 
208
  # Logs History Handler (/logs)
209
  # -------------------------------------------------------------------
210
  def logs_history(chat_id):
211
+ # Return a response containing the last 50 log lines (if any) in HTML format.
212
+ if live_log_lines:
213
+ log_text = "<pre>" + "\n".join(live_log_lines[-50:]) + "</pre>"
214
+ else:
215
+ log_text = "<pre>No logs available yet.</pre>"
216
+ # Prepend error notification if present.
217
+ global error_notification
218
  if error_notification:
219
  if log_text.startswith("<pre>"):
220
  log_text = f"<pre>ERROR: {error_notification}\n\n" + log_text[5:]
 
232
  # -------------------------------------------------------------------
233
  def handle_start(chat_id):
234
  global current_step, user_inputs, conversation_fields, advanced_mode
235
+ # Use simple mode by default (unless advanced_mode has been enabled)
236
  user_inputs = {}
237
  if not advanced_mode:
238
  conversation_fields = ["input_url", "output_url"]
 
345
  out_audio_stream.layout = "stereo"
346
  video_stream.codec_context.time_base = fractions.Fraction(1, video_stream.rate)
347
  logging.info("Streaming started successfully.")
348
+ # Start live log updater (if not already running)
349
  global live_log_thread
350
  if live_log_thread is None or not live_log_thread.is_alive():
351
  live_log_thread = threading.Thread(target=live_log_updater)
352
  live_log_thread.daemon = True
353
  live_log_thread.start()
354
  logging.info("Live log updater thread started.")
355
+ # Streaming loop
356
  while streaming_state in ["streaming", "paused"]:
357
  for packet in input_stream.demux():
358
  if streaming_state == "stopped":
 
492
  async def telegram_webhook(request: Request):
493
  update = await request.json()
494
  logging.debug(f"Received update: {update}")
 
 
495
  if "message" in update:
496
  chat_id = update["message"]["chat"]["id"]
497
  text = update["message"].get("text", "").strip()
 
513
  return stream_status(chat_id)
514
  else:
515
  return handle_conversation(chat_id, text)
 
 
516
  elif "callback_query" in update:
517
  callback_data = update["callback_query"]["data"]
518
  chat_id = update["callback_query"]["message"]["chat"]["id"]
519
  message_id = update["callback_query"]["message"]["message_id"]
 
520
  if callback_data == "pause":
521
  response = pause_stream(chat_id)
522
  elif callback_data == "resume":
 
529
  response = start_streaming(chat_id)
530
  else:
531
  response = send_guide_message_html(chat_id, "❓ Unknown callback command.")
 
532
  response["method"] = "editMessageText"
533
  response["message_id"] = message_id
534
  response["reply_markup"] = get_inline_keyboard_for_stream()
535
  return response
 
536
  return {"status": "ok"}