Skip to content

Commit 9760ba2

Browse files
authored
Implement guild configuration (#146)
1 parent 179c3ba commit 9760ba2

14 files changed

+1116
-170
lines changed

bot/cogs/config.py

+492-30
Large diffs are not rendered by default.

bot/cogs/tickets.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ async def create_ticket(self, ticket: TicketThread) -> Optional[TicketOutput]:
243243
]
244244
processed_tags = [tag for tag in applied_tags if tag is not None]
245245

246-
content = f"({ticket.user.display_name}, {discord.utils.format_dt(ticket.created_at)})\n\n{ticket.content}"
246+
content = f"({ticket.mention} - {ticket.user.display_name}, {discord.utils.format_dt(ticket.created_at)})\n\n{ticket.content}"
247247
created_ticket = await tc.create_thread(
248248
applied_tags=processed_tags,
249249
name=ticket.title,

bot/launcher.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from aiohttp import ClientSession
88
from libs.utils import KeyboardInterruptHandler, RodhajLogger
99
from libs.utils.config import RodhajConfig
10-
from rodhaj import Rodhaj
10+
from rodhaj import Rodhaj, init
1111

1212
if os.name == "nt":
1313
from winloop import run
@@ -27,7 +27,7 @@
2727

2828
async def main() -> None:
2929
async with ClientSession() as session, asyncpg.create_pool(
30-
dsn=POSTGRES_URI, min_size=25, max_size=25, command_timeout=30
30+
dsn=POSTGRES_URI, min_size=25, max_size=25, init=init, command_timeout=30
3131
) as pool:
3232
async with Rodhaj(
3333
config=config, intents=intents, session=session, pool=pool

bot/libs/tickets/structs.py

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class TicketThread(msgspec.Struct):
2929
title: str
3030
user: Union[discord.User, discord.Member]
3131
location_id: int
32+
mention: str
3233
content: str
3334
tags: list[str]
3435
files: list[discord.File]

bot/libs/tickets/views.py

+41
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
if TYPE_CHECKING:
1414
from libs.utils.context import RoboContext
1515

16+
from bot.cogs.config import Config
1617
from bot.cogs.tickets import Tickets
1718
from bot.rodhaj import Rodhaj
1819

@@ -133,6 +134,7 @@ def __init__(
133134
bot: Rodhaj,
134135
ctx: RoboContext,
135136
cog: Tickets,
137+
config_cog: Config,
136138
content: str,
137139
guild: discord.Guild,
138140
delete_after: bool = True,
@@ -142,6 +144,7 @@ def __init__(
142144
self.bot = bot
143145
self.ctx = ctx
144146
self.cog = cog
147+
self.config_cog = config_cog
145148
self.content = content
146149
self.guild = guild
147150
self.delete_after = delete_after
@@ -162,6 +165,18 @@ async def delete_response(self, interaction: discord.Interaction):
162165

163166
self.stop()
164167

168+
async def get_or_fetch_member(self, member_id: int) -> Optional[discord.Member]:
169+
member = self.guild.get_member(member_id)
170+
if member is not None:
171+
return member
172+
173+
members = await self.guild.query_members(
174+
limit=1, user_ids=[member_id], cache=True
175+
)
176+
if not members:
177+
return None
178+
return members[0]
179+
165180
@discord.ui.button(
166181
label="Checklist",
167182
style=discord.ButtonStyle.primary,
@@ -228,6 +243,31 @@ async def confirm(
228243

229244
applied_tags = [k for k, v in tags.items() if v is True]
230245

246+
guild_settings = await self.config_cog.get_guild_settings(self.guild.id)
247+
potential_member = await self.get_or_fetch_member(author.id)
248+
249+
if not guild_settings:
250+
await interaction.response.send_message(
251+
"Unable to find guild settings", ephemeral=True
252+
)
253+
return
254+
255+
if (self.guild.created_at - interaction.created_at) < guild_settings.guild_age:
256+
await interaction.response.send_message(
257+
"The guild is too young in order to utilize Rodhaj.", ephemeral=True
258+
)
259+
return
260+
elif (
261+
potential_member
262+
): # Since we are checking join times, if we don't have the proper member, we can only skip it.
263+
joined_at = potential_member.joined_at or discord.utils.utcnow()
264+
if (joined_at - interaction.created_at) < guild_settings.account_age:
265+
await interaction.response.send_message(
266+
"This account joined the server too soon in order to utilize Rodhaj.",
267+
ephemeral=True,
268+
)
269+
return
270+
231271
if not status.title.is_set() or not status.tags.is_set():
232272
dict_status = {"title": status.title, "tags": status.tags}
233273
formatted_status = "\n".join(
@@ -255,6 +295,7 @@ async def confirm(
255295
title=title,
256296
user=author,
257297
location_id=self.guild.id,
298+
mention=guild_settings.mention,
258299
content=self.content,
259300
tags=applied_tags,
260301
files=files,

bot/libs/utils/config.py

+37
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pathlib import Path
22
from typing import Any, Generic, Optional, TypeVar, Union, overload
33

4+
import orjson
45
import yaml
56

67
_T = TypeVar("_T")
@@ -44,3 +45,39 @@ def __len__(self) -> int:
4445

4546
def all(self) -> dict[str, Union[_T, Any]]:
4647
return self._config
48+
49+
50+
class OptionsHelp(Generic[_T]):
51+
def __init__(self, path: Path):
52+
self.path = path
53+
self._config: dict[str, Union[_T, Any]] = {}
54+
self.load_from_file()
55+
56+
def load_from_file(self) -> None:
57+
try:
58+
with open(self.path, "r") as f:
59+
self._config: dict[str, Union[_T, Any]] = orjson.loads(f.read())
60+
except FileNotFoundError:
61+
self._config = {}
62+
63+
@overload
64+
def get(self, key: Any) -> Optional[Union[_T, Any]]: ...
65+
66+
@overload
67+
def get(self, key: Any, default: Any) -> Union[_T, Any]: ...
68+
69+
def get(self, key: Any, default: Any = None) -> Optional[Union[_T, Any]]:
70+
"""Retrieves a config entry."""
71+
return self._config.get(str(key), default)
72+
73+
def __contains__(self, item: Any) -> bool:
74+
return str(item) in self._config
75+
76+
def __getitem__(self, item: Any) -> Union[_T, Any]:
77+
return self._config[str(item)]
78+
79+
def __len__(self) -> int:
80+
return len(self._config)
81+
82+
def all(self) -> dict[str, Union[_T, Any]]:
83+
return self._config

0 commit comments

Comments
 (0)