Kanhshsh commited on
Commit
ba34f84
Β·
verified Β·
1 Parent(s): bea787a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +152 -54
app.py CHANGED
@@ -1,69 +1,167 @@
1
  import os
2
- import gradio as gr
3
- import logging
4
- from multiprocessing import Process
5
  from pyrogram import Client, filters
6
- from io import StringIO
7
- from time import sleep
8
 
9
- # ---------- FIXED CONFIG ----------
10
  API_ID = int(os.environ.get("API_ID", "6"))
11
  API_HASH = os.environ.get("API_HASH", "eb06d4abfb49dc3eeb1aeb98ae0f581e")
12
  BOT_TOKEN = os.environ.get("BOT_TOKEN", "7510817339:AAHFZoFzPkUO_-nAwfh9bjY_qHsWMprM2PI")
13
 
14
- # ---------- LOGGING ----------
15
- log_stream = StringIO()
16
- logging.basicConfig(stream=log_stream, level=logging.INFO, format="%(asctime)s - %(message)s")
17
- logger = logging.getLogger()
18
 
19
- # ---------- BOT FUNCTION ----------
20
- def run_bot():
21
- app = Client("my_bot", api_id=API_ID, api_hash=API_HASH, bot_token=BOT_TOKEN)
 
22
 
23
- @app.on_message(filters.command("start") & filters.private)
24
- async def start_cmd(client, message):
25
- await message.reply("hi")
26
- logger.info(f"Replied to /start from user ID: {message.from_user.id}")
27
 
28
- logger.info("Bot started.")
29
- app.run()
30
- logger.info("Bot stopped.")
 
 
 
31
 
32
- # ---------- PROCESS CONTROL ----------
33
- bot_process = None
 
 
 
34
 
35
  def start_bot():
36
- global bot_process
37
- if bot_process and bot_process.is_alive():
38
- return "Bot is already running."
39
- bot_process = Process(target=run_bot)
40
- bot_process.start()
41
- sleep(2)
42
- return "βœ… Bot started."
 
43
 
44
  def stop_bot():
45
- global bot_process
46
- if bot_process and bot_process.is_alive():
47
- bot_process.terminate()
48
- bot_process.join()
49
- logger.info("Bot manually stopped.")
50
- return "πŸ›‘ Bot stopped."
51
- return "Bot is not running."
52
-
53
- def get_logs():
54
- return log_stream.getvalue()[-20000:]
55
-
56
- # ---------- GRADIO UI ----------
57
- with gr.Blocks() as ui:
58
- gr.Markdown("## πŸ€– Telegram Bot Control Panel")
59
- start_btn = gr.Button("πŸš€ Start Bot")
60
- stop_btn = gr.Button("πŸ›‘ Stop Bot")
61
- refresh_btn = gr.Button("πŸ”„ Refresh Logs")
62
- logs_box = gr.Textbox(label="πŸ“œ Bot Logs", lines=25)
63
-
64
- start_btn.click(fn=start_bot, outputs=logs_box)
65
- stop_btn.click(fn=stop_bot, outputs=logs_box)
66
- refresh_btn.click(fn=get_logs, outputs=logs_box)
67
-
68
- if __name__ == "__main__":
69
- ui.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
+ import asyncio
3
+ import threading
 
4
  from pyrogram import Client, filters
5
+ import gradio as gr
 
6
 
 
7
  API_ID = int(os.environ.get("API_ID", "6"))
8
  API_HASH = os.environ.get("API_HASH", "eb06d4abfb49dc3eeb1aeb98ae0f581e")
9
  BOT_TOKEN = os.environ.get("BOT_TOKEN", "7510817339:AAHFZoFzPkUO_-nAwfh9bjY_qHsWMprM2PI")
10
 
 
 
 
 
11
 
12
+ app = Client("my_bot", api_id=API_ID, api_hash=API_HASH, bot_token=BOT_TOKEN)
13
+
14
+ bot_running = False
15
+ bot_lock = threading.Lock()
16
 
17
+ command_history = []
18
+ history_pos = -1
19
+ output_logs = ""
 
20
 
21
+ def append_log(text):
22
+ global output_logs
23
+ output_logs += text + "\n"
24
+ # Limit to last 20k chars to keep it manageable
25
+ if len(output_logs) > 20000:
26
+ output_logs = output_logs[-20000:]
27
 
28
+ # Telegram /start command handler
29
+ @app.on_message(filters.command("start"))
30
+ async def start_handler(client, message):
31
+ await message.reply_text("Hi πŸ‘‹")
32
+ append_log(f"[BOT] Replied 'Hi' to user {message.from_user.id}")
33
 
34
  def start_bot():
35
+ global bot_running
36
+ with bot_lock:
37
+ if not bot_running:
38
+ asyncio.run(app.start())
39
+ bot_running = True
40
+ append_log("[SYSTEM] Bot started")
41
+ else:
42
+ append_log("[SYSTEM] Bot already running")
43
 
44
  def stop_bot():
