diff --git a/bot.py b/bot.py index 9592911..565b6a1 100644 --- a/bot.py +++ b/bot.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import os +import re # thank you claude import asyncio import json import time @@ -157,6 +158,14 @@ def steal_media(text: str): with MEDIA_FILE.open("a", encoding="utf-8") as f: f.write(text + "\n") +def resolve_mentions(content: str, guild) -> str: # thank you claude + if not guild: + return content + def replace(m): + member = guild.get_member(int(m.group(1))) + return f"@{member.display_name}" if member else m.group(0) + return re.sub(r'<@!?(\d+)>', replace, content) + def is_member_in_server(member: discord.Member) -> bool: guild = client.get_guild(server) return guild and guild.get_member(member.id) is not None @@ -316,23 +325,31 @@ async def on_message(message): if str(message.author.id) in block_id: return + # drop guild messages outside allowed channels before doing anything else, thank you claude + if message.guild and message.channel.name not in ["general", "announcements"]: + return + + content = resolve_mentions(message.content, message.guild) + # always detect replies replied_message = None replied_to_bot = False + replied_content = "" if message.reference: try: replied_message = message.reference.resolved or await message.channel.fetch_message(message.reference.message_id) if replied_message: if replied_message.author == client.user: replied_to_bot = True - log_message(f'[{timestamp()}] {message.author} replied to {replied_message.author} saying: "{replied_message.content}" with reply: "{message.content}"') + replied_content = resolve_mentions(replied_message.content, message.guild) + log_message(f'[{timestamp()}] {message.author} replied to {replied_message.author} saying: "{replied_content}" with reply: "{content}"') else: - log_message(f'[{timestamp()}] {message.author} said: {message.content}') + log_message(f'[{timestamp()}] {message.author} said: {content}') except Exception as e: log_error(f"[{timestamp()}] failed to resolve reply: {e}") - log_message(f'[{timestamp()}] {message.author} said: {message.content}') + log_message(f'[{timestamp()}] {message.author} said: {content}') else: - log_message(f'[{timestamp()}] {message.author} said: {message.content}') + log_message(f'[{timestamp()}] {message.author} said: {content}') interaction_count += 1 rebuild = (interaction_count % 150 == 0) @@ -342,9 +359,9 @@ async def on_message(message): return dm_sent = False if replied_message: - user_input = f'{message.author} replied to {replied_message.author} saying: "{replied_message.content}" with reply: "{message.content}"' + user_input = f'{message.author} replied to {replied_message.author} saying: "{replied_content}" with reply: "{content}"' else: - user_input = f"{message.author} said in DM: {message.content}" + user_input = f"{message.author} said in DM: {content}" payload = build_payload(system_prompt, user_input, rebuild) stop_typing = asyncio.Event() asyncio.create_task(keep_typing(message.channel, stop_typing)) @@ -355,16 +372,13 @@ async def on_message(message): return try: await message.reply(result) - print(f"[{timestamp()}] DM from {message.author}: {message.content} Bot replied in DM: {result}") - log_message(f"[{timestamp()}] DM from {message.author}: {message.content}") + print(f"[{timestamp()}] DM from {message.author}: {content} Bot replied in DM: {result}") + log_message(f"[{timestamp()}] DM from {message.author}: {content}") log_message(f"[{timestamp()}] Faggot-chan replied in DM: {result}") except Exception as e: await handle_error(f"[{timestamp()}] failed to send DM reply: {e}", notify_user=message.author) return - if message.channel.name not in ["general", "announcements"]: - return - mentioned = client.user.mentioned_in(message) # if it replied to bot, treat it as a mention automatically @@ -375,9 +389,9 @@ async def on_message(message): return if replied_message: - user_input = f'{message.author} replied to {replied_message.author} saying: "{replied_message.content}" with reply: "{message.content}"' + user_input = f'{message.author} replied to {replied_message.author} saying: "{replied_content}" with reply: "{content}"' else: - user_input = f"{message.author} said: {message.content}" + user_input = f"{message.author} said: {content}" payload = build_payload(system_prompt, user_input, rebuild) stop_typing = asyncio.Event() @@ -390,8 +404,8 @@ async def on_message(message): try: await message.reply(result) - print(f"[{timestamp()}] {message.author} said: {message.content}\n[{timestamp()}] Faggot-chan said: {result}") - log_message(f"[{timestamp()}] {message.author} said: {message.content}\n[{timestamp()}] Faggot-chan said: {result}") + print(f"[{timestamp()}] {message.author} said: {content}\n[{timestamp()}] Faggot-chan said: {result}") + log_message(f"[{timestamp()}] {message.author} said: {content}\n[{timestamp()}] Faggot-chan said: {result}") except Exception as e: await handle_error(f"[{timestamp()}] failed to send reply: {e}", notify_channel=message.channel) diff --git a/main.py b/main.py index 7baa30b..c489b21 100644 --- a/main.py +++ b/main.py @@ -1,20 +1,15 @@ #!/usr/bin/env python3 import asyncio import json +import re # thank you claude import ollama import websockets from websockets.server import serve from datetime import datetime -chatmodel = "hf.co/Orenguteng/Llama-3.1-8B-Lexi-Uncensored-V2-GGUF:Llama-3.1-8B-Lexi-Uncensored_V2_Q4.gguf" +chatmodel = "hf.co/Stetsoncody/Llama-3.2-3B-Instruct-abliterated-GGUF:Q4_K_M" embedmodel = 'hf.co/CompendiumLabs/bge-base-en-v1.5-gguf' -# these are test models just ignore -#chatmodel = 'hf.co/bartowski/Llama-3.2-1B-Instruct-GGUF' -#chatmodel = 'hf.co/VibeStudio/Nidum-Llama-3.2-3B-Uncensored-GGUF' -#chatmodel = "faggotchan" -#chatmodel = "qwen3.5:4b" - NUM_THREADS = 6 # hardcoded since threads.txt is gone, change if needed def times() -> str: @@ -160,16 +155,17 @@ async def ollamachat(websocket): model=chatmodel, messages=messages, options={ - "temperature": 0.8, - "top_p": 0.9, + "temperature": 0.83, + "top_p": 0.9 "top_k": 40, "repeat_penalty": 1.1, - "num_predict": 4096, + "num_predict": 1024, "num_thread": NUM_THREADS, } ) - bot_reply = response["message"]["content"].strip() + # strip blocks in case the model ignores think=False, thank you claude + bot_reply = re.sub(r'.*?', '', response["message"]["content"], flags=re.DOTALL).strip() print(messages) print(f"[{times()}] reply: {bot_reply}\n")