From 7fa85d7dd96ab293d7e1bdbf85066384fcde14c1 Mon Sep 17 00:00:00 2001 From: Kingston-SCYD Date: Fri, 31 Jul 2026 20:41:40 -0500 Subject: [PATCH] Rename greeptchat cog to assistant - generic AI chatbot branding --- README.md | 174 ++++++++++++++++++ assistant/__init__.py | 5 + .../greeptchat.py => assistant/assistant.py | 56 +++--- assistant/info.json | 11 ++ greeptchat/__init__.py | 5 - greeptchat/info.json | 11 -- 6 files changed, 218 insertions(+), 44 deletions(-) create mode 100644 assistant/__init__.py rename greeptchat/greeptchat.py => assistant/assistant.py (83%) create mode 100644 assistant/info.json delete mode 100644 greeptchat/__init__.py delete mode 100644 greeptchat/info.json diff --git a/README.md b/README.md index e9344c0..da7758c 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,13 @@ Homepage: https://homepage.kingstons-scrapyard.net/ - [Permissions Required](#permissions-required) - [Scrapyard Cogworks Modifications](#scrapyard-cogworks-modifications) +**Assistant** +- [Assistant](#assistant) +- [Assistant Installation](#assistant-installation) +- [Assistant User Commands](#assistant-user-commands) +- [Assistant Admin/Owner Commands](#assistant-adminowner-commands) +- [Assistant Behavior](#assistant-behavior) + **TtsToy** - [TtsToy](#ttstoy) - [TtsToy User Commands](#user-commands-1) @@ -560,6 +567,173 @@ The `[p]autoroom allow` command now accepts multiple users/roles in a single com --- --- +# Assistant + +AI chatbot cog that responds in a dedicated channel or when the bot is @mentioned. Uses an OpenAI-compatible API backend. Designed for fun, unpredictable responses — crank the temperature and give it a wild system prompt. + +### Features + +- **Chat channel mode** — set a channel where the bot responds to every message +- **Ping mode** — responds when @mentioned in any channel +- **Custom system prompt** — control the bot's personality +- **Temperature control** — turn it up for chaotic/funny responses +- **Question mode** — optionally restrict responses to messages ending with `?` +- **Conversation history** — remembers the last 20 messages per channel (in memory only) +- **Long response handling** — automatically chunks replies over 2000 characters + +### Requirements + +- Python 3.11+ +- Red-DiscordBot 3.5.0+ +- Dependencies: `aiohttp` + +--- + +## Assistant Installation + +``` +[p]cog install scrapyard assistant +[p]load assistant +``` + +--- + +## Assistant User Commands + +The assistant responds automatically in the configured chat channel or when pinged. There are no user-invoked "chat" commands — just talk to it. + +**In the chat channel:** Send any message and the bot replies. + +**Anywhere else:** @mention the bot with your message. + +``` +@Bot what's the meaning of life? +``` + +If **question mode** is on, messages must end with `?` or they'll be ignored. + +--- + +## Assistant Admin/Owner Commands + +All commands are under the `[p]assistant` group. + +--- + +### `[p]assistant setkey` + +**Requires:** Bot Owner + +Set the API key via a private modal dialog. The key is stored globally (shared across all servers the bot is in). + +--- + +### `[p]assistant toggle` + +Toggle the assistant on or off for the current server. Enabled by default. + +--- + +### `[p]assistant channel [#channel]` + +Set the dedicated chat channel where the bot responds to all messages. + +- With a channel: sets that channel as the chat channel. +- Without a channel: clears the setting (bot only responds to @mentions). + +**Examples:** +``` +[p]assistant channel #bot-chat +[p]assistant channel +``` + +--- + +### `[p]assistant model ` + +Set the AI model to use. + +**Examples:** +``` +[p]assistant model gemma4 +[p]assistant model green-l +[p]assistant model green-r +``` + +--- + +### `[p]assistant temp ` + +Set the response temperature. + +- Range: `0.0` to `2.0` +- Lower values (0.1–0.5) = focused, predictable responses +- Higher values (1.2–2.0) = creative, chaotic, funny responses + +**Examples:** +``` +[p]assistant temp 0.3 +[p]assistant temp 1.8 +``` + +--- + +### `[p]assistant system ` + +Set the system prompt that defines the bot's personality and behavior. + +**Examples:** +``` +[p]assistant system You are a helpful assistant. +[p]assistant system You are an unhinged gremlin who gives terrible life advice in the style of a 90s infomercial host. Everything is an emergency. +[p]assistant system You are a pirate who only speaks in nautical metaphors and refuses to acknowledge anything invented after 1750. +``` + +--- + +### `[p]assistant question` + +Toggle question mode. When ON, the bot only responds to messages that end with `?`. Everything else is ignored. + +This is a toggle — run again to disable. + +--- + +### `[p]assistant clear` + +Clear the conversation history for the current channel. The bot will forget all previous context. + +--- + +### `[p]assistant settings` + +Display the current configuration as an embed: + +- Enabled (yes/no) +- Chat Channel +- API Key (set/not set) +- Model +- Temperature +- Question Mode (on/off) +- System Prompt (first 200 chars) + +--- + +## Assistant Behavior + +- **History:** The bot keeps the last 20 messages (user + assistant) per channel in memory. History is lost on cog reload/bot restart. +- **Typing indicator:** The bot shows "typing..." while waiting for the API response. +- **Long responses:** Replies over 2000 characters are split into multiple messages. +- **Error handling:** If the API is down or returns an error, the bot replies with the error info. +- **No response to bots:** The assistant ignores messages from other bots. +- **Per-guild settings:** Model, temperature, system prompt, channel, and question mode are all configured per server. +- **Global API key:** The API key is set once by the bot owner and applies to all servers. + +--- + +--- +--- + # TtsToy Multi-engine text-to-speech cog with voice cloning, emoji-triggered sound effects, inline voice switching, a TTS queue system, and a companion web UI. Plays audio in voice channels and uploads MP3 files to chat. diff --git a/assistant/__init__.py b/assistant/__init__.py new file mode 100644 index 0000000..f9507f3 --- /dev/null +++ b/assistant/__init__.py @@ -0,0 +1,5 @@ +from .assistant import Assistant + + +async def setup(bot): + await bot.add_cog(Assistant(bot)) diff --git a/greeptchat/greeptchat.py b/assistant/assistant.py similarity index 83% rename from greeptchat/greeptchat.py rename to assistant/assistant.py index 12b7cf0..0f20692 100644 --- a/greeptchat/greeptchat.py +++ b/assistant/assistant.py @@ -6,12 +6,12 @@ from redbot.core.bot import Red class APIKeyModal(discord.ui.Modal): def __init__(self, config): - super().__init__(title="GreenPT API Key") + super().__init__(title="API Key") self.config = config self.key_input = discord.ui.TextInput( label="API Key", style=discord.TextStyle.short, - placeholder="Paste your GreenPT API key here", + placeholder="Paste your API key here", required=True, ) self.add_item(self.key_input) @@ -21,8 +21,8 @@ class APIKeyModal(discord.ui.Modal): await interaction.response.send_message("API key saved.", ephemeral=True) -class GreeptChat(commands.Cog): - """AI chat via the GreenPT API. Set a chat channel or get responses when pinged.""" +class Assistant(commands.Cog): + """AI chatbot assistant. Set a chat channel or get responses when the bot is pinged.""" BASE_URL = "https://greenpt.com/v1" @@ -97,7 +97,7 @@ class GreeptChat(commands.Cog): reply = await self._chat(guild, message.channel.id, content) if reply is None: - await message.reply("No response from GreenPT.") + await message.reply("No response from the assistant.") return if len(reply) <= 2000: @@ -167,24 +167,24 @@ class GreeptChat(commands.Cog): # Commands # --------------------------------------------------------------------------- - greept = commands.Group("greept", "GreenPT chat settings.", guild_only=True) + assistant = commands.Group("assistant", "AI assistant settings.", guild_only=True) - @greept.command(name="setkey") + @assistant.command(name="setkey") @checks.is_owner() - async def greept_setkey(self, ctx: commands.Context): - """Set the GreenPT API key (opens a private modal).""" + async def assistant_setkey(self, ctx: commands.Context): + """Set the API key (opens a private modal).""" await ctx.send_modal(APIKeyModal(self.config)) - @greept.command(name="toggle") - async def greept_toggle(self, ctx: commands.Context): - """Toggle the cog on or off for this server.""" + @assistant.command(name="toggle") + async def assistant_toggle(self, ctx: commands.Context): + """Toggle the assistant on or off for this server.""" current = await self.config.guild(ctx.guild).enabled() await self.config.guild(ctx.guild).enabled.set(not current) state = "enabled" if not current else "disabled" - await ctx.send(f"GreeptChat **{state}** for this server.") + await ctx.send(f"Assistant **{state}** for this server.") - @greept.command(name="channel") - async def greept_channel(self, ctx: commands.Context, channel: discord.TextChannel | None = None): + @assistant.command(name="channel") + async def assistant_channel(self, ctx: commands.Context, channel: discord.TextChannel | None = None): """Set the dedicated chat channel. Omit to clear.""" if channel is None: await self.config.guild(ctx.guild).chat_channel.set(None) @@ -193,14 +193,14 @@ class GreeptChat(commands.Cog): await self.config.guild(ctx.guild).chat_channel.set(channel.id) await ctx.send(f"Chat channel set to {channel.mention}.") - @greept.command(name="model") - async def greept_model(self, ctx: commands.Context, model: str): + @assistant.command(name="model") + async def assistant_model(self, ctx: commands.Context, model: str): """Set the model (e.g. gemma4, green-l, green-r).""" await self.config.guild(ctx.guild).model.set(model) await ctx.send(f"Model set to **{model}**.") - @greept.command(name="temp") - async def greept_temp(self, ctx: commands.Context, temperature: float): + @assistant.command(name="temp") + async def assistant_temp(self, ctx: commands.Context, temperature: float): """Set the temperature (0.0 - 2.0).""" if not 0.0 <= temperature <= 2.0: await ctx.send("Must be between 0.0 and 2.0.") @@ -208,29 +208,29 @@ class GreeptChat(commands.Cog): await self.config.guild(ctx.guild).temperature.set(temperature) await ctx.send(f"Temperature set to **{temperature}**.") - @greept.command(name="system") - async def greept_system(self, ctx: commands.Context, *, prompt: str): + @assistant.command(name="system") + async def assistant_system(self, ctx: commands.Context, *, prompt: str): """Set the system prompt.""" await self.config.guild(ctx.guild).system_prompt.set(prompt) await ctx.send("System prompt updated.") - @greept.command(name="question") - async def greept_question(self, ctx: commands.Context): + @assistant.command(name="question") + async def assistant_question(self, ctx: commands.Context): """Toggle question mode (messages must end with ?).""" current = await self.config.guild(ctx.guild).question_mode() await self.config.guild(ctx.guild).question_mode.set(not current) state = "ON" if not current else "OFF" await ctx.send(f"Question mode **{state}**.") - @greept.command(name="clear") - async def greept_clear(self, ctx: commands.Context): + @assistant.command(name="clear") + async def assistant_clear(self, ctx: commands.Context): """Clear conversation history for this channel.""" key = (ctx.guild.id, ctx.channel.id) self.history.pop(key, None) await ctx.send("History cleared for this channel.") - @greept.command(name="settings") - async def greept_settings(self, ctx: commands.Context): + @assistant.command(name="settings") + async def assistant_settings(self, ctx: commands.Context): """Show current settings.""" cfg = self.config.guild(ctx.guild) enabled = await cfg.enabled() @@ -243,7 +243,7 @@ class GreeptChat(commands.Cog): channel_str = f"<#{chat_channel}>" if chat_channel else "None" - embed = discord.Embed(title="GreeptChat Settings", color=await ctx.embed_color()) + embed = discord.Embed(title="Assistant Settings", color=await ctx.embed_color()) embed.add_field(name="Enabled", value=str(enabled), inline=True) embed.add_field(name="Chat Channel", value=channel_str, inline=True) embed.add_field(name="API Key", value="Set" if has_key else "Not set", inline=True) diff --git a/assistant/info.json b/assistant/info.json new file mode 100644 index 0000000..d6888e1 --- /dev/null +++ b/assistant/info.json @@ -0,0 +1,11 @@ +{ + "author": ["Scrapyard Cogworks"], + "install_msg": "Assistant cog installed. Use [p]assistant to configure.", + "name": "Assistant", + "short": "AI chatbot assistant with channel and ping modes.", + "description": "AI chatbot assistant using an OpenAI-compatible API. Set a dedicated chat channel or get responses when the bot is pinged. Supports temperature, model, system prompt, and question mode.", + "tags": ["ai", "chat", "assistant", "gpt", "llm"], + "requirements": ["aiohttp"], + "min_bot_version": "3.5.0", + "end_user_data_statement": "This cog stores conversation history per channel in memory only." +} diff --git a/greeptchat/__init__.py b/greeptchat/__init__.py deleted file mode 100644 index f9ebd24..0000000 --- a/greeptchat/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .greeptchat import GreeptChat - - -async def setup(bot): - await bot.add_cog(GreeptChat(bot)) diff --git a/greeptchat/info.json b/greeptchat/info.json deleted file mode 100644 index 78f67da..0000000 --- a/greeptchat/info.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "author": ["Scrapyard Cogworks"], - "install_msg": "GreeptChat cog installed. Use [p]greept to configure.", - "name": "GreeptChat", - "short": "AI chat via GreenPT API with channel and ping modes.", - "description": "Connects to the GreenPT OpenAI-compatible API for AI chat. Set a dedicated chat channel or get responses when the bot is pinged. Supports temperature, model, system prompt, and question mode.", - "tags": ["ai", "chat", "greenpt", "gpt", "llm"], - "requirements": ["aiohttp"], - "min_bot_version": "3.5.0", - "end_user_data_statement": "This cog stores conversation history per channel in memory only." -}