45
+ global bot_running
46
+ with bot_lock:
47
+ if bot_running:
48
+ asyncio.run(app.stop())
49
+ bot_running = False
50
+ append_log("[SYSTEM] Bot stopped")
51
+ else:
52
+ append_log("[SYSTEM] Bot already stopped")
53
+
54
+ def run_command(cmd):
55
+ """
56
+ This simulates running a command in the 'terminal'.
57
+ We support:
58
+ - telegram commands: /start etc will be sent to the bot (simulate)
59
+ - shell commands: run on local shell and return output
60
+ """
61
+ append_log(f"> {cmd}")
62
+ # For example purposes, just handle /start command specially
63
+ if cmd.strip() == "/start":
64
+ # simulate bot reply (because real bot interaction needs telegram user)
65
+ append_log("[BOT] Hi πŸ‘‹")
66
+ else:
67
+ # Run shell command and capture output
68
+ import subprocess
69
+ try:
70
+ output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, timeout=10, text=True)
71
+ append_log(output.strip())
72
+ except subprocess.CalledProcessError as e:
73
+ append_log(f"Error:\n{e.output}")
74
+ except Exception as e:
75
+ append_log(f"Exception: {str(e)}")
76
+ return output_logs
77
+
78
+ # --- Gradio interface callbacks ---
79
+
80
+ def on_send_command(cmd, hist_pos):
81
+ global command_history, history_pos
82
+ if cmd.strip():
83
+ command_history.append(cmd.strip())
84
+ history_pos = len(command_history) # reset position after new command
85
+ logs = run_command(cmd)
86
+ return "", logs, history_pos
87
+ else:
88
+ return "", output_logs, hist_pos
89
+
90
+ def on_up_arrow(hist_pos):
91
+ global command_history
92
+ if command_history and hist_pos > 0:
93
+ hist_pos -= 1
94
+ return command_history[hist_pos], output_logs, hist_pos
95
+ return gr.Textbox.update(), output_logs, hist_pos
96
+
97
+ def on_down_arrow(hist_pos):
98
+ global command_history
99
+ if command_history and hist_pos < len(command_history) - 1:
100
+ hist_pos += 1
101
+ return command_history[hist_pos], output_logs, hist_pos
102
+ elif hist_pos == len(command_history) - 1:
103
+ hist_pos += 1
104
+ return "", output_logs, hist_pos
105
+ return gr.Textbox.update(), output_logs, hist_pos
106
+
107
+ def start_bot_ui():
108
+ threading.Thread(target=start_bot).start()
109
+ return output_logs
110
+
111
+ def stop_bot_ui():
112
+ threading.Thread(target=stop_bot).start()
113
+ return output_logs
114
+
115
+ with gr.Blocks() as demo:
116
+ gr.Markdown("# Telegram Bot Terminal with Start/Stop and Command History")
117
+
118
+ with gr.Row():
119
+ start_btn = gr.Button("πŸš€ Start Bot")
120
+ stop_btn = gr.Button("πŸ›‘ Stop Bot")
121
+ logs = gr.Textbox(label="Logs / Terminal Output", lines=20, interactive=False)
122
+ cmd_input = gr.Textbox(label="Enter command", lines=1, interactive=True)
123
+
124
+ # Hidden state for history position
125
+ hist_pos_state = gr.State(value=len(command_history))
126
+
127
+ # Button clicks
128
+ start_btn.click(start_bot_ui, outputs=logs)
129
+ stop_btn.click(stop_bot_ui, outputs=logs)
130
+
131
+ # Send command on Enter
132
+ cmd_input.submit(on_send_command, inputs=[cmd_input, hist_pos_state], outputs=[cmd_input, logs, hist_pos_state])
133
+
134
+ # JavaScript events to detect arrow keys
135
+ # We use custom JS to send event to Gradio for arrow keys pressed in the textbox
136
+ # Note: Gradio does not natively support up/down key callbacks,
137
+ # so we inject this JS trick below.
138
+
139
+ cmd_input.js(
140
+ """
141
+ () => {
142
+ const input = document.querySelector('textarea[aria-label="Enter command"]');
143
+ input.addEventListener('keydown', e => {
144
+ if (e.key === "ArrowUp") {
145
+ e.preventDefault();
146
+ gradioApp().getElementById('up-arrow-btn').click();
147
+ }
148
+ if (e.key === "ArrowDown") {
149
+ e.preventDefault();
150
+ gradioApp().getElementById('down-arrow-btn').click();
151
+ }
152
+ });
153
+ }
154
+ """
155
+ )
156
+
157
+ # Hidden buttons for up/down arrow to call Python
158
+ up_btn = gr.Button(visible=False, elem_id="up-arrow-btn")
159
+ down_btn = gr.Button(visible=False, elem_id="down-arrow-btn")
160
+
161
+ up_btn.click(on_up_arrow, inputs=hist_pos_state, outputs=[cmd_input, logs, hist_pos_state])
162
+ down_btn.click(on_down_arrow, inputs=hist_pos_state, outputs=[cmd_input, logs, hist_pos_state])
163
+
164
+ # Initialize logs textbox content
165
+ logs.value = output_logs
166
+
167
+ demo.launch()