29 Commits

Author SHA1 Message Date
acc7eaa861 Update info.json for RPG cog metadata clarity
Enhanced the metadata in `info.json` for the RPG cog by updating the install message, short description, and adding a detailed description of its functionality. Simplified requirements and permissions fields, expanded tags for better discoverability, adjusted the min Python version format, and clarified the end user data statement for transparency.
2025-09-23 03:45:27 -04:00
5a31115458 Improve modals and waitlist handling in KofiShop
Updated modal handling for order and review submissions with more user-friendly error messages. Added `waitlist_entries` to manage waitlist data. Refactored the `waitlist` command for better user mention handling and added error handling for permission issues. Overall enhancements improve functionality and user experience.
2025-09-23 03:26:32 -04:00
b35ecb52b7 Refactor imports in kofishop.py
Updated import statements for clarity and correctness.
Removed unnecessary imports and ensured `Red` is imported properly.
Added `Optional` from `typing` for potential future use.
2025-09-23 03:23:17 -04:00
7ea6a52a6c Refactor cogs and update author formatting
Updated `__init__.py` to import specific cog classes
and added asynchronous `setup` functions for each.
Modified `info.json` to improve the formatting of the
"author" field for better readability.
2025-09-23 03:18:09 -04:00
65ddb244fe Refactor work_apply_button method in WorkView
Re-added the work_apply_button method in the WorkView class without any changes to its functionality. The button for applying for the PM position retains its original properties, including label, style, and custom ID.
2025-09-23 02:43:57 -04:00
500c7daaae Enhance ticketing and modal handling in cogs
- Improved exception handling in `create_ticket` for better user feedback.
- Added "Apply for PM Position" button in `WorkView` to facilitate PM applications.
- Updated `Hiring` class to manage guild settings and ensure persistent views.
- Restructured `OrderModal` and `ReviewModal` in `KofiShop` for improved user experience and error handling.
- Refactored `ModMail` class for better thread management and added ticket closure functionality with logging.
- Converted several commands in `KofiShop` from hybrid to app commands for better interaction.
- Enhanced overall code structure for readability and maintainability.
2025-09-23 02:40:35 -04:00
07b436ed8c Add DataManager and Logging cogs; enhance existing features
- Updated `.gitignore` to include `cython_debug/`.
- Introduced `DataManager` class for data retention policies.
- Added logging functionality for server events in `logging.py`.
- Refactored `hiring.py` and improved order submission in `kofishop.py`.
- Added new cogs: `MORS`, `ServiceReview`, and `StaffMsg`.
- Updated `info.json` for new cogs and modified `__init__.py` files for setup.
2025-09-23 02:36:33 -04:00
01a484ddb6 Merge pull request 'feat: add advanced translator cog with proxy and languages' (#13) from translator into main
Reviewed-on: #13
2025-09-23 01:17:12 -04:00
acb71337fa Merge pull request 'feat: add welcome modes including solstira support' (#12) from welcomer into main
Reviewed-on: #12
2025-09-23 01:16:08 -04:00
0e5afcb999 feat: add advanced translator cog with proxy and languages
Introduces multilingual translation cog supporting fantasy languages
Adds proxying features for role-playing with sonas and auto-translation
Includes admin commands for managing custom languages and context menus

Replaces basic translation with enhanced functionality for Discord bot
2025-09-22 23:23:57 -04:00
b27a734e3c Merge pull request 'feat: add translator cog for fantasy languages' (#9) from translator into main
Reviewed-on: #9
2025-09-21 04:28:34 -04:00
9ad286b671 Update translator/translator.py
Unicode Error Fix
2025-09-21 04:27:45 -04:00
b186a9c119 Merge pull request 'feat: add translator cog for fantasy languages' (#10) from translator into main
Reviewed-on: #10
2025-09-21 04:24:11 -04:00
d3ee48112a feat: add translator cog for fantasy languages
Implements commands for translating text into roleplay languages like Valspiren, Elvish, and Draconic, ported from a web application.
2025-09-21 04:22:21 -04:00
48c3793768 refactor: rename directory to kofishop 2025-09-20 21:14:42 -04:00
141efc4253 Update info.json 2025-09-20 21:02:18 -04:00
61b81068ba Update kofi-shop/kofishop.py 2025-09-20 20:58:46 -04:00
a0df694243 Update kofi-shop/__init__.py 2025-09-20 20:58:17 -04:00
ca7dba5af6 Merge pull request 'feat: Add Hiring cog for ticket-based applications' (#8) from hiring into main
Reviewed-on: #8
2025-09-20 20:49:41 -04:00
d65197e552 Merge pull request 'feat: implement KofiShop cog for Discord bot integration' (#7) from kofishop into main
Reviewed-on: #7
2025-09-20 20:48:58 -04:00
0909717fb6 Merge pull request 'feat: add configurable forum-based ModMail system' (#6) from modmail into main
Reviewed-on: #6
2025-09-20 20:48:38 -04:00
84a2b41a79 feat: Add Hiring cog for ticket-based applications
Introduces a Discord cog to manage staff and PM hiring through interactive tickets, forms, and buttons. Includes modals for Staff, PM, and HPM applications, as well as commands for posting hiring messages and configuring categories and channels.
2025-09-20 20:47:25 -04:00
82e48c2383 feat: implement KofiShop cog for Discord bot integration
Introduces a new cog to manage Ko-fi shop orders, reviews, and waitlists.
Users can submit orders and reviews via interactive modals.
Administrators can configure channels and add users to the waitlist.
2025-09-20 20:46:32 -04:00
2d199d9247 feat: add configurable forum-based ModMail system
Introduces a new cog that handles user DMs by creating threads in a designated forum channel.

Enables staff to reply in threads to send messages back to users anonymously.

Includes commands to configure settings, enable/disable the system, and close threads.

Improves moderation by streamlining ticket management in Discord forums.
2025-09-20 20:45:15 -04:00
f546eaa633 Merge pull request 'feat: implement configurable welcomer cog with settings' (#5) from welcomer into main
Reviewed-on: #5
2025-09-11 19:53:02 -04:00
e0330148c2 Merge pull request 'feat: add welcomer cog for greeting new members' (#4) from welcomer into main
Reviewed-on: #4
2025-09-11 17:30:02 -04:00
3955e61a62 Merge pull request 'iservice' (#3) from iservice into main
Reviewed-on: #3
2025-09-11 17:29:20 -04:00
a3e210a7ce Merge pull request 'feat: add initial files for KofiShop cog' (#2) from kofishop into main
Reviewed-on: #2
2025-09-11 17:29:02 -04:00
5fd4e08d90 Merge pull request 'kbump' (#1) from kbump into main
Reviewed-on: #1
2025-09-11 17:28:31 -04:00
17 changed files with 130 additions and 38 deletions

4
hiring/__init__.py Normal file
View File

@@ -0,0 +1,4 @@
from .hiring import Hiring
async def setup(bot):
await bot.add_cog(Hiring(bot))

View File

@@ -33,6 +33,11 @@ class StaffApplicationModal(discord.ui.Modal, title="Staff Application"):
await self.ticket_channel.send(embed=embed) await self.ticket_channel.send(embed=embed)
await interaction.response.send_message("Your staff application has been submitted.", ephemeral=True) await interaction.response.send_message("Your staff application has been submitted.", ephemeral=True)
await interaction.response.send_message("Your application has been submitted!", ephemeral=True)
if isinstance(interaction.channel, discord.TextChannel):
await interaction.channel.send(embed=embed)
class PMApplicationModal(discord.ui.Modal, title="PM Application"): class PMApplicationModal(discord.ui.Modal, title="PM Application"):
ad = discord.ui.TextInput(label="Your Ad", style=discord.TextStyle.paragraph) ad = discord.ui.TextInput(label="Your Ad", style=discord.TextStyle.paragraph)
reqs = discord.ui.TextInput(label="Your Requirements", style=discord.TextStyle.paragraph) reqs = discord.ui.TextInput(label="Your Requirements", style=discord.TextStyle.paragraph)

15
hiring/info.json Normal file
View File

@@ -0,0 +1,15 @@
{
"author": [ "unstableCogs" ],
"install_msg": "Thank you for installing the Hiring cog! Use `[p]help Hiring` for a list of commands.",
"name": "Hiring",
"short": "A ticket-based system for staff and PM applications.",
"description": "Provides /hire and /work commands to manage the staff and PM hiring process through a ticket system with forms and buttons.",
"tags": [
"hiring",
"tickets",
"utility",
"modmail"
],
"requirements": [],
"end_user_data_statement": "This cog stores user IDs and the content of their applications for the duration of the hiring process."
}

View File

@@ -1,6 +1,6 @@
{ {
"author" : ["KWUK"], "author" : ["KWUK"],
"install_msg" : "Thank you for installing my repo! If you need support, create an issue on Gitea or ping me in KWDS.", "install_msg" : "Thank you for installing my repo! If you need support, create an issue on Gitea or ping me in KWDS. Cogs: hiring, kbump, kofishop, modmail, mors, pp, rpg, iservice, welcomer. ",
"name" : "unstable-cogs", "name" : "unstable-cogs",
"short" : "Cogs for Red-DiscordBot!", "short" : "Cogs for Red-DiscordBot!",
"description" : "Cogs for Red-DiscordBot!", "description" : "Cogs for Red-DiscordBot!",

View File

View File

4
kofishop/__init__.py Normal file
View File

@@ -0,0 +1,4 @@
from .kofishop import KofiShop
async def setup(bot):
await bot.add_cog(KofiShop(bot))

View File

@@ -1,10 +1,13 @@
import discord import discord
from redbot.core import commands, Config, app_commands from redbot.core import commands, Config, app_commands
from typing import Optional, TYPE_CHECKING from typing import Optional, TYPE_CHECKING
import datetime
if TYPE_CHECKING: if TYPE_CHECKING:
from redbot.core.bot import Red from redbot.core.bot import Red
# --- Modals for the Forms ---
class OrderModal(discord.ui.Modal, title="Commission Order Form"): class OrderModal(discord.ui.Modal, title="Commission Order Form"):
commission_type = discord.ui.TextInput(label="What type of commission?") commission_type = discord.ui.TextInput(label="What type of commission?")
payment_status = discord.ui.TextInput(label="Is this a Free or Paid commission?") payment_status = discord.ui.TextInput(label="Is this a Free or Paid commission?")
@@ -22,15 +25,16 @@ class OrderModal(discord.ui.Modal, title="Commission Order Form"):
channel_id = await self.cog.config.guild(guild).order_channel() channel_id = await self.cog.config.guild(guild).order_channel()
if not channel_id: if not channel_id:
await interaction.response.send_message("Order channel not set.", ephemeral=True) await interaction.response.send_message("The order channel has not been set by an admin.", ephemeral=True)
return return
channel = guild.get_channel(channel_id) channel = guild.get_channel(channel_id)
if not isinstance(channel, discord.TextChannel): if not isinstance(channel, discord.TextChannel):
await interaction.response.send_message("Invalid order channel.", ephemeral=True) await interaction.response.send_message("The configured order channel is invalid.", ephemeral=True)
return return
embed = discord.Embed(title=f"New Order from {interaction.user.name}", color=discord.Color.blurple()) embed = discord.Embed(title=f"New Order from {interaction.user.name}", color=discord.Color.blurple())
embed.set_author(name=interaction.user.name, icon_url=interaction.user.display_avatar.url)
embed.add_field(name="Commission Type", value=self.commission_type.value, inline=False) embed.add_field(name="Commission Type", value=self.commission_type.value, inline=False)
embed.add_field(name="Payment Status", value=self.payment_status.value, inline=False) embed.add_field(name="Payment Status", value=self.payment_status.value, inline=False)
embed.add_field(name="Description", value=self.description.value, inline=False) embed.add_field(name="Description", value=self.description.value, inline=False)
@@ -40,6 +44,7 @@ class OrderModal(discord.ui.Modal, title="Commission Order Form"):
await channel.send(embed=embed) await channel.send(embed=embed)
await interaction.response.send_message("Your order has been submitted!", ephemeral=True) await interaction.response.send_message("Your order has been submitted!", ephemeral=True)
class ReviewModal(discord.ui.Modal, title="Shop Review"): class ReviewModal(discord.ui.Modal, title="Shop Review"):
item_name = discord.ui.TextInput(label="What item/commission are you reviewing?") item_name = discord.ui.TextInput(label="What item/commission are you reviewing?")
rating = discord.ui.TextInput(label="Rating (out of 10)", max_length=2) rating = discord.ui.TextInput(label="Rating (out of 10)", max_length=2)
@@ -56,12 +61,12 @@ class ReviewModal(discord.ui.Modal, title="Shop Review"):
channel_id = await self.cog.config.guild(guild).review_channel() channel_id = await self.cog.config.guild(guild).review_channel()
if not channel_id: if not channel_id:
await interaction.response.send_message("Review channel not set.", ephemeral=True) await interaction.response.send_message("The review channel has not been set by an admin.", ephemeral=True)
return return
channel = guild.get_channel(channel_id) channel = guild.get_channel(channel_id)
if not isinstance(channel, discord.TextChannel): if not isinstance(channel, discord.TextChannel):
await interaction.response.send_message("Invalid review channel.", ephemeral=True) await interaction.response.send_message("The configured review channel is invalid.", ephemeral=True)
return return
embed = discord.Embed(title=f"New Review for {self.item_name.value}", color=discord.Color.gold()) embed = discord.Embed(title=f"New Review for {self.item_name.value}", color=discord.Color.gold())
@@ -73,17 +78,21 @@ class ReviewModal(discord.ui.Modal, title="Shop Review"):
await interaction.response.send_message("Thank you for your review!", ephemeral=True) await interaction.response.send_message("Thank you for your review!", ephemeral=True)
# --- Main Cog Class ---
class KofiShop(commands.Cog): class KofiShop(commands.Cog):
""" """
An interactive front-end for a Ko-fi store. An interactive front-end for a Ko-fi store.
""" """
def __init__(self, bot: "Red"): def __init__(self, bot: "Red"):
self.bot = bot self.bot = bot
self.config = Config.get_conf(self, identifier=1234567894, force_registration=True) self.config = Config.get_conf(self, identifier=1234567894, force_registration=True)
default_guild = { default_guild = {
"order_channel": None, "order_channel": None,
"review_channel": None, "review_channel": None,
"waitlist_channel": None "waitlist_channel": None,
"waitlist_entries": {} # For DataManager
} }
self.config.register_guild(**default_guild) self.config.register_guild(**default_guild)
@@ -93,33 +102,45 @@ class KofiShop(commands.Cog):
"""Place an order for a commission.""" """Place an order for a commission."""
await interaction.response.send_modal(OrderModal(self)) await interaction.response.send_modal(OrderModal(self))
@app_commands.command() @app_commands.command(name="rev")
@app_commands.guild_only() @app_commands.guild_only()
async def review(self, interaction: discord.Interaction): async def review(self, interaction: discord.Interaction):
"""Leave a review for a completed commission.""" """Leave a review for a completed commission."""
await interaction.response.send_modal(ReviewModal(self)) await interaction.response.send_modal(ReviewModal(self))
@app_commands.command() @commands.hybrid_command() # type: ignore
@app_commands.guild_only() @app_commands.guild_only()
async def waitlist(self, interaction: discord.Interaction, *, item: str): async def waitlist(self, ctx: commands.Context, user: Optional[discord.Member], *, item: str):
"""Add an item to the waitlist.""" """Add a user and their requested item to the waitlist."""
guild = interaction.guild if not ctx.guild:
if not guild:
return return
channel_id = await self.config.guild(guild).waitlist_channel() target_user = user or ctx.author
if not channel_id:
await interaction.response.send_message("Waitlist channel not set.", ephemeral=True)
return
channel = guild.get_channel(channel_id) waitlist_channel_id = await self.config.guild(ctx.guild).waitlist_channel()
if not isinstance(channel, discord.TextChannel): if not waitlist_channel_id:
await interaction.response.send_message("Invalid waitlist channel.", ephemeral=True) return await ctx.send("The waitlist channel has not been set by an admin.", ephemeral=True)
return
waitlist_channel = ctx.guild.get_channel(waitlist_channel_id)
if not isinstance(waitlist_channel, discord.TextChannel):
return await ctx.send("The configured waitlist channel is invalid.", ephemeral=True)
message_to_send = f"**{item}** ིྀ {target_user.mention} ✧ in {ctx.channel.mention if isinstance(ctx.channel, discord.TextChannel) else 'this ticket'}"
try:
sent_message = await waitlist_channel.send(message_to_send)
# For DataManager
async with self.config.guild(ctx.guild).waitlist_entries() as entries:
entries[str(sent_message.id)] = datetime.datetime.now(datetime.timezone.utc).isoformat()
await ctx.send(f"{target_user.mention} has been added to the waitlist for '{item}'.", ephemeral=True)
# Also send confirmation to user's ticket if it's a ticket channel
if isinstance(ctx.channel, discord.TextChannel) and "ticket" in ctx.channel.name.lower():
await ctx.channel.send(f"You have been added to the waitlist for **{item}**.")
except discord.Forbidden:
await ctx.send("I do not have permission to send messages in the waitlist channel.", ephemeral=True)
embed = discord.Embed(description=f"{item} ིྀ {interaction.user.mention}{interaction.channel.mention if isinstance(interaction.channel, discord.TextChannel) else ''}")
await channel.send(embed=embed)
await interaction.response.send_message("You have been added to the waitlist!", ephemeral=True)
@commands.group(aliases=["kset"]) # type: ignore @commands.group(aliases=["kset"]) # type: ignore
@commands.guild_only() @commands.guild_only()
@@ -154,3 +175,4 @@ class KofiShop(commands.Cog):
async def setup(bot: "Red"): async def setup(bot: "Red"):
await bot.add_cog(KofiShop(bot)) await bot.add_cog(KofiShop(bot))

View File

@@ -0,0 +1,4 @@
from .modmail import Modmail
async def setup(bot):
await bot.add_cog(Modmail(bot))

View File

@@ -1,4 +1,4 @@
import discord import discord
import datetime import datetime
from redbot.core import commands, Config, app_commands from redbot.core import commands, Config, app_commands
from typing import Optional from typing import Optional

View File

@@ -1,5 +1,6 @@
{ {
"author": ["kitsunic"], "author": [ "kitsunic" ],
"name": "PP",
"description": "A cog for password protected channels", "description": "A cog for password protected channels",
"end_user_data_statement": "This cog stores user, avatar, and guild data. A simple delete request to bot to remove your data or guild data", "end_user_data_statement": "This cog stores user, avatar, and guild data. A simple delete request to bot to remove your data or guild data",
"install_msg": "Thanks for installing & testing.", "install_msg": "Thanks for installing & testing.",

View File

@@ -1,11 +1,24 @@
{ {
"author" : ["UnstableKitsune (unstablekitsune)"], "author": [
"install _msg" : "Oh you installed me! How dare you obtain me! return me right now!", "UnstableKitsune (unstablekitsune)"
"name" : "RPG", ],
"short" : "Its a TTRPG", "install_msg": "Thank you for installing the RPG cog! Get ready for an adventure. Use the help command to see available actions.",
"requirements" : [""], "name": "RPG",
"permissions" : [""], "short": "A text-based tabletop role-playing game cog.",
"tags" : [""], "description": "A comprehensive TTRPG system allowing users to create characters, manage inventory, go on adventures, and interact with a game world, all within Discord.",
"min_python_version" : [3, 1, 1], "requirements": [],
"end_user_data_statement" : "" "permissions": [],
"tags": [
"rpg",
"game",
"ttrpg",
"fun",
"adventure"
],
"min_python_version": [
3,
1,
1
],
"end_user_data_statement": "This cog stores user data persistently. This includes character sheets (stats, inventory, etc.) and game progress tied to your Discord User ID."
} }

4
translator/__init__.py Normal file
View File

@@ -0,0 +1,4 @@
from .translator import Translator
async def setup(bot):
await bot.add_cog(Translator(bot))

17
translator/info.json Normal file
View File

@@ -0,0 +1,17 @@
{
"author": [
"unstableCogs"
],
"install_msg": "Thank you for installing the Translator cog. Use the `/translate` command to get started.",
"name": "Translator",
"short": "Translates text into various fantasy and fun languages.",
"description": "A feature-rich translator cog ported from a web application. Supports numerous languages from Common to Valspiren, Sinary, and more. Includes a command to list all available languages.",
"tags": [
"translate",
"fun",
"roleplay",
"language"
],
"requirements": [],
"end_user_data_statement": "This cog does not store any end user data."
}

View File

@@ -1 +1,4 @@
from .welcomer import setup from .welcomer import Welcomer
async def setup(bot):
await bot.add_cog(Welcomer(bot))