Muttered3 commited on
Commit
c53bbc2
Β·
verified Β·
1 Parent(s): 28e763a

Update bot.py

Browse files
Files changed (1) hide show
  1. bot.py +73 -69
bot.py CHANGED
@@ -11,6 +11,14 @@ def get_admins():
11
  def is_admin(event):
12
  return event.sender_id in get_admins()
13
 
 
 
 
 
 
 
 
 
14
  async def generate_status_msg():
15
  state = await db.get_state()
16
  counts = await db.get_counts()
@@ -55,13 +63,7 @@ def setup_handlers(client):
55
  await event.respond("β›” Unauthorized.")
56
  return
57
 
58
- buttons = [
59
- [Button.inline("▢️ Start Scan", b"start_scan"), Button.inline("⏸ Pause", b"pause_scan")],
60
- [Button.inline("⏹ Stop", b"stop_scan"), Button.inline("πŸ“Š Status", b"show_status")],
61
- [Button.inline("⚑ Set Speed", b"set_speed"), Button.inline("πŸ“₯ Export", b"export_files")],
62
- [Button.inline("πŸ”„ Load Words", b"load_words"), Button.inline("πŸ’£ Reset", b"reset_confirm")]
63
- ]
64
- await event.respond("πŸ‘‹ Fragment Scanner Bot", buttons=buttons)
65
 
66
  @client.on(events.NewMessage(pattern='/upload'))
67
  async def upload_cmd(event):
@@ -80,28 +82,32 @@ def setup_handlers(client):
80
  return
81
 
82
  msg = await event.respond("πŸ“₯ Downloading massive file to server disk...")
83
-
84
  await reply_msg.download_media(file="words.txt")
85
-
86
- await msg.edit("βœ… **File uploaded to server successfully!**\n\nClick **πŸ”„ Load Words** to bite off the first 200,000 words into the database.")
87
 
88
  @client.on(events.NewMessage(pattern='/load'))
89
  async def load_cmd(event):
90
  if not is_admin(event):
91
  await event.respond("β›” Unauthorized.")
92
  return
93
- await _load_words(event.respond)
 
 
 
 
 
 
 
94
 
95
- async def _load_words(reply_func):
96
  try:
97
  with open("words.txt", "r", encoding="utf-8") as f:
98
  all_lines = [line.strip().lower() for line in f if line.strip()]
99
  except Exception:
100
- await reply_func("❌ words.txt not found. Please upload your master list using `/upload`.")
101
  return
102
 
103
  if not all_lines:
104
- await reply_func("⚠️ The `words.txt` file on the server is empty. You've processed everything! Upload a new file.")
105
  return
106
 
107
  # --- SERVER DISK BUFFER LOGIC ---
@@ -126,12 +132,11 @@ def setup_handlers(client):
126
  except Exception as e:
127
  err_str = str(e).lower()
128
  if "oom" in err_str or "maxmemory" in err_str:
129
- await reply_func("❌ **Error:** Redis ran out of memory! Click πŸ’£ Reset, then try loading again.")
130
  else:
131
- await reply_func(f"❌ **Database Error:** {str(e)}")
132
- return # Abort before modifying the text file so no data is lost
133
 
134
- # If successfully pushed to Redis, overwrite the file with the remaining lines
135
  with open("words.txt", "w", encoding="utf-8") as f:
136
  f.write("\n".join(remaining_lines))
137
 
@@ -144,104 +149,103 @@ def setup_handlers(client):
144
  else:
145
  msg += "βœ… **No words remaining on server disk.**"
146
 
147
- await reply_func(msg)
148
 
149
  @client.on(events.CallbackQuery())
150
  async def button_handler(event):
151
  if not is_admin(event):
152
- await event.answer("β›” Unauthorized.", alert=True)
 
 
 
153
  return
154
 
 
 
 
 
 
 
155
  data = event.data.decode('utf-8')
156
 
157
- if data == "load_words":
158
- await event.answer()
159
- await _load_words(event.reply)
 
 
 
160
 
161
  elif data == "start_scan":
162
  await db.set_state(running="1", paused="0", start_time=str(time.time()))
163
  qlen = await db.queue_size()
164
- await event.answer()
165
- await event.reply(f"πŸš€ Scan started! {qlen} words in queue.")
166
 
167
  elif data == "pause_scan":
168
  state = await db.get_state()
169
  if state.get("paused") == "1":
170
  await db.set_state(paused="0")
171
- await event.answer()
172
- await event.reply("▢️ Scan resumed.")
173
  else:
174
  await db.set_state(paused="1")
175
- await event.answer()
176
- await event.reply("⏸ Scan paused.")
177
 
178
  elif data == "stop_scan":
179
  await db.set_state(running="0", paused="0")
180
- await event.answer()
181
- await event.reply("⏹ Scan stopped. Progress saved.")
182
 
183
- elif data == "show_status":
184
- msg = await generate_status_msg()
185
- await event.answer()
186
- await event.reply(msg, buttons=[[Button.inline("πŸ”„ Refresh Live", b"refresh_status")]])
187
-
188
- elif data == "refresh_status":
189
  msg = await generate_status_msg()
 
 
 
 
190
  try:
191
- await event.edit(msg, buttons=[[Button.inline("πŸ”„ Refresh Live", b"refresh_status")]])
192
- await event.answer("πŸ”„ Status Updated!")
193
  except Exception as e:
194
- if "not modified" in str(e).lower():
195
- await event.answer("⚠️ Already up to date.", alert=False)
196
- else:
197
- await event.answer("Error updating status.", alert=True)
198
 
199
  elif data == "set_speed":
200
  buttons = [
201
  [Button.inline("🐒 10", b"spd_10"), Button.inline("🚢 20", b"spd_20"), Button.inline("πŸš— 30", b"spd_30")],
202
- [Button.inline("πŸš€ 50", b"spd_50"), Button.inline("⚑ 75", b"spd_75"), Button.inline("πŸ”₯ 100", b"spd_100")]
 
203
  ]
204
- await event.answer()
205
- await event.reply("Select Speed:", buttons=buttons)
206
 
207
  elif data.startswith("spd_"):
208
  try:
209
  speed_limit = int(data.split("_")[1])
210
  await db.set_concurrency(speed_limit)
211
- await event.answer()
212
- await event.reply(f"⚑ Speed set to {speed_limit} concurrent workers.")
213
- except (IndexError, ValueError):
214
- await event.answer("❌ Invalid speed value.", alert=True)
215
- except Exception as e:
216
- await event.answer("❌ Error setting speed.", alert=True)
217
 
218
  elif data == "export_files":
219
- await event.answer()
 
220
  taken = sorted(await db.get_all_taken())
221
  unavail = sorted(await db.get_all_unavailable())
222
 
223
- f_taken = io.BytesIO("\n".join(taken).encode('utf-8'))
224
- f_taken.name = "taken.txt"
225
- await client.send_file(event.chat_id, file=f_taken)
 
226
 
227
- f_unavail = io.BytesIO("\n".join(unavail).encode('utf-8'))
228
- f_unavail.name = "unavailable.txt"
229
- await client.send_file(event.chat_id, file=f_unavail)
 
230
 
231
- await event.reply(f"βœ… Exported {len(taken):,} taken, {len(unavail):,} unavailable.")
232
 
233
  elif data == "reset_confirm":
234
  buttons = [
235
- [Button.inline("βœ… Yes, WIPE ALL DATA", b"reset_do"), Button.inline("❌ Cancel", b"reset_cancel")]
 
236
  ]
237
- await event.answer()
238
- await event.reply("⚠️ Are you sure you want to completely wipe the database?", buttons=buttons)
239
 
240
  elif data == "reset_do":
 
241
  await db.flush_all()
242
- await event.answer()
243
- await event.reply("πŸ’£ Database wiped. Click **πŸ”„ Load Words** to grab the next batch from the server disk!")
244
-
245
- elif data == "reset_cancel":
246
- await event.answer()
247
- await event.reply("Cancelled.")
 
11
  def is_admin(event):
12
  return event.sender_id in get_admins()
13
 
14
+ def get_main_buttons():
15
+ return [
16
+ [Button.inline("▢️ Start Scan", b"start_scan"), Button.inline("⏸ Pause", b"pause_scan")],
17
+ [Button.inline("⏹ Stop", b"stop_scan"), Button.inline("πŸ“Š Status", b"show_status")],
18
+ [Button.inline("⚑ Set Speed", b"set_speed"), Button.inline("πŸ“₯ Export", b"export_files")],
19
+ [Button.inline("πŸ”„ Load Words", b"load_words"), Button.inline("πŸ’£ Reset", b"reset_confirm")]
20
+ ]
21
+
22
  async def generate_status_msg():
23
  state = await db.get_state()
24
  counts = await db.get_counts()
 
63
  await event.respond("β›” Unauthorized.")
64
  return
65
 
66
+ await event.respond("πŸ‘‹ **Fragment Scanner Bot**\nSelect an action below:", buttons=get_main_buttons())
 
 
 
 
 
 
67
 
68
  @client.on(events.NewMessage(pattern='/upload'))
69
  async def upload_cmd(event):
 
82
  return
83
 
84
  msg = await event.respond("πŸ“₯ Downloading massive file to server disk...")
 
85
  await reply_msg.download_media(file="words.txt")
86
+ await msg.edit("βœ… **File uploaded to server successfully!**\n\nClick **πŸ”„ Load Words** to bite off the first 200,000 words into the database.", buttons=get_main_buttons())
 
87
 
88
  @client.on(events.NewMessage(pattern='/load'))
89
  async def load_cmd(event):
90
  if not is_admin(event):
91
  await event.respond("β›” Unauthorized.")
92
  return
93
+ await _load_words(event, is_callback=False)
94
+
95
+ async def _load_words(event, is_callback=True):
96
+ async def update_msg(text):
97
+ if is_callback:
98
+ await event.edit(text, buttons=get_main_buttons())
99
+ else:
100
+ await event.respond(text, buttons=get_main_buttons())
101
 
 
102
  try:
103
  with open("words.txt", "r", encoding="utf-8") as f:
104
  all_lines = [line.strip().lower() for line in f if line.strip()]
105
  except Exception:
106
+ await update_msg("❌ `words.txt` not found. Please upload your master list using `/upload`.")
107
  return
108
 
109
  if not all_lines:
110
+ await update_msg("⚠️ The `words.txt` file on the server is empty. You've processed everything! Upload a new file.")
111
  return
112
 
113
  # --- SERVER DISK BUFFER LOGIC ---
 
132
  except Exception as e:
133
  err_str = str(e).lower()
134
  if "oom" in err_str or "maxmemory" in err_str:
135
+ await update_msg("❌ **Error:** Redis ran out of memory! Click **πŸ’£ Reset**, then try loading again.")
136
  else:
137
+ await update_msg(f"❌ **Database Error:** {str(e)}")
138
+ return
139
 
 
140
  with open("words.txt", "w", encoding="utf-8") as f:
141
  f.write("\n".join(remaining_lines))
142
 
 
149
  else:
150
  msg += "βœ… **No words remaining on server disk.**"
151
 
152
+ await update_msg(msg)
153
 
154
  @client.on(events.CallbackQuery())
155
  async def button_handler(event):
156
  if not is_admin(event):
157
+ try:
158
+ await event.answer("β›” Unauthorized.", alert=True)
159
+ except Exception:
160
+ pass
161
  return
162
 
163
+ # --- CRITICAL FIX: Answer immediately to prevent QueryIdInvalidError timeouts ---
164
+ try:
165
+ await event.answer()
166
+ except Exception:
167
+ pass
168
+
169
  data = event.data.decode('utf-8')
170
 
171
+ if data == "back_main":
172
+ await event.edit("πŸ‘‹ **Fragment Scanner Bot**\nSelect an action below:", buttons=get_main_buttons())
173
+
174
+ elif data == "load_words":
175
+ await event.edit("⏳ Reading and loading words... Please wait.")
176
+ await _load_words(event, is_callback=True)
177
 
178
  elif data == "start_scan":
179
  await db.set_state(running="1", paused="0", start_time=str(time.time()))
180
  qlen = await db.queue_size()
181
+ await event.edit(f"πŸš€ **Scan started!**\n`{qlen:,}` words currently in the processing queue.", buttons=get_main_buttons())
 
182
 
183
  elif data == "pause_scan":
184
  state = await db.get_state()
185
  if state.get("paused") == "1":
186
  await db.set_state(paused="0")
187
+ await event.edit("▢️ **Scan resumed.**", buttons=get_main_buttons())
 
188
  else:
189
  await db.set_state(paused="1")
190
+ await event.edit("⏸ **Scan paused.**", buttons=get_main_buttons())
 
191
 
192
  elif data == "stop_scan":
193
  await db.set_state(running="0", paused="0")
194
+ await event.edit("⏹ **Scan stopped.** Progress has been saved.", buttons=get_main_buttons())
 
195
 
196
+ elif data in ("show_status", "refresh_status"):
 
 
 
 
 
197
  msg = await generate_status_msg()
198
+ buttons = [
199
+ [Button.inline("πŸ”„ Refresh Live", b"refresh_status")],
200
+ [Button.inline("πŸ”™ Back to Menu", b"back_main")]
201
+ ]
202
  try:
203
+ await event.edit(msg, buttons=buttons)
 
204
  except Exception as e:
205
+ pass # Ignores "Message is not modified" errors on spam click
 
 
 
206
 
207
  elif data == "set_speed":
208
  buttons = [
209
  [Button.inline("🐒 10", b"spd_10"), Button.inline("🚢 20", b"spd_20"), Button.inline("πŸš— 30", b"spd_30")],
210
+ [Button.inline("πŸš€ 50", b"spd_50"), Button.inline("⚑ 75", b"spd_75"), Button.inline("πŸ”₯ 100", b"spd_100")],
211
+ [Button.inline("πŸ”™ Cancel", b"back_main")]
212
  ]
213
+ await event.edit("⚑ **Select Scanner Speed (Concurrent Workers):**", buttons=buttons)
 
214
 
215
  elif data.startswith("spd_"):
216
  try:
217
  speed_limit = int(data.split("_")[1])
218
  await db.set_concurrency(speed_limit)
219
+ await event.edit(f"⚑ **Speed updated successfully!**\nNow running with `{speed_limit}` concurrent workers.", buttons=get_main_buttons())
220
+ except Exception:
221
+ await event.edit("❌ Error setting speed.", buttons=get_main_buttons())
 
 
 
222
 
223
  elif data == "export_files":
224
+ await event.edit("⏳ **Exporting data...**\nPlease wait while files are generated.", buttons=get_main_buttons())
225
+
226
  taken = sorted(await db.get_all_taken())
227
  unavail = sorted(await db.get_all_unavailable())
228
 
229
+ if taken:
230
+ f_taken = io.BytesIO("\n".join(taken).encode('utf-8'))
231
+ f_taken.name = "taken.txt"
232
+ await client.send_file(event.chat_id, file=f_taken)
233
 
234
+ if unavail:
235
+ f_unavail = io.BytesIO("\n".join(unavail).encode('utf-8'))
236
+ f_unavail.name = "unavailable.txt"
237
+ await client.send_file(event.chat_id, file=f_unavail)
238
 
239
+ await event.edit(f"βœ… **Export Complete!**\nSent `{len(taken):,}` taken and `{len(unavail):,}` unavailable usernames.", buttons=get_main_buttons())
240
 
241
  elif data == "reset_confirm":
242
  buttons = [
243
+ [Button.inline("βœ… Yes, WIPE ALL DATA", b"reset_do")],
244
+ [Button.inline("❌ Cancel", b"back_main")]
245
  ]
246
+ await event.edit("⚠️ **DANGER ZONE** ⚠️\n\nAre you sure you want to completely wipe the Redis database? All progress will be lost.", buttons=buttons)
 
247
 
248
  elif data == "reset_do":
249
+ await event.edit("⏳ **Wiping database...**")
250
  await db.flush_all()
251
+ await event.edit("πŸ’£ **Database wiped.**\n\nRedis is completely clear. Click **πŸ”„ Load Words** to grab the next batch from the server disk!", buttons=get_main_buttons())