# utils/core.py import asyncio import aiohttp import re import globals from langchain_community.vectorstores import FAISS from langchain_text_splitters import CharacterTextSplitter, RecursiveCharacterTextSplitter from langchain_core.documents import Document from utils.logger import get_logger logger = get_logger('core') # switch_model() removed - llama-swap handles model switching automatically async def is_miku_addressed(message) -> bool: # Check if this is a DM (no guild) if message.guild is None: # In DMs, always respond to every message return True # Safety check: ensure guild and guild.me exist if not message.guild or not message.guild.me: logger.warning(f"Invalid guild or guild.me in message from {message.author}") return False # If message contains a ping for Miku, return true if message.guild.me in message.mentions: return True # If message is a reply, check the referenced message author if message.reference: try: referenced_msg = await message.channel.fetch_message(message.reference.message_id) if referenced_msg.author == message.guild.me: return True except Exception as e: logger.warning(f"Could not fetch referenced message: {e}") cleaned = message.content.strip().lower() # Base names for Miku in different scripts base_names = [ 'miku', 'мику', 'みく', 'ミク', '未来' ] # Japanese honorifics - all scripts combined for simpler matching honorifics_all_scripts = [ # Latin 'chan', 'san', 'kun', 'nyan', 'hime', 'tan', 'chin', 'heika', 'denka', 'kakka', 'shi', 'chama', 'kyun', 'dono', 'sensei', 'senpai', 'jou', # Hiragana 'ちゃん', 'さん', 'くん', 'にゃん', 'ひめ', 'たん', 'ちん', 'へいか', 'でんか', 'かっか', 'し', 'ちゃま', 'きゅん', 'どの', 'せんせい', 'せんぱい', 'じょう', # Katakana 'チャン', 'サン', 'クン', 'ニャン', 'ヒメ', 'タン', 'チン', 'ヘイカ', 'デンカ', 'カッカ', 'シ', 'チャマ', 'キュン', 'ドノ', 'センセイ', 'センパイ', 'ジョウ', # Cyrillic 'чан', 'сан', 'кун', 'ньян', 'химе', 'тан', 'чин', 'хэйка', 'дэнка', 'какка', 'си', 'чама', 'кюн', 'доно', 'сэнсэй', 'сэнпай', 'жо' ] # Optional o- prefix in different scripts o_prefixes = ['o-', 'о-', 'お', 'オ'] # Strategy: Just check if any base name appears (case insensitive for latin/cyrillic) # Then allow any honorific to optionally follow for base in base_names: base_lower = base.lower() # Check for just the base name if re.search(r'(?