diff --git a/reginaldCog/reginald.py b/reginaldCog/reginald.py index b821293..715b802 100644 --- a/reginaldCog/reginald.py +++ b/reginaldCog/reginald.py @@ -16,7 +16,6 @@ from .weather import time_now, get_current_weather, get_weather_forecast from .tools_description import TOOLS from .debug_stuff import debug - CALLABLE_FUNCTIONS = { # Dictionary with functions to call. # You can use globals()[func_name](**args) instead, but that's too implicit. @@ -71,7 +70,7 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): async def on_message(self, message): if message.author.bot or not message.guild: return # Ignore bots and DMs - + # ✅ Check if user is blacklisted if await self.is_blacklisted(message.author): return # Ignore message if user is explicitly blacklisted @@ -80,7 +79,6 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): if not (await self.is_admin(message) or await self.has_access(message.author)): return # Ignore message if user has no permissions - guild = message.guild channel_id = str(message.channel.id) user_id = str(message.author.id) @@ -115,8 +113,8 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): await message.channel.send(random.choice(["Yes?", "How may I assist?", "You rang?"])) return explicit_invocation = True - - # ✅ Passive Listening: Check if the message contains relevant keywords + + # ✅ Passive Listening: Check if the message contains relevant keywords elif self.should_reginald_interject(message_content): prompt = message_content explicit_invocation = False @@ -124,11 +122,11 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): else: return # Ignore irrelevant messages - # ✅ Context Handling: Maintain conversation flow + # ✅ Context Handling: Maintain conversation flow if memory and memory[-1]["user"] == user_name: prompt = f"Continuation of the discussion:\n{prompt}" - # ✅ Prepare context messages + # ✅ Prepare context messages formatted_messages = [{"role": "system", "content": self.get_reginald_persona()}] if user_profile: @@ -145,10 +143,10 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): "content": f"[{summary['timestamp']}] Topics: {', '.join(summary['topics'])}\n{summary['summary']}" }) - formatted_messages += [{"role": "user", "content": f"{entry['user']}: {entry['content']}"} for entry in memory] + formatted_messages += [{"role": "user", "content": f"{entry['user']}: {entry['content']}"} for entry in + memory] formatted_messages.append({"role": "user", "content": f"{user_name}: {prompt}"}) - ################################################## # # ## Generate AI Response, put into response_text ## @@ -166,7 +164,8 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): memory.append({"user": "Reginald", "content": response_text}) if len(memory) > self.short_term_memory_limit: - summary = await self.summarize_memory(message, memory[:int(self.short_term_memory_limit * self.summary_retention_ratio)]) + summary = await self.summarize_memory(message, memory[:int( + self.short_term_memory_limit * self.summary_retention_ratio)]) mid_memory.setdefault(channel_id, []).append({ "timestamp": datetime.datetime.now().strftime("%Y-%m-%d %H:%M"), "topics": self.extract_topics_from_summary(summary), @@ -174,20 +173,20 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): }) if len(mid_memory[channel_id]) > self.summary_retention_limit: mid_memory[channel_id].pop(0) - memory = memory[-(self.short_term_memory_limit - int(self.short_term_memory_limit * self.summary_retention_ratio)):] + memory = memory[-(self.short_term_memory_limit - int( + self.short_term_memory_limit * self.summary_retention_ratio)):] short_memory[channel_id] = memory await self.send_split_message(message.channel, response_text) - def should_reginald_interject(self, message_content: str) -> bool: """Determines if Reginald should respond to a message based on keywords.""" direct_invocation = { - "reginald," - } + "reginald," + } message_lower = message_content.lower() - + return any(message_lower.startswith(invocation) for invocation in direct_invocation) @debug @@ -227,8 +226,8 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): 'content': func_result, 'tool_call_id': tool_call_id, }) - - completion_args["messages"] = messages + + completion_args["messages"] = messages # Second completion required if functions has been called to interpret the result into user-friendly # chat message. response = await client.chat.completions.create(**completion_args) @@ -261,11 +260,12 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): await self.config.guild(ctx.guild).openai_api_key.set(api_key) await ctx.send("OpenAI API key set successfully.") - @commands.command(name="reginald_set_listening_channel", help="Set the channel where Reginald listens for messages.") + @commands.command(name="reginald_set_listening_channel", + help="Set the channel where Reginald listens for messages.") @commands.has_permissions(administrator=True) async def set_listening_channel(self, ctx, channel: discord.TextChannel): """Sets the channel where Reginald will listen for passive responses.""" - + if not channel: await ctx.send("❌ Invalid channel. Please mention a valid text channel.") return @@ -273,12 +273,13 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): await self.config.guild(ctx.guild).listening_channel.set(channel.id) await ctx.send(f"✅ Reginald will now listen only in {channel.mention}.") - @commands.command(name="reginald_get_listening_channel", help="Check which channel Reginald is currently listening in.") + @commands.command(name="reginald_get_listening_channel", + help="Check which channel Reginald is currently listening in.") @commands.has_permissions(administrator=True) async def get_listening_channel(self, ctx): """Displays the current listening channel.""" channel_id = await self.config.guild(ctx.guild).listening_channel() - + if channel_id: channel = ctx.guild.get_channel(channel_id) if channel: # ✅ Prevents crash if channel was deleted @@ -288,18 +289,17 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): else: await ctx.send("❌ No listening channel has been set.") + # async def send_long_message(self, ctx, message, prefix: str = ""): + # """Splits and sends a long message to avoid Discord's 2000-character limit.""" + # chunk_size = 1900 # Leave some space for formatting + # if prefix: + # prefix_length = len(prefix) + # chunk_size -= prefix_length + # + # for i in range(0, len(message), chunk_size): + # chunk = message[i:i + chunk_size] + # await ctx.send(f"{prefix}{chunk}") - async def send_long_message(self, ctx, message, prefix: str = ""): - """Splits and sends a long message to avoid Discord's 2000-character limit.""" - chunk_size = 1900 # Leave some space for formatting - if prefix: - prefix_length = len(prefix) - chunk_size -= prefix_length - - for i in range(0, len(message), chunk_size): - chunk = message[i:i + chunk_size] - await ctx.send(f"{prefix}{chunk}") - async def send_split_message(self, ctx, content: str, prefix: str = ""): """ Sends a long message to Discord while ensuring it does not exceed the 2000-character limit. @@ -351,4 +351,4 @@ class ReginaldCog(PermissionsMixin, BlacklistMixin, MemoryMixin, commands.Cog): async def setup(bot): """✅ Correct async cog setup for Redbot""" - await bot.add_cog(ReginaldCog(bot)) \ No newline at end of file + await bot.add_cog(ReginaldCog(bot))