Spaces:
Paused
Paused
Update bot.py
Browse files
bot.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
|
| 2 |
import os
|
| 3 |
import re
|
| 4 |
import time
|
|
@@ -27,7 +26,7 @@ def get_main_menu():
|
|
| 27 |
def get_settings_menu():
|
| 28 |
return [
|
| 29 |
[Button.inline("πΎ Load Database", b"load_words")],
|
| 30 |
-
[Button.inline("β‘ Set Speed
|
| 31 |
[Button.inline("π΄ Wipe Database", b"reset_confirm")],
|
| 32 |
[Button.inline("Β« Back to Main Menu", b"back_main")]
|
| 33 |
]
|
|
@@ -105,6 +104,7 @@ async def generate_status_msg():
|
|
| 105 |
|
| 106 |
total = int(state.get("total", 0))
|
| 107 |
processed = int(state.get("processed", 0))
|
|
|
|
| 108 |
pct = (processed / total * 100) if total > 0 else 0
|
| 109 |
|
| 110 |
run_str = "π’ RUNNING" if state.get("running") == "1" else "βΉ STOPPED"
|
|
@@ -120,6 +120,7 @@ async def generate_status_msg():
|
|
| 120 |
f"**State:** `{run_str}`\n"
|
| 121 |
f"**Queue:** `{qlen:,}` waiting\n"
|
| 122 |
f"**Speed:** `{concurrency}` workers\n"
|
|
|
|
| 123 |
f"**Progress:** `{pct:.2f}%`\n"
|
| 124 |
f"`[{bar}]`\n"
|
| 125 |
f"`{processed:,} / {total:,}`\n\n"
|
|
@@ -141,8 +142,10 @@ def write_file_sync(lines):
|
|
| 141 |
with open("words.txt", "w", encoding="utf-8") as f:
|
| 142 |
f.write("\n".join(lines))
|
| 143 |
|
| 144 |
-
def filter_words_sync(chunk):
|
| 145 |
-
|
|
|
|
|
|
|
| 146 |
|
| 147 |
# --- HANDLER SETUP ---
|
| 148 |
def setup_handlers(client):
|
|
@@ -250,11 +253,15 @@ def setup_handlers(client):
|
|
| 250 |
if not all_lines:
|
| 251 |
return await event.edit("Empty file.")
|
| 252 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 253 |
CHUNK = 200000
|
| 254 |
current = all_lines[:CHUNK]
|
| 255 |
remaining = all_lines[CHUNK:]
|
| 256 |
|
| 257 |
-
valid = await asyncio.to_thread(filter_words_sync, current)
|
| 258 |
r = await db.get_redis()
|
| 259 |
done = await r.smembers("frag:done")
|
| 260 |
to_q = list(valid - done)
|
|
@@ -267,7 +274,7 @@ def setup_handlers(client):
|
|
| 267 |
|
| 268 |
await asyncio.to_thread(write_file_sync, remaining)
|
| 269 |
await db.set_state(total=len(valid))
|
| 270 |
-
await event.edit(f"β
Loaded {len(to_q):,} words.", buttons=get_main_menu())
|
| 271 |
|
| 272 |
@client.on(events.CallbackQuery())
|
| 273 |
async def button_handler(event):
|
|
@@ -282,8 +289,20 @@ def setup_handlers(client):
|
|
| 282 |
elif data == "menu_settings":
|
| 283 |
await event.edit("**System Settings**", buttons=get_settings_menu())
|
| 284 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 285 |
elif data == "load_words":
|
| 286 |
-
await event.edit("β³
|
| 287 |
await _load_words(event)
|
| 288 |
|
| 289 |
elif data == "start_scan":
|
|
@@ -305,14 +324,13 @@ def setup_handlers(client):
|
|
| 305 |
msg = await generate_status_msg()
|
| 306 |
await event.edit(msg, buttons=[[Button.inline("π Refresh", b"refresh_status")], [Button.inline("Β« Back", b"back_main")]])
|
| 307 |
except Exception as e:
|
| 308 |
-
# Silently catch the MessageNotModifiedError when numbers haven't changed
|
| 309 |
if "not modified" in str(e).lower() or "MessageNotModifiedError" in str(type(e)):
|
| 310 |
pass
|
| 311 |
else:
|
| 312 |
print(f"Status Error: {e}")
|
| 313 |
|
| 314 |
elif data == "set_speed":
|
| 315 |
-
await event.edit("Select
|
| 316 |
[Button.inline("10", b"spd_10"), Button.inline("20", b"spd_20")],
|
| 317 |
[Button.inline("30", b"spd_30"), Button.inline("50", b"spd_50")],
|
| 318 |
[Button.inline("Β« Back", b"menu_settings")]
|
|
@@ -323,7 +341,7 @@ def setup_handlers(client):
|
|
| 323 |
await event.edit("β
Speed Updated", buttons=get_settings_menu())
|
| 324 |
|
| 325 |
elif data == "export_files":
|
| 326 |
-
await event.edit("β³
|
| 327 |
exported_count = 0
|
| 328 |
|
| 329 |
for s in ["taken", "unavailable", "sold", "forsale", "auction"]:
|
|
@@ -331,9 +349,13 @@ def setup_handlers(client):
|
|
| 331 |
if lst:
|
| 332 |
f = io.BytesIO("\n".join(lst).encode('utf-8'))
|
| 333 |
f.name = f"{s}.txt"
|
| 334 |
-
|
| 335 |
await client.send_file(event.chat_id, file=f)
|
| 336 |
exported_count += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 337 |
|
| 338 |
if exported_count > 0:
|
| 339 |
await event.edit(f"β
Export complete! Sent {exported_count} files.", buttons=get_main_menu())
|
|
@@ -341,8 +363,8 @@ def setup_handlers(client):
|
|
| 341 |
await event.edit("β οΈ No data to export yet. Start a scan first!", buttons=get_main_menu())
|
| 342 |
|
| 343 |
elif data == "reset_confirm":
|
| 344 |
-
await event.edit("β οΈ WIPE ALL?", buttons=[[Button.inline("CONFIRM", b"reset_do")], [Button.inline("Cancel", b"menu_settings")]])
|
| 345 |
|
| 346 |
elif data == "reset_do":
|
| 347 |
await db.flush_all()
|
| 348 |
-
await event.edit("π£
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
import re
|
| 3 |
import time
|
|
|
|
| 26 |
def get_settings_menu():
|
| 27 |
return [
|
| 28 |
[Button.inline("πΎ Load Database", b"load_words")],
|
| 29 |
+
[Button.inline("β‘ Set Speed", b"set_speed"), Button.inline("π Set Length", b"set_min_length")],
|
| 30 |
[Button.inline("π΄ Wipe Database", b"reset_confirm")],
|
| 31 |
[Button.inline("Β« Back to Main Menu", b"back_main")]
|
| 32 |
]
|
|
|
|
| 104 |
|
| 105 |
total = int(state.get("total", 0))
|
| 106 |
processed = int(state.get("processed", 0))
|
| 107 |
+
min_len = int(state.get("min_length", 4))
|
| 108 |
pct = (processed / total * 100) if total > 0 else 0
|
| 109 |
|
| 110 |
run_str = "π’ RUNNING" if state.get("running") == "1" else "βΉ STOPPED"
|
|
|
|
| 120 |
f"**State:** `{run_str}`\n"
|
| 121 |
f"**Queue:** `{qlen:,}` waiting\n"
|
| 122 |
f"**Speed:** `{concurrency}` workers\n"
|
| 123 |
+
f"**Filter:** `Min {min_len} letters`\n"
|
| 124 |
f"**Progress:** `{pct:.2f}%`\n"
|
| 125 |
f"`[{bar}]`\n"
|
| 126 |
f"`{processed:,} / {total:,}`\n\n"
|
|
|
|
| 142 |
with open("words.txt", "w", encoding="utf-8") as f:
|
| 143 |
f.write("\n".join(lines))
|
| 144 |
|
| 145 |
+
def filter_words_sync(chunk, min_length):
|
| 146 |
+
# Dynamically filters words based on the minimum length setting
|
| 147 |
+
pattern = re.compile(rf'^[a-z0-9_]{{{min_length},32}}$')
|
| 148 |
+
return {w for w in chunk if pattern.match(w)}
|
| 149 |
|
| 150 |
# --- HANDLER SETUP ---
|
| 151 |
def setup_handlers(client):
|
|
|
|
| 253 |
if not all_lines:
|
| 254 |
return await event.edit("Empty file.")
|
| 255 |
|
| 256 |
+
# Get minimum word length setting
|
| 257 |
+
state = await db.get_state()
|
| 258 |
+
min_length = int(state.get("min_length", 4))
|
| 259 |
+
|
| 260 |
CHUNK = 200000
|
| 261 |
current = all_lines[:CHUNK]
|
| 262 |
remaining = all_lines[CHUNK:]
|
| 263 |
|
| 264 |
+
valid = await asyncio.to_thread(filter_words_sync, current, min_length)
|
| 265 |
r = await db.get_redis()
|
| 266 |
done = await r.smembers("frag:done")
|
| 267 |
to_q = list(valid - done)
|
|
|
|
| 274 |
|
| 275 |
await asyncio.to_thread(write_file_sync, remaining)
|
| 276 |
await db.set_state(total=len(valid))
|
| 277 |
+
await event.edit(f"β
Loaded {len(to_q):,} words (Min length: {min_length}).", buttons=get_main_menu())
|
| 278 |
|
| 279 |
@client.on(events.CallbackQuery())
|
| 280 |
async def button_handler(event):
|
|
|
|
| 289 |
elif data == "menu_settings":
|
| 290 |
await event.edit("**System Settings**", buttons=get_settings_menu())
|
| 291 |
|
| 292 |
+
elif data == "set_min_length":
|
| 293 |
+
await event.edit("π **Select Minimum Word Length:**", buttons=[
|
| 294 |
+
[Button.inline("4 Letters", b"min_len_4"), Button.inline("5 Letters", b"min_len_5")],
|
| 295 |
+
[Button.inline("6 Letters", b"min_len_6"), Button.inline("7 Letters", b"min_len_7")],
|
| 296 |
+
[Button.inline("Β« Back", b"menu_settings")]
|
| 297 |
+
])
|
| 298 |
+
|
| 299 |
+
elif data.startswith("min_len_"):
|
| 300 |
+
new_len = int(data.split("_")[2])
|
| 301 |
+
await db.set_state(min_length=new_len)
|
| 302 |
+
await event.edit(f"β
Filter updated: Sniping words with at least `{new_len}` letters.", buttons=get_settings_menu())
|
| 303 |
+
|
| 304 |
elif data == "load_words":
|
| 305 |
+
await event.edit("β³ Processing and loading chunk...")
|
| 306 |
await _load_words(event)
|
| 307 |
|
| 308 |
elif data == "start_scan":
|
|
|
|
| 324 |
msg = await generate_status_msg()
|
| 325 |
await event.edit(msg, buttons=[[Button.inline("π Refresh", b"refresh_status")], [Button.inline("Β« Back", b"back_main")]])
|
| 326 |
except Exception as e:
|
|
|
|
| 327 |
if "not modified" in str(e).lower() or "MessageNotModifiedError" in str(type(e)):
|
| 328 |
pass
|
| 329 |
else:
|
| 330 |
print(f"Status Error: {e}")
|
| 331 |
|
| 332 |
elif data == "set_speed":
|
| 333 |
+
await event.edit("β‘ **Select Concurrent Workers:**", buttons=[
|
| 334 |
[Button.inline("10", b"spd_10"), Button.inline("20", b"spd_20")],
|
| 335 |
[Button.inline("30", b"spd_30"), Button.inline("50", b"spd_50")],
|
| 336 |
[Button.inline("Β« Back", b"menu_settings")]
|
|
|
|
| 341 |
await event.edit("β
Speed Updated", buttons=get_settings_menu())
|
| 342 |
|
| 343 |
elif data == "export_files":
|
| 344 |
+
await event.edit("β³ Generating text files...")
|
| 345 |
exported_count = 0
|
| 346 |
|
| 347 |
for s in ["taken", "unavailable", "sold", "forsale", "auction"]:
|
|
|
|
| 349 |
if lst:
|
| 350 |
f = io.BytesIO("\n".join(lst).encode('utf-8'))
|
| 351 |
f.name = f"{s}.txt"
|
|
|
|
| 352 |
await client.send_file(event.chat_id, file=f)
|
| 353 |
exported_count += 1
|
| 354 |
+
|
| 355 |
+
# Export unknown statuses if the file exists
|
| 356 |
+
if os.path.exists("other.txt"):
|
| 357 |
+
await client.send_file(event.chat_id, "other.txt", caption="other.txt (Unknown HTML Responses)")
|
| 358 |
+
exported_count += 1
|
| 359 |
|
| 360 |
if exported_count > 0:
|
| 361 |
await event.edit(f"β
Export complete! Sent {exported_count} files.", buttons=get_main_menu())
|
|
|
|
| 363 |
await event.edit("β οΈ No data to export yet. Start a scan first!", buttons=get_main_menu())
|
| 364 |
|
| 365 |
elif data == "reset_confirm":
|
| 366 |
+
await event.edit("β οΈ WIPE ALL REDIS DATA?", buttons=[[Button.inline("CONFIRM WIPE", b"reset_do")], [Button.inline("Cancel", b"menu_settings")]])
|
| 367 |
|
| 368 |
elif data == "reset_do":
|
| 369 |
await db.flush_all()
|
| 370 |
+
await event.edit("π£ Memory purged successfully.", buttons=get_settings_menu())
|