understanding commited on
Commit
288ea5d
Β·
verified Β·
1 Parent(s): 89c0dd4

Update bot/handlers.py

Browse files
Files changed (1) hide show
  1. bot/handlers.py +80 -33
bot/handlers.py CHANGED
@@ -14,6 +14,7 @@ from bot.core.auth import is_owner_id, require_allowed
14
  from bot.core.progress import SpeedETA, human_bytes, human_eta
15
  from bot.core.tasks import create_task, set_task
16
 
 
17
  from bot.integrations.cf_worker1 import profile_add, profile_list, profile_set_default
18
  from bot.integrations.cf_worker2 import (
19
  allow_user, disallow_user, pick_profile, access_token, record_upload, stats_today
@@ -30,6 +31,7 @@ from bot.youtube.uploader import upload_video
30
  # values: "json" | "ci"
31
  _AWAIT_AUTH: Dict[int, str] = {}
32
 
 
33
  def setup_handlers(app: Client) -> None:
34
 
35
  @app.on_message(filters.command(["start"]) & filters.private)
@@ -45,7 +47,7 @@ def setup_handlers(app: Client) -> None:
45
  uid = m.from_user.id if m.from_user else None
46
  await safe_reply(m, f"πŸ‘€ Your ID: `{uid}`")
47
 
48
- # -------- OWNER allow/disallow via forward OR id --------
49
  @app.on_message(filters.command(["allow"]) & filters.private)
50
  async def allow_cmd(_: Client, m: Message):
51
  if not is_owner_id(m.from_user.id if m.from_user else None):
@@ -62,10 +64,15 @@ def setup_handlers(app: Client) -> None:
62
  target = int(parts[1])
63
 
64
  if not target:
65
- return await safe_reply(m, "Usage:\nβ€’ Reply/forward user msg then /allow\nβ€’ or /allow <user_id>")
 
 
 
 
 
66
 
67
  j = await allow_user(target)
68
- await safe_reply(m, f"βœ… allowed: `{target}`\n{j}")
69
 
70
  @app.on_message(filters.command(["disallow"]) & filters.private)
71
  async def disallow_cmd(_: Client, m: Message):
@@ -75,9 +82,10 @@ def setup_handlers(app: Client) -> None:
75
  parts = (m.text or "").split()
76
  if len(parts) < 2 or not parts[1].isdigit():
77
  return await safe_reply(m, "Usage: /disallow <user_id>")
 
78
  target = int(parts[1])
79
  j = await disallow_user(target)
80
- await safe_reply(m, f"βœ… disallowed: `{target}`\n{j}")
81
 
82
  # -------- Owner stats + diag --------
83
  @app.on_message(filters.command(["stats"]) & filters.private)
@@ -91,21 +99,40 @@ def setup_handlers(app: Client) -> None:
91
  async def diag_cmd(_: Client, m: Message):
92
  if not is_owner_id(m.from_user.id if m.from_user else None):
93
  return await safe_reply(m, texts.OWNER_ONLY)
94
- # quick DNS/connect check
95
  from bot.integrations.http import get_client
 
96
  c = get_client()
97
- res1 = res2 = None
98
- try:
99
- res1 = await c.get((Workers.WORKER1_URL or "") + "/")
100
- r1 = f"{res1.status_code}"
101
- except Exception as e:
102
- r1 = f"ERR:{type(e).__name__}:{e}"
103
- try:
104
- res2 = await c.get((Workers.WORKER2_URL or "") + "/")
105
- r2 = f"{res2.status_code}"
106
- except Exception as e:
107
- r2 = f"ERR:{type(e).__name__}:{e}"
108
- await safe_reply(m, f"πŸ”Ž DIAG\nW1={Workers.WORKER1_URL} -> {r1}\nW2={Workers.WORKER2_URL} -> {r2}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
  # -------- AUTH UI --------
111
  @app.on_message(filters.command(["auth"]) & filters.private)
@@ -119,46 +146,54 @@ def setup_handlers(app: Client) -> None:
119
 
120
  @app.on_message(filters.command(["cancel"]) & filters.private)
121
  async def cancel_cmd(_: Client, m: Message):
122
- _AWAIT_AUTH.pop(m.from_user.id, None)
123
  await safe_reply(m, texts.CANCELLED)
124
 
125
  @app.on_callback_query()
126
  async def cb(_: Client, q: CallbackQuery):
127
  uid = q.from_user.id if q.from_user else 0
128
  action, value = parse_cb(q.data or "")
 
129
  if action in (AUTH_JSON, AUTH_CI, CANCEL):
130
  if action == CANCEL:
131
  _AWAIT_AUTH.pop(uid, None)
132
- return await q.answer("Cancelled")
 
133
  if action == AUTH_JSON:
134
  _AWAIT_AUTH[uid] = "json"
135
  await q.message.edit_text(texts.ASK_JSON)
136
- return await q.answer("Paste JSON")
 
137
  if action == AUTH_CI:
138
  _AWAIT_AUTH[uid] = "ci"
139
  await q.message.edit_text(texts.ASK_ID_SECRET)
140
- return await q.answer("Send ID & Secret")
141
- return
142
 
143
- # handle set default profile callbacks too
144
  if action == "setdef" and value:
145
- # owner/allowed only
146
- from bot.core.auth import require_allowed
147
  if not await require_allowed(uid):
148
  return await q.answer("Not allowed", show_alert=True)
 
149
  j = await profile_set_default(uid, value)
150
  if not j.get("ok"):
151
  return await q.answer("Failed", show_alert=True)
 
152
  await q.answer("Default set βœ…", show_alert=False)
153
  try:
154
  await q.message.edit_text(f"βœ… Default set: `{value}`")
155
  except Exception:
156
  pass
157
  return
 
158
  await q.answer("OK")
159
 
160
- # message sink for auth states
161
- @app.on_message(filters.private & filters.text & ~filters.command(["start","ping","me","auth","cancel","profiles","stats","allow","disallow","diag"]))
 
 
 
 
162
  async def auth_sink(_: Client, m: Message):
163
  uid = m.from_user.id if m.from_user else 0
164
  mode = _AWAIT_AUTH.get(uid)
@@ -167,17 +202,14 @@ def setup_handlers(app: Client) -> None:
167
 
168
  try:
169
  if mode == "json":
170
- # parse JSON
171
  data = json.loads(m.text)
172
- # accept both shapes
173
  root = data.get("installed") or data.get("web") or {}
174
  client_id = root.get("client_id") or data.get("client_id")
175
  client_secret = root.get("client_secret") or data.get("client_secret")
176
  if not client_id or not client_secret:
177
  return await safe_reply(m, texts.PARSE_FAIL)
178
  else:
179
- # expect "id\nsecret" or "id | secret"
180
- txt = m.text.strip()
181
  parts = [p.strip() for p in re.split(r"[|\n]+", txt) if p.strip()]
182
  if len(parts) < 2:
183
  return await safe_reply(m, texts.PARSE_FAIL)
@@ -186,6 +218,7 @@ def setup_handlers(app: Client) -> None:
186
  j = await profile_add(uid, client_id, client_secret, label="main", ttl_sec=600)
187
  if not j.get("ok"):
188
  return await safe_reply(m, texts.PROFILE_ADD_FAIL.format(j))
 
189
  _AWAIT_AUTH.pop(uid, None)
190
  await safe_reply(m, texts.SENT_AUTH_LINK + j["login_url"])
191
 
@@ -206,7 +239,10 @@ def setup_handlers(app: Client) -> None:
206
  profiles = j.get("profiles") or []
207
  txt = f"Default: `{j.get('default_profile_id')}`\n\n"
208
  for p in profiles:
209
- txt += f"- `{p['profile_id']}` | {p.get('label')} | refresh={p.get('has_refresh')} | ch={p.get('channel_title')}\n"
 
 
 
210
 
211
  kb = profiles_keyboard(profiles)
212
  await safe_reply(m, txt, reply_markup=kb)
@@ -230,6 +266,7 @@ def setup_handlers(app: Client) -> None:
230
  default_id = pl.get("default_profile_id")
231
  profiles = pl.get("profiles") or []
232
  dp = next((p for p in profiles if p.get("profile_id") == default_id), None)
 
233
  if not dp or not dp.get("has_refresh"):
234
  return await safe_reply(m, texts.NEED_AUTH)
235
 
@@ -240,11 +277,13 @@ def setup_handlers(app: Client) -> None:
240
  pick = await pick_profile(uid, channel_id)
241
  if not pick.get("ok"):
242
  return await safe_reply(m, texts.PICK_FAIL.format(pick))
 
243
  use_profile_id = pick["profile_id"]
244
 
245
  tok = await access_token(uid, use_profile_id)
246
  if not tok.get("ok"):
247
  return await safe_reply(m, texts.TOKEN_FAIL.format(tok))
 
248
  access_tok = tok["access_token"]
249
 
250
  status = await safe_reply(m, texts.UPLOAD_START)
@@ -277,7 +316,14 @@ def setup_handlers(app: Client) -> None:
277
  await safe_edit(status, txt)
278
 
279
  set_task(task_id, "uploading", "")
280
- yt_url = await upload_video(access_tok, file_path, title, desc, privacy="private", progress_cb=prog)
 
 
 
 
 
 
 
281
 
282
  await record_upload(uid, use_profile_id)
283
 
@@ -287,6 +333,7 @@ def setup_handlers(app: Client) -> None:
287
  except Exception as e:
288
  set_task(task_id, "error", str(e))
289
  await safe_reply(m, f"❌ Upload failed: `{type(e).__name__}: {e}`")
 
290
  finally:
291
  if file_path:
292
  cleanup_file(file_path)
 
14
  from bot.core.progress import SpeedETA, human_bytes, human_eta
15
  from bot.core.tasks import create_task, set_task
16
 
17
+ from bot.integrations.diag_extra import dns_check
18
  from bot.integrations.cf_worker1 import profile_add, profile_list, profile_set_default
19
  from bot.integrations.cf_worker2 import (
20
  allow_user, disallow_user, pick_profile, access_token, record_upload, stats_today
 
31
  # values: "json" | "ci"
32
  _AWAIT_AUTH: Dict[int, str] = {}
33
 
34
+
35
  def setup_handlers(app: Client) -> None:
36
 
37
  @app.on_message(filters.command(["start"]) & filters.private)
 
47
  uid = m.from_user.id if m.from_user else None
48
  await safe_reply(m, f"πŸ‘€ Your ID: `{uid}`")
49
 
50
+ # -------- OWNER allow/disallow via reply OR forward OR id --------
51
  @app.on_message(filters.command(["allow"]) & filters.private)
52
  async def allow_cmd(_: Client, m: Message):
53
  if not is_owner_id(m.from_user.id if m.from_user else None):
 
64
  target = int(parts[1])
65
 
66
  if not target:
67
+ return await safe_reply(
68
+ m,
69
+ "Usage:\n"
70
+ "β€’ Reply/forward user msg then /allow\n"
71
+ "β€’ or /allow <user_id>"
72
+ )
73
 
74
  j = await allow_user(target)
75
+ await safe_reply(m, f"βœ… allowed: `{target}`\n`{j}`")
76
 
77
  @app.on_message(filters.command(["disallow"]) & filters.private)
78
  async def disallow_cmd(_: Client, m: Message):
 
82
  parts = (m.text or "").split()
83
  if len(parts) < 2 or not parts[1].isdigit():
84
  return await safe_reply(m, "Usage: /disallow <user_id>")
85
+
86
  target = int(parts[1])
87
  j = await disallow_user(target)
88
+ await safe_reply(m, f"βœ… disallowed: `{target}`\n`{j}`")
89
 
90
  # -------- Owner stats + diag --------
91
  @app.on_message(filters.command(["stats"]) & filters.private)
 
99
  async def diag_cmd(_: Client, m: Message):
100
  if not is_owner_id(m.from_user.id if m.from_user else None):
101
  return await safe_reply(m, texts.OWNER_ONLY)
102
+
103
  from bot.integrations.http import get_client
104
+
105
  c = get_client()
106
+ headers = {"User-Agent": "hf-diag/1.0", "Accept": "*/*"}
107
+
108
+ # HTTP checks
109
+ if not Workers.WORKER1_URL:
110
+ r1 = "ERR:missing_WORKER1_URL"
111
+ else:
112
+ try:
113
+ res1 = await c.get(Workers.WORKER1_URL + "/", headers=headers)
114
+ r1 = f"{res1.status_code}"
115
+ except Exception as e:
116
+ r1 = f"ERR:{type(e).__name__}:{e}"
117
+
118
+ if not Workers.WORKER2_URL:
119
+ r2 = "ERR:missing_WORKER2_URL"
120
+ else:
121
+ try:
122
+ res2 = await c.get(Workers.WORKER2_URL + "/", headers=headers)
123
+ r2 = f"{res2.status_code}"
124
+ except Exception as e:
125
+ r2 = f"ERR:{type(e).__name__}:{e}"
126
+
127
+ await safe_reply(
128
+ m,
129
+ "πŸ”Ž DIAG\n"
130
+ f"W1={Workers.WORKER1_URL} -> {r1}\n"
131
+ f"W2={Workers.WORKER2_URL} -> {r2}\n\n"
132
+ f"DNS W1 -> {dns_check(Workers.WORKER1_URL)}\n"
133
+ f"DNS W2 -> {dns_check(Workers.WORKER2_URL)}\n"
134
+ f"DNS google -> {dns_check('https://www.google.com')}\n"
135
+ )
136
 
137
  # -------- AUTH UI --------
138
  @app.on_message(filters.command(["auth"]) & filters.private)
 
146
 
147
  @app.on_message(filters.command(["cancel"]) & filters.private)
148
  async def cancel_cmd(_: Client, m: Message):
149
+ _AWAIT_AUTH.pop(m.from_user.id if m.from_user else 0, None)
150
  await safe_reply(m, texts.CANCELLED)
151
 
152
  @app.on_callback_query()
153
  async def cb(_: Client, q: CallbackQuery):
154
  uid = q.from_user.id if q.from_user else 0
155
  action, value = parse_cb(q.data or "")
156
+
157
  if action in (AUTH_JSON, AUTH_CI, CANCEL):
158
  if action == CANCEL:
159
  _AWAIT_AUTH.pop(uid, None)
160
+ await q.answer("Cancelled")
161
+ return
162
  if action == AUTH_JSON:
163
  _AWAIT_AUTH[uid] = "json"
164
  await q.message.edit_text(texts.ASK_JSON)
165
+ await q.answer("Paste JSON")
166
+ return
167
  if action == AUTH_CI:
168
  _AWAIT_AUTH[uid] = "ci"
169
  await q.message.edit_text(texts.ASK_ID_SECRET)
170
+ await q.answer("Send ID & Secret")
171
+ return
172
 
173
+ # set default profile callback
174
  if action == "setdef" and value:
 
 
175
  if not await require_allowed(uid):
176
  return await q.answer("Not allowed", show_alert=True)
177
+
178
  j = await profile_set_default(uid, value)
179
  if not j.get("ok"):
180
  return await q.answer("Failed", show_alert=True)
181
+
182
  await q.answer("Default set βœ…", show_alert=False)
183
  try:
184
  await q.message.edit_text(f"βœ… Default set: `{value}`")
185
  except Exception:
186
  pass
187
  return
188
+
189
  await q.answer("OK")
190
 
191
+ # -------- auth message sink --------
192
+ @app.on_message(
193
+ filters.private
194
+ & filters.text
195
+ & ~filters.command(["start", "ping", "me", "auth", "cancel", "profiles", "stats", "allow", "disallow", "diag"])
196
+ )
197
  async def auth_sink(_: Client, m: Message):
198
  uid = m.from_user.id if m.from_user else 0
199
  mode = _AWAIT_AUTH.get(uid)
 
202
 
203
  try:
204
  if mode == "json":
 
205
  data = json.loads(m.text)
 
206
  root = data.get("installed") or data.get("web") or {}
207
  client_id = root.get("client_id") or data.get("client_id")
208
  client_secret = root.get("client_secret") or data.get("client_secret")
209
  if not client_id or not client_secret:
210
  return await safe_reply(m, texts.PARSE_FAIL)
211
  else:
212
+ txt = (m.text or "").strip()
 
213
  parts = [p.strip() for p in re.split(r"[|\n]+", txt) if p.strip()]
214
  if len(parts) < 2:
215
  return await safe_reply(m, texts.PARSE_FAIL)
 
218
  j = await profile_add(uid, client_id, client_secret, label="main", ttl_sec=600)
219
  if not j.get("ok"):
220
  return await safe_reply(m, texts.PROFILE_ADD_FAIL.format(j))
221
+
222
  _AWAIT_AUTH.pop(uid, None)
223
  await safe_reply(m, texts.SENT_AUTH_LINK + j["login_url"])
224
 
 
239
  profiles = j.get("profiles") or []
240
  txt = f"Default: `{j.get('default_profile_id')}`\n\n"
241
  for p in profiles:
242
+ txt += (
243
+ f"- `{p['profile_id']}` | {p.get('label')} | "
244
+ f"refresh={p.get('has_refresh')} | ch={p.get('channel_title')}\n"
245
+ )
246
 
247
  kb = profiles_keyboard(profiles)
248
  await safe_reply(m, txt, reply_markup=kb)
 
266
  default_id = pl.get("default_profile_id")
267
  profiles = pl.get("profiles") or []
268
  dp = next((p for p in profiles if p.get("profile_id") == default_id), None)
269
+
270
  if not dp or not dp.get("has_refresh"):
271
  return await safe_reply(m, texts.NEED_AUTH)
272
 
 
277
  pick = await pick_profile(uid, channel_id)
278
  if not pick.get("ok"):
279
  return await safe_reply(m, texts.PICK_FAIL.format(pick))
280
+
281
  use_profile_id = pick["profile_id"]
282
 
283
  tok = await access_token(uid, use_profile_id)
284
  if not tok.get("ok"):
285
  return await safe_reply(m, texts.TOKEN_FAIL.format(tok))
286
+
287
  access_tok = tok["access_token"]
288
 
289
  status = await safe_reply(m, texts.UPLOAD_START)
 
316
  await safe_edit(status, txt)
317
 
318
  set_task(task_id, "uploading", "")
319
+ yt_url = await upload_video(
320
+ access_tok,
321
+ file_path,
322
+ title,
323
+ desc,
324
+ privacy="private",
325
+ progress_cb=prog
326
+ )
327
 
328
  await record_upload(uid, use_profile_id)
329
 
 
333
  except Exception as e:
334
  set_task(task_id, "error", str(e))
335
  await safe_reply(m, f"❌ Upload failed: `{type(e).__name__}: {e}`")
336
+
337
  finally:
338
  if file_path:
339
  cleanup_file(file_path)