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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -146
app.py CHANGED
@@ -1,167 +1,157 @@
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()
 
1
+ import gradio as gr
2
+ import subprocess
3
  import asyncio
4
  import threading
5
+ from queue import Queue, Empty
6
+ import os
7
+ from telegram import Update
8
+ from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes
9
 
10
+ # Env vars or hardcode your Telegram bot token here
 
11
  BOT_TOKEN = os.environ.get("BOT_TOKEN", "7510817339:AAHFZoFzPkUO_-nAwfh9bjY_qHsWMprM2PI")
12
+ # Globals
13
+ bot_app = None # Telegram Application instance
14
+ bot_thread = None
15
+ bot_running = False
16
+ log_queue = Queue()
17
+ telegram_cmd_logs = []
18
+
19
+ # -- Telegram Bot Handlers --
20
+
21
+ async def bash_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
22
+ cmd = ' '.join(context.args)
23
+ if not cmd:
24
+ await update.message.reply_text("Usage: /bash <command>")
25
+ return
26
+
27
+ log_queue.put(f"[Telegram] Received command: {cmd}")
28
+
29
+ # Run command and collect output (limit max 4000 chars for Telegram)
30
+ try:
31
+ proc = await asyncio.create_subprocess_shell(
32
+ cmd,
33
+ stdout=asyncio.subprocess.PIPE,
34
+ stderr=asyncio.subprocess.STDOUT,
35
+ )
36
+ stdout, _ = await proc.communicate()
37
+ output = stdout.decode().strip()
38
+ if len(output) > 4000:
39
+ output = output[:4000] + "\n...[truncated]"
40
+ except Exception as e:
41
+ output = f"Error running command: {e}"
42
+
43
+ await update.message.reply_text(f"$ {cmd}\n{output}")
44
+
45
+ telegram_cmd_logs.append(f"$ {cmd}\n{output}")
46
+ # Limit logs to last 50 commands
47
+ if len(telegram_cmd_logs) > 50:
48
+ telegram_cmd_logs.pop(0)
49
 
50
+ def start_bot():
51
+ global bot_app, bot_running
52
 
53
+ if bot_running:
54
+ log_queue.put("[Bot] Already running.")
55
+ return
 
56
 
57
+ async def run_bot():
58
+ global bot_app, bot_running
59
+ bot_app = ApplicationBuilder().token(BOT_TOKEN).build()
60
+ bot_app.add_handler(CommandHandler("bash", bash_command))
61
+ bot_running = True
62
+ log_queue.put("[Bot] Bot started.")
63
+ await bot_app.run_polling()
64
 
65
+ loop = asyncio.new_event_loop()
 
 
 
 
 
66
 
67
+ def runner():
68
+ asyncio.set_event_loop(loop)
69
+ loop.run_until_complete(run_bot())
 
 
70
 
71
+ global bot_thread
72
+ bot_thread = threading.Thread(target=runner, daemon=True)
73
+ bot_thread.start()
 
 
 
 
 
 
74
 
75
  def stop_bot():
76
+ global bot_app, bot_running
77
+ if not bot_running:
78
+ log_queue.put("[Bot] Bot is not running.")
79
+ return
80
+
81
+ async def shutdown():
82
+ await bot_app.shutdown()
83
+ await bot_app.stop()
84
+ log_queue.put("[Bot] Bot stopped.")
85
+
86
+ asyncio.run(shutdown())
87
+ bot_running = False
88
+
89
+ # -- Gradio Web Terminal --
90
+
91
+ def live_terminal(cmd):
92
+ if not cmd.strip():
93
+ yield "$ "
94
+ return
95
+ yield f"$ {cmd}\n"
96
+ process = subprocess.Popen(
97
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True
98
+ )
99
+ for line in iter(process.stdout.readline, ''):
100
+ yield line
101
+ process.stdout.close()
102
+ process.wait()
103
+ yield "$ "
104
+
105
+ def run_terminal(cmd):
106
+ return live_terminal(cmd)
107
+
108
+ def update_log_box():
109
+ # Show last 20 logs
110
+ logs = []
111
+ try:
112
+ while True:
113
+ log = log_queue.get_nowait()
114
+ logs.append(log)
115
+ except Empty:
116
+ pass
117
+
118
+ logs.extend(telegram_cmd_logs[-20:])
119
+ return "\n".join(logs[-20:])
120
+
121
+ # -- Gradio UI --
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
  with gr.Blocks() as demo:
124
+ gr.Markdown("### Live Terminal with Telegram Bot Control")
125
 
126
  with gr.Row():
127
+ terminal_output = gr.Textbox(value="$ ", label="Live Terminal", lines=20, interactive=False)
128
+ cmd_input = gr.Textbox(placeholder="Type command here and press Enter", label="Command Input")
129
+
130
+ with gr.Row():
131
+ start_btn = gr.Button("Start Telegram Bot")
132
+ stop_btn = gr.Button("Stop Telegram Bot")
133
+
134
+ log_output = gr.Textbox(value="", label="Bot Logs & Telegram Bash Command Logs", lines=15, interactive=False)
135
+
136
+ # Command input triggers terminal
137
+ cmd_input.submit(run_terminal, inputs=cmd_input, outputs=terminal_output)
138
+
139
+ # Start/stop buttons update logs
140
+ def start_click():
141
+ start_bot()
142
+ return update_log_box()
143
+
144
+ def stop_click():
145
+ stop_bot()
146
+ return update_log_box()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
+ start_btn.click(start_click, outputs=log_output)
149
+ stop_btn.click(stop_click, outputs=log_output)
 
150
 
151
+ # Auto-update logs every 3 seconds
152
+ def auto_update():
153
+ return update_log_box()
154
 
155
+ demo.load(auto_update, None, log_output, every=3)
 
156
 
157
  demo.launch()