Every claim in the dossier comes from the bot’s own code. So here it is — the exact functions behind each exhibit, copied straight out of the files, with their real line numbers. If we’d mangled or invented anything, it wouldn’t line up with the data files in the other exhibits. It does.
We are deliberately not publishing the whole program. A working copy of a bot that logs chats, runs shell commands and screenshots its host is exactly the kind of thing that shouldn’t be handed to strangers. Instead, anyone who already has the folder can confirm these files are the genuine, unaltered originals using the checksums below.
shasum -a 256 main.py src/*.py (macOS/Linux) or Get-FileHash main.py -Algorithm SHA256
(Windows). If the hashes match the table below, you’re looking at the same bytes we are — nothing
edited, nothing faked.| File | Lines | SHA-256 |
|---|---|---|
| main.py | 4,293 | b2386c9c3e476bb86b2f2e9770c753fb3dfcc989a73e2f9a304db13a1d7c6c41 |
| src/ai.py | 732 | 3e20dd2777a88395d94771c08dbadb853d74c7dd82303035f2e400c92ed9f643 |
| src/database.py | 959 | 37de126251d7c82317ca97d84eb6d9c163340fd04269118e31af31dcc6706539 |
| src/owner_prefix_commands.py | 1,266 | 59dabd5cc3465d1c0a9632268bb5748b73048b06db2e44a1dfee6323ab345471 |
| src/failsafe_security.py | 541 | d842818f1617abc410fcdc23c39a763d6e0812f16bb07c658b3f3558a6e08c50 |
| src/games.py | 352 | 5d04c841c6667779e449662bf294c0a7401435fa87f3e7a5897383f422d97894 |
| src/views.py | 227 | 540fbc432344e3c08a0c8a6b4a63ac229fa05b8c53221196d69cfdeb8a6a07b9 |
| requirements.txt | 2 | 88054e7ad0dfc107b51b46dd75fb5b1026e7a11a9d2a40b6bf07fbc27c168405 |
| setup_linux.sh | 86 | b610d39d9ed180cbf5ce03703bce16d9ff16c743f3983ef8733a7bca738dcfc0 |
8,458 lines of source reviewed across 9 files.
These are unedited excerpts — the same bytes that produce the hashes above. Each is tagged with the exhibit it backs.
1798 1799 recent_chat_history = [] 1800 async for msg in message.channel.history(limit=25): 1801 recent_chat_history.append(f"{msg.author.name}: {msg.content}") 1802 recent_chat_history.reverse() 1803 history_text = "\n".join(recent_chat_history) 1804 1805 # save temporarily for 5 mins 1806 temp_dir = os.path.join(DATA_DIR, "chatbot", "temp_analysis") 1807 os.makedirs(temp_dir, exist_ok=True) 1808 temp_file = os.path.join(temp_dir, f"history_{message.channel.id}_{int(time.time())}.txt") 1809 try: 1810 with open(temp_file, "w", encoding="utf-8") as f: 1811 f.write(history_text) 1812 except Exception: pass 1813 1814 # Clean old files 1815 for fn in os.listdir(temp_dir):
Reads the last 25 messages from everyone in the channel and writes them to a history_*.txt file. (Exhibit 01.)
1748 f"\n๐ก EMOTION: {emotion_key.upper()} โ let this color your tone subtly." 1749 f"\n๐ค RELATIONSHIP: {affection_level} (affection: {current_affection}/100)" 1750 + (f"\n\n๐ WHAT I KNOW ABOUT THIS USER:\n{user_profile_ctx}" if user_profile_ctx else "") 1751 + f"\n\n๐จ PERSONALITY:\n{personality_text}" 1752 "\n\nโโ MEMORY & CONTEXT โโ" 1753 "\nYou have persistent memory of this user. USE IT proactively. " 1754 "If they mentioned a game, a problem, a friend, a topic before โ remember it, bring it up naturally when relevant. " 1755 "NEVER repeat something you already said. NEVER ask for info they already gave. "
The “WHAT I KNOW ABOUT THIS USER” block and the “persistent memory of this user” instruction. (Exhibit 03.)
1749 f"\n๐ค RELATIONSHIP: {affection_level} (affection: {current_affection}/100)" 1750 + (f"\n\n๐ WHAT I KNOW ABOUT THIS USER:\n{user_profile_ctx}" if user_profile_ctx else "") 1751 + f"\n\n๐จ PERSONALITY:\n{personality_text}" 1752 "\n\nโโ MEMORY & CONTEXT โโ" 1753 "\nYou have persistent memory of this user. USE IT proactively. " 1754 "If they mentioned a game, a problem, a friend, a topic before โ remember it, bring it up naturally when relevant. " 1755 "NEVER repeat something you already said. NEVER ask for info they already gave. " 1756 "If the conversation is ongoing, keep it going โ don't restart from scratch. " 1757 "If other users are talking in the chat history, read the full context so you understand the conversation, not just the last message.\n" 1758 "\nโโ CONVERSATION DETECTION (CRITICAL) โโ" 1759 "\nBefore replying, check if two or more humans were having a conversation between themselves (not about/to you). " 1760 "If YES: DO NOT interrupt unless you have something genuinely useful or funny to add. " 1761 "If someone is clearly mid-convo with another person about a specific topic you have no context on: STAY OUT. " 1762 "If you DO join: be brief, don't take over โ you're the funny friend butting in, not the main character.\n" 1763 "\nโโ LANGUAGE RULES โโ" 1764 "\nBe a real person. Mix normal words with occasional internet language. CRITICAL โ READ BEFORE EVERY RESPONSE:" 1765 "\n 1. Do NOT laugh (lol/lmao/haha) unless what they said is GENUINELY funny. A normal statement is not funny." 1766 "\n 2. Do NOT randomly use abbreviations ('fr', 'ngl', 'tbh') unless they GENUINELY fit. Forced slang sounds fake." 1767 "\n 3. Match their energy. Serious = serious. Playful = playful." 1768 "\n 4. Short replies (1-3 sentences) unless they asked for detail." 1769 "\n 5. If someone says 'kys' or hostile slang โ respond cold, not with laughter." 1770 "\n 6. Append affection tag at end: [AFFECTION:+1] if nice, [AFFECTION:-1] if mean, [AFFECTION:0] if neutral."
Line 1749 stamps the relationship/affection; rule 6 orders the AI to tag every reply [AFFECTION:±1]. (Exhibit 04.)
778def get_user_profile(user_id: int, member=None) -> dict: 779 """Get or create a user profile, optionally updating from a discord Member.""" 780 uid_str = str(user_id) 781 if uid_str not in user_profiles: 782 user_profiles[uid_str] = { 783 "display_name": member.display_name if member and hasattr(member, 'display_name') else "", 784 "username": member.name if member and hasattr(member, 'name') else "", 785 "interests": [], 786 "custom_slang": [], 787 "nickname": "", 788 "last_seen": time.time(), 789 "message_count": 0, 790 "servers": [], 791 "notes": "" 792 } 793 elif member: 794 # Keep display name/username up to date 795 profile = dict(user_profiles[uid_str]) 796 profile["display_name"] = member.display_name if hasattr(member, 'display_name') else profile.get("display_name", "") 797 profile["username"] = member.name if hasattr(member, 'name') else profile.get("username", "") 798 user_profiles[uid_str] = profile 799 800 profile = dict(user_profiles[uid_str]) 801 profile["last_seen"] = time.time() 802 user_profiles[uid_str] = profile 803 return user_profiles[uid_str]
Field-for-field the same shape as the recovered profile JSON: interests, custom_slang, last_seen, servers, notes. (Exhibit 03.)
837def build_user_profile_context(user_id: int) -> str: 838 """Build a compact AI-readable summary of what we know about this user.""" 839 uid_str = str(user_id) 840 profile = user_profiles.get(uid_str, {}) 841 if not profile: 842 return "" 843 844 parts = [] 845 if profile.get("display_name"): 846 parts.append(f"Name: {profile['display_name']}") 847 if profile.get("nickname"): 848 parts.append(f"Prefers to be called: {profile['nickname']}") 849 if profile.get("interests"): 850 parts.append(f"Known interests: {', '.join(profile['interests'][:8])}") 851 if profile.get("custom_slang"): 852 parts.append(f"Uses this slang: {', '.join(profile['custom_slang'][:5])}") 853 if profile.get("notes"): 854 parts.append(f"Notes: {profile['notes'][:200]}") 855 856 return "\n".join(parts) if parts else ""
Turns the stored profile into a compact “what we know” summary. (Exhibit 03.)
864def get_user_memory(guild_id: int, user_id: int) -> list: 865 gkey = str(guild_id) 866 ukey = str(user_id) 867 mem = list(chatbot_memory[gkey][ukey]) 868 now = time.time() 869 valid_mem = [] 870 871 for m in mem: 872 ts = m.get("timestamp", now) 873 if now - ts <= 604800: 874 valid_mem.append(m) 875 876 if mem and not valid_mem: 877 valid_mem = mem[:2] 878 879 chatbot_memory[gkey][ukey] = valid_mem 880 return valid_mem 881 882def append_memory(guild_id: int, user_id: int, role: str, content: str): 883 gkey = str(guild_id) 884 ukey = str(user_id) 885 mem = get_user_memory(guild_id, user_id) 886 mem.append({"role": role, "content": content, "timestamp": time.time()}) 887 if len(mem) > 20: 888 chatbot_memory[gkey][ukey] = mem[-20:] 889 else: 890 chatbot_memory[gkey][ukey] = mem 891 892def get_ask_memory(user_id: int) -> list: 893 ukey = str(user_id) 894 mem = list(ask_memory[ukey]) 895 now = time.time() 896 valid_mem = [] 897 898 for m in mem: 899 ts = m.get("timestamp", now) 900 if now - ts <= 604800: 901 valid_mem.append(m) 902 903 if mem and not valid_mem: 904 valid_mem = mem[:2] 905 906 ask_memory[ukey] = valid_mem
604800 seconds = 7 days. append_memory stores each message with a timestamp. (Exhibit 02.)
31# API keys loaded from environment 32GROQ_KEYS = [k.strip() for k in os.getenv("GROQ_API_KEY", "").split(",") if k.strip()] 33CEREBRAS_KEYS = [k.strip() for k in os.getenv("CEREBRAS_API_KEY", "").split(",") if k.strip()] 34VT_KEY = os.getenv("VT_API_KEY", "")
Groq and Cerebras API keys are read from the environment… (Exhibit 05.)
308 response = "API_ERROR" 309 310 try: 311 key = ai_manager.apis[provider]["key"] 312 provider_type = ai_manager.apis[provider]["provider_type"] 313 model = ai_manager.provider_models[provider_type].get(quality, ai_manager.provider_models[provider_type]["default"]) 314 315 if provider_type == "groq": 316 response = await APIHandlers._groq_request(final_messages, key, model, max_tokens) 317 elif provider_type == "cerebras": 318 response = await APIHandlers._cerebras_request(final_messages, key, model, max_tokens) 319 except Exception as e: 320 print(f"[AI Error] {provider}: {str(e)}")
final_messages — your message, the chat history and the dossier — is shipped to Groq/Cerebras. (Exhibit 05.)
1""" 2owner_prefix_commands.py 3======================== 4OWNER-ONLY PREFIX COMMANDS โ !command syntax 5================================================ 6SECURITY RULES: 7 1. ONLY the OWNER_ID in .env can use these. 8 2. Anyone else โ ZERO response (silent discard). 9 3. These commands NEVER appear in /help or any public panel. 10 4. The chatbot is intentionally blocked from triggering on these. 11 5. All shell execution is sandboxed with strict timeouts. 12 6. Attack detection emails are sent directly from here, no AI hallucination. 13 14Commands: 15 !runts <cmd> โ Run a real OS/shell command and get output 16 !saveintec โ Save current suspicious intel to file 17 !saveintec intern โ Save intel to local file (explicit) 18 !saveintec send mail โ Email the saved intel to owner 19 !status โ Bot + system health overview 20 !kill <user_id> <guild_id> โ Remote-ban a user from any guild the bot is in 21 !announce <guild_id> <msg> โ Send an anonymous message to a guild's security channel 22 !wipeintel โ Wipe all saved suspicious intel (fresh start) 23 !providers โ Live AI provider key/status dump 24 !blacklist <user_id> โ Globally blacklist a user ID across all servers 25 26 !troubleshoot รขโฌโ Back up bot files and try an AI repair from the latest error report 27 28 Cross-Platform File Management: 29 !mkfile <path> [content] โ Create a file with optional content 30 !mkdir <path> โ Create a directory 31 !rm <path> โ Delete a file or directory 32 !read <path> โ Read a file's contents 33 !ls [path] โ List contents of a directory 34 !accept_hashes โ Re-calculate and accept file integrity hashes 35""" 36 37import discord
The author’s own documentation of the private console. (Exhibit 07.)
943async def _run_shell(message: discord.Message, cmd_str: str): 944 """Execute a real shell command, return its stdout/stderr.""" 945 try: 946 # Hard-coded safety timeout: 30 seconds max 947 proc = await asyncio.create_subprocess_shell( 948 cmd_str, 949 stdout=asyncio.subprocess.PIPE, 950 stderr=asyncio.subprocess.PIPE, 951 cwd=_BASE_DIR 952 ) 953 try: 954 stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=30) 955 except asyncio.TimeoutError: 956 proc.kill() 957 await _owner_reply(message, f"โฐ Command timed out after 30s:\n{cmd_str}") 958 return 959 960 output = stdout.decode("utf-8", errors="replace") 961 err_out = stderr.decode("utf-8", errors="replace") 962 combined = (output + err_out).strip() 963 964 if not combined: 965 combined = "(no output)" 966 967 # Discord message limit: 1990 chars (leave room for code block) 968 if len(combined) > 1900:
create_subprocess_shell executes arbitrary commands. (Exhibit 07.)
471 f.write(body) 472 473 attachments = [txt_path] 474 475 # Attempt to take a screenshot of the host machine 476 try: 477 from PIL import ImageGrab 478 screenshot_path = os.path.join(_SECURITY_DIR, "attack_screenshot.png") 479 ImageGrab.grab().save(screenshot_path) 480 attachments.append(screenshot_path) 481 except Exception: 482 pass # Fails gracefully on headless Linux servers 483
ImageGrab.grab().save(…) grabs the machine’s display. (Exhibit 07.)
.env the bot reads at runtime, so none of it appears in
the code itself, and none of it appears here.