diff --git a/README.md b/README.md
index e0bb701..98e60b5 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ Main Contributors/Developers:
JasonLovesDoggo
Levani Vashadze
-The bot is currently on release: 2.0
+The bot is currently on release: 2.2
License: MIT
Contributing
diff --git a/cogs/AI.py b/cogs/AI.py
index 5bce980..0fd82e3 100644
--- a/cogs/AI.py
+++ b/cogs/AI.py
@@ -1,7 +1,7 @@
import base64
import time
from io import BytesIO
-
+from better_profanity import profanity
import disnake
from disnake.ext import commands
@@ -13,11 +13,21 @@ def __init__(self, bot: OGIROID):
self.bot = bot
@commands.slash_command(description="Generates ai art")
- async def ai_art(self, inter: disnake.ApplicationCommandInteraction, text):
+ async def ai_art(
+ self, inter: disnake.ApplicationCommandInteraction, text: str
+ ):
+ if profanity.contains_profanity(text):
+ return await inter.send(
+ f"NSFW requests are not allowed!", ephemeral=True
+ )
+ if "bot" in inter.channel.name or "command" in inter.channel.name:
+ hidden = False
+ else:
+ hidden = True
ETA = int(time.time() + 60)
await inter.send(
f"Go grab a coffee this may take a while... ETA: ",
- ephemeral=True,
+ ephemeral=hidden,
)
response = await self.bot.session.post(
"https://backend.craiyon.com/generate", json={"prompt": text}
@@ -25,11 +35,15 @@ async def ai_art(self, inter: disnake.ApplicationCommandInteraction, text):
r = await response.json()
raw_images = r["images"]
images = [
- disnake.File(BytesIO(base64.decodebytes(i.encode("utf-8"))), "image.png")
+ disnake.File(
+ BytesIO(base64.decodebytes(i.encode("utf-8"))), "image.png"
+ )
for i in raw_images
]
- await inter.edit_original_response(files=images, content="Here you go!")
+ await inter.edit_original_response(
+ files=images, content="Here you go!"
+ )
def setup(bot):
diff --git a/cogs/Animals.py b/cogs/Animals.py
index eaf511d..bd62fdd 100644
--- a/cogs/Animals.py
+++ b/cogs/Animals.py
@@ -10,7 +10,9 @@ class Animals(commands.Cog):
def __init__(self, bot: OGIROID):
self.bot = bot
- @commands.slash_command(description="Gets a random picture of the specified animal")
+ @commands.slash_command(
+ description="Gets a random picture of the specified animal"
+ )
@commands.cooldown(1, 3, commands.BucketType.user)
async def animal(self, inter):
pass
@@ -18,7 +20,9 @@ async def animal(self, inter):
@animal.sub_command(name="cat", description="Get a random cat picture")
async def cat(self, inter):
"""Get a random cat picture!"""
- response = await self.bot.session.get("https://some-random-api.ml/animal/cat")
+ response = await self.bot.session.get(
+ "https://some-random-api.com/animal/cat"
+ )
data = await response.json()
embed = disnake.Embed(
title="Cat Picture! π±",
@@ -30,12 +34,16 @@ async def cat(self, inter):
text=f"Command issued by: {inter.author.name}",
icon_url=inter.author.display_avatar,
)
- await inter.response.send_message(f"**Fun Fact: **" + data["fact"], embed=embed)
+ await inter.response.send_message(
+ f"**Fun Fact: **" + data["fact"], embed=embed
+ )
@animal.sub_command(name="dog", description="Get a random dog picture")
async def dog(self, inter):
"""Get a random dog picture!"""
- response = await self.bot.session.get("https://some-random-api.ml/animal/dog")
+ response = await self.bot.session.get(
+ "https://some-random-api.com/animal/dog"
+ )
data = await response.json()
embed = disnake.Embed(
title="Dog Picture! πΆ",
@@ -47,12 +55,16 @@ async def dog(self, inter):
text=f"Command issued by: {inter.author.name}",
icon_url=inter.author.display_avatar,
)
- await inter.response.send_message("**Fun Fact: **" + data["fact"], embed=embed)
+ await inter.response.send_message(
+ "**Fun Fact: **" + data["fact"], embed=embed
+ )
@animal.sub_command(name="bird", description="Get a random bird picture")
async def bird(self, inter):
"""Get a random bird picture!"""
- response = await self.bot.session.get("https://some-random-api.ml/animal/bird")
+ response = await self.bot.session.get(
+ "https://some-random-api.com/animal/bird"
+ )
data = await response.json()
embed = disnake.Embed(
title="Bird Picture! π¦",
@@ -64,12 +76,16 @@ async def bird(self, inter):
text=f"Command issued by: {inter.author.name}",
icon_url=inter.author.display_avatar,
)
- await inter.response.send_message("**Fun Fact: **" + data["fact"], embed=embed)
+ await inter.response.send_message(
+ "**Fun Fact: **" + data["fact"], embed=embed
+ )
@animal.sub_command(name="fox", description="Get a random fox picture")
async def fox(self, inter):
"""Get a random fox picture!"""
- response = await self.bot.session.get("https://some-random-api.ml/animal/fox")
+ response = await self.bot.session.get(
+ "https://some-random-api.com/animal/fox"
+ )
data = await response.json()
embed = disnake.Embed(
title="Fox Picture! π¦",
@@ -81,12 +97,16 @@ async def fox(self, inter):
text=f"Command issued by: {inter.author.name}",
icon_url=inter.author.display_avatar,
)
- await inter.response.send_message("**Fun Fact: **" + data["fact"], embed=embed)
+ await inter.response.send_message(
+ "**Fun Fact: **" + data["fact"], embed=embed
+ )
@animal.sub_command(name="panda", description="Get a random panda picture")
async def panda(self, inter):
"""Get a random panda picture!"""
- response = await self.bot.session.get("https://some-random-api.ml/animal/panda")
+ response = await self.bot.session.get(
+ "https://some-random-api.com/animal/panda"
+ )
data = await response.json()
embed = disnake.Embed(
title="Panda Picture! πΌ",
@@ -98,12 +118,16 @@ async def panda(self, inter):
text=f"Command issued by: {inter.author.name}",
icon_url=inter.author.display_avatar,
)
- await inter.response.send_message("**Fun Fact: **" + data["fact"], embed=embed)
+ await inter.response.send_message(
+ "**Fun Fact: **" + data["fact"], embed=embed
+ )
@animal.sub_command(name="koala", description="Get a random cat picture")
async def koala(self, inter):
"""Get a random koala picture!"""
- response = await self.bot.session.get("https://some-random-api.ml/animal/koala")
+ response = await self.bot.session.get(
+ "https://some-random-api.com/animal/koala"
+ )
data = await response.json()
embed = disnake.Embed(
title="Koala Picture! π¨",
@@ -115,7 +139,9 @@ async def koala(self, inter):
text=f"Command issued by: {inter.author.name}",
icon_url=inter.author.display_avatar,
)
- await inter.response.send_message("**Fun Fact: **" + data["fact"], embed=embed)
+ await inter.response.send_message(
+ "**Fun Fact: **" + data["fact"], embed=embed
+ )
def setup(bot):
diff --git a/cogs/Birthdays.py b/cogs/Birthdays.py
index d16c051..f565ef5 100644
--- a/cogs/Birthdays.py
+++ b/cogs/Birthdays.py
@@ -12,6 +12,20 @@
from utils.shortcuts import QuickEmb, sucEmb, errorEmb
+async def get_days_until_birthday(user_data) -> (int, str):
+ """returns the days until the next birthday and the next birthday date formatted for discord"""
+ next_birthday = datetime.datetime.strptime(
+ user_data.birthday + f"/{dt.datetime.now().year}", "%d/%m/%Y"
+ )
+ if next_birthday < datetime.datetime.now():
+ next_birthday = datetime.datetime.strptime(
+ user_data.birthday + f"/{dt.datetime.now().year + 1}", "%d/%m/%Y"
+ )
+ return (
+ next_birthday - datetime.datetime.now()
+ ).days, f""
+
+
class Birthday(commands.Cog):
def __init__(self, bot: OGIROID):
self.bot = bot
@@ -21,17 +35,22 @@ def __init__(self, bot: OGIROID):
@commands.Cog.listener()
async def on_ready(self):
if not self.bot.ready_:
- self.birthday: BirthdayHandler = BirthdayHandler(self.bot, self.bot.db)
+ self.birthday: BirthdayHandler = BirthdayHandler(
+ self.bot, self.bot.db
+ )
def cog_unload(self):
self.birthday_check.cancel()
- @commands.slash_command(name="birthday")
+ @commands.slash_command(
+ name="birthday", description="Birthdays base command"
+ )
async def birthday(self, inter: disnake.ApplicationCommandInteraction):
pass
@birthday.sub_command(
- name="set", description="Set your birthday. Cant be removed without Staff."
+ name="set",
+ description="Set your birthday. Cant be removed without Staff.",
)
async def set(
self,
@@ -49,7 +68,9 @@ async def set(
),
):
if month is None or day is None:
- return await errorEmb(inter, "You need to provide a month and a day")
+ return await errorEmb(
+ inter, "You need to provide a month and a day"
+ )
if day < 1 or day > 31:
return await errorEmb(inter, "The day must be between 1 and 31")
@@ -63,7 +84,8 @@ async def set(
@commands.has_permissions(manage_roles=True)
@birthday.sub_command(
- name="edit", description="Edit a users birthday. Can only be done by Staff."
+ name="edit",
+ description="Edit a users birthday. Can only be done by Staff.",
)
async def edit(
self,
@@ -82,13 +104,18 @@ async def edit(
):
try:
await self.birthday.update_user(user.id, f"{day}/{month}")
- return await sucEmb(inter, f"Birthday has been updated to {day}/{month}")
+ return await sucEmb(
+ inter, f"Birthday has been updated to {day}/{month}"
+ )
except UserNotFound:
- return await errorEmb(inter, "The User doesn't have a birthday set")
+ return await errorEmb(
+ inter, "The User doesn't have a birthday set"
+ )
@commands.has_permissions(manage_roles=True)
@birthday.sub_command(
- name="remove", description="Remove a birthday. Can only be done by Staff."
+ name="remove",
+ description="Remove a birthday. Can only be done by Staff.",
)
async def remove(
self,
@@ -100,13 +127,17 @@ async def remove(
try:
await self.birthday.delete_user(user.id)
except UserNotFound:
- return await errorEmb(inter, "This user doesn't have a birthday set")
+ return await errorEmb(
+ inter, "This user doesn't have a birthday set"
+ )
await sucEmb(inter, "The birthday has been removed")
@birthday.sub_command(name="get", description="Get the birthday of a user")
async def get(
- self, inter, user: disnake.User = commands.Param(name="user", default=None)
+ self,
+ inter,
+ user: disnake.User = commands.Param(name="user", default=None),
):
if user is None:
user = inter.author
@@ -115,19 +146,47 @@ async def get(
birthday = await self.birthday.get_user(user.id)
if birthday is None:
- return await errorEmb(inter, "This user doesn't have a birthday set")
+ return await errorEmb(
+ inter, "This user doesn't have a birthday set"
+ )
- next_birthday = datetime.datetime.strptime(
- birthday.birthday + f"/{dt.datetime.now().year}", "%d/%m/%Y"
- )
- if next_birthday < datetime.datetime.now():
- next_birthday = datetime.datetime.strptime(
- birthday.birthday + f"/{dt.datetime.now().year + 1}", "%d/%m/%Y"
+ days, discord_date = await get_days_until_birthday(birthday)
+ await QuickEmb(
+ inter,
+ f"{user.mention}'s birthday is in {days} Days." f"{discord_date}",
+ ).send()
+
+ @birthday.sub_command(name="next", description="Get the next birthday")
+ async def next(self, inter: disnake.ApplicationCommandInteraction):
+ upcoming_birthdays = []
+ # loop gets next birthday
+ for user in await self.birthday.get_users():
+ # gets days until birthday and the discord date
+ days, discord_date = await get_days_until_birthday(user)
+ # checks if user is in the guild
+ upcoming_birthdays.append(
+ {"days": days, "user": user, "discord_date": discord_date}
)
+
+ # sorts birthdays by days
+ upcoming_birthdays.sort(key=lambda x: x["days"])
+ # gets the next birthday's user
+ next_birthday = upcoming_birthdays[0]["user"]
+ # checks if user is in the guild
+ while await inter.guild.fetch_member(next_birthday.user_id) is None:
+ upcoming_birthdays.pop(0)
+ next_birthday = upcoming_birthdays[0]["user"]
+
+ member = await self.bot.fetch_user(next_birthday.user_id)
+
+ if next_birthday is None:
+ return await errorEmb(inter, "There are no birthdays set")
+
+ days, discord_date = await get_days_until_birthday(next_birthday)
await QuickEmb(
inter,
- f"{user.mention}'s birthday is in {(next_birthday - datetime.datetime.now()).days} Days."
- f" ",
+ f"{member.mention}'s birthday is in {days} Days."
+ f"{discord_date}",
).send()
# @tasks.loop(time=[dt.time(dt.datetime.utcnow().hour, dt.datetime.utcnow().minute, dt.datetime.utcnow().second + 10)])
@@ -135,22 +194,26 @@ async def get(
@tasks.loop(time=[dt.time(8, 0, 0)])
# loops every day at 8:00 UTC time
async def birthday_check(self):
- channel = self.bot.get_channel(self.bot.config.channels.birthdays)
- guild = self.bot.get_guild(self.bot.config.guilds.main_guild)
+ channel = await self.bot.fetch_channel(
+ self.bot.config.channels.birthdays
+ )
+ guild = await self.bot.fetch_guild(self.bot.config.guilds.main_guild)
if channel is None:
return
today = dt.datetime.utcnow().strftime("%d/%m")
# Gets all users from the db
users = await self.birthday.get_users()
for user in users:
- member = await guild.fetch_member(user.user_id)
+ member = await guild.getch_member(user.user_id)
# if the member is None, the user is not in the server anymore
if member is None:
continue
# if the birthday is today, congratulate the user
if user.birthday == today:
- await member.add_roles(guild.get_role(self.bot.config.roles.birthday))
+ await member.add_roles(
+ guild.get_role(self.bot.config.roles.birthday)
+ )
congrats_msg = await channel.send(
f"{random.choice(congrats_messages)} {member.mention}! π"
)
diff --git a/cogs/Blacklist.py b/cogs/Blacklist.py
index dd8bd9a..33d96bd 100644
--- a/cogs/Blacklist.py
+++ b/cogs/Blacklist.py
@@ -43,7 +43,11 @@ async def check_user_removal(self, user: BlacklistedUser):
return # already being removed
elif user.is_expired():
await self.blacklist.remove(user.id)
- elif int(time.time()) <= user.expires <= (int(time.time()) + timings.HOUR):
+ elif (
+ int(time.time())
+ <= user.expires
+ <= (int(time.time()) + timings.HOUR)
+ ):
self.del_que.append(user.id)
await self.run_at(user.expires, self.blacklist.remove, user.id)
@@ -59,10 +63,14 @@ async def blacklist(self, inter):
pass
@commands.cooldown(1, 5, commands.BucketType.user)
- @blacklist.sub_command(name="info", description="Get info about a blacklisted user")
+ @blacklist.sub_command(
+ name="info", description="Get info about a blacklisted user"
+ )
async def blacklist_info(self, inter, user: Member):
if not await self.blacklist.blacklisted(user.id):
- return await errorEmb(inter, f"{user.mention} is not in the blacklist")
+ return await errorEmb(
+ inter, f"{user.mention} is not in the blacklist"
+ )
bl_user = await self.blacklist.get_user(user.id)
embed = Embed(
title=f"Blacklisted user: {user.name}",
@@ -83,11 +91,16 @@ async def edit(self, inter):
@commands.has_permissions(manage_messages=True)
@edit.sub_command(
- name="flags", description="Edit the user's blacklist flags in the blacklist"
+ name="flags",
+ description="Edit the user's blacklist flags in the blacklist",
)
- async def flags(self, inter, user: Member, bot: bool, tickets: bool, tags: bool):
+ async def flags(
+ self, inter, user: Member, bot: bool, tickets: bool, tags: bool
+ ):
if not await self.blacklist.blacklisted(user.id):
- return await errorEmb(inter, f"{user.mention} is not in the blacklist")
+ return await errorEmb(
+ inter, f"{user.mention} is not in the blacklist"
+ )
await self.blacklist.edit_flags(user.id, bot, tickets, tags)
await sucEmb(
inter,
@@ -96,11 +109,14 @@ async def flags(self, inter, user: Member, bot: bool, tickets: bool, tags: bool)
@commands.has_permissions(manage_messages=True)
@edit.sub_command(
- name="reason", description="Edit the user's blacklist reason in the blacklist"
+ name="reason",
+ description="Edit the user's blacklist reason in the blacklist",
)
async def reason(self, inter, user: Member, reason: str):
if not await self.blacklist.blacklisted(user.id):
- return await errorEmb(inter, f"{user.mention} is not in the blacklist")
+ return await errorEmb(
+ inter, f"{user.mention} is not in the blacklist"
+ )
await self.blacklist.edit_reason(user.id, reason)
await sucEmb(
inter,
@@ -109,11 +125,14 @@ async def reason(self, inter, user: Member, reason: str):
@commands.has_permissions(manage_messages=True)
@edit.sub_command(
- name="expiry", description="Edit the user's blacklist expiry in the blacklist"
+ name="expiry",
+ description="Edit the user's blacklist expiry in the blacklist",
)
async def expiry(self, inter, user: Member, expires: str):
if not await self.blacklist.blacklisted(user.id):
- return await errorEmb(inter, f"{user.mention} is not in the blacklist")
+ return await errorEmb(
+ inter, f"{user.mention} is not in the blacklist"
+ )
expiry = int((await timeconversions.convert(expires)).dt.timestamp())
await self.blacklist.edit_expiry(user.id, expiry)
await sucEmb(
@@ -128,10 +147,14 @@ async def expiry(self, inter, user: Member, expires: str):
)
async def remove(self, inter, user: Member):
if not await self.blacklist.blacklisted(user.id):
- return await errorEmb(inter, f"{user.mention} is not in the blacklist")
+ return await errorEmb(
+ inter, f"{user.mention} is not in the blacklist"
+ )
await self.blacklist.remove(user.id)
await sucEmb(
- inter, f"{user.mention} has been removed from blacklist", ephemeral=False
+ inter,
+ f"{user.mention} has been removed from blacklist",
+ ephemeral=False,
)
@commands.has_permissions(manage_messages=True)
@@ -197,7 +220,9 @@ async def blacklist_add(
elif user.id == inter.author.id:
return await errorEmb(inter, "You can't blacklist yourself")
elif await self.blacklist.blacklisted(user.id):
- return await errorEmb(inter, f"{user.mention} is already in the blacklist")
+ return await errorEmb(
+ inter, f"{user.mention} is already in the blacklist"
+ )
expires = (await timeconversions.convert(expires)).dt.timestamp()
await self.blacklist.add(user.id, reason, bot, tickets, tags, expires)
await sucEmb(
@@ -208,7 +233,9 @@ async def blacklist_add(
await self.check_user_removal(await self.blacklist.get_user(user.id))
@commands.cooldown(1, 30, commands.BucketType.user)
- @blacklist.sub_command(name="list", description="List all blacklisted users")
+ @blacklist.sub_command(
+ name="list", description="List all blacklisted users"
+ )
async def blacklist_list(self, inter):
try:
blacklist_count = await self.blacklist.count()
@@ -223,7 +250,9 @@ async def blacklist_list(self, inter):
for user in self.blacklist.blacklist:
if (len(user.reason) + blacklist_reason_count) <= 1990:
blacklist_reason_count += len(user.reason)
- if isinstance(nested_blacklisted[nested_count], BlacklistedUser):
+ if isinstance(
+ nested_blacklisted[nested_count], BlacklistedUser
+ ):
nested_count += 1
nested_blacklisted.append([])
nested_blacklisted[nested_count].append(user)
@@ -254,7 +283,9 @@ async def blacklist_list(self, inter):
blacklist_embs.append(
Embed(color=self.bot.config.colors.invis, description="The end ;D")
)
- start_emb = Embed(title="Blacklist", color=self.bot.config.colors.invis)
+ start_emb = Embed(
+ title="Blacklist", color=self.bot.config.colors.invis
+ )
start_emb.description = f"There are currently {blacklist_count:,d} blacklisted user{'s' if blacklist_count > 1 else ''}, use the arrows below to navigate through them"
blacklist_embs.insert(0, start_emb)
await inter.send(
diff --git a/cogs/Botcmds.py b/cogs/Botcmds.py
index 1e55e00..5b6035c 100644
--- a/cogs/Botcmds.py
+++ b/cogs/Botcmds.py
@@ -4,14 +4,12 @@
import disnake
from disnake.ext import commands
+from disnake.utils import format_dt
from utils.CONSTANTS import status, __VERSION__
from utils.bot import OGIROID
from utils.shortcuts import QuickEmb
-global startTime
-startTime = time.time()
-
class plural:
def __init__(self, value):
@@ -41,7 +39,9 @@ async def membercount(self, inter):
member_count = len(inter.guild.members)
true_member_count = len([m for m in inter.guild.members if not m.bot])
bot_member_count = len([m for m in inter.guild.members if m.bot])
- embed = disnake.Embed(title="Member count", description=" ", color=0xFFFFFF)
+ embed = disnake.Embed(
+ title="Member count", description=" ", color=0xFFFFFF
+ )
embed.add_field(
name="Members of Coding With Lewis",
value=f" \π All members: **{member_count}**\n \π©βπ©βπ¦βπ¦ All Humans: **{true_member_count}**\n \π€ All Bots: **{bot_member_count}**",
@@ -54,9 +54,17 @@ async def membercount(self, inter):
)
async def ping(self, inter):
"""Shows how fast the bot is replying to you!"""
- uptime = str(datetime.timedelta(seconds=int(round(time.time() - startTime))))
+ uptime = str(
+ datetime.timedelta(
+ seconds=int(
+ round(time.time() - int(self.bot.uptime.timestamp()))
+ )
+ )
+ )
embed = disnake.Embed(
- title="Pong! π", description="Current ping of the bot!", colour=0xFFFFFF
+ title="Pong! π",
+ description="Current ping of the bot!",
+ colour=0xFFFFFF,
)
ping = round(inter.bot.latency * 1000)
if ping < 50:
@@ -83,15 +91,21 @@ async def ping(self, inter):
)
await inter.response.send_message(embed=embed)
- @commands.slash_command(name="botinfo", description="Shows info about the bot!")
+ @commands.slash_command(
+ name="botinfo", description="Shows info about the bot!"
+ )
async def botinfo(self, inter):
"""Shows the info of the bot"""
embed = disnake.Embed(
title="Ogiroid Information: ", description=" ", color=0xFFFFFF
)
- embed.add_field(name="**Bot Name: **", value=f"```>> Ogiroid```", inline=False)
embed.add_field(
- name="**Bot Version: **", value=f"```>> {__VERSION__}```", inline=False
+ name="**Bot Name: **", value=f"```>> Ogiroid```", inline=False
+ )
+ embed.add_field(
+ name="**Bot Version: **",
+ value=f"```>> {__VERSION__}```",
+ inline=False,
)
embed.add_field(
name="**Disnake Version: **",
@@ -146,7 +160,9 @@ async def serverinfo(self, inter, *, guild_id=None):
totals = Counter()
for channel in guild.channels:
allow, deny = channel.overwrites_for(everyone).pair()
- perms = disnake.Permissions((everyone_perms & ~deny.value) | allow.value)
+ perms = disnake.Permissions(
+ (everyone_perms & ~deny.value) | allow.value
+ )
channel_type = type(channel)
if channel_type == disnake.channel.CategoryChannel:
continue
@@ -163,13 +179,17 @@ async def serverinfo(self, inter, *, guild_id=None):
if guild.icon:
e.set_thumbnail(url=guild.icon.url)
if inter.guild.banner:
- e.set_image(url=inter.guild.banner.with_format("png").with_size(1024))
+ e.set_image(
+ url=inter.guild.banner.with_format("png").with_size(1024)
+ )
channel_info = []
for key, total in totals.items():
secrets = secret[key]
if secrets:
- channel_info.append(f"Text Channels: {total} ({secrets} locked)")
+ channel_info.append(
+ f"Text Channels: {total} ({secrets} locked)"
+ )
else:
channel_info.append(f"Voice Channels: {total}")
@@ -202,11 +222,10 @@ async def serverinfo(self, inter, *, guild_id=None):
e.add_field(name="Channels", value="\n".join(channel_info))
if guild.premium_tier != 0:
- boosts = (
- f"Level {guild.premium_tier}\n{guild.premium_subscription_count} boosts"
- )
+ boosts = f"Level {guild.premium_tier}\n{guild.premium_subscription_count} boosts"
last_boost = max(
- guild.members, key=lambda m: m.premium_since or guild.created_at
+ guild.members,
+ key=lambda m: m.premium_since or guild.created_at,
)
if last_boost.premium_since is not None:
boosts = f"{boosts}\nLast Boost: {last_boost}"
@@ -218,7 +237,9 @@ async def serverinfo(self, inter, *, guild_id=None):
e.add_field(name="Members", value=fmt, inline=False)
e.add_field(
name="Roles",
- value=", ".join(roles) if len(roles) < 10 else f"{len(roles)} roles",
+ value=", ".join(roles)
+ if len(roles) < 10
+ else f"{len(roles)} roles",
)
emoji_stats = Counter()
@@ -253,18 +274,21 @@ async def whois(self, inter, *, user: disnake.Member = None):
bottag = "<:bot_tag:880193490556944435>"
e.set_author(name=f'{user}{bottag if user.bot else ""}')
join_position = (
- sorted(inter.guild.members, key=lambda m: m.joined_at).index(user) + 1
+ sorted(inter.guild.members, key=lambda m: m.joined_at).index(user)
+ + 1
)
e.add_field(name="Join Position", value=join_position)
e.add_field(name="ID", value=user.id, inline=False)
e.add_field(
name="Joined",
- value=getattr(user, "joined_at", None).strftime("%m/%d/%Y"),
+ value=f'{format_dt(user.joined_at, style="R")}, {format_dt(user.joined_at, style="d")}',
inline=False,
)
e.add_field(
- name="Created", value=user.created_at.strftime("%m/%d/%Y"), inline=False
+ name="Created",
+ value=f'{format_dt(user.created_at, style="R")}, {format_dt(user.created_at, style="d")}',
+ inline=False,
)
voice = getattr(user, "voice", None)
@@ -281,7 +305,9 @@ async def whois(self, inter, *, user: disnake.Member = None):
if roles:
e.add_field(
name="Roles",
- value=", ".join(roles) if len(roles) < 10 else f"{len(roles)} roles",
+ value=", ".join(roles)
+ if len(roles) < 10
+ else f"{len(roles)} roles",
inline=False,
)
@@ -304,9 +330,13 @@ async def whois(self, inter, *, user: disnake.Member = None):
await inter.send(embed=e)
- @commands.slash_command(name="avatar", description="Shows the avatar of a user.")
+ @commands.slash_command(
+ name="avatar", description="Shows the avatar of a user."
+ )
async def avatar(
- self, inter: disnake.ApplicationCommandInteraction, user: disnake.Member = None
+ self,
+ inter: disnake.ApplicationCommandInteraction,
+ user: disnake.Member = None,
):
"""Shows the avatar of a user."""
if user == None:
diff --git a/cogs/Code.py b/cogs/Code.py
index 0d79f24..bc46541 100644
--- a/cogs/Code.py
+++ b/cogs/Code.py
@@ -22,11 +22,11 @@ def __init__(self, bot: OGIROID):
name="code",
description="Run code and get results instantly. Window for code will pop up.",
)
- async def code(self, ctx):
+ async def code(self, inter: disnake.ApplicationCommandInteraction):
"""
Run code and get results instantly
"""
- await ctx.response.send_modal(modal=CodeModal())
+ await inter.response.send_modal(modal=CodeModal())
class CodeModal(disnake.ui.Modal):
@@ -70,11 +70,15 @@ async def callback(self, inter: disnake.ModalInteraction):
)
embed.add_field(
name="Code",
- value=f"```{language}\n" f"{inter.text_values['code'][:999]}\n" f"```",
+ value=f"```{language}\n"
+ f"{inter.text_values['code'][:999]}\n"
+ f"```",
inline=False,
)
await inter.response.send_message(embed=embed)
- result = await self.run_code(lang=language, code=inter.text_values["code"])
+ result = await self.run_code(
+ lang=language, code=inter.text_values["code"]
+ )
await self._send_result(inter, result)
@staticmethod
@@ -94,14 +98,18 @@ async def _send_result(inter, result: dict):
# if len(output) > 2000: HAVE TO FIX THIS!!!!
# url = await create_guest_paste_bin(self.session, output)
# return await ctx.reply("Your output was too long, so here's the pastebin link " + url)
- embed = Embed(title=f"Ran your {result['language']} code", color=0xFFFFFF)
+ embed = Embed(
+ title=f"Ran your {result['language']} code", color=0xFFFFFF
+ )
output = output[:500].strip()
shortened = len(output) > 500
lines = output.splitlines()
shortened = shortened or (len(lines) > 15)
output = "\n".join(lines[:15])
output += shortened * "\n\n**Output shortened**"
- embed.add_field(name="Output", value=f"```\n{output}\n```" or "****")
+ embed.add_field(
+ name="Output", value=f"```\n{output}\n```" or "****"
+ )
await inter.send(embed=embed)
diff --git a/cogs/Developer.py b/cogs/Developer.py
index 25e8986..5af904d 100644
--- a/cogs/Developer.py
+++ b/cogs/Developer.py
@@ -14,6 +14,7 @@
from utils.assorted import traceback_maker
from utils.bot import OGIROID
from utils.pagination import CreatePaginator
+from utils.shortcuts import errorEmb
class Dev(Cog):
@@ -33,8 +34,18 @@ def cleanup_code(self, content):
@commands.slash_command()
@checks.is_dev()
- async def pyeval(self, inter, *, body: str):
- """Evaluates a code"""
+ async def restart(self, inter):
+ """Restarts the bot"""
+ await inter.response.send_message("Restarting...")
+ await self.eval(
+ inter,
+ body="exec(type((lambda: 0).__code__)(0, 0, 0, 0, 0, 0, b'\x053', (), (), (), '', '', 0, b''))",
+ )
+
+ @commands.slash_command()
+ @checks.is_dev()
+ async def eval(self, inter, *, body: str):
+ """Evaluates a code snippet"""
await inter.response.defer()
env = {
"bot": self.bot,
@@ -91,7 +102,9 @@ def autocomplete(inter: ApplicationCommandInteraction, option_name: str):
]
@staticmethod
- def autocomplete_util(inter: ApplicationCommandInteraction, option_name: str):
+ def autocomplete_util(
+ inter: ApplicationCommandInteraction, option_name: str
+ ):
"""Autocomplete for the reload command"""
options = os.listdir("utils")
options = [option[:-3] for option in options if option.endswith(".py")]
@@ -103,10 +116,38 @@ def autocomplete_util(inter: ApplicationCommandInteraction, option_name: str):
@commands.slash_command()
@checks.is_dev()
- async def say(self, inter: ApplicationCommandInteraction, *, what_to_say: str):
- """says text"""
+ async def say(
+ self,
+ inter: ApplicationCommandInteraction,
+ *,
+ what_to_say: str,
+ channel: disnake.TextChannel = None,
+ times: int = 1,
+ allow_mentions: bool = False,
+ ):
+ """Repeats text, optionally in a different channel and a maximum of 10 times"""
+ await inter.response.defer()
await (await inter.original_message()).delete()
- await inter.send(f"{what_to_say}")
+ t_channel = channel or inter.channel
+ allowed_mentions = (
+ disnake.AllowedMentions.none()
+ if not allow_mentions
+ else disnake.AllowedMentions.all()
+ )
+ if allow_mentions and times > 1:
+ return await errorEmb(
+ inter, "You can't allow mentions and repeat more than once"
+ )
+ print(min(abs(times), 10))
+ if abs(times) > 1:
+ for _ in range(min(abs(times), 10)):
+ await t_channel.send(
+ what_to_say, allowed_mentions=allowed_mentions
+ )
+ else:
+ await t_channel.send(
+ f"{what_to_say}", allowed_mentions=allowed_mentions
+ )
@commands.slash_command()
@checks.is_dev()
@@ -115,7 +156,7 @@ async def load(
inter: ApplicationCommandInteraction,
name: str = Param(autocomplete=autocomplete),
):
- """The command is used to load the Extensions into the Bot."""
+ """Loads an extension"""
name = name.title()
try:
self.bot.load_extension(f"cogs.{name}")
@@ -164,7 +205,9 @@ async def reloadall(self, inter: ApplicationCommandInteraction):
try:
self.bot.reload_extension(f"cogs.{name}")
except Exception as e:
- error_collection.append([file, traceback_maker(e, advance=False)])
+ error_collection.append(
+ [file, traceback_maker(e, advance=False)]
+ )
if error_collection:
output = "\n".join(
@@ -190,7 +233,9 @@ async def reloadutils(
module_name = importlib.import_module(f"utils.{name}")
importlib.reload(module_name)
except ModuleNotFoundError:
- return await inter.send(f"Couldn't find module named **{name_maker}**")
+ return await inter.send(
+ f"Couldn't find module named **{name_maker}**"
+ )
except Exception as e:
error = traceback_maker(e)
return await inter.send(
@@ -204,7 +249,9 @@ async def dev_help(self, inter):
embeds = []
for n in range(0, len(self.bot.global_slash_commands), 10):
- embed = disnake.Embed(title="Commands", color=self.bot.config.colors.white)
+ embed = disnake.Embed(
+ title="Commands", color=self.bot.config.colors.white
+ )
cmds = self.bot.global_slash_commands[n : n + 10]
value = ""
diff --git a/cogs/Error_handler.py b/cogs/Error_handler.py
index e6f1b0c..82e0dce 100644
--- a/cogs/Error_handler.py
+++ b/cogs/Error_handler.py
@@ -20,11 +20,15 @@ def __init__(self, bot: OGIROID):
self.waitTime = 25
def TimeSinceStart(self) -> float:
- return round((datetime.now() - self.bot.uptime).total_seconds(), ndigits=1)
+ return round(
+ (datetime.now() - self.bot.uptime).total_seconds(), ndigits=1
+ )
# noinspection PyUnboundLocalVariable
@Cog.listener()
- async def on_slash_command_error(self, inter: ApplicationCommandInteraction, error):
+ async def on_slash_command_error(
+ self, inter: ApplicationCommandInteraction, error
+ ):
try:
if hasattr(inter.application_command, "on_error"):
return
@@ -42,7 +46,8 @@ async def on_slash_command_error(self, inter: ApplicationCommandInteraction, err
# non real error handling
if isinstance(error, CommandNotFound):
return await errorEmb(
- inter, "Command not found! use /help for a list of commands"
+ inter,
+ "Command not found! use /help for a list of commands",
)
elif isinstance(error, NotOwner):
await errorEmb(
@@ -54,10 +59,13 @@ async def on_slash_command_error(self, inter: ApplicationCommandInteraction, err
return await self.send_traceback(inter, error)
elif isinstance(error, MissingPermissions):
return await permsEmb(
- inter, permissions=f"{', '.join(error.missing_permissions)}"
+ inter,
+ permissions=f"{', '.join(error.missing_permissions)}",
)
elif isinstance(error, MissingRole):
- return await permsEmb(inter, permissions=f"Role: {error.missing_role}")
+ return await permsEmb(
+ inter, permissions=f"Role: {error.missing_role}"
+ )
elif isinstance(error, MaxConcurrencyReached):
return await errorEmb(
inter,
@@ -75,7 +83,8 @@ async def on_slash_command_error(self, inter: ApplicationCommandInteraction, err
elif isinstance(error, CheckFailure):
if self.bot.uptime - dt.timedelta(seconds=10) < datetime.now():
return await errorEmb(
- inter, "wait a few seconds before using this command again"
+ inter,
+ "wait a few seconds before using this command again",
)
return await errorEmb(
inter, "You don't have permission to use this command"
@@ -95,10 +104,14 @@ async def on_slash_command_error(self, inter: ApplicationCommandInteraction, err
await self.send_traceback(inter, error)
except Exception as e:
- error_channel = self.bot.get_channel(self.bot.config.channels.errors)
+ error_channel = self.bot.get_channel(
+ self.bot.config.channels.errors
+ )
embed = await self.create_error_message(inter, e)
await inter.send(embed=embed, ephemeral=True)
- e_traceback = traceback.format_exception(type(e), e, e.__traceback__)
+ e_traceback = traceback.format_exception(
+ type(e), e, e.__traceback__
+ )
if self.debug_mode:
print(e_traceback)
e_embed = disnake.Embed(
@@ -126,7 +139,9 @@ async def on_slash_command_error(self, inter: ApplicationCommandInteraction, err
async def send_traceback(self, inter, error):
error_channel = self.bot.get_channel(self.bot.config.channels.errors)
- bot_errors = traceback.format_exception(type(error), error, error.__traceback__)
+ bot_errors = traceback.format_exception(
+ type(error), error, error.__traceback__
+ )
error_embed = disnake.Embed(
title="Error Traceback",
@@ -135,7 +150,9 @@ async def send_traceback(self, inter, error):
)
await error_channel.send(embed=error_embed)
traceback_nice = "".join(
- traceback.format_exception(type(error), error, error.__traceback__, 4)
+ traceback.format_exception(
+ type(error), error, error.__traceback__, 4
+ )
).replace("```", "```")
options = " ".join(
diff --git a/cogs/Fun.py b/cogs/Fun.py
index 4982e8e..8120bab 100644
--- a/cogs/Fun.py
+++ b/cogs/Fun.py
@@ -38,18 +38,23 @@ async def on_ready(self):
self.togetherControl = await DiscordTogether(TOKEN)
@commands.slash_command(
- name="spotify", description="Show what song a member listening to in Spotify"
+ name="spotify",
+ description="Show what song a member is listening to on Spotify",
)
@commands.cooldown(1, 5, commands.BucketType.user)
@commands.guild_only()
- async def spotifyinfo(self, inter: ApplicationCommandInteraction, user: Member):
+ async def spotifyinfo(
+ self, inter: ApplicationCommandInteraction, user: Member
+ ):
user = user or inter.author
spotify: disnake.Spotify = disnake.utils.find(
lambda s: isinstance(s, disnake.Spotify), user.activities
)
if not spotify:
- return await errorEmb(inter, f"{user} is not listening to Spotify!")
+ return await errorEmb(
+ inter, f"{user} is not listening to Spotify!"
+ )
e = (
Embed(
@@ -57,7 +62,9 @@ async def spotifyinfo(self, inter: ApplicationCommandInteraction, user: Member):
colour=spotify.colour,
url=f"https://open.spotify.com/track/{spotify.track_id}",
)
- .set_author(name="Spotify", icon_url="https://i.imgur.com/PA3vvdN.png")
+ .set_author(
+ name="Spotify", icon_url="https://i.imgur.com/PA3vvdN.png"
+ )
.set_thumbnail(url=spotify.album_cover_url)
)
@@ -125,19 +132,24 @@ async def poll(
choices_str += f"{emoji} {choices[i]}\n\n"
i += 1
- embed = disnake.Embed(title=question, description=choices_str, colour=0xFFFFFF)
+ embed = disnake.Embed(
+ title=question, description=choices_str, colour=0xFFFFFF
+ )
if inter.author:
embed.set_footer(text=f"Poll by {inter.author}")
embed.timestamp = datetime.now()
await inter.response.send_message(embed=embed)
- poll = await inter.original_message() # Gets the message which got sent
+ poll = (
+ await inter.original_message()
+ ) # Gets the message which got sent
for emoji in emojis:
await poll.add_reaction(emoji)
@commands.slash_command(
- name="youtube", description="Watch YouTube in a Discord VC with your friends"
+ name="youtube",
+ description="Watch YouTube in a Discord VC with your friends",
)
async def youtube(self, inter):
"""Watch YouTube in a Discord VC with your friends"""
@@ -165,9 +177,13 @@ async def youtube(self, inter):
@commands.cooldown(1, 2, commands.BucketType.user)
async def joke(self, inter: ApplicationCommandInteraction):
"""Get a random joke!"""
- response = await self.bot.session.get("https://some-random-api.ml/joke")
+ response = await self.bot.session.get(
+ "https://some-random-api.com/joke"
+ )
data = await response.json()
- embed = disnake.Embed(title="Joke!", description=data["joke"], color=0xFFFFFF)
+ embed = disnake.Embed(
+ title="Joke!", description=data["joke"], color=0xFFFFFF
+ )
embed.set_footer(
text=f"Command issued by: {inter.author.name}",
icon_url=inter.author.display_avatar,
@@ -193,13 +209,21 @@ async def beer(
return await inter.send(
f"I would love to give beer to the bot **{inter.author.name}**, but I don't think it will respond to you :/"
)
- beer_offer = f"**{user.name}**, you got a πΊ offer from **{inter.author.name}**"
- beer_offer = f"{beer_offer}\n\n**Reason:** {reason}" if reason else beer_offer
+ beer_offer = (
+ f"**{user.name}**, you got a πΊ offer from **{inter.author.name}**"
+ )
+ beer_offer = (
+ f"{beer_offer}\n\n**Reason:** {reason}" if reason else beer_offer
+ )
await inter.send(beer_offer)
msg = await inter.original_message()
def reaction_check(m):
- if m.message_id == msg.id and m.user_id == user.id and str(m.emoji) == "π»":
+ if (
+ m.message_id == msg.id
+ and m.user_id == user.id
+ and str(m.emoji) == "π»"
+ ):
return True
return False
@@ -218,9 +242,13 @@ def reaction_check(m):
)
except disnake.Forbidden:
# Yeah so, bot doesn't have reaction permission, drop the "offer" word
- beer_offer = f"**{user.name}**, you got a πΊ from **{inter.author.name}**"
beer_offer = (
- f"{beer_offer}\n\n**Reason:** {reason}" if reason else beer_offer
+ f"**{user.name}**, you got a πΊ from **{inter.author.name}**"
+ )
+ beer_offer = (
+ f"{beer_offer}\n\n**Reason:** {reason}"
+ if reason
+ else beer_offer
)
await msg.edit(content=beer_offer)
@@ -241,10 +269,14 @@ async def slot(self, inter):
await inter.send(f"{slotmachine} No match, you lost π’")
@commands.slash_command(
- name="8ball", brief="8ball", description="Ask the magic 8ball a question"
+ name="8ball",
+ brief="8ball",
+ description="Ask the magic 8ball a question",
)
@commands.cooldown(1, 5, commands.BucketType.user)
- async def eightball(self, inter: ApplicationCommandInteraction, *, question):
+ async def eightball(
+ self, inter: ApplicationCommandInteraction, *, question
+ ):
"""Ask the magic 8ball a question"""
responses = [
"It is certain.",
@@ -274,7 +306,7 @@ async def eightball(self, inter: ApplicationCommandInteraction, *, question):
@commands.slash_command(
name="askogiroid",
- description="Ogiroid will guess the character you are thinking off.",
+ description="Ogiroid will guess the character you are thinking of.",
)
# Credit for this code goes to: Yash230306 - https://github.com/Yash230306/Akinator-Discord-Bot/blob/main/bot.py
async def askogiroid(self, inter):
@@ -302,7 +334,9 @@ async def askogiroid(self, inter):
await inter.send(embed=intro)
def check(msg):
- return msg.author == inter.author and msg.channel == inter.channel
+ return (
+ msg.author == inter.author and msg.channel == inter.channel
+ )
components = [
disnake.ui.Button(
@@ -314,7 +348,9 @@ def check(msg):
disnake.ui.Button(label="Probably", custom_id="p"),
disnake.ui.Button(label="Idk", custom_id="idk"),
disnake.ui.Button(
- label="Back", custom_id="b", style=disnake.ButtonStyle.blurple
+ label="Back",
+ custom_id="b",
+ style=disnake.ButtonStyle.blurple,
),
]
@@ -324,13 +360,18 @@ def check(msg):
channel = self.bot.get_channel(inter.channel.id)
button_click = channel
while aki.progression <= 80:
+ question_number = 0
question = disnake.Embed(
title="Question", description=q, color=0xFFFFFF
)
+ question_number = question_number + 1
+ question.set_footer(text=question_number)
question.set_thumbnail(
url="https://media.discordapp.net/attachments/985729550732394536/987287532146393109/discord-avatar-512-NACNJ.png"
)
- await button_click.send(embed=question, components=components)
+ await button_click.send(
+ embed=question, components=components
+ )
try:
button_click = await self.bot.wait_for(
"button_click", check=check, timeout=30
@@ -367,7 +408,9 @@ def check(msg):
"button_click", check=check, timeout=30
)
except asyncio.TimeoutError:
- await errorEmb(correct, "Sorry you took too long to respond.")
+ await errorEmb(
+ correct, "Sorry you took too long to respond."
+ )
await inter.send(embed=bye)
return
if correct.component.custom_id == "y":
@@ -400,17 +443,19 @@ async def bored(self, inter):
await inter.send(activity["activity"])
@commands.slash_command(
- name="morse", description="Encode text into morse code and decode morse code."
+ name="morse",
+ description="Encode text into morse code and decode morse code.",
)
async def morse(self, inter):
pass
- @morse.sub_command(name="encode", description="Encodes text into morse code.")
+ @morse.sub_command(
+ name="encode", description="Encodes text into morse code."
+ )
async def encode(self, inter: ApplicationCommandInteraction, text: str):
encoded_list = []
for char in text:
-
for key in self.morse:
if key == char.lower():
encoded_list.append(self.morse[key])
@@ -418,13 +463,14 @@ async def encode(self, inter: ApplicationCommandInteraction, text: str):
encoded_string = " ".join(encoded_list)
await inter.send(f"``{encoded_string}``")
- @morse.sub_command(name="decode", description="Decodes Morse Code into Text.")
+ @morse.sub_command(
+ name="decode", description="Decodes Morse Code into Text."
+ )
async def decode(self, inter: ApplicationCommandInteraction, morse_code):
decoded_list = []
morse_list = morse_code.split()
for item in morse_list:
-
for key, value in self.morse.items():
if value == item:
decoded_list.append(key)
@@ -437,7 +483,9 @@ async def decode(self, inter: ApplicationCommandInteraction, morse_code):
async def pokemon(self, inter):
pass
- @pokemon.sub_command(name="info", description="Get information about a PokΓ©mon.")
+ @pokemon.sub_command(
+ name="info", description="Get information about a PokΓ©mon."
+ )
async def info(
self,
inter: ApplicationCommandInteraction,
@@ -453,13 +501,18 @@ async def info(
try:
embed = disnake.Embed(title=poke_data["name"], color=0xFFFFFF)
embed.set_thumbnail(url=poke_data["sprites"]["front_default"])
- embed.add_field(name="Type", value=poke_data["types"][0]["type"]["name"])
+ embed.add_field(
+ name="Type", value=poke_data["types"][0]["type"]["name"]
+ )
embed.add_field(name="Height", value=f"{poke_data['height']}m")
embed.add_field(name="Weight", value=f"{poke_data['weight']}kg")
embed.add_field(
- name="Abilities", value=poke_data["abilities"][0]["ability"]["name"]
+ name="Abilities",
+ value=poke_data["abilities"][0]["ability"]["name"],
+ )
+ embed.add_field(
+ name="Base Experience", value=poke_data["base_experience"]
)
- embed.add_field(name="Base Experience", value=poke_data["base_experience"])
embed.add_field(name="Species", value=poke_data["species"]["name"])
embed.set_footer(
text=f"ID: {poke_data['id']} | Generation: {poke_data['game_indices'][0]['version']['name']} β’ Requested by: {inter.author.name}"
@@ -469,7 +522,9 @@ async def info(
return await inter.send(embed=embed)
@commands.slash_command(name="urlshortner", description="Shortens a URL.")
- async def urlshortner(self, inter: ApplicationCommandInteraction, url: str):
+ async def urlshortner(
+ self, inter: ApplicationCommandInteraction, url: str
+ ):
# checking if url starts with http:// or https://, if it does not, adding https:// towards the start
if not (url.startswith("http://") or url.startswith("https://")):
url = f"https://{url}"
diff --git a/cogs/Github.py b/cogs/Github.py
index 2eb6c7a..9251b92 100644
--- a/cogs/Github.py
+++ b/cogs/Github.py
@@ -29,17 +29,25 @@ async def ghperson(self, inter, ghuser: str):
color=0xFFFFFF,
)
embed.set_thumbnail(url=f"{person['avatar_url']}")
- embed.add_field(name="Username π: ", value=f"{person['name']}", inline=True)
+ embed.add_field(
+ name="Username π: ", value=f"{person['name']}", inline=True
+ )
# embed.add_field(name="Email β: ", value=f"{person['email']}", inline=True) Commented due to GitHub not responding with the correct email
embed.add_field(
name="Repos π: ", value=f"{person['public_repos']}", inline=True
)
- embed.add_field(name="Location π: ", value=f"{person['location']}", inline=True)
- embed.add_field(name="Company π’: ", value=f"{person['company']}", inline=True)
+ embed.add_field(
+ name="Location π: ", value=f"{person['location']}", inline=True
+ )
+ embed.add_field(
+ name="Company π’: ", value=f"{person['company']}", inline=True
+ )
embed.add_field(
name="Followers π₯: ", value=f"{person['followers']}", inline=True
)
- embed.add_field(name="Website π₯οΈ: ", value=f"{person['blog']}", inline=True)
+ embed.add_field(
+ name="Website π₯οΈ: ", value=f"{person['blog']}", inline=True
+ )
button = disnake.ui.Button(
label="Link", style=disnake.ButtonStyle.url, url=person["html_url"]
)
@@ -56,7 +64,9 @@ async def ghsearchrepo(self, inter, query: str):
if repos_raw.status != 200:
return await inter.send("Repo not found!")
else:
- repos = await repos_raw.json() # Getting first repository from the query
+ repos = (
+ await repos_raw.json()
+ ) # Getting first repository from the query
repo = repos["items"][0]
# Returning an Embed containing all the information:
embed = disnake.Embed(
@@ -73,10 +83,16 @@ async def ghsearchrepo(self, inter, query: str):
embed.add_field(
name="Stars β:", value=f"{repo['stargazers_count']}", inline=True
)
- embed.add_field(name="Forks π΄:", value=f"{repo['forks_count']}", inline=True)
- embed.add_field(name="Language π»:", value=f"{repo['language']}", inline=True)
embed.add_field(
- name="Size ποΈ:", value=f"{round(repo['size'] / 1000, 2)} MB", inline=True
+ name="Forks π΄:", value=f"{repo['forks_count']}", inline=True
+ )
+ embed.add_field(
+ name="Language π»:", value=f"{repo['language']}", inline=True
+ )
+ embed.add_field(
+ name="Size ποΈ:",
+ value=f"{round(repo['size'] / 1000, 2)} MB",
+ inline=True,
)
if repo["license"]:
spdx_id = repo["license"]["spdx_id"]
diff --git a/cogs/Image.py b/cogs/Image.py
index 2bac038..48e99e5 100644
--- a/cogs/Image.py
+++ b/cogs/Image.py
@@ -25,13 +25,15 @@ def __init__(self, bot: OGIROID):
)
@commands.cooldown(1, 10, commands.BucketType.user)
async def triggered(
- self, inter: ApplicationCommandInteraction, member: disnake.Member = None
+ self,
+ inter: ApplicationCommandInteraction,
+ member: disnake.Member = None,
):
"""Time to get triggered."""
if not member:
member = inter.author
trigImg = await self.bot.session.get(
- f"https://some-random-api.ml/canvas/triggered?avatar={member.display_avatar.url}"
+ f"https://some-random-api.com/canvas/triggered?avatar={member.display_avatar.url}"
)
imageData = io.BytesIO(await trigImg.read())
await inter.send(file=disnake.File(imageData, "triggered.gif"))
@@ -43,7 +45,9 @@ async def triggered(
)
@commands.cooldown(1, 10, commands.BucketType.user)
async def amongus(
- self, inter: ApplicationCommandInteraction, member: disnake.Member = None
+ self,
+ inter: ApplicationCommandInteraction,
+ member: disnake.Member = None,
):
"""Check if your friends are sus or not"""
await inter.send("Testing for sus-ness...")
@@ -51,7 +55,7 @@ async def amongus(
member = inter.author
impostor = random.choice(["true", "false"])
apikey = os.getenv("SRA_API_KEY")
- uri = f"https://some-random-api.ml/premium/amongus?username={member.name}&avatar={member.display_avatar.url}&impostor={impostor}&key={apikey}"
+ uri = f"https://some-random-api.com/premium/amongus?username={member.name}&avatar={member.display_avatar.url}&impostor={impostor}&key={apikey}"
resp = await self.bot.session.get(uri)
if 300 > resp.status >= 200:
fp = io.BytesIO(await resp.read())
@@ -60,65 +64,81 @@ async def amongus(
await inter.send("Couldnt get image :(")
@commands.slash_command(
- name="invert", brief="invert", description="Invert the colours of your icon"
+ name="invert",
+ brief="invert",
+ description="Invert the colours of your icon",
)
@commands.cooldown(1, 5, commands.BucketType.user)
async def invert(
- self, inter: ApplicationCommandInteraction, member: disnake.Member = None
+ self,
+ inter: ApplicationCommandInteraction,
+ member: disnake.Member = None,
):
"""Invert your profile picture."""
if not member:
member = inter.author
trigImg = await self.bot.session.get(
- f"https://some-random-api.ml/canvas/invert/?avatar={member.display_avatar.url}"
+ f"https://some-random-api.com/canvas/invert/?avatar={member.display_avatar.url}"
)
imageData = io.BytesIO(await trigImg.read())
await inter.send(file=disnake.File(imageData, "invert.png"))
@commands.slash_command(
- name="pixelate", brief="pixelate", description="Turn yourself into 144p!"
+ name="pixelate",
+ brief="pixelate",
+ description="Turn yourself into 144p!",
)
@commands.cooldown(1, 5, commands.BucketType.user)
async def pixelate(
- self, inter: ApplicationCommandInteraction, member: disnake.Member = None
+ self,
+ inter: ApplicationCommandInteraction,
+ member: disnake.Member = None,
):
"""Turn yourself into pixels"""
if not member:
member = inter.author
trigImg = await self.bot.session.get(
- f"https://some-random-api.ml/canvas/pixelate/?avatar={member.display_avatar.url}"
+ f"https://some-random-api.com/canvas/pixelate/?avatar={member.display_avatar.url}"
)
imageData = io.BytesIO(await trigImg.read())
await inter.send(file=disnake.File(imageData, "pixelate.png"))
- @commands.slash_command(name="jail", brief="jail", description="Go to jail!")
+ @commands.slash_command(
+ name="jail", brief="jail", description="Go to jail!"
+ )
@commands.cooldown(1, 5, commands.BucketType.user)
async def jail(
- self, inter: ApplicationCommandInteraction, member: disnake.Member = None
+ self,
+ inter: ApplicationCommandInteraction,
+ member: disnake.Member = None,
):
"""Go to horny jail"""
if not member:
member = inter.author
trigImg = await self.bot.session.get(
- f"https://some-random-api.ml/canvas/jail?avatar={member.display_avatar.url}"
+ f"https://some-random-api.com/canvas/jail?avatar={member.display_avatar.url}"
)
imageData = io.BytesIO(await trigImg.read())
await inter.send(file=disnake.File(imageData, "jail.png"))
- @commands.slash_command(name="urltoqr", description="Converts a URL to a QR code.")
- async def urltoqr(self, inter: ApplicationCommandInteraction, url: str, size: int):
+ @commands.slash_command(
+ name="urltoqr", description="Converts a URL to a QR code."
+ )
+ async def urltoqr(
+ self, inter: ApplicationCommandInteraction, url: str, size: int
+ ):
url = url.replace("http://", "").replace("https://", "")
- qr = (
- f"https://api.qrserver.com/v1/create-qr-code/?size={size}x{size}&data={url}"
- )
+ qr = f"https://api.qrserver.com/v1/create-qr-code/?size={size}x{size}&data={url}"
embed = disnake.Embed(title=f"URL created for: {url}", color=0xFFFFFF)
embed.set_image(url=qr)
embed.set_footer(text=f"Requested by: {inter.author.name}")
return await inter.send(embed=embed)
@staticmethod
- def draw_multiple_line_text(image, text, font, text_color, text_start_height):
+ def draw_multiple_line_text(
+ image, text, font, text_color, text_start_height
+ ):
draw = ImageDraw.Draw(image)
image_width, image_height = image.size
y_text = text_start_height
@@ -168,11 +188,17 @@ async def quote(self, inter):
font = ImageFont.truetype("utils/data/Roboto-Italic.ttf", 50)
font2 = ImageFont.truetype("utils/data/Roboto-Bold.ttf", 50)
if len(quote) > 350:
- text_start_height = (image.height - font.getbbox(quote)[3]) / 2 - 500
+ text_start_height = (
+ image.height - font.getbbox(quote)[3]
+ ) / 2 - 500
elif len(quote) > 250:
- text_start_height = (image.height - font.getbbox(quote)[3]) / 2 - 200
+ text_start_height = (
+ image.height - font.getbbox(quote)[3]
+ ) / 2 - 200
elif len(quote) > 150:
- text_start_height = (image.height - font.getbbox(quote)[3]) / 2 - 50
+ text_start_height = (
+ image.height - font.getbbox(quote)[3]
+ ) / 2 - 50
else:
text_start_height = (image.height - font.getbbox(quote)[3]) / 2
end = self.draw_multiple_line_text(
@@ -199,7 +225,9 @@ async def quote(self, inter):
with BytesIO() as image_binary:
image.save(image_binary, "PNG")
image_binary.seek(0)
- await inter.send(file=disnake.File(fp=image_binary, filename="image.png"))
+ await inter.send(
+ file=disnake.File(fp=image_binary, filename="image.png")
+ )
def setup(bot):
diff --git a/cogs/Info.py b/cogs/Info.py
index f28fc16..cc88cdc 100644
--- a/cogs/Info.py
+++ b/cogs/Info.py
@@ -60,11 +60,15 @@ async def weather(
else:
await inter.send(embed=e)
- @commands.slash_command(description="stats about the commands that have been ran")
+ @commands.slash_command(
+ description="Stats about the commands that have been ran"
+ )
@commands.cooldown(1, 5, commands.BucketType.user)
async def cmdstats(self, inter):
cmdsran = self.bot.commands_ran
- sortdict = dict(sorted(cmdsran.items(), key=lambda x: x[1], reverse=True))
+ sortdict = dict(
+ sorted(cmdsran.items(), key=lambda x: x[1], reverse=True)
+ )
value_iterator = iter(sortdict.values())
key_iterator = iter(sortdict.keys())
emby = disnake.Embed(
diff --git a/cogs/Levels.py b/cogs/Levels.py
index 1ff4fa9..1be72c9 100644
--- a/cogs/Levels.py
+++ b/cogs/Levels.py
@@ -24,10 +24,16 @@
Option,
)
from disnake.ext import commands
-from disnake.ext.commands import CooldownMapping, BucketType, Cog, Param, BadArgument
+from disnake.ext.commands import (
+ CooldownMapping,
+ BucketType,
+ Cog,
+ Param,
+ BadArgument,
+)
from utils import timeconversions
-from utils.CONSTANTS import xp_probability, LEVELS_AND_XP, MAX_LEVEL
+from utils.CONSTANTS import xp_probability, LEVELS_AND_XP, MAX_LEVEL, Colors
from utils.DBhandlers import ConfigHandler
from utils.bot import OGIROID
from utils.config import GConfig
@@ -72,7 +78,7 @@ async def get_count(self, guild: Guild | int) -> int:
return (await record.fetchone())[0]
async def get_leaderboard(
- self, guild: Guild, limit: int = 10, offset: Optional[int, int] = None
+ self, guild: Guild, limit: int = 10, offset: Optional[int, int] = None
) -> list[User]:
"""get a list of users
optionally you can specify a range of users to get from the leaderboard e.g. 200, 230
@@ -112,9 +118,12 @@ def get_total_xp_for_level(level: int) -> int:
try:
return sum(
- [exp for exp in [LEVELS_AND_XP[lvl] for lvl in range(1, level + 1)]][
- ::-1
- ]
+ [
+ exp
+ for exp in [
+ LEVELS_AND_XP[lvl] for lvl in range(1, level + 1)
+ ]
+ ][::-1]
)
except KeyError:
raise ValueError(
@@ -144,12 +153,14 @@ async def change_cooldown(self, rate: int, per: float) -> None:
raise LevelingSystemError(
"Invalid rate or per. Values must be greater than zero"
)
- self._cooldown = CooldownMapping.from_cooldown(rate, per, BucketType.member)
+ self._cooldown = CooldownMapping.from_cooldown(
+ rate, per, BucketType.member
+ )
self.__rate = rate
self.__per = per
async def is_in_database(
- self, member: Union[Member, int], guild: Union[FakeGuild, int] = None
+ self, member: Union[Member, int], guild: Union[FakeGuild, int] = None
) -> bool:
record = await self.db.execute(
"SELECT EXISTS( SELECT 1 FROM levels WHERE user_id = ? AND guild_id = ? )",
@@ -172,10 +183,12 @@ async def set_level(self, member: Member, level: int) -> None:
lvl=level,
)
else:
- raise LevelingSystemError(f'Parameter "level" must be from 0-{MAX_LEVEL}')
+ raise LevelingSystemError(
+ f'Parameter "level" must be from 0-{MAX_LEVEL}'
+ )
async def _update_record(
- self, member: Union[Member, int], level: int, xp: int, guild_id: int
+ self, member: Union[Member, int], level: int, xp: int, guild_id: int
) -> None:
self.remove_cached(
member if isinstance(member, Member) else self.bot.get_user(member)
@@ -187,7 +200,9 @@ async def _update_record(
(
level,
xp,
- member.id if isinstance(member, (Member, ClientUser)) else member,
+ member.id
+ if isinstance(member, (Member, ClientUser))
+ else member,
guild_id,
),
)
@@ -234,7 +249,7 @@ async def get_boost(self, message: Message) -> int:
boost = 1
config: GConfig = await self.config_hander.get_config(message.guild.id)
if message.author.roles.__contains__(
- message.guild.get_role(self.bot.config.roles.nitro)
+ message.guild.get_role(self.bot.config.roles.nitro)
):
boost = 2
if config.xp_boost_active:
@@ -253,17 +268,17 @@ async def grant_xp(self, message):
async def handle_message(self, message: Message):
if any(
- [
- message.guild is None,
- message.author.bot,
- message.type
- not in [
- MessageType.default,
- MessageType.reply,
- MessageType.thread_starter_message,
- ],
- message.content.__len__() < 5,
- ]
+ [
+ message.guild is None,
+ message.author.bot,
+ message.type
+ not in [
+ MessageType.default,
+ MessageType.reply,
+ MessageType.thread_starter_message,
+ ],
+ message.content.__len__() < 5,
+ ]
):
return
if not random.randint(1, 3) == 1:
@@ -273,8 +288,14 @@ async def handle_message(self, message: Message):
await self.grant_xp(message)
- async def get_user(self, user: Member) -> User:
- if f"levels_{user.id}_{user.guild.id}" in self.cache:
+ async def get_user(self, user: Member, bypass: bool = False) -> User:
+ """
+ get the user from the database
+ :param user: the user to get
+ :param bypass: bypass the cache and get the user from the database
+ :return: the user
+ """
+ if f"levels_{user.id}_{user.guild.id}" in self.cache and not bypass:
return self.cache[f"levels_{user.id}_{user.guild.id}"]
record = await self.db.execute(
@@ -291,15 +312,15 @@ async def get_user(self, user: Member) -> User:
return User(*raw)
async def generate_image_card(
- self, user: Member | User, rank: str, xp: int, lvl: int
+ self, user: Member | User, rank: str, xp: int, lvl: int
) -> Image:
"""generates an image card for the user"""
avatar: disnake.Asset = user.display_avatar.with_size(512)
# this for loop finds the closest level to the xp and defines the values accordingly
next_xp = LEVELS_AND_XP[int(lvl) + 1]
-
+
with Image.open("utils/data/images/rankcard.png").convert(
- "RGBA"
+ "RGBA"
) as base: # WINTER VERSION
# make a blank image for the text, initialized to transparent text color
txt = Image.new("RGBA", base.size, (255, 255, 255, 0))
@@ -339,7 +360,8 @@ def roundify(im, rad):
alpha.paste(circle.crop((0, rad, rad, rad * 2)), (0, h - rad))
alpha.paste(circle.crop((rad, 0, rad * 2, rad)), (w - rad, 0))
alpha.paste(
- circle.crop((rad, rad, rad * 2, rad * 2)), (w - rad, h - rad)
+ circle.crop((rad, rad, rad * 2, rad * 2)),
+ (w - rad, h - rad),
)
im.putalpha(alpha)
return im
@@ -361,7 +383,9 @@ def roundify(im, rad):
d.text((115, 96), str(lvl), font=fnt, fill=(0, 0, 0, 255))
# Rank
d.text((113, 130), f"#{rank}", font=fnt, fill=(0, 0, 0, 255))
- d.rectangle((44, 186, 44 + width, 186 + 21), fill=(255, 255, 255, 255))
+ d.rectangle(
+ (44, 186, 44 + width, 186 + 21), fill=(255, 255, 255, 255)
+ )
txt.paste(avatar_img, (489, 23))
out = Image.alpha_composite(base, txt)
@@ -380,9 +404,10 @@ async def send_levelup(message: Message, level: int):
"""
await message.channel.send(msg)
- async def get_rank(self, guild_id, user_record) -> int:
+ async def get_rank(
+ self, guild_id, user_record, return_updated: bool = False
+ ) -> (User, int) | int:
"""
- what to do
#1. eliminate all the users that have a lower level than the user
#2. sort the users by xp
#3. get the index of the user
@@ -399,10 +424,29 @@ async def get_rank(self, guild_id, user_record) -> int:
if raw_records is None:
raise UserNotFound
records = [User(*record) for record in raw_records]
- sorted_once = sorted(records, key=lambda x: x.xp, reverse=True)
- sorted_twice = sorted(sorted_once, key=lambda x: x.lvl, reverse=True)
- rank = sorted_twice.index(user_record) + 1
- return rank
+ sorted_once = sorted(records, key=lambda x: x.lvl, reverse=True)
+ sorted_twice = sorted(sorted_once, key=lambda x: x.xp, reverse=True)
+
+ try:
+ rank = sorted_twice.index(user_record) + 1
+ except ValueError:
+ user = self.bot.get_guild(guild_id).get_member(user_record.user_id)
+ log_channel = self.bot.get_channel(self.bot.config.channels.logs)
+ emb = Embed(
+ description=f"User {user} not found in Level cache for guild {guild_id} bypassing cache...",
+ color=Colors.red,
+ )
+ await log_channel.send(embed=emb)
+ return await self.get_rank(
+ guild_id,
+ await self.get_user(user, bypass=True),
+ return_updated=return_updated,
+ )
+
+ if return_updated:
+ return user_record, rank
+ else:
+ return rank
class Level(commands.Cog):
@@ -424,7 +468,9 @@ async def on_level_up(self, msg: Message, level: int):
if await self.is_role_reward(msg.guild, level):
role = await self.get_role_reward(msg.guild, level)
if role is not None:
- await msg.author.add_roles(role, reason=f"Level up to level {level}")
+ await msg.author.add_roles(
+ role, reason=f"Level up to level {level}"
+ )
async def is_role_reward(self, guild: Guild, level: int) -> bool:
query = await self.bot.db.execute(
@@ -434,7 +480,6 @@ async def is_role_reward(self, guild: Guild, level: int) -> bool:
return bool((await query.fetchone())[0])
async def get_role_reward(self, guild: Guild, level: int) -> Role:
-
query = await self.bot.db.execute(
"SELECT role_id FROM role_rewards WHERE guild_id = ? AND required_lvl = ?",
(guild.id, level),
@@ -451,7 +496,6 @@ async def on_message(self, message):
try:
await self.controller.handle_message(message)
except AttributeError: # bot has not fully started up yet
-
await self.bot.wait_until_ready()
await asyncio.sleep(5)
await self.on_message(message)
@@ -462,7 +506,7 @@ async def on_ready(self):
if not self.bot.ready_:
print("[Levels] Ready")
- @commands.slash_command()
+ @commands.slash_command(description="XP boost base command")
@commands.guild_only()
@commands.has_permissions(manage_roles=True)
async def xp_boost(self, inter: ApplicationCommandInteraction):
@@ -472,6 +516,7 @@ async def xp_boost(self, inter: ApplicationCommandInteraction):
@commands.has_permissions(manage_roles=True)
@xp_boost.sub_command()
async def active(self, inter: ApplicationCommandInteraction, active: bool):
+ """Enable or disable xp boost"""
await self.bot.db.execute(
"UPDATE config SET xp_boost_enabled = ? WHERE guild_id = ?",
(active, inter.guild.id),
@@ -486,17 +531,19 @@ async def active(self, inter: ApplicationCommandInteraction, active: bool):
@xp_boost.sub_command()
async def get(self, inter: ApplicationCommandInteraction):
async with self.bot.db.execute(
- "SELECT * FROM config WHERE guild_id = ?", (inter.guild.id,)
+ "SELECT * FROM config WHERE guild_id = ?", (inter.guild.id,)
) as cur:
config = await cur.fetchone()
if config is None:
- return await inter.response.send_message("There is no config setup for this server")
+ return await inter.response.send_message(
+ "There is no config setup for this server"
+ )
emb = Embed(
title="XP Boost",
description=f"XP Boost is currently {'enabled' if config[4] else 'disabled'}",
color=0x2F3136,
)
- emb.add_field(name="Multiplier", value=str(config[1]) + 'x')
+ emb.add_field(name="Multiplier", value=str(config[1]) + "x")
emb.add_field(name="Duration", value=get_expiry(config[2]))
await inter.response.send_message(embed=emb)
@@ -504,17 +551,17 @@ async def get(self, inter: ApplicationCommandInteraction):
@commands.has_permissions(manage_roles=True)
@xp_boost.sub_command()
async def set(
- self,
- inter: ApplicationCommandInteraction,
- amount=Option(
- name="amount",
- type=Union[float, int],
- required=True,
- description="The amount to boost by",
- max_value=10,
- min_value=0.1,
- ),
- expires: str = "Never",
+ self,
+ inter: ApplicationCommandInteraction,
+ amount=Option(
+ name="amount",
+ type=Union[float, int],
+ required=True,
+ description="The amount to boost by",
+ max_value=10,
+ min_value=0.1,
+ ),
+ expires: str = "Never",
):
"""Set the xp boost for the server and optionally set an expiration date"""
try:
@@ -535,23 +582,27 @@ async def set(
@commands.slash_command()
@commands.guild_only()
async def rank(
- self, inter: ApplicationCommandInteraction, user: Optional[Member] = None
+ self,
+ inter: ApplicationCommandInteraction,
+ user: Optional[Member] = None,
):
"""
Get the rank of a user in the server or yourself if no user is specified
"""
user = user if user is not None else inter.author
- await inter.response.defer()
- if user.bot:
+ if user.bot or user.system:
return await errorEmb(inter, text="Bots can't rank up!")
+ await inter.response.defer()
try:
user_record = await self.controller.get_user(user)
if not user_record:
print("[Levels] User not found")
await self.controller.add_user(user, inter.guild)
return await self.rank(inter, user)
- rank = await self.controller.get_rank(inter.guild.id, user_record)
+ user_record, rank = await self.controller.get_rank(
+ inter.guild.id, user_record, return_updated=True
+ )
image = await self.controller.generate_image_card(
user, rank, user_record.xp, user_record.lvl
)
@@ -574,7 +625,9 @@ async def leaderboard(self, inter: ApplicationCommandInteraction):
await inter.response.defer()
limit = 10
set_user = False
- records = await self.controller.get_leaderboard(inter.guild, limit=limit)
+ records = await self.controller.get_leaderboard(
+ inter.guild, limit=limit
+ )
try:
cmd_user = await self.controller.get_user(inter.author)
except UserNotFound:
@@ -588,14 +641,14 @@ async def leaderboard(self, inter: ApplicationCommandInteraction):
user = await self.bot.fetch_user(record.user_id)
if record.user_id == inter.author.id:
embed.add_field(
- name=f"{i + 1}. {user} ~ You ",
+ name=f"{i + 1}. {user.name} ~ You ",
value=f"Level: {record.lvl}\nTotal XP: {record.total_exp:,}",
inline=False,
)
set_user = True
else:
embed.add_field(
- name=f"{i + 1}. {user}",
+ name=f"{i + 1}. {user.name}",
value=f"Level: {record.lvl}\nTotal XP: {record.total_exp:,}",
inline=False,
)
@@ -615,7 +668,9 @@ async def leaderboard(self, inter: ApplicationCommandInteraction):
await inter.send(
embed=embed,
view=LeaderboardView(
- controller=self.controller, firstemb=embed, author=inter.author.id
+ controller=self.controller,
+ firstemb=embed,
+ author=inter.author.id,
),
)
@@ -623,10 +678,12 @@ async def leaderboard(self, inter: ApplicationCommandInteraction):
@commands.guild_only()
@commands.has_any_role("Staff", "staff")
async def set_lvl(
- self,
- inter: ApplicationCommandInteraction,
- user: Member,
- level: int = Param(description="The level to set the user to", le=100, ge=0),
+ self,
+ inter: ApplicationCommandInteraction,
+ user: Member,
+ level: int = Param(
+ description="The level to set the user to", le=100, ge=0
+ ),
):
"""
Set a user's level
@@ -642,38 +699,41 @@ async def set_lvl(
except LevelingSystemError:
return await errorEmb(inter, text="Invalid mofo")
await sucEmb(
- inter, text=f"Set {user.mention}'s level to {level}", ephemeral=False
+ inter,
+ text=f"Set {user.mention}'s level to {level}",
+ ephemeral=False,
)
- @commands.slash_command()
+ @commands.slash_command(description="Role rewards base command")
@commands.guild_only()
@commands.has_permissions(manage_roles=True)
async def role_reward(self, inter: ApplicationCommandInteraction):
-
return
@role_reward.sub_command()
@commands.has_permissions(manage_roles=True)
async def add(
- self,
- inter: ApplicationCommandInteraction,
- role: Role = Param(name="role", description="what role to give"),
- level_needed: int = Param(
- name="level_needed", description="The level needed to get the role"
- ),
+ self,
+ inter: ApplicationCommandInteraction,
+ role: Role = Param(name="role", description="What role to give"),
+ level_needed: int = Param(
+ name="level_needed", description="The level needed to get the role"
+ ),
):
- """adds a role to the reward list"""
+ """Adds a role to the reward list"""
if int(level_needed) not in self.levels:
return await errorEmb(
inter, text=f"Level must be within 1-{MAX_LEVEL} found"
)
if await self.bot.db.execute(
- "SELECT 1 FROM role_rewards WHERE guild_id = ? AND role_id = ?",
- (inter.guild.id, role.id),
+ "SELECT 1 FROM role_rewards WHERE guild_id = ? AND role_id = ?",
+ (inter.guild.id, role.id),
):
sql = "INSERT OR IGNORE INTO role_rewards (guild_id, role_id, required_lvl) VALUES (?, ?, ?)"
- await self.bot.db.execute(sql, (inter.guild.id, role.id, level_needed))
+ await self.bot.db.execute(
+ sql, (inter.guild.id, role.id, level_needed)
+ )
await self.bot.db.commit()
return await sucEmb(
inter,
@@ -686,14 +746,14 @@ async def add(
@role_reward.sub_command()
@commands.has_permissions(manage_roles=True)
async def remove(
- self,
- inter: ApplicationCommandInteraction,
- role: Role = Param(name="role", description="what role to remove"),
+ self,
+ inter: ApplicationCommandInteraction,
+ role: Role = Param(name="role", description="What role to remove"),
):
- """remove a role reward"""
+ """Remove a role reward"""
if await self.bot.db.execute(
- "SELECT 1 FROM role_rewards WHERE guild_id = ? AND role_id = ?",
- (inter.guild.id, role.id),
+ "SELECT 1 FROM role_rewards WHERE guild_id = ? AND role_id = ?",
+ (inter.guild.id, role.id),
):
sql = "DELETE FROM role_rewards WHERE guild_id = ? AND role_id = ?"
await self.bot.db.execute(sql, (inter.guild.id, role.id))
@@ -708,7 +768,7 @@ async def remove(
@role_reward.sub_command()
async def list(self, inter: ApplicationCommandInteraction):
- """list all role rewards"""
+ """List all role rewards"""
sql = "SELECT * FROM role_rewards WHERE guild_id = ?"
records = await self.bot.db.execute(sql, (inter.guild.id,))
records = await records.fetchall()
diff --git a/cogs/Lewis.py b/cogs/Lewis.py
index 2a28b07..988c169 100644
--- a/cogs/Lewis.py
+++ b/cogs/Lewis.py
@@ -28,10 +28,12 @@ async def upload_check(self):
response = await self.bot.session.get(self.youtube_api_url)
response = await response.json()
-
- video_id = response["items"][0]["id"]["videoId"]
+ try:
+ video_id = response["items"][0]["id"]["videoId"]
+ except KeyError:
+ print("Issue with request, skipping upload check")
+ return
video_url = f"https://www.youtube.com/watch?v={video_id}"
- # Credits to Simon for the idea and part of the code
video_release_time = response["items"][0]["snippet"]["publishedAt"]
year = video_release_time.split("-")[0]
@@ -41,7 +43,12 @@ async def upload_check(self):
minute = video_release_time.split("T")[1].split(":")[1]
second = video_release_time.split("T")[1].split(":")[2].split("Z")[0]
time = dt.datetime(
- int(year), int(month), int(day), int(hour), int(minute), int(second)
+ int(year),
+ int(month),
+ int(day),
+ int(hour),
+ int(minute),
+ int(second),
)
if check_time - time < dt.timedelta(minutes=30):
return await channel.send(
diff --git a/cogs/Logs.py b/cogs/Logs.py
index a70769e..823efd6 100644
--- a/cogs/Logs.py
+++ b/cogs/Logs.py
@@ -31,7 +31,10 @@ async def on_user_update(self, before, after):
timestamp=datetime.now(),
)
- fields = [("Before", before.name, False), ("After", after.name, False)]
+ fields = [
+ ("Before", before.name, False),
+ ("After", after.name, False),
+ ]
for name, value, inline in fields:
embed.add_field(name=name, value=value, inline=inline)
@@ -82,6 +85,20 @@ async def on_user_update(self, before, after):
@Cog.listener()
async def on_member_update(self, before, after):
+ before_roles = []
+ after_roles = []
+ for role in before.roles:
+ before_roles.append(str(role.mention))
+
+ before_roles.reverse()
+ before_roles.pop()
+
+ for role in after.roles:
+ after_roles.append(str(role.mention))
+
+ after_roles.reverse()
+ after_roles.pop()
+
if before.display_name != after.display_name:
embed = Embed(
title="Nickname change",
@@ -110,8 +127,8 @@ async def on_member_update(self, before, after):
)
fields = [
- ("Before", ", ".join([r.mention for r in before.roles]), False),
- ("After", ", ".join([r.mention for r in after.roles]), False),
+ ("Before", ", ".join(before_roles), False),
+ ("After", ", ".join(after_roles), False),
]
for name, value, inline in fields:
@@ -155,14 +172,19 @@ async def on_message_delete(self, message):
timestamp=datetime.now(),
)
- fields = [("Content", message.content, False)]
-
- for name, value, inline in fields:
- embed.add_field(name=name, value=value, inline=inline)
-
embed.set_footer(
text=f"{message.author.name}#{message.author.discriminator}"
)
+
+ n = 0
+ while len(message.content) > n:
+ embed.add_field(
+ name="content",
+ value=message.content[n : n + 1024],
+ inline=False,
+ )
+ n += 1024
+
await self.log_channel.send(embed=embed)
@Cog.listener()
@@ -175,17 +197,23 @@ async def on_slash_command(self, inter):
timestamp=datetime.now(),
)
- embed.set_author(name=inter.author, icon_url=inter.author.display_avatar.url)
+ embed.set_author(
+ name=inter.author, icon_url=inter.author.display_avatar.url
+ )
options = " ".join(
- [f"{name}: {value}" for name, value in inter.options.items()]
+ [
+ f"{name}: {value}" if value else name
+ for name, value in inter.options.items()
+ ]
)
-
embed.description = (
- f"`/{inter.data['name']}{' ' + options if options != '' else options}`"
+ f"`/{inter.data['name']} {options if options != '' else options}`"
)
- embed.set_footer(text=f"{inter.author.name}#{inter.author.discriminator}")
+ embed.set_footer(
+ text=f"{inter.author.name}#{inter.author.discriminator}"
+ )
await ogiroid_log_channel.send(embed=embed)
@Cog.listener()
@@ -216,14 +244,87 @@ async def on_guild_role_delete(self, role: disnake.Role):
await self.log_channel.send(embed=embed)
@Cog.listener()
- async def on_guild_role_update(self, before: disnake.Role, after: disnake.Role):
+ async def on_guild_role_update(
+ self, before: disnake.Role, after: disnake.Role
+ ):
"""Sends a message in log channel when role edites in the server."""
title = "Role edited"
- if before.name != after.name:
- content = f"**{before.name}** has been named to **{after.name}**"
- else: # needs to check perms aswell
+ before_, after_ = [], []
+
+ for before_name in before.permissions:
+ before_.append(before_name)
+
+ for after_name in after.permissions:
+ after_.append(after_name)
+
+ added, removed = [], []
+ check = set(after_) - set(before_)
+
+ for name in list(check):
+ names = name[0]
+ values = name[1]
+ if values:
+ value = True
+ string = str(value)
+ values = string.replace("True", "added")
+ else:
+ value = False
+ string = str(value)
+ values = string.replace("False", "removed")
+
+ names_raw = names.replace("_", " ").replace("guild", "server")
+
+ if "added" in values:
+ added.append(names_raw)
+ else:
+ removed.append(names_raw)
+
+ if len(added) == 0 and len(removed) > 0 and after_ != before_:
+ content = f"**Removed: ** {', '.join(removed)}"
+ elif len(removed) == 0 and len(added) > 0 and after_ != before_:
+ content = f"**Added: ** {','.join(added)}\n"
+ elif (
+ len(added) == 0
+ and len(removed) > 0
+ and after_ != before_
+ and after.name != before.name
+ ):
+ content = (
+ f"**Old name: ** `{before.name}`\n"
+ f"**New name: ** `{after.name}`\n"
+ f"**Removed: ** {','.join(removed)}\n"
+ )
+ elif (
+ len(removed) == 0
+ and len(added) > 0
+ and after_ != before_
+ and after.name != before.name
+ ):
+ content = (
+ f"**Old name: ** `{before.name}`\n"
+ f"**New name: ** `{after.name}`\n"
+ f"**Added: ** {','.join(added)}\n"
+ )
+ elif after_ != before_ and after.name != before.name:
+ content = (
+ f"**Old name: ** `{before.name}`\n"
+ f"**New name: ** `{after.name}`\n"
+ f"**Added: ** {','.join(added)}\n"
+ f"**Removed: ** {', '.join(removed)}"
+ )
+ elif after_ != before_:
+ content = (
+ f"**Added: ** {','.join(added)}\n"
+ f"**Removed: ** {', '.join(removed)}"
+ )
+ elif after.name != before.name:
+ content = (
+ f"**Old name: ** `{before.name}`\n"
+ f"**New name: ** `{after.name}`"
+ )
+ else:
return
embed = Embed(
@@ -236,7 +337,9 @@ async def on_guild_role_update(self, before: disnake.Role, after: disnake.Role):
await self.log_channel.send(embed=embed)
@Cog.listener()
- async def on_guild_update(self, before: disnake.Guild, after: disnake.Guild):
+ async def on_guild_update(
+ self, before: disnake.Guild, after: disnake.Guild
+ ):
"""Sends a message in log channel when guild updates."""
if before.name != after.name:
message = (
@@ -256,13 +359,16 @@ async def on_guild_update(self, before: disnake.Guild, after: disnake.Guild):
f"Before: `{before.afk_timeout}`\n"
f"After: `{after.afk_timeout}`"
)
+ else:
+ message = None
embed = Embed(
title="Server edited",
- description=message,
colour=self.bot.config.colors.white,
timestamp=datetime.now(),
)
+ if message is not None:
+ embed.description = message
await self.log_channel.send(embed=embed)
@@ -280,7 +386,9 @@ async def on_thread_create(self, thread: disnake.Thread):
await self.log_channel.send(embed=embed)
@Cog.listener()
- async def on_thread_update(self, before: disnake.Thread, after: disnake.Thread):
+ async def on_thread_update(
+ self, before: disnake.Thread, after: disnake.Thread
+ ):
"""Sends a message in log channel when thread updates."""
embed = Embed(
title="Thread name edited",
@@ -334,7 +442,9 @@ async def on_member_unban(self, guild: disnake.Guild, user: disnake.User):
timestamp=datetime.now(),
)
- await self.log_channel.send(embed=embed)
+ await self.log_channel.send(
+ embed=embed
+ ) # todo switch to guild channel.
def setup(bot):
diff --git a/cogs/Memes.py b/cogs/Memes.py
index caa6719..ee09461 100644
--- a/cogs/Memes.py
+++ b/cogs/Memes.py
@@ -20,7 +20,9 @@ async def onlyfans(self, inter):
)
@commands.slash_command(
- name="meme", aliases=["dankmeme"], description="Random meme from r/memes"
+ name="meme",
+ aliases=["dankmeme"],
+ description="Random meme from r/memes",
)
async def meme(self, inter):
"""Random meme from r/memes"""
diff --git a/cogs/Password.py b/cogs/Password.py
index 3cbd2d3..13b7aa4 100644
--- a/cogs/Password.py
+++ b/cogs/Password.py
@@ -15,23 +15,24 @@ def __init__(self, bot: OGIROID):
@commands.slash_command(
name="password",
aliases=["pass"],
- description="Generate a random password & DM's it!",
+ description="Generates a random password & DM's it!",
)
async def password(self, inter, length: int):
"""Generate a random password & DMs it!"""
if length > 100:
length = 100
password = "".join(
- secrets.choice(string.ascii_letters + string.digits) for _ in range(length)
+ secrets.choice(string.ascii_letters + string.digits)
+ for _ in range(length)
)
# try to DM if fails send the password to the channel
try:
- await inter.author.send(f"Your password is: `{password}`")
+ await inter.author.send(f"Your password is: ||{password}||")
await inter.response.send_message("Your password has been sent!")
# If DMs are closed, send the password to the channel
except:
await inter.response.send_message(
- f"Your password is: `{password}`", ephemeral=True
+ f"Your password is: ||{password}||", ephemeral=True
)
diff --git a/cogs/Search.py b/cogs/Search.py
index eab785a..069f83e 100644
--- a/cogs/Search.py
+++ b/cogs/Search.py
@@ -1,3 +1,5 @@
+from urllib.parse import quote_plus
+
from disnake.ext import commands
from utils.bot import OGIROID
@@ -20,7 +22,7 @@ async def search(
query: str = commands.Param(description="The query to search for"),
):
"""Searches the keyword entered"""
- query = query.rstrip().replace(" ", "+")
+ query = quote_plus(query.rstrip().rstrip())
if engine == "google":
await inter.send(f"https://google.com/search?q={query}")
elif engine == "duckduckgo":
@@ -39,7 +41,9 @@ async def lucky(self, inter, query):
query = query.rstrip().replace(" ", "+")
await inter.send(f"https://www.google.com/search?q={query}&btnI")
- @commands.slash_command(description="Returns a StackOverflow search for your query")
+ @commands.slash_command(
+ description="Returns a StackOverflow search for your query"
+ )
async def stackoverflow(self, inter, query):
"""Searches StackOverflow for the query"""
query = query.rstrip().replace(" ", "+")
diff --git a/cogs/Snipe.py b/cogs/Snipe.py
index 116bfde..d3cb1dd 100644
--- a/cogs/Snipe.py
+++ b/cogs/Snipe.py
@@ -24,7 +24,8 @@ async def on_message_edit(self, before, after):
self.edit_snipes[after.channel] = (before, after)
@commands.slash_command(
- name="snipe", description="Get the most recently deleted message in a channel"
+ name="snipe",
+ description="Get the most recently deleted message in a channel",
)
async def snipe_group(self, inter: ApplicationCommandInteraction):
"""Get the most recently deleted message in a channel"""
@@ -32,11 +33,13 @@ async def snipe_group(self, inter: ApplicationCommandInteraction):
try:
sniped_message = self.delete_snipes[inter.channel]
except KeyError:
- await inter.send("There are no deleted messages in this channel to snipe!")
+ await inter.send(
+ "There are no deleted messages in this channel to snipe!"
+ )
else:
result = disnake.Embed(
color=disnake.Color.red(),
- description=sniped_message.content,
+ description=sniped_message.content[:1024],
timestamp=sniped_message.created_at,
)
result.set_author(
@@ -65,13 +68,22 @@ async def editsnipe(self, inter: ApplicationCommandInteraction):
try:
before, after = self.edit_snipes[inter.channel]
except KeyError:
- await inter.send("There are no message edits in this channel to snipe!")
+ await inter.send(
+ "There are no message edits in this channel to snipe!"
+ )
else:
- result = disnake.Embed(color=disnake.Color.red(), timestamp=after.edited_at)
- result.add_field(name="Before", value=before.content, inline=False)
- result.add_field(name="After", value=after.content, inline=False)
+ result = disnake.Embed(
+ color=disnake.Color.red(), timestamp=after.edited_at
+ )
+ result.add_field(
+ name="Before", value=before.content[:1024], inline=False
+ )
+ result.add_field(
+ name="After", value=after.content[:1024], inline=False
+ )
result.set_author(
- name=after.author.display_name, icon_url=after.author.avatar.url
+ name=after.author.display_name,
+ icon_url=after.author.avatar.url,
)
is_staff = disnake.utils.find(
lambda r: r.name.lower() == "staff", inter.guild.roles
diff --git a/cogs/Staff.py b/cogs/Staff.py
index 2a97c06..d2d6429 100644
--- a/cogs/Staff.py
+++ b/cogs/Staff.py
@@ -15,7 +15,13 @@
from utils.DBhandlers import RolesHandler, WarningHandler
from utils.bot import OGIROID
from utils.exceptions import ReactionAlreadyExists, ReactionNotFound
-from utils.shortcuts import sucEmb, errorEmb, warning_embed, QuickEmb, warnings_embed
+from utils.shortcuts import (
+ sucEmb,
+ errorEmb,
+ warning_embed,
+ QuickEmb,
+ warnings_embed,
+)
class StaffVote(disnake.ui.Modal):
@@ -75,7 +81,9 @@ async def on_ready(self):
self.warning: WarningHandler = WarningHandler(self.bot, self.bot.db)
await self.reaction_roles.startup()
- @commands.slash_command(name="ban", description="Bans a user from the server.")
+ @commands.slash_command(
+ name="ban", description="Bans a user from the server."
+ )
@commands.has_permissions(ban_members=True)
@commands.guild_only()
async def ban(
@@ -118,7 +126,9 @@ async def softban(
await asyncio.sleep(5)
await inter.guild.unban(user=user, reason="softban unban")
- @commands.slash_command(name="kick", description="Kicks a user from the server.")
+ @commands.slash_command(
+ name="kick", description="Kicks a user from the server."
+ )
@commands.has_permissions(kick_members=True)
@commands.guild_only()
async def kick(
@@ -131,7 +141,9 @@ async def kick(
await member.kick(reason=reason)
await sucEmb(inter, "User has been kicked successfully!")
- @commands.slash_command(name="unban", description="Unbans a user from the server.")
+ @commands.slash_command(
+ name="unban", description="Unbans a user from the server."
+ )
@commands.has_permissions(ban_members=True)
@commands.guild_only()
async def unban(
@@ -139,7 +151,9 @@ async def unban(
):
"""Unbans a user from the server."""
try:
- await inter.guild.unban(disnake.Object(id=int(user_id)), reason=reason)
+ await inter.guild.unban(
+ disnake.Object(id=int(user_id)), reason=reason
+ )
except ValueError:
return await errorEmb(inter, "Invalid user ID!")
except disnake.errors.NotFound:
@@ -148,15 +162,17 @@ async def unban(
await sucEmb(inter, "User has been unbanned successfully!")
@commands.slash_command(
- name="mute", description="Timeout(mute)'s a user from the server."
+ name="mute", description="'timeout's a user from the server."
)
- @commands.has_role("Staff")
+ @commands.has_permissions(moderate_members=True)
@commands.guild_only()
async def mute(
self,
inter: ApplicationCommandInteraction,
member: disnake.Member,
- duration: str = ParamInfo(description="Format: 1s, 1m, 1h, 1d, max: 28d"),
+ duration: str = ParamInfo(
+ description="Format: 1s, 1m, 1h, 1d, max: 28d"
+ ),
reason: str = None,
):
"""Mutes a user from the server."""
@@ -191,7 +207,7 @@ async def mute(
@commands.slash_command(
name="unmute", description="Unmutes a user from the server."
)
- @commands.has_role("Staff")
+ @commands.has_permissions(moderate_members=True)
@commands.guild_only()
async def unmute(
self,
@@ -209,8 +225,10 @@ async def unmute(
await sucEmb(inter, "User has been unmuted successfully!")
- @commands.slash_command(name="warn", description="Warns a user from the server.")
- @commands.has_role("Staff")
+ @commands.slash_command(
+ name="warn", description="Warns a user from the server."
+ )
+ @commands.has_permissions(manage_roles=True)
@commands.guild_only()
async def warn(
self,
@@ -220,7 +238,10 @@ async def warn(
):
"""Warns a user from the server."""
await self.warning.create_warning(
- member.id, reason, moderator_id=inter.author.id
+ member.id,
+ reason,
+ moderator_id=inter.author.id,
+ guild_id=inter.guild.id,
)
await warning_embed(inter, user=member, reason=reason)
@@ -228,17 +249,19 @@ async def warn(
name="removewarning",
description="Removes a warning from a user from the server.",
)
- @commands.has_role("Staff")
+ @commands.has_permissions(manage_roles=True)
@commands.guild_only()
async def remove_warning(
self, inter: ApplicationCommandInteraction, member: disnake.Member
):
"""Removes a warning from a user from the server."""
- warnings = await self.warning.get_warnings(member.id)
+ warnings = await self.warning.get_warnings(member.id, inter.guild.id)
if len(warnings) == 0:
return await errorEmb(inter, "User has no warnings!")
elif len(warnings) == 1:
- status = await self.warning.remove_warning(warnings[0].warning_id)
+ status = await self.warning.remove_warning(
+ warnings[0].warning_id, inter.guild.id
+ )
if status:
await sucEmb(inter, "Warning has been removed successfully!")
else:
@@ -256,7 +279,9 @@ def check(m):
return m.author == inter.author and m.channel == inter.channel
try:
- msg = await self.bot.wait_for("message", check=check, timeout=60)
+ msg = await self.bot.wait_for(
+ "message", check=check, timeout=60
+ )
except asyncio.TimeoutError:
return await errorEmb(inter, "Timed out!")
@@ -264,7 +289,9 @@ def check(m):
if id > len(warnings) or id < 1:
return await errorEmb(inter, "Invalid warning index!")
- status = await self.warning.remove_warning(warnings[id - 1].warning_id)
+ status = await self.warning.remove_warning(
+ warnings[id - 1].warning_id, inter.guild.id
+ )
if status:
await sucEmb(inter, "Warning has been removed successfully!")
else:
@@ -277,37 +304,33 @@ def check(m):
await msg.delete()
@commands.slash_command(
- name="warnings", description="Shows the warnings of a user from the server."
+ name="warnings",
+ description="Shows the warnings of a user from the server.",
)
- @commands.has_role("Staff")
+ @commands.has_permissions(manage_roles=True)
@commands.guild_only()
async def warnings(
self, inter: ApplicationCommandInteraction, member: disnake.Member
):
"""Shows the warnings of a user from the server."""
- warnings = await self.warning.get_warnings(member.id)
+ warnings = await self.warning.get_warnings(member.id, inter.guild.id)
if not warnings:
return await QuickEmb(inter, "User has no warnings!").send()
await warnings_embed(inter, member=member, warnings=warnings)
- @commands.slash_command()
- @commands.has_role("Staff")
- async def punishments(self, inter: ApplicationCommandInteraction):
- """Shows the punishments"""
- return await inter.send(
- "https://media.discordapp.net/attachments/905182869410955356/985264301591916594/unknown-18.png?width=521&height=683",
- ephemeral=True,
- )
-
- @commands.slash_command(description="Steals an emoji from a different server.")
+ @commands.slash_command(
+ description="Steals an emoji from a different server."
+ )
@commands.guild_only()
@commands.has_permissions(manage_emojis=True)
async def stealemoji(
self,
inter: ApplicationCommandInteraction,
emoji: disnake.PartialEmoji,
- name=Option(name="name", required=False, description="Name of the emoji"),
+ name=Option(
+ name="name", required=False, description="Name of the emoji"
+ ),
):
"""This clones a specified emoji that optionally only specified roles
are allowed to use.
@@ -324,7 +347,8 @@ async def stealemoji(
)
await inter.send(
embed=disnake.Embed(
- description=f"emoji successfully stolen", color=Color.random()
+ description=f"emoji successfully stolen",
+ color=Color.random(),
).set_image(url=emoji.url)
)
except Exception as e:
@@ -338,7 +362,8 @@ async def addemoji(
inter: ApplicationCommandInteraction,
name: str,
input_type: str = commands.Param(
- choices=["file(image)", "url(image)"], description="What you will input."
+ choices=["file(image)", "url(image)"],
+ description="What you will input.",
),
):
"""Adds an image to the server emojis"""
@@ -346,11 +371,14 @@ async def addemoji(
try:
msg = await self.bot.wait_for(
"message",
- check=lambda m: m.author == inter.author and m.channel == inter.channel,
+ check=lambda m: m.author == inter.author
+ and m.channel == inter.channel,
)
except asyncio.TimeoutError:
return await inter.send("Timed out!")
+ image = None
+
if input_type == "url(image)":
response = await self.bot.session.get(
msg.content.strip().replace("webp", "png")
@@ -371,19 +399,9 @@ async def addemoji(
except ValueError:
pass
- @commands.slash_command(name="faq")
- @commands.guild_only()
- @commands.has_role("Staff")
- async def faq(self, inter: ApplicationCommandInteraction, person: disnake.Member):
- """FAQ command for the staff team"""
- channel = self.bot.get_channel(self.bot.config.channels.reddit_faq)
- await channel.send(f"{person.mention}", delete_after=2)
- # Sending Done so this Application didn't respond error can be avoided
- await inter.send("Done", delete_after=1)
-
@commands.slash_command(name="prune")
@commands.guild_only()
- @commands.has_role("Staff")
+ @commands.has_permissions(manage_messages=True)
async def prune(self, inter: ApplicationCommandInteraction, amount: int):
"""Delete messages, max limit set to 25."""
# Checking if amount > 25:
@@ -391,13 +409,17 @@ async def prune(self, inter: ApplicationCommandInteraction, amount: int):
await inter.send("Amount is too high, please use a lower amount")
return
await inter.channel.purge(limit=amount)
- await inter.send(f"Deleted {amount} messages successfully!", ephemeral=True)
+ await inter.send(
+ f"Deleted {amount} messages successfully!", ephemeral=True
+ )
@commands.slash_command(name="channellock")
@commands.guild_only()
- @commands.has_role("Staff")
+ @commands.has_permissions(manage_channels=True)
async def channellock(
- self, inter: ApplicationCommandInteraction, channel: disnake.TextChannel = None
+ self,
+ inter: ApplicationCommandInteraction,
+ channel: disnake.TextChannel = None,
):
"""Lock a channel"""
# Lock's a channel by not letting anyone send messages to it
@@ -414,9 +436,11 @@ async def channellock(
@commands.slash_command(name="channelunlock")
@commands.guild_only()
- @commands.has_role("Staff")
+ @commands.has_permissions(manage_channels=True)
async def channelunlock(
- self, inter: ApplicationCommandInteraction, channel: disnake.TextChannel = None
+ self,
+ inter: ApplicationCommandInteraction,
+ channel: disnake.TextChannel = None,
):
"""Unlock a channel"""
# Unlock's a channel by letting everyone send messages to it
@@ -433,10 +457,11 @@ async def channelunlock(
# Reaction Roles with buttons:
@commands.slash_command(
- name="addreactionrole", description="Add a reaction based role to a message"
+ name="addreactionrole",
+ description="Add a reaction based role to a message",
)
@commands.guild_only()
- @commands.has_role("Staff")
+ @commands.has_permissions(manage_roles=True)
async def add_reaction_role(
self,
inter: ApplicationCommandInteraction,
@@ -452,7 +477,9 @@ async def add_reaction_role(
emoji = PartialEmoji.from_str(emoji)
try:
- await self.reaction_roles.create_message(message_id, role.id, str(emoji))
+ await self.reaction_roles.create_message(
+ message_id, role.id, str(emoji)
+ )
except ReactionAlreadyExists:
return await errorEmb(inter, "Reaction already exists!")
@@ -465,7 +492,7 @@ async def add_reaction_role(
description="Remove a reaction based role from a message",
)
@commands.guild_only()
- @commands.has_role("Staff")
+ @commands.has_permissions(manage_roles=True)
async def remove_reaction_role(
self, inter, message_id, emoji: str, role: disnake.Role
):
@@ -479,7 +506,9 @@ async def remove_reaction_role(
await message.remove_reaction(emoji, inter.author)
try:
- await self.reaction_roles.remove_message(message_id, str(emoji), role.id)
+ await self.reaction_roles.remove_message(
+ message_id, str(emoji), role.id
+ )
except ReactionNotFound:
return await errorEmb(inter, "Reaction does not exist!")
@@ -519,8 +548,8 @@ async def on_raw_reaction_remove(self, payload):
description="Create a Message with Buttons where users click them and get roles.",
)
@commands.guild_only()
- @commands.has_role("Staff")
- async def initialise_message(
+ @commands.has_permissions(manage_roles=True)
+ async def initialise_message( # todo create better cmd and clean this section up.
self,
inter: disnake.ApplicationCommandInteraction,
emoji: str = ParamInfo(
@@ -544,7 +573,9 @@ def check(m):
await inter.send("Please send the message", ephemeral=True)
try:
- msg = await self.bot.wait_for("message", check=check, timeout=300.0)
+ msg = await self.bot.wait_for(
+ "message", check=check, timeout=300.0
+ )
except asyncio.exceptions.TimeoutError:
return await errorEmb(
inter, "Due to no response the operation was canceled"
@@ -571,7 +602,8 @@ def check(m):
await self.reaction_roles.create_message(msg.id, role.id, str(emoji))
await sucEmb(
- inter, "Successfully created message. To add more buttons use `/add_button`"
+ inter,
+ "Successfully created message. To add more buttons use `/add_button`",
)
@commands.slash_command(
@@ -580,7 +612,7 @@ def check(m):
" Use /initialise-message for that.",
)
@commands.guild_only()
- @commands.has_role("Staff")
+ @commands.has_permissions(manage_roles=True)
async def add_button(
self,
inter,
@@ -596,7 +628,6 @@ async def add_button(
description="The channel where the message is sent.",
),
):
-
emoji = PartialEmoji.from_str(new_emoji.strip())
message_id = int(message_id)
@@ -625,7 +656,9 @@ async def add_button(
components = disnake.ui.View.from_message(message)
- custom_id = f"{role.id}-{emoji.name if emoji.is_unicode_emoji() else emoji.id}"
+ custom_id = (
+ f"{role.id}-{emoji.name if emoji.is_unicode_emoji() else emoji.id}"
+ )
new_button = disnake.ui.Button(
emoji=emoji, custom_id=custom_id, style=disnake.ButtonStyle[color]
@@ -633,7 +666,9 @@ async def add_button(
components.add_item(new_button)
try:
- await self.reaction_roles.create_message(message.id, role.id, str(emoji))
+ await self.reaction_roles.create_message(
+ message.id, role.id, str(emoji)
+ )
except ReactionAlreadyExists:
return await errorEmb(inter, "This Reaction already exists")
@@ -646,8 +681,10 @@ async def add_button(
description="Edit a message the bot sent(Role messages with buttons only).",
)
@commands.guild_only()
- @commands.has_role("Staff")
- async def edit_message(self, inter, message_id, channel: disnake.TextChannel):
+ @commands.has_permissions(manage_roles=True)
+ async def edit_message(
+ self, inter, message_id, channel: disnake.TextChannel
+ ):
exists = False
message_id = int(message_id)
for message in self.reaction_roles.messages:
@@ -671,7 +708,9 @@ def check(m):
await inter.send("Please send the new message", ephemeral=True)
try:
- msg = await self.bot.wait_for("message", check=check, timeout=300.0)
+ msg = await self.bot.wait_for(
+ "message", check=check, timeout=300.0
+ )
except asyncio.exceptions.TimeoutError:
return await errorEmb(
inter, "Due to no response the operation was canceled"
@@ -695,8 +734,10 @@ def check(m):
description="Delete a message the bot sent(Role messages with buttons only).",
)
@commands.guild_only()
- @commands.has_role("Staff")
- async def delete_message(self, inter, message_id, channel: disnake.TextChannel):
+ @commands.has_permissions(manage_roles=True)
+ async def delete_message(
+ self, inter, message_id, channel: disnake.TextChannel
+ ):
exists = False
message_id = int(message_id)
for message in self.reaction_roles.messages:
@@ -729,7 +770,7 @@ async def delete_message(self, inter, message_id, channel: disnake.TextChannel):
name="remove-button", description="Remove a button from a message."
)
@commands.guild_only()
- @commands.has_role("Staff")
+ @commands.has_permissions(manage_roles=True)
async def remove_button(
self,
inter,
@@ -741,11 +782,15 @@ async def remove_button(
message_id = int(message_id.strip())
emoji = PartialEmoji.from_str(emoji.strip())
- button = await self.reaction_roles.exists(message_id, str(emoji), role.id)
+ button = await self.reaction_roles.exists(
+ message_id, str(emoji), role.id
+ )
if not button:
return await errorEmb(inter, "The button does not exist.")
- await self.reaction_roles.remove_message(message_id, str(emoji), role.id)
+ await self.reaction_roles.remove_message(
+ message_id, str(emoji), role.id
+ )
message = await channel.fetch_message(message_id)
@@ -781,7 +826,9 @@ async def button_click(self, inter):
except ValueError:
return
- if not await self.reaction_roles.exists(message.id, str(emoji), role_id):
+ if not await self.reaction_roles.exists(
+ message.id, str(emoji), role_id
+ ):
return await errorEmb(inter, "This doesnt exists in the database")
await self.reaction_roles.increment_roles_given(message.id, str(emoji))
@@ -792,19 +839,23 @@ async def button_click(self, inter):
await member.add_roles(
role, reason=f"Clicked button to get role. gave {role.name}"
)
- await self.reaction_roles.increment_roles_given(message.id, str(emoji))
- return await sucEmb(inter, "Added Role")
+ await self.reaction_roles.increment_roles_given(
+ message.id, str(emoji)
+ )
+ return await sucEmb(inter, f"Added Role {role.mention}")
else:
await member.remove_roles(
role,
reason=f"Clicked button while already having the role. removed {role.name}",
)
- return await sucEmb(inter, "Removed Role")
+ return await sucEmb(inter, f"Removed Role {role.mention}")
- @commands.slash_command(name="staffvote", description="Propose a Staff Vote.")
+ @commands.slash_command(
+ name="staffvote", description="Propose a Staff Vote."
+ )
@commands.guild_only()
- @commands.has_role("Staff")
- async def staffvote(self, inter):
+ @commands.has_permissions(ban_members=True)
+ async def staffvote(self, inter): # todo remove
"""Propose a Staff Vote."""
await inter.response.send_modal(modal=StaffVote(self.bot))
@@ -812,12 +863,14 @@ async def staffvote(self, inter):
name="staffhelp", description="Get the help for the staff commands."
)
@commands.guild_only()
- @commands.has_role("Staff")
+ @commands.has_permissions(manage_roles=True)
async def staffhelp(self, inter):
"""Get the help for the staff commands."""
staff_commands = commands.Cog.get_slash_commands(self)
emb = disnake.Embed(
- title="Staff Commands", description="All staff commands", color=0xFFFFFF
+ title="Staff Commands",
+ description="All staff commands",
+ color=0xFFFFFF,
)
for command in staff_commands:
emb.add_field(
@@ -828,6 +881,13 @@ async def staffhelp(self, inter):
await inter.send(embed=emb)
+ @commands.slash_command(name="anonymous_dm", description="Send an anonymous dm to a user.")
+ @commands.guild_only()
+ @commands.has_permissions(manage_messages=True)
+ async def anonymous_dm(self, inter, user: disnake.Member, *, message: str):
+ """Send an anonymous dm to a user."""
+ await user.send(message)
+ await sucEmb(inter, "Sent!")
def setup(bot):
bot.add_cog(Staff(bot))
diff --git a/cogs/Starboard.py b/cogs/Starboard.py
index c574e03..82ae405 100644
--- a/cogs/Starboard.py
+++ b/cogs/Starboard.py
@@ -22,8 +22,13 @@ async def on_raw_reaction_add(self, payload):
):
return
message = await channel.fetch_message(payload.message_id)
- starboard_channel = message.guild.get_channel(self.starboard_channel_id)
- if payload.emoji.name == self.star_emoji and not channel == starboard_channel:
+ starboard_channel = message.guild.get_channel(
+ self.starboard_channel_id
+ )
+ if (
+ payload.emoji.name == self.star_emoji
+ and not channel == starboard_channel
+ ):
for reaction in message.reactions:
if (
reaction.emoji == self.star_emoji
@@ -35,7 +40,8 @@ async def on_raw_reaction_add(self, payload):
timestamp=datetime.now(),
)
embed.set_author(
- name=message.author, icon_url=message.author.display_avatar.url
+ name=message.author,
+ icon_url=message.author.display_avatar.url,
)
await starboard_channel.send(embed=embed)
diff --git a/cogs/Support.py b/cogs/Support.py
index 3c25481..c6dd722 100644
--- a/cogs/Support.py
+++ b/cogs/Support.py
@@ -66,11 +66,15 @@ async def callback(self, inter: disnake.ModalInteraction):
)
embed.add_field(
- name="Expected Result: ", value=inter.text_values["expected"], inline=False
+ name="Expected Result: ",
+ value=inter.text_values["expected"],
+ inline=False,
)
embed.add_field(
- name="Actual Result:", value=inter.text_values["actual"], inline=False
+ name="Actual Result:",
+ value=inter.text_values["actual"],
+ inline=False,
)
embed.add_field(
@@ -86,7 +90,9 @@ async def callback(self, inter: disnake.ModalInteraction):
self.bot.config.channels.bug_report_reddit_bot
)
else:
- channel = self.bot.get_channel(self.bot.config.channels.bug_report_ogiroid)
+ channel = self.bot.get_channel(
+ self.bot.config.channels.bug_report_ogiroid
+ )
await channel.send(embed=embed)
await inter.send(
@@ -135,10 +141,14 @@ async def callback(self, inter: disnake.ModalInteraction):
embed.add_field(name="Type:", value=suggestion_type)
- embed.add_field(name="Title:", value=inter.text_values["title"], inline=False)
+ embed.add_field(
+ name="Title:", value=inter.text_values["title"], inline=False
+ )
embed.add_field(
- name="Description:", value=inter.text_values["description"], inline=False
+ name="Description:",
+ value=inter.text_values["description"],
+ inline=False,
)
if suggestion_type == "Reddit-Bot":
@@ -146,7 +156,9 @@ async def callback(self, inter: disnake.ModalInteraction):
self.bot.config.channels.suggestion_reddit_bot
)
else:
- channel = self.bot.get_channel(self.bot.config.channels.suggestion_ogiroid)
+ channel = self.bot.get_channel(
+ self.bot.config.channels.suggestion_ogiroid
+ )
await channel.send(embed=embed)
await inter.response.send_message(
"Sent suggestion.\nThank you for your suggestion.", ephemeral=True
@@ -172,8 +184,12 @@ def __init__(self, bot: OGIROID):
],
connectors={"for": "bug_report_for"},
)
- async def bug(self, inter: ApplicationCommandInteraction, bug_report_for: str):
- await inter.response.send_modal(modal=BugModal(self.bot, bug_report_for))
+ async def bug(
+ self, inter: ApplicationCommandInteraction, bug_report_for: str
+ ):
+ await inter.response.send_modal(
+ modal=BugModal(self.bot, bug_report_for)
+ )
@commands.slash_command(
name="suggest",
@@ -189,7 +205,9 @@ async def bug(self, inter: ApplicationCommandInteraction, bug_report_for: str):
connectors={"for": "suggestion_for"},
)
async def suggestion(self, inter, suggestion_for: str):
- await inter.response.send_modal(modal=SuggestionModal(self.bot, suggestion_for))
+ await inter.response.send_modal(
+ modal=SuggestionModal(self.bot, suggestion_for)
+ )
def setup(bot):
diff --git a/cogs/Tags.py b/cogs/Tags.py
index c366c8c..15e0358 100644
--- a/cogs/Tags.py
+++ b/cogs/Tags.py
@@ -1,6 +1,7 @@
from __future__ import annotations
import re
+from typing import Optional
import disnake
from disnake import Embed, ApplicationCommandInteraction
@@ -8,6 +9,7 @@
from utils.CONSTANTS import tag_help
from utils.DBhandlers import TagManager
+from utils.assorted import getPosition
from utils.bot import OGIROID
from utils.exceptions import *
from utils.models import *
@@ -40,34 +42,45 @@ async def valid_name(name) -> bool:
def db(self):
return self.bot.db
- @commands.slash_command()
+ @commands.slash_command(description="Tags base command")
@commands.guild_only()
async def tag(self, inter):
pass
@commands.slash_command(
- name="t", aliases=["tg"], description="Get a tag", hidden=True
+ name="t", description="An alias for `/tag get`", hidden=True
)
async def get_tag(
- self, inter: ApplicationCommandInteraction, *, name: str, embeded: bool = False
+ self,
+ inter: ApplicationCommandInteraction,
+ *,
+ name: str,
+ embedded: Optional[bool] = False,
):
- return await self.get(inter, name, embeded)
+ return await self.get(inter, name, embedded)
@tag.sub_command(name="get", description="Gets you the tags value")
@commands.guild_only()
async def get(
- self, inter: ApplicationCommandInteraction, name: str, embeded: bool = False
+ self,
+ inter: ApplicationCommandInteraction,
+ name: str,
+ embedded: Optional[bool] = False,
):
+ if not embedded:
+ embedded = False
+
if not name:
return await errorEmb(inter, "You need to specify a tag name")
name = name.casefold()
try:
tag = await self.tags.get(name)
await self.tags.increment_views(name)
- if embeded:
+ if embedded:
owner = self.bot.get_user(tag.owner)
emb = Embed(
- color=disnake.Color.random(seed=hash(tag.name)), title=f"{tag.name}"
+ color=disnake.Color.random(seed=hash(tag.name)),
+ title=f"{tag.name}",
)
emb.set_footer(
text=f'{f"Tag owned by {owner.display_name}" if owner else ""} - Views: {tag.views + 1}'
@@ -80,7 +93,7 @@ async def get(
content, allowed_mentions=disnake.AllowedMentions.none()
)
except TagNotFound:
- await errorEmb(inter, f"tag {name} does not exist")
+ await errorEmb(inter, f"tag **{name}** does not exist")
@tag.sub_command(name="random", description="Gets a random tag")
async def random(self, inter):
@@ -101,10 +114,12 @@ async def create(
try:
await self.tags.exists(name, TagAlreadyExists, should=False)
except TagAlreadyExists:
- return await errorEmb(inter, f"tag {name} already exists")
+ return await errorEmb(inter, f"tag **{name}** already exists")
if len(content) >= 1900:
- return await errorEmb(inter, "The tag's content must be under 1900 chars")
+ return await errorEmb(
+ inter, "The tag's content must be under 1900 chars"
+ )
elif not await self.valid_name(name):
return (
await QuickEmb(
@@ -119,13 +134,13 @@ async def create(
return (
await QuickEmb(
inter,
- f"I have successfully made **{name}**. To view it do /tag get {name}",
+ f"I have successfully made **{name}**. To view it do `/tag get: {name}` or `/t: {name}`",
)
.success()
.send()
)
except TagAlreadyExists:
- return await errorEmb(inter, f"tag {name} already exists")
+ return await errorEmb(inter, f"tag **{name}** already exists")
@tag.sub_command(name="edit", description="Edits the tag")
@commands.guild_only()
@@ -137,7 +152,8 @@ async def edit(
*,
content: str = commands.Param(le=1900),
):
- name = name.casefold()
+ name = await self.tags.get_name(name.casefold())
+
try:
if (
inter.author.id != (await self.tags.get(name)).owner
@@ -150,22 +166,27 @@ async def edit(
await self.tags.update(name, "content", content)
await QuickEmb(
inter,
- f"I have successfully updated **{name}**.\n\nuse /tag get {name} to access it.",
+ f"I have successfully updated **{name}**.\n\nuse `/tag get: {name}` or `/t: {name}` to access it.",
).success().send()
except TagNotFound:
- return await errorEmb(inter, f"tag {name} does not exist")
+ return await errorEmb(inter, f"tag **{name}** does not exist")
@tag.sub_command(name="transfer", description="Transfers the tag's owner")
@commands.guild_only()
@commands.cooldown(1, 5, commands.BucketType.user)
async def transfer(
- self, inter: ApplicationCommandInteraction, name, new_owner: disnake.Member
+ self,
+ inter: ApplicationCommandInteraction,
+ name,
+ new_owner: disnake.Member,
):
try:
name = name.casefold()
await self.tags.exists(name, TagNotFound, should=True)
if new_owner.bot:
- return await errorEmb(inter, "You can't transfer a tag to a bot!")
+ return await errorEmb(
+ inter, "You can't transfer a tag to a bot!"
+ )
elif (
inter.author.id != (await self.tags.get(name)).owner
) and not manage_messages_perms(inter):
@@ -178,7 +199,7 @@ async def transfer(
f"I have successfully transferred **{name}** to {new_owner.display_name}",
).success().send()
except TagNotFound:
- return await errorEmb(inter, f"tag {name} does not exist")
+ return await errorEmb(inter, f"tag **{name}** does not exist")
@tag.sub_command(
name="claim",
@@ -198,7 +219,9 @@ async def claim(self, inter: ApplicationCommandInteraction, name):
):
await self.tags.transfer(name, inter.author.id)
return (
- await QuickEmb(inter, f"I have transferred **{name}** to you")
+ await QuickEmb(
+ inter, f"I have transferred **{name}** to you"
+ )
.success()
.send()
)
@@ -218,7 +241,7 @@ async def claim(self, inter: ApplicationCommandInteraction, name):
.send()
)
except TagNotFound:
- return await errorEmb(inter, f"tag {name} does not exist")
+ return await errorEmb(inter, f"tag **{name}** does not exist")
@tag.sub_command(name="delete", description="Deletes the tag")
@commands.guild_only()
@@ -233,20 +256,20 @@ async def deltag(self, inter: ApplicationCommandInteraction, name):
return await errorEmb(
inter, "You must be the owner of the tag to delete it!"
)
- await self.tags.delete(name)
await QuickEmb(
inter, f"I have successfully deleted **{name}**."
).success().send()
+ await self.tags.delete(name)
except TagNotFound:
- return await errorEmb(inter, f"tag {name} does not exist")
+ return await errorEmb(inter, f"tag **{name}** does anot exist")
@tag.sub_command(name="info", description="Gives you the tags info")
@commands.guild_only()
@commands.cooldown(1, 3, commands.BucketType.user)
async def info(self, inter: ApplicationCommandInteraction, name):
name = name.casefold()
- await self.tags.exists(name, TagNotFound, should=True)
try:
+ await self.tags.exists(name, TagNotFound, should=True)
tag = await self.tags.get(name)
await self.tags.increment_views(name)
owner = self.bot.get_user(tag.owner)
@@ -257,24 +280,56 @@ async def info(self, inter: ApplicationCommandInteraction, name):
emb.add_field(name="Owner", value=owner.mention)
aliases = await self.tags.get_aliases(name)
if aliases:
- emb.add_field(name="Aliases", value=", ".join(tag for tag in aliases))
+ emb.add_field(
+ name="Aliases", value=", ".join(tag for tag in aliases)
+ )
emb.add_field(name="Created At", value=f"")
emb.add_field(name="Times Called", value=abs(tag.views))
await inter.send(embed=emb)
except TagNotFound:
- return await errorEmb(inter, f"tag {name} does not exist")
+ return await errorEmb(inter, f"tag **{name}** does not exist")
+
+ @tag.sub_command(
+ name="leaderboard", description="Lists shows top tags (by views)"
+ )
+ @commands.guild_only()
+ @commands.cooldown(1, 30, commands.BucketType.guild)
+ async def leaderboard(self, inter: ApplicationCommandInteraction):
+ try:
+ tags = await self.tags.all(orderby="views", limit=10)
+ except AttributeError:
+ return await errorEmb(inter, "wait for the bot to load")
+ except TagsNotFound:
+ return await errorEmb(inter, "There are no tags")
+ lb_string = ""
+ lb_header = "Place ***-*** Name ***-*** Total Views ***-*** Owner"
+
+ for i, tag in enumerate(tags):
+ owner: Optional = self.bot.get_user(tag.owner)
+ if owner is None:
+ username = None
+ else:
+ username = owner.display_name
+ lb_string += f"{getPosition(i)} **-** {tag.name} **-** ***{tag.views}*** **-** {username if username is not None else '**Open tag, no owner. use __/tag claim__**'}\n"
+ embed = disnake.Embed(
+ title="Flag Quiz All time Leaderboard",
+ description=f"The top 10 Tags in this server. Sorted by views\n",
+ color=disnake.Color.random(seed=inter.user.id),
+ )
+ embed.add_field(name=lb_header, value=lb_string)
+ await inter.send(embed=embed)
@tag.sub_command(name="list", description="Lists tags")
@commands.guild_only()
@commands.cooldown(1, 15, commands.BucketType.channel)
@commands.cooldown(1, 15, commands.BucketType.user)
- async def list_tags(self, ctx):
+ async def list_tags(self, inter: ApplicationCommandInteraction):
try:
tag_count = await self.tags.count()
except AttributeError:
- return await errorEmb(ctx, "wait for the bot to load")
+ return await errorEmb(inter, "wait for the bot to load")
if tag_count == 0:
- return await errorEmb(ctx, "There are no tags")
+ return await errorEmb(inter, "There are no tags")
tags = await self.tags.all(limit=0)
tag_embs = []
@@ -315,7 +370,9 @@ async def list_tags(self, ctx):
start_emb = Embed(title="Tags", color=self.bot.config.colors.invis)
start_emb.description = f"There are currently {tag_count:,d} tag{'s' if tag_count > 1 else ''}, use the arrows below to navigate through them"
tag_embs.insert(0, start_emb)
- await ctx.send(embed=tag_embs[0], view=CreatePaginator(tag_embs, ctx.author.id))
+ await inter.send(
+ embed=tag_embs[0], view=CreatePaginator(tag_embs, inter.author.id)
+ )
@tag.sub_command(name="rename", description="Renames a tag")
@commands.guild_only()
@@ -344,10 +401,11 @@ async def rename(self, inter, name, new_name):
)
await self.tags.rename(name, new_name)
await QuickEmb(
- inter, f"I have successfully renamed **{name}** to **{new_name}**."
+ inter,
+ f"I have successfully renamed **{name}** to **{new_name}**.",
).success().send()
except TagNotFound:
- return await errorEmb(inter, f"tag {name} does not exist")
+ return await errorEmb(inter, f"tag **{name}** does not exist")
except TagAlreadyExists:
return await errorEmb(
inter, f"A tag with the name {new_name} already exists"
@@ -355,7 +413,7 @@ async def rename(self, inter, name, new_name):
@tag.sub_command(name="help", description="Help for the tag system")
@commands.guild_only()
- async def help(self, ctx):
+ async def help(self, inter):
emb = Embed(title="Tag Help", color=self.bot.config.colors.invis)
general_cmds = ""
owner_cmds = ""
@@ -363,19 +421,21 @@ async def help(self, ctx):
for cmd, desc in tag_help["public"].items():
general_cmds += f"**/{cmd}** *~~* {desc}\n\t"
for cmd, desc in tag_help["owner_only"].items():
- owner_cmds += f"**/{cmd}** *~~* {desc} (only usable by the tag's owner)\n"
+ owner_cmds += (
+ f"**/{cmd}** *~~* {desc} (only usable by the tag's owner)\n"
+ )
emb.add_field(
name=f"General commands", value=general_cmds + "\n\n", inline=False
)
- emb.add_field(name=f"Owner only commands", value=owner_cmds, inline=False)
- emb.set_footer(
- text="Tag system made by @JasonLovesDoggo & @FreebieII",
- icon_url=self.bot.user.display_avatar.url,
+ emb.add_field(
+ name=f"Tag owner only commands", value=owner_cmds, inline=False
)
- await ctx.send(embed=emb)
+ await inter.send(embed=emb)
- @tag.sub_command_group(name="alias", description="Aliases a tag", hidden=True)
+ @tag.sub_command_group(
+ name="alias", description="Aliases a tag", hidden=True
+ )
@commands.guild_only()
async def alias(self, inter):
pass
@@ -409,13 +469,17 @@ async def add_alias(self, inter, name, alias):
f"I have successfully added **{alias}** as an alias for **{name}**",
).success().send()
except TagNotFound:
- return await errorEmb(inter, f"tag {name} does not exist")
+ return await errorEmb(inter, f"tag **{name}** does not exist")
except AliasAlreadyExists:
- return await errorEmb(inter, f"tag {alias} already exists")
+ return await errorEmb(inter, f"alias **{alias}** already exists")
except AliasLimitReached:
- return await errorEmb(inter, "You can only have 10 aliases per tag")
+ return await errorEmb(
+ inter, "You can only have 10 aliases per tag"
+ )
- @alias.sub_command(name="remove", description="Removes an alias from a tag")
+ @alias.sub_command(
+ name="remove", description="Removes an alias from a tag"
+ )
@commands.guild_only()
async def remove_alias(self, inter, name, alias):
try:
@@ -434,12 +498,13 @@ async def remove_alias(self, inter, name, alias):
)
await self.tags.remove_alias(name, alias)
await QuickEmb(
- inter, f"I have successfully removed **{alias}** from **{name}**"
+ inter,
+ f"I have successfully removed **{alias}** from **{name}**",
).success().send()
except TagNotFound:
- return await errorEmb(inter, f"tag {name} does not exist")
+ return await errorEmb(inter, f"tag **{name}** does not exist")
except AliasNotFound:
- return await errorEmb(inter, f"alias {alias} does not exist")
+ return await errorEmb(inter, f"alias **{alias}** does not exist")
def setup(bot):
diff --git a/cogs/Tickets.py b/cogs/Tickets.py
index dbed242..16305cd 100644
--- a/cogs/Tickets.py
+++ b/cogs/Tickets.py
@@ -55,7 +55,9 @@ def check(m):
return m.author == inter.author and m.channel == inter.channel
try:
- msg = await self.bot.wait_for("message", check=check, timeout=300.0)
+ msg = await self.bot.wait_for(
+ "message", check=check, timeout=300.0
+ )
except asyncio.exceptions.TimeoutError:
return await errorEmb(
inter, "Due to no response the operation was canceled"
@@ -90,7 +92,9 @@ async def on_button_click(self, inter):
# checks if user has a ticket already open
for channel in guild.channels:
try:
- if int(channel.name.strip().replace("ticket-", "")) == int(user.id):
+ if int(channel.name.strip().replace("ticket-", "")) == int(
+ user.id
+ ):
await errorEmb(
inter,
"You already have a ticket open. Please close it before opening a new one",
@@ -148,7 +152,9 @@ async def add_user(self, inter, member: disnake.Member):
else:
await errorEmb(inter, "This is not a ticket channel.")
- @commands.slash_command(name="removeuser", description="Remove user from channel")
+ @commands.slash_command(
+ name="removeuser", description="Remove user from channel"
+ )
@commands.has_role("Staff")
async def remove_user(self, inter, member: disnake.Member):
if self.check_if_ticket_channel(inter):
diff --git a/cogs/Timezone.py b/cogs/Timezone.py
index 01fd1de..3f4528b 100644
--- a/cogs/Timezone.py
+++ b/cogs/Timezone.py
@@ -23,9 +23,13 @@ def __init__(self, bot: OGIROID):
@commands.Cog.listener()
async def on_ready(self):
if not self.bot.ready_:
- self.db_timezone: TimezoneHandler = TimezoneHandler(self.bot, self.bot.db)
+ self.db_timezone: TimezoneHandler = TimezoneHandler(
+ self.bot, self.bot.db
+ )
- @commands.slash_command(name="timezone")
+ @commands.slash_command(
+ name="timezone", description="Timezone base command"
+ )
async def timezone(self, inter: disnake.ApplicationCommandInteraction):
pass
@@ -39,11 +43,18 @@ async def set(
autocomplete=autocomplete_timezones,
),
):
-
if timezone is None:
return await errorEmb(inter, "You need to provide a timezone")
- if timezone not in timezones:
- return await errorEmb(inter, "The timezone you provided is not valid")
+ elif timezone not in timezones:
+ return await errorEmb(
+ inter, "The timezone you provided is not valid"
+ )
+ elif timezone == "Europe/Tbilisi":
+ timezone = "Asia/Tbilisi"
+ display_timezone = "Europe/Tbilisi"
+ else:
+ display_timezone = timezone
+
try:
await self.db_timezone.create_user(inter.author.id, timezone)
except UserAlreadyExists:
@@ -51,7 +62,7 @@ async def set(
await sucEmb(
inter,
- f"Your timezone has been set to {timezone}."
+ f"Your timezone has been set to {display_timezone}."
f" Its should be {dt.datetime.now(pytz.timezone(timezone)).strftime('%H:%M')} at your location.",
)
@@ -67,17 +78,28 @@ async def edit(
):
if timezone is None:
return await errorEmb(inter, "You need to provide a timezone")
- if timezone not in timezones:
- return await errorEmb(inter, "The timezone you provided is not valid")
+ elif timezone not in timezones:
+ return await errorEmb(
+ inter, "The timezone you provided is not valid"
+ )
+ # handles tbilisi cause its annoying me
+ elif timezone == "Europe/Tbilisi":
+ timezone = "Asia/Tbilisi"
+ display_timezone = "Europe/Tbilisi"
+ else:
+ display_timezone = timezone
+
try:
await self.db_timezone.update_user(inter.author.id, timezone)
await sucEmb(
inter,
- f"Your timezone has been set to {timezone}."
- f" Its should be {dt.datetime.now(pytz.timezone(timezone)).strftime('%H:%M')} at your location.",
+ f"Your timezone has been set to {display_timezone}."
+ f" It should be {dt.datetime.now(pytz.timezone(timezone)).strftime('%H:%M')} at your location.",
)
except UserNotFound:
- return await errorEmb(inter, "The User doesn't have a timezone set")
+ return await errorEmb(
+ inter, "The User doesn't have a timezone set"
+ )
@timezone.sub_command(name="remove", description="Remove your timezone.")
async def remove(
@@ -87,13 +109,17 @@ async def remove(
try:
await self.db_timezone.delete_user(inter.author.id)
except UserNotFound:
- return await errorEmb(inter, "This user doesn't have a timezone set")
+ return await errorEmb(
+ inter, "This user doesn't have a timezone set"
+ )
await sucEmb(inter, "The timezone has been removed")
@timezone.sub_command(name="get", description="Get the timezone of a user")
async def get(
- self, inter, user: disnake.User = commands.Param(name="user", default=None)
+ self,
+ inter,
+ user: disnake.User = commands.Param(name="user", default=None),
):
if user is None:
user = inter.author
@@ -102,10 +128,19 @@ async def get(
timezone = await self.db_timezone.get_user(user.id)
if timezone is None:
- return await errorEmb(inter, "This user doesn't have a timezone set")
+ return await errorEmb(
+ inter, "This user doesn't have a timezone set"
+ )
+
+ # Handles tbilisi naming cause its annoying me.
+ if timezone.timezone == "Asia/Tbilisi":
+ display_timezone = "Europe/Tbilisi"
+ else:
+ display_timezone = timezone.timezone
+
await QuickEmb(
inter,
- f"{user.mention}'s timezone is {timezone.timezone}."
+ f"{user.mention}'s timezone is {display_timezone}."
f" Its currently {dt.datetime.now(pytz.timezone(timezone.timezone)).strftime('%H:%M')} for them",
).send()
diff --git a/cogs/Trivia.py b/cogs/Trivia.py
index 33fc94e..b55f3f7 100644
--- a/cogs/Trivia.py
+++ b/cogs/Trivia.py
@@ -24,7 +24,9 @@ def __init__(self, bot: OGIROID):
@commands.Cog.listener()
async def on_ready(self):
await self.bot.wait_until_ready()
- self.flag_quiz: FlagQuizHandler = FlagQuizHandler(self.bot, self.bot.db)
+ self.flag_quiz: FlagQuizHandler = FlagQuizHandler(
+ self.bot, self.bot.db
+ )
@commands.slash_command(name="flagquiz", description="Guess the flags.")
async def guess_the_flag(self, inter):
@@ -37,10 +39,14 @@ async def guess_the_flag(self, inter):
correct = 0
tries = 0
try:
- user = await self.flag_quiz.get_user(inter.author.id)
+ user = await self.flag_quiz.get_user(
+ inter.author.id, inter.guild.id
+ )
except UserNotFound:
await self.flag_quiz.add_user(inter.author.id)
- user = await self.flag_quiz.get_user(inter.author.id)
+ user = await self.flag_quiz.get_user(
+ inter.author.id, inter.guild.id
+ )
def check(m):
return (
@@ -54,7 +60,11 @@ def check(m):
retry = True
while retry:
user = await self.flag_quiz.add_data(
- user_id=inter.author.id, user=user, correct=correct, tries=tries
+ user_id=inter.author.id,
+ user=user,
+ correct=correct,
+ tries=tries,
+ guild_id=inter.guild.id,
)
embed = disnake.Embed(
title="Guess the Flag.",
@@ -73,7 +83,11 @@ def check(m):
channel, "Due to no response the quiz ended early."
).error().send()
await self.flag_quiz.add_data(
- inter.author.id, tries - 1, correct, user=user
+ inter.author.id,
+ tries - 1,
+ correct,
+ user=user,
+ guild_id=inter.guild.id,
)
return
@@ -87,7 +101,8 @@ def check(m):
>= 0.7
):
await QuickEmb(
- channel, f"Correct. The country indeed was {country[0]}"
+ channel,
+ f"Correct. The country indeed was {country[0]}",
).success().send()
correct += 1
retry = False
@@ -107,7 +122,9 @@ def check(m):
if guess.content.lower() == "skip":
if type(country) == list:
country = country[0]
- await QuickEmb(channel, f"The country was {country}").send()
+ await QuickEmb(
+ channel, f"The country was {country}"
+ ).send()
retry = False
elif guess.content.casefold() == "give up":
await guess.reply(
@@ -139,20 +156,27 @@ def check(m):
f"Your Score: {correct}/{tries - 1}. Thanks for playing.",
).send()
await self.flag_quiz.add_data(
- guess.author.id, tries - 1, correct, user=user
+ guess.author.id,
+ tries - 1,
+ correct,
+ user=user,
+ guild_id=inter.guild.id,
)
return
# If retry is still True (not changed) then the guess was incorrect
elif retry:
await errorEmb(inter, "Incorrect")
- await self.flag_quiz.add_data(inter.author.id, tries, correct, user=user)
+ await self.flag_quiz.add_data(
+ inter.author.id, tries, correct, user=user, guild_id=inter.guild.id
+ )
await channel.send(
f"Great Job on finishing the entire Quiz. Score: {correct}/{tries}"
)
@commands.slash_command(
- name="flagquiz-leaderboard", description="Leaderboard for the flag quiz."
+ name="flagquiz-leaderboard",
+ description="Leaderboard for the flag quiz.",
)
async def flag_quiz_leaderboard(
self,
@@ -166,7 +190,9 @@ async def flag_quiz_leaderboard(
),
):
try:
- leaderboard = await self.flag_quiz.get_leaderboard(order_by=sortby)
+ leaderboard = await self.flag_quiz.get_leaderboard(
+ order_by=sortby, guild_id=inter.guild.id
+ )
except UsersNotFound:
return (
await QuickEmb(inter, "No users have taken the quiz yet.")
@@ -181,9 +207,7 @@ async def flag_quiz_leaderboard(
leaderboard_string = ""
leaderboard_header = "Place ***-*** User ***-*** Correct Guesses/Total Guesses ***-*** Completed "
- i = 0
- for user in leaderboard:
- i += 1
+ for i, user in enumerate(leaderboard):
username = self.bot.get_user(user.user_id)
leaderboard_string += f"{getPosition(i)} **-** {username} **-** {user.correct}/{user.tries} **-** {user.completed}\n"
embed = disnake.Embed(
@@ -205,10 +229,11 @@ async def flag_quiz_user(self, inter, user: disnake.User = None):
else:
user_id = inter.author.id
try:
- player = await self.flag_quiz.get_user(user_id)
+ player = await self.flag_quiz.get_user(user_id, inter.guild.id)
except UserNotFound:
await errorEmb(
- inter, "This user never took part in the flag quiz or doesn't exist."
+ inter,
+ "This user never took part in the flag quiz or doesn't exist.",
)
return
@@ -264,7 +289,9 @@ async def flag_quiz_user(self, inter, user: disnake.User = None):
"Entertainment: Cartoon & Animations",
],
),
- Option(name="amount", description="Amount of Questions", min_value=1),
+ Option(
+ name="amount", description="Amount of Questions", min_value=1
+ ),
Option(
name="difficulty",
description="Difficulty of the questions",
@@ -283,11 +310,18 @@ async def flag_quiz_user(self, inter, user: disnake.User = None):
)
@commands.cooldown(1, 5, commands.BucketType.user)
async def trivia(
- self, inter, category="Any", difficulty=None, amount: int = 5, kind="multiple"
+ self,
+ inter,
+ category="Any",
+ difficulty=None,
+ amount: int = 5,
+ kind="multiple",
):
if int(amount) <= 1:
return (
- await QuickEmb(inter, "The amount of questions needs to be at least 1")
+ await QuickEmb(
+ inter, "The amount of questions needs to be at least 1"
+ )
.error()
.send()
)
@@ -316,13 +350,18 @@ def check(m):
)
data = await response.json()
embed = disnake.Embed(title="Created Quiz", colour=0xFFFFFF)
- embed.set_author(name=inter.author, icon_url=inter.author.display_avatar)
+ embed.set_author(
+ name=inter.author, icon_url=inter.author.display_avatar
+ )
embed.set_thumbnail(url=inter.author.display_avatar)
embed.add_field(name="Category:", value=category + " ")
embed.add_field(
- name="Difficulty:", value=difficulty if difficulty else "Any Difficulty"
+ name="Difficulty:",
+ value=difficulty if difficulty else "Any Difficulty",
+ )
+ embed.add_field(
+ name="Amount of Questions:", value=amount, inline=False
)
- embed.add_field(name="Amount of Questions:", value=amount, inline=False)
embed.add_field(name="Type:", value=kind, inline=False)
await inter.send(embed=embed)
@@ -339,7 +378,9 @@ def check(m):
answers_string = ""
for i in range(len(answers)):
answers_string += f"{emojis[i]}: {html.unescape(answers[i])}\n"
- components.append(disnake.ui.Button(emoji=emojis[i], custom_id=f"{i}"))
+ components.append(
+ disnake.ui.Button(emoji=emojis[i], custom_id=f"{i}")
+ )
embed = disnake.Embed(
title=html.unescape(question["question"]),
@@ -353,7 +394,9 @@ def check(m):
)
except asyncio.exceptions.TimeoutError:
return (
- await QuickEmb(channel, "Due to no response the quiz ended early.")
+ await QuickEmb(
+ channel, "Due to no response the quiz ended early."
+ )
.error()
.send()
)
@@ -385,7 +428,8 @@ def check(m):
).error().send()
await QuickEmb(
- channel, f"Thanks for playing. Your final Score is {correct} / {questions}."
+ channel,
+ f"Thanks for playing. Your final Score is {correct} / {questions}.",
).send()
diff --git a/cogs/Welcome.py b/cogs/Welcome.py
index d22c0ae..e62a924 100644
--- a/cogs/Welcome.py
+++ b/cogs/Welcome.py
@@ -17,10 +17,14 @@ async def on_member_join(self, member: disnake.Member):
if member.guild.id != self.bot.config.guilds.main_guild:
return
if member.dm_channel is None:
- introduction = self.bot.get_channel(self.bot.config.channels.introduction)
+ introduction = self.bot.get_channel(
+ self.bot.config.channels.introduction
+ )
general = self.bot.get_channel(self.bot.config.channels.general)
roles = self.bot.get_channel(self.bot.config.channels.roles)
- reddit_bot = self.bot.get_channel(self.bot.config.channels.reddit_bot)
+ reddit_bot = self.bot.get_channel(
+ self.bot.config.channels.reddit_bot
+ )
rules = self.bot.get_channel(self.bot.config.channels.rules)
await member.create_dm()
@@ -41,7 +45,9 @@ async def on_member_join(self, member: disnake.Member):
inline=True,
)
embed.add_field(
- name="Roles:", value=f"Select some roles, {roles.mention}", inline=True
+ name="Roles:",
+ value=f"Select some roles, {roles.mention}",
+ inline=True,
)
embed.add_field(
name="Reddit Bot Related:",
@@ -49,7 +55,9 @@ async def on_member_join(self, member: disnake.Member):
inline=True,
)
embed.add_field(
- name="Rules:", value=f"Checkout the rules, {rules.mention}", inline=True
+ name="Rules:",
+ value=f"Checkout the rules, {rules.mention}",
+ inline=True,
)
embed.set_thumbnail(url=member.display_avatar)
try:
@@ -59,7 +67,14 @@ async def on_member_join(self, member: disnake.Member):
else:
pass
- greetings = ["Hello", "Hi", "Greetings", "Hola", "Bonjour", "Konnichiwa"]
+ greetings = [
+ "Hello",
+ "Hi",
+ "Greetings",
+ "Hola",
+ "Bonjour",
+ "Konnichiwa",
+ ]
secondary_greeting = [
"Welcome to Lewis Menelaws' Official Discord Server! Feel free to look around & introduce yourself.",
"Welcome to the server! We wish you have a great time here, make sure you tell us a little bit about yourself.",
diff --git a/requirements.txt b/requirements.txt
index 3ac0eff..97be370 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,16 +1,16 @@
aiohttp~=3.8.3
-aiosqlite==0.17.0
+aiosqlite==0.18.0
akinator~=1.0.3
-disnake==2.7.0
+disnake==2.8.0
parsedatetime==2.6
-python-dotenv==0.21.0
-requests==2.28.1
+python-dotenv==0.21.1
+requests==2.28.2
textdistance~=4.5.0
-aiocache==0.11.1
-Pillow~=9.3.0
+aiocache==0.12.0
+Pillow==9.4.0
expr.py~=0.3.0
-cachetools~=5.2.0
+cachetools==5.3.0
python-dateutil~=2.8.2
-pytz==2022.6
-asyncpg~=0.27.0
+pytz==2022.7.1
discord_together==1.2.6
+better_profanity==0.7.0
\ No newline at end of file
diff --git a/secrets.env.template b/secrets.env.template
index 10da747..e6a5d4c 100644
--- a/secrets.env.template
+++ b/secrets.env.template
@@ -6,9 +6,5 @@ SRA_API_TOKEN=
OPEN_WEATHER_MAP_API_KEY=
# Used for the upload checker can be ignored in development
YT_API_KEY=
-POSTGRES_USER=
-POSTGRES_PASSWORD=
-POSTGRES_HOST=
-POSTGRES_PORT=
# Needs to be set to true or false
-DEVELOPMENT=
\ No newline at end of file
+DEVELOPMENT=
diff --git a/setup.sql b/setup.sql
index bbdfa0b..22c9bda 100644
--- a/setup.sql
+++ b/setup.sql
@@ -32,7 +32,8 @@ IF NOT EXISTS flag_quizz
user_id BIGINT,
tries INTEGER,
correct INTEGER,
- completed INTEGER
+ completed INTEGER,
+ guild_id INTEGER
);
CREATE TABLE
@@ -60,7 +61,8 @@ IF NOT EXISTS warnings
warning_id SERIAL PRIMARY KEY,
user_id BIGINT,
moderator_id BIGINT,
- reason TEXT
+ reason TEXT,
+ guild_id BIGINT
);
CREATE TABLE
diff --git a/utils/CONSTANTS.py b/utils/CONSTANTS.py
index 81fe1ac..870c30a 100644
--- a/utils/CONSTANTS.py
+++ b/utils/CONSTANTS.py
@@ -2,7 +2,7 @@
from dataclasses import dataclass
-__VERSION__ = "2.1"
+__VERSION__ = "2.2"
from typing import Final
@@ -96,6 +96,7 @@ def dev(cls):
class Colors:
invis: int = 0x2F3136
white: int = 0xFFFFFF
+ red: int = 0xE23636
@dataclass
@@ -192,6 +193,7 @@ def status(stat):
"Europe/Sofia",
"Europe/Tallinn",
"Europe/Vilnius",
+ "Europe/Tbilisi",
"Asia/Baghdad",
"Asia/Kuwait",
"Africa/Nairobi",
@@ -201,7 +203,6 @@ def status(stat):
"Asia/Baku",
"Europe/Volgograd",
"Asia/Muscat",
- "Asia/Tbilisi",
"Asia/Yerevan",
"Asia/Kabul",
"Asia/Karachi",
diff --git a/utils/DBhandlers.py b/utils/DBhandlers.py
index a3dfd30..3391760 100644
--- a/utils/DBhandlers.py
+++ b/utils/DBhandlers.py
@@ -2,7 +2,7 @@
import random
import time
-from typing import List, Literal, Optional, TYPE_CHECKING, Dict
+from typing import List, Literal, Optional, TYPE_CHECKING, Dict, TypeVar
from utils.CONSTANTS import timings
from utils.cache import AsyncTTL
@@ -21,6 +21,35 @@
if TYPE_CHECKING:
from utils.bot import OGIROID
+Key = TypeVar("Key", int, str)
+
+
+class BaseModal:
+ async def save(self):
+ pass
+
+ async def delete(self):
+ pass
+
+
+class RocksDBHandler:
+ def __init__(self, bot: "OGIROID"):
+ self.bot = bot
+
+ async def update(self, key: Key, values: dict[Key, Key]):
+ """get a model from the database, update it based on key then update it based off of values then put it back"""
+ values = list(values.items())
+
+ modal: BaseModal = await self.get(key)
+ for key, value in values:
+ modal.__setattr__(key, value)
+
+ await modal.save()
+
+ async def get(self, key: Key, key2: Optional[Key] = None):
+ """get a model from the database and if key2 is provided just return that"""
+ pass
+
class ConfigHandler:
def __init__(self, bot: "OGIROID", db):
@@ -62,39 +91,47 @@ def __init__(self, bot: "OGIROID", db):
self.db = db
self.cache = AsyncTTL(timings.MINUTE * 4)
- async def get_user(self, user_id: int) -> FlagQuizUser:
- user = await self.cache.get(str(user_id))
+ async def get_user(self, user_id: int, guild_id: int) -> FlagQuizUser:
+ # get cache by combining user_id and guild_id
+ user = await self.cache.get(str(user_id) + str(guild_id))
if user is not None:
return user
- elif await self.exists(user_id):
+ elif await self.exists(user_id, guild_id):
+ # not prone to injection since it's just id's
async with self.db.execute(
- f"SELECT * FROM flag_quizz WHERE user_id = {user_id}"
+ f"SELECT * FROM flag_quizz WHERE user_id = {user_id} AND guild_id = {guild_id}"
) as cur:
rawUserData = await cur.fetchone()
user = FlagQuizUser(*rawUserData)
- await self.cache.set(str(user_id), user)
+ # set unique index by combining user_id and guild_id
+ await self.cache.set(str(user_id) + str(guild_id), user)
return user
else:
raise UserNotFound
- async def exists(self, user_id: int):
+ async def exists(self, user_id: int, guild_id: int) -> bool:
async with self.db.execute(
- f"SELECT EXISTS(SELECT 1 FROM flag_quizz WHERE user_id=?)", [user_id]
+ f"SELECT EXISTS(SELECT 1 FROM flag_quizz WHERE user_id=? AND guild_id = ?)",
+ [user_id, guild_id],
) as cur:
return bool((await cur.fetchone())[0])
- async def get_leaderboard(self, order_by="correct"):
+ async def get_leaderboard(
+ self, order_by="correct", guild_id: int = None
+ ) -> List[FlagQuizUser]:
leaderboard = []
async with self.db.execute(
- f"SELECT user_id, tries, correct, completed FROM flag_quizz ORDER BY {order_by} DESC LIMIT 10"
+ f"SELECT user_id, tries, correct, completed, guild_id FROM flag_quizz WHERE guild_id = {guild_id} ORDER BY {order_by} DESC LIMIT 10"
) as cur:
async for row in cur:
leaderboard.append(FlagQuizUser(*row))
if len(leaderboard) == 0:
raise UsersNotFound
leaderboard = sorted(
- leaderboard, key=lambda x: x.correct + (x.completed * 199), reverse=True
+ leaderboard,
+ key=lambda x: x.correct + (x.completed * 199),
+ reverse=True,
) # line might fail lol idk
return leaderboard
@@ -104,12 +141,13 @@ async def add_data(
tries: int,
correct: int,
user: Optional[FlagQuizUser] = None,
- ) -> FlagQuizUser:
+ guild_id: int = None,
+ ) -> FlagQuizUser or None:
if user is not None:
try:
- user = await self.get_user(user_id)
+ user = await self.get_user(user_id, guild_id)
except UserNotFound:
- await self.add_user(user_id, tries, correct)
+ await self.add_user(user_id, tries, correct, guild_id=guild_id)
return
if correct == 199:
@@ -120,19 +158,26 @@ async def add_data(
correct += user.correct
async with self.db.execute(
- f"UPDATE flag_quizz SET tries = {tries}, correct = {correct}, completed = {completed} WHERE user_id = {user_id}"
+ # not prone to injection since it's just id's
+ f"UPDATE flag_quizz SET tries = {tries}, correct = {correct}, completed = {completed} WHERE user_id = {user_id} AND guild_id = {guild_id}"
):
await self.db.commit()
- return FlagQuizUser(user_id, tries, correct, completed)
+ return FlagQuizUser(user_id, tries, correct, completed, guild_id)
- async def add_user(self, user_id: int, tries: int = 0, correct: int = 0):
+ async def add_user(
+ self,
+ user_id: int,
+ tries: int = 0,
+ correct: int = 0,
+ guild_id: int = None,
+ ):
if correct == 199:
completed = 1
else:
completed = 0
async with self.db.execute(
- f"INSERT INTO flag_quizz (user_id, tries, correct, completed) VALUES ({user_id}, {tries}, {correct}, {completed})"
+ f"INSERT INTO flag_quizz (user_id, tries, correct, completed, guild_id) VALUES ({user_id}, {tries}, {correct}, {completed}, {guild_id})"
):
await self.db.commit()
@@ -187,7 +232,9 @@ async def load_blacklist(self):
blacklist.append(BlacklistedUser(*row).fix_db_types())
if len(blacklist) == 0:
raise BlacklistNotFound
- print(f"[BLACKLIST] {len(blacklist)} blacklisted users found and loaded")
+ print(
+ f"[BLACKLIST] {len(blacklist)} blacklisted users found and loaded"
+ )
self.blacklist = blacklist
async def get(self, user_id: int) -> BlacklistedUser:
@@ -215,7 +262,9 @@ async def add(
async def remove(self, user_id: int):
"""Removes a user from the blacklist"""
- await self.db.execute(f"DELETE FROM blacklist WHERE user_id = ?", [user_id])
+ await self.db.execute(
+ f"DELETE FROM blacklist WHERE user_id = ?", [user_id]
+ )
await self.db.commit()
self.blacklist.remove(await self.get_user(user_id))
await self.cache.remove(user_id)
@@ -230,7 +279,9 @@ async def blacklisted(self, user_id: int) -> bool:
else:
return False
- async def edit_flags(self, user_id: int, bot: bool, tickets: bool, tags: bool):
+ async def edit_flags(
+ self, user_id: int, bot: bool, tickets: bool, tags: bool
+ ):
"""Edits the flags (blacklist perms) of a user"""
await self.db.execute(
f"UPDATE blacklist SET bot = ?, tickets = ?, tags = ? WHERE user_id = ?",
@@ -248,7 +299,8 @@ async def edit_flags(self, user_id: int, bot: bool, tickets: bool, tags: bool):
async def edit_reason(self, user_id: int, reason: str):
"""Edits the blacklist reason of a user"""
await self.db.execute(
- f"UPDATE blacklist SET reason = ? WHERE user_id = ?", [reason, user_id]
+ f"UPDATE blacklist SET reason = ? WHERE user_id = ?",
+ [reason, user_id],
)
await self.db.commit()
indx = await self.get_user_index(user_id)
@@ -260,7 +312,8 @@ async def edit_reason(self, user_id: int, reason: str):
async def edit_expiry(self, user_id: int, expires: int):
"""Edits when the blacklist expires of a user"""
await self.db.execute(
- f"UPDATE blacklist SET expires = ? WHERE user_id = ?", [expires, user_id]
+ f"UPDATE blacklist SET expires = ? WHERE user_id = ?",
+ [expires, user_id],
)
await self.db.commit()
indx = await self.get_user_index(user_id)
@@ -281,7 +334,6 @@ def __init__(self, bot: "OGIROID", db):
self.session = self.bot.session
self.names = {"tags": [], "aliases": []}
self.cache = AsyncTTL(timings.DAY / 2) # cache tags for 12 hrs
- # self.pool = self.bot.pool todo re-add
async def startup(self):
await self.bot.wait_until_ready()
@@ -301,7 +353,9 @@ async def get_tag_from_cache(self, name):
name = await self.get_name(name)
return await self.cache.get(name)
- async def exists(self, name, exception: TagException, should: bool) -> bool:
+ async def exists(
+ self, name, exception: TagException, should: bool
+ ) -> bool:
"""Returns True if the tag exists"""
name = name.casefold()
if await self.cache.exists(name):
@@ -327,13 +381,15 @@ async def create(self, name, content, owner):
)
await self.db.commit()
self.names["tags"].append(name)
- await self.cache.add(name, Tag(name, content, owner, int(time.time()), 0))
+ await self.cache.add(
+ name, Tag(name, content, owner, int(time.time()), 0)
+ )
async def get(self, name, /, force: bool = False) -> Tag:
"""
Returns the tag object of the tag with the given name or alias
args:
- name: the name of the tag
+ name: the name or alias of the tag
force: if True, will ignore the cache and get the tag from the database
"""
name = await self.get_name(name)
@@ -344,7 +400,9 @@ async def get(self, name, /, force: bool = False) -> Tag:
else:
await self.cache.add(name, await self.get(name, force=True))
- _cur = await self.db.execute("SELECT * FROM tags WHERE tag_id= ?", [name])
+ _cur = await self.db.execute(
+ "SELECT * FROM tags WHERE tag_id = ? ", (name,)
+ )
raw = await _cur.fetchone()
if raw is None:
return
@@ -391,7 +449,8 @@ async def rename(self, name, new_name):
name = await self.get_name(name)
await self.update(name, "tag_id", new_name)
async with self.db.execute(
- f"UPDATE tag_relations SET tag_id = ? WHERE tag_id = ?", [new_name, name]
+ f"UPDATE tag_relations SET tag_id = ? WHERE tag_id = ?",
+ [new_name, name],
):
await self.db.commit()
@@ -404,12 +463,13 @@ async def transfer(self, name, new_owner: int):
async def increment_views(self, name):
name = await self.get_name(name)
+
tag = await self.cache.get(name, default=False)
if tag:
tag.views += 1
await self.cache.set(name, tag)
await self.db.execute(
- "UPDATE tags SET views = views + 1 WHERE tag_id = ?", [name]
+ f"UPDATE tags SET views = {tag.views} WHERE tag_id = ?", [name]
)
await self.db.commit()
@@ -425,7 +485,10 @@ async def get_top(self, limit=10):
return tags
async def get_tags_by_owner(
- self, owner: int, limit=10, orderby: Literal["views", "created_at"] = "views"
+ self,
+ owner: int,
+ limit=10,
+ orderby: Literal["views", "created_at"] = "views",
):
tags = []
async with self.db.execute(
@@ -441,10 +504,12 @@ async def count(self) -> int:
async with self.db.execute("SELECT COUNT(*) FROM tags") as cur:
return int(tuple(await cur.fetchone())[0])
- async def get_name(self, name_or_alias):
+ async def get_name(self, name_or_alias: str | tuple):
"""gets the true name of a tag (not the alias)"""
+ if isinstance(name_or_alias, tuple):
+ return await self.get_name(name_or_alias[0])
- name_or_alias = name_or_alias.casefold()
+ name_or_alias = name_or_alias.casefold() # todo fix.
if name_or_alias in self.names["tags"]:
return name_or_alias # it's a tag
_cur = await self.db.execute(
@@ -453,7 +518,7 @@ async def get_name(self, name_or_alias):
value = await _cur.fetchone()
if value is None:
raise TagNotFound(name_or_alias)
- return value
+ return value[0]
async def add_alias(self, name, alias):
name = await self.get_name(name)
@@ -463,7 +528,8 @@ async def add_alias(self, name, alias):
elif len(aliases) > 10:
raise AliasLimitReached
await self.db.execute(
- "INSERT INTO tag_relations (tag_id, alias) VALUES (?, ?)", [name, alias]
+ "INSERT INTO tag_relations (tag_id, alias) VALUES (?, ?)",
+ [name, alias],
)
await self.db.commit()
self.names["aliases"].append(alias)
@@ -474,7 +540,8 @@ async def remove_alias(self, name, alias):
if alias not in (await self.get_aliases(name)):
raise AliasNotFound
await self.db.execute(
- "DELETE FROM tag_relations WHERE tag_id = ? AND alias = ?", [name, alias]
+ "DELETE FROM tag_relations WHERE tag_id = ? AND alias = ?",
+ [name, alias],
)
await self.db.commit()
self.names["aliases"].remove(alias)
@@ -489,10 +556,14 @@ async def remove_aliases(self, name):
for alias in aliases:
self.names["aliases"].remove(alias)
await self.cache.delete(alias)
- await self.db.execute("DELETE FROM tag_relations WHERE tag_id = ?", [name])
+ await self.db.execute(
+ "DELETE FROM tag_relations WHERE tag_id = ?", [name]
+ )
await self.db.commit()
- async def get_aliases(self, name: Optional = None) -> List[str] | TagNotFound:
+ async def get_aliases(
+ self, name: Optional = None
+ ) -> List[str] | TagNotFound:
if not name:
async with self.db.execute("SELECT * FROM tag_relations") as cur:
content = await cur.fetchall()
@@ -587,7 +658,9 @@ async def remove_messages(self, message_id: int):
"DELETE FROM reaction_roles WHERE message_id = ?", [message_id]
)
await self.db.commit()
- self.messages = [msg for msg in self.messages if msg.message_id != message_id]
+ self.messages = [
+ msg for msg in self.messages if msg.message_id != message_id
+ ]
class WarningHandler:
@@ -604,35 +677,46 @@ async def get_warning(self, warning_id: int) -> Optional[WarningModel]:
return None
return WarningModel(*content)
- async def get_warnings(self, user_id: int) -> List[WarningModel]:
+ async def get_warnings(
+ self, user_id: int, guild_id: int
+ ) -> List[WarningModel]:
warnings = []
async with self.db.execute(
- "SELECT * FROM warnings WHERE user_id = ?", [user_id]
+ "SELECT * FROM warnings WHERE user_id = ? AND guild_id = ?",
+ [user_id, guild_id],
) as cur:
async for row in cur:
warnings.append(WarningModel(*row))
return warnings
- async def create_warning(self, user_id: int, reason: str, moderator_id: int):
+ async def create_warning(
+ self, user_id: int, reason: str, moderator_id: int, guild_id: int
+ ):
await self.db.execute(
- "INSERT INTO warnings (user_id, reason, moderator_id) VALUES (?, ?, ?)",
- [user_id, reason, moderator_id],
+ "INSERT INTO warnings (user_id, reason, moderator_id, guild_id) VALUES (?, ?, ?, ?)",
+ [user_id, reason, moderator_id, guild_id],
)
await self.db.commit()
return True
- async def remove_all_warnings(self, user_id: int) -> bool:
- warnings = await self.get_warnings(user_id)
+ async def remove_all_warnings(self, user_id: int, guild_id: int) -> bool:
+ warnings = await self.get_warnings(user_id, guild_id)
if len(warnings) == 0:
return False
- await self.db.execute("DELETE FROM warnings WHERE user_id = ?", [user_id])
+ await self.db.execute(
+ "DELETE FROM warnings WHERE user_id = ? AND guild_id = ?",
+ [user_id, guild_id],
+ )
await self.db.commit()
- async def remove_warning(self, warning_id: int) -> bool:
+ async def remove_warning(self, warning_id: int, guild_id: int) -> bool:
warning = await self.get_warning(warning_id)
if warning is None:
return False
- await self.db.execute("DELETE FROM warnings WHERE warning_id = ?", [warning_id])
+ await self.db.execute(
+ "DELETE FROM warnings WHERE warning_id = ? AND guild_id = ?",
+ [warning_id, guild_id],
+ )
await self.db.commit()
return True
@@ -662,7 +746,9 @@ async def delete_user(self, user_id: int) -> bool:
user = await self.get_user(user_id)
if user is None:
raise UserNotFound
- await self.db.execute("DELETE FROM birthday WHERE user_id = ?", [user_id])
+ await self.db.execute(
+ "DELETE FROM birthday WHERE user_id = ?", [user_id]
+ )
await self.db.commit()
return True
@@ -714,7 +800,9 @@ async def delete_user(self, user_id: int) -> bool:
user = await self.get_user(user_id)
if user is None:
raise UserNotFound
- await self.db.execute("DELETE FROM timezone WHERE user_id = ?", [user_id])
+ await self.db.execute(
+ "DELETE FROM timezone WHERE user_id = ?", [user_id]
+ )
await self.db.commit()
return True
diff --git a/utils/assorted.py b/utils/assorted.py
index 865bb05..5803079 100644
--- a/utils/assorted.py
+++ b/utils/assorted.py
@@ -4,7 +4,9 @@
def traceback_maker(err, advance: bool = True):
"""A way to debug your code anywhere"""
_traceback = "".join(traceback.format_tb(err.__traceback__))
- error = "```py\n{1}{0}: {2}\n```".format(type(err).__name__, _traceback, err)
+ error = "```py\n{1}{0}: {2}\n```".format(
+ type(err).__name__, _traceback, err
+ )
return error if advance else f"{type(err).__name__}: {err}"
diff --git a/utils/bot.py b/utils/bot.py
index 6b01518..3add0a4 100644
--- a/utils/bot.py
+++ b/utils/bot.py
@@ -1,10 +1,8 @@
import asyncio
-import json
from datetime import datetime
from os import listdir
import aiosqlite
-import asyncpg
import disnake
from disnake import ApplicationCommandInteraction, OptionType
from disnake.ext import commands
@@ -23,10 +21,11 @@
class OGIROID(commands.InteractionBot):
def __init__(self, *args, **kwargs):
-
super().__init__(
intents=disnake.Intents.all(),
- command_sync_flags=commands.CommandSyncFlags(sync_commands_debug=True),
+ command_sync_flags=commands.CommandSyncFlags(
+ sync_commands_debug=True
+ ),
*args,
**kwargs,
)
@@ -37,7 +36,6 @@ def __init__(self, *args, **kwargs):
self.commands_ran = {}
self.total_commands_ran = 0
self.db = None
- self.pool: asyncpg.Pool = None
self.blacklist: BlacklistHandler = None
self.add_app_command_check(
self.blacklist_check, slash_commands=True, call_once=True
@@ -107,7 +105,9 @@ async def on_ready(self):
"--------------------------------------------------------------------------------"
)
print("Bot is ready! Logged in as: " + self.user.name)
- print("Bot devs: HarryDaDev | FreebieII | JasonLovesDoggo | Levani")
+ print(
+ "Bot devs: HarryDaDev | FreebieII | JasonLovesDoggo | Levani"
+ )
print(f"Bot version: {__VERSION__}")
print(
"--------------------------------------------------------------------------------"
@@ -126,18 +126,11 @@ async def _setup(self):
self.blacklist: BlacklistHandler = BlacklistHandler(self, self.db)
await self.blacklist.startup()
- async def ensure_db_uri_can_run(self) -> bool:
- connection: asyncpg.Connection = await asyncpg.connect(
- user=self.config.Database.user,
- password=self.config.Database.password,
- database=self.config.Database.database,
- host=self.config.Database.host,
- port=self.config.Database.port,
- )
- await connection.close()
- return True
+ async def load_db(self):
+ pass
async def start(self, *args, **kwargs):
+ await self.load_db()
async with aiosqlite.connect("data.db") as self.db:
await self.db.executescript(SETUP_SQL)
# run the db migrations in /migrations
@@ -145,37 +138,8 @@ async def start(self, *args, **kwargs):
if file.endswith(".sql"):
with open(f"migrations/{file}", "r") as migration_sql:
await self.db.executescript(migration_sql.read())
- # self.pool: asyncpg.Pool = await self.create_pool() todo re-add
await super().start(*args, **kwargs)
- async def create_pool(self) -> asyncpg.Pool:
- def _encode_jsonb(value):
- return json.dumps(value)
-
- def _decode_jsonb(value):
- return json.loads(value)
-
- async def init(con):
- await con.set_type_codec(
- "jsonb",
- schema="pg_catalog",
- encoder=_encode_jsonb,
- decoder=_decode_jsonb,
- format="text",
- )
-
- return await asyncpg.create_pool(
- user=self.config.Database.user,
- password=self.config.Database.password,
- database=self.config.Database.database,
- host=self.config.Database.host,
- port=self.config.Database.port,
- init=init,
- command_timeout=60,
- max_size=20,
- min_size=20,
- )
-
@property
def ready_(self):
return self._ready_
diff --git a/utils/checks.py b/utils/checks.py
index 05865da..d09f534 100644
--- a/utils/checks.py
+++ b/utils/checks.py
@@ -3,7 +3,12 @@
def is_dev():
- devs = [511724576674414600, 662656158129192961, 963860161976467498]
+ devs = [
+ 511724576674414600,
+ 662656158129192961,
+ 963860161976467498,
+ 627450451297566733,
+ ]
def predicate(inter: ApplicationCommandInteraction):
return inter.author.id in devs
diff --git a/utils/config.py b/utils/config.py
index 80053c6..9cd0f10 100644
--- a/utils/config.py
+++ b/utils/config.py
@@ -46,7 +46,7 @@ class Tokens:
@dataclass
-class Database:
+class Database: # Todo switch to rockdb info
user: str = os.getenv("POSTGRES_USER")
password: str = os.getenv("POSTGRES_PASSWORD")
host: str = os.getenv("POSTGRES_HOST")
@@ -66,7 +66,9 @@ class Config:
elif os.getenv("DEVELOPMENT").lower() == "false":
Development: bool = False
else:
- raise ValueError("DEVELOPMENT in secrets.env must be set to true or false")
+ raise ValueError(
+ "DEVELOPMENT in secrets.env must be set to true or false"
+ )
colors = Colors
colours = colors
tokens = Tokens
diff --git a/utils/formats.py b/utils/formats.py
index 2d5115d..347ccea 100644
--- a/utils/formats.py
+++ b/utils/formats.py
@@ -2,7 +2,9 @@
from typing import Sequence, Optional
-def human_join(seq: Sequence[str], delim: str = ", ", final: str = "or") -> str:
+def human_join(
+ seq: Sequence[str], delim: str = ", ", final: str = "or"
+) -> str:
size = len(seq)
if size == 0:
return ""
diff --git a/utils/models.py b/utils/models.py
index 8918e66..172032c 100644
--- a/utils/models.py
+++ b/utils/models.py
@@ -36,7 +36,12 @@ def get_exp(self, level: int):
@property
def total_exp(self):
return sum(
- [exp for exp in [self.get_exp(lvl) for lvl in range(1, self.lvl + 1)]][::-1]
+ [
+ exp
+ for exp in [
+ self.get_exp(lvl) for lvl in range(1, self.lvl + 1)
+ ]
+ ][::-1]
+ [self.xp]
)
@@ -105,6 +110,7 @@ class FlagQuizUser:
tries: int
correct: int
completed: int
+ guild_id: int
@dataclass
@@ -121,6 +127,7 @@ class WarningModel:
user_id: int
moderator_id: int
reason: str
+ guild_id: int
@dataclass
diff --git a/utils/pagination.py b/utils/pagination.py
index e6e9529..cc8c812 100644
--- a/utils/pagination.py
+++ b/utils/pagination.py
@@ -81,8 +81,12 @@ async def next(self, button, inter):
"You cannot interact with these buttons.", ephemeral=True
)
elif self.CurrentEmbed == len(self.embeds) - 1:
- return await inter.send("you are already at the end", ephemeral=True)
- await inter.response.edit_message(embed=self.embeds[self.CurrentEmbed + 1])
+ return await inter.send(
+ "you are already at the end", ephemeral=True
+ )
+ await inter.response.edit_message(
+ embed=self.embeds[self.CurrentEmbed + 1]
+ )
self.CurrentEmbed += 1
except:
@@ -96,8 +100,12 @@ async def end(self, button, inter):
"You cannot interact with these buttons.", ephemeral=True
)
elif self.CurrentEmbed == len(self.embeds) - 1:
- return await inter.send("you are already at the end", ephemeral=True)
- await inter.response.edit_message(embed=self.embeds[len(self.embeds) - 1])
+ return await inter.send(
+ "you are already at the end", ephemeral=True
+ )
+ await inter.response.edit_message(
+ embed=self.embeds[len(self.embeds) - 1]
+ )
self.CurrentEmbed = len(self.embeds) - 1
except:
@@ -123,7 +131,6 @@ def __init__(
set_user: bool = False,
timeout: float = None,
):
-
self.controller = controller
self.author = author
self.CurrentEmbed = 0
@@ -184,7 +191,9 @@ async def create_page(self, inter, page_num) -> Embed:
inline=False,
)
- embed.set_footer(text=f"{inter.author}", icon_url=inter.author.avatar.url)
+ embed.set_footer(
+ text=f"{inter.author}", icon_url=inter.author.avatar.url
+ )
embed.timestamp = dt.datetime.now()
return embed
@@ -239,7 +248,9 @@ async def next(self, button, inter):
"You cannot interact with these buttons.", ephemeral=True
)
elif await self.at_last_page(inter):
- return await inter.send("you are already at the end", ephemeral=True)
+ return await inter.send(
+ "you are already at the end", ephemeral=True
+ )
await inter.response.edit_message(
embed=await self.create_page(inter, self.CurrentEmbed + 1)
)
@@ -255,7 +266,9 @@ async def end(self, button, inter):
"You cannot interact with these buttons.", ephemeral=True
)
elif await self.at_last_page(inter):
- return await inter.send("you are already at the end", ephemeral=True)
+ return await inter.send(
+ "you are already at the end", ephemeral=True
+ )
record_count = await self.controller.get_count(inter.guild.id)
if (
record_count % 10 == 0
diff --git a/utils/rankcard.py b/utils/rankcard.py
index f1c703f..e51399c 100644
--- a/utils/rankcard.py
+++ b/utils/rankcard.py
@@ -42,7 +42,9 @@ def __init__(self):
"STATUS_POS": (290, 330, -40, 20),
}
- async def getavatar(self, user: Union[disnake.User, disnake.Member]) -> bytes:
+ async def getavatar(
+ self, user: Union[disnake.User, disnake.Member]
+ ) -> bytes:
async with session.get(str(user.display_avatar.url)) as response:
avatarbytes = await response.read()
with Image.open(BytesIO(avatarbytes)) as im:
@@ -80,11 +82,12 @@ async def create_img(
# status
try:
-
if user.status == disnake.Status.online:
draw.ellipse(self.POSITIONS["STATUS_POS"], fill=(67, 181, 129))
elif user.status == disnake.Status.offline:
- draw.ellipse(self.POSITIONS["STATUS_POS"], fill=(116, 127, 141))
+ draw.ellipse(
+ self.POSITIONS["STATUS_POS"], fill=(116, 127, 141)
+ )
elif user.status == disnake.Status.dnd:
draw.ellipse(self.POSITIONS["STATUS_POS"], fill=(240, 71, 71))
elif user.status == disnake.Status.idle:
diff --git a/utils/shortcuts.py b/utils/shortcuts.py
index 86d470c..1a8753e 100644
--- a/utils/shortcuts.py
+++ b/utils/shortcuts.py
@@ -59,7 +59,9 @@ async def warning_embed(inter: ApplicationCommandInteraction, user, reason):
await inter.send(embed=emb)
-async def warnings_embed(inter: ApplicationCommandInteraction, member, warnings):
+async def warnings_embed(
+ inter: ApplicationCommandInteraction, member, warnings
+):
embed = disnake.Embed(title=f"{member.name}'s warnings", color=0xFFFFFF)
warning_string = ""
i = 0
@@ -90,7 +92,9 @@ async def sucEmb(inter: ApplicationCommandInteraction, text, ephemeral=True):
class QuickEmb:
- def __init__(self, inter: ApplicationCommandInteraction, msg, color=0xFFFFFF):
+ def __init__(
+ self, inter: ApplicationCommandInteraction, msg, color=0xFFFFFF
+ ):
self.inter = inter
self.msg = msg
self.color = color
diff --git a/utils/timeconversions.py b/utils/timeconversions.py
index 6c51529..242bac1 100644
--- a/utils/timeconversions.py
+++ b/utils/timeconversions.py
@@ -35,7 +35,9 @@ class ShortTime:
re.VERBOSE,
)
- def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None):
+ def __init__(
+ self, argument: str, *, now: Optional[datetime.datetime] = None
+ ):
match = self.compiled.fullmatch(argument)
if match is None or not match.group(0):
raise commands.BadArgument("invalid time provided")
@@ -52,7 +54,9 @@ async def convert(cls, ctx: Context, argument: str) -> Self:
class HumanTime:
calendar = pdt.Calendar(version=pdt.VERSION_CONTEXT_STYLE)
- def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None):
+ def __init__(
+ self, argument: str, *, now: Optional[datetime.datetime] = None
+ ):
now = now or datetime.datetime.utcnow()
dt, status = self.calendar.parseDT(argument, sourceTime=now)
if not status.hasDateOrTime:
@@ -78,7 +82,9 @@ async def convert(cls, ctx: Context, argument: str) -> Self:
class Time(HumanTime):
- def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None):
+ def __init__(
+ self, argument: str, *, now: Optional[datetime.datetime] = None
+ ):
try:
o = ShortTime(argument, now=now)
except Exception:
@@ -89,7 +95,9 @@ def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None):
class FutureTime(Time):
- def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None):
+ def __init__(
+ self, argument: str, *, now: Optional[datetime.datetime] = None
+ ):
super().__init__(argument, now=now)
if self._past:
@@ -106,7 +114,9 @@ def __init__(self, dt: datetime.datetime):
self.dt = dt
self.arg = ""
- async def ensure_constraints(self, now: datetime.datetime, remaining: str) -> None:
+ async def ensure_constraints(
+ self, now: datetime.datetime, remaining: str
+ ) -> None:
if self.dt.replace(tzinfo=None) < now.replace(tzinfo=None):
raise commands.BadArgument("This time is in the past.")
@@ -194,7 +204,9 @@ def format_relative(dt: datetime.datetime) -> str:
async def convert(argument: str) -> FriendlyTimeResult:
try:
if argument.casefold() == "never":
- return FriendlyTimeResult(datetime.datetime.fromtimestamp(9999999999))
+ return FriendlyTimeResult(
+ datetime.datetime.fromtimestamp(9999999999)
+ )
calendar = HumanTime.calendar
regex = ShortTime.compiled
now = datetime.datetime.fromtimestamp(int(time.time()))
@@ -251,7 +263,9 @@ async def convert(argument: str) -> FriendlyTimeResult:
if begin == 1:
# check if it's quoted:
if argument[0] != '"':
- raise commands.BadArgument("Expected quote before time input...")
+ raise commands.BadArgument(
+ "Expected quote before time input..."
+ )
if not (end < len(argument) and argument[end] == '"'):
raise commands.BadArgument(
"If the time is quoted, you must unquote it."
diff --git a/utils/wrappers/OpenWeatherMap.py b/utils/wrappers/OpenWeatherMap.py
index cddac3d..943f6e3 100644
--- a/utils/wrappers/OpenWeatherMap.py
+++ b/utils/wrappers/OpenWeatherMap.py
@@ -16,7 +16,9 @@ def __str__(self):
return "{} K".format(round(self.temperature, 2))
def __repr__(self):
- return "Temperature=({}, default_type=K)".format(round(self.temperature, 2))
+ return "Temperature=({}, default_type=K)".format(
+ round(self.temperature, 2)
+ )
@property
def kelvin(self):
@@ -68,7 +70,9 @@ def __init__(self, data):
self.country = data["sys"]["country"]
self.wind = Wind(data["wind"])
self.icon = data["weather"][0]["icon"]
- self.iconUrl = "https://openweathermap.org/img/wn/{}@2x.png".format(self.icon)
+ self.iconUrl = "https://openweathermap.org/img/wn/{}@2x.png".format(
+ self.icon
+ )
self.temp = Temperature(data["main"]["temp"])
self.tempMin = Temperature(data["main"]["temp_min"])
self.tempMax = Temperature(data["main"]["temp_max"])
@@ -104,9 +108,7 @@ def __init__(self, key, session=None):
"""
self.apiKey = key
self.session = session or aiohttp.ClientSession()
- self.baseUrl = (
- "https://api.openweathermap.org/data/2.5/weather?{type}={query}&appid={key}"
- )
+ self.baseUrl = "https://api.openweathermap.org/data/2.5/weather?{type}={query}&appid={key}"
async def get(self, _type, query):
"""Get weather report."""