mirror of
https://github.com/UiO-Gaming/mustafa.git
synced 2026-11-05 13:56:48 +01:00
follow contribution guidelines
This commit is contained in:
19 files changed
+1092
-313
No files matched your search
+126
-30
@@ -10,8 +10,7 @@ from cogs.utils import embed_templates
|
||||
|
||||
|
||||
class Anime(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
"""View information about different media on Anilist"""
|
||||
|
||||
anilist = app_commands.Group(name='anilist', description='Hent informasjon fra Anilist')
|
||||
anilist_profile = app_commands.Group(parent=anilist, name='profil', description='Hent informasjon om en bruker på Anilist')
|
||||
@@ -22,12 +21,13 @@ class Anime(commands.Cog):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
color: The color string returned from the Anilist API
|
||||
color (str): The color string returned from the Anilist API
|
||||
|
||||
Returns
|
||||
----------
|
||||
(int): The color in hex for use in discord embeds
|
||||
"""
|
||||
|
||||
colors = {
|
||||
'blue': 0x3db4f2,
|
||||
'purple': 0xc063ff,
|
||||
@@ -37,6 +37,7 @@ class Anime(commands.Cog):
|
||||
'green': 0x4CCA51,
|
||||
'gray': 0x677B94
|
||||
}
|
||||
|
||||
return colors.get(color, 0x677B94)
|
||||
|
||||
def __convert_media_format(self, media_format: str) -> str:
|
||||
@@ -45,12 +46,13 @@ class Anime(commands.Cog):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
media_format: The english media format name returned from the Anilist API
|
||||
media_format (str): The english media format name returned from the Anilist API
|
||||
|
||||
Returns
|
||||
----------
|
||||
(str): The media format name in norwegian. If a translation doesn't exist it returns the english name
|
||||
"""
|
||||
|
||||
media_formats = {
|
||||
'TV': 'TV-Serie',
|
||||
'TV_SHORT': 'Kort TV-Serie',
|
||||
@@ -69,12 +71,13 @@ class Anime(commands.Cog):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
language_name: The english language name returned from the Anilist API
|
||||
language_name (str): The english language name returned from the Anilist API
|
||||
|
||||
Returns
|
||||
----------
|
||||
(str): The language name in norwegian. If a translation doesn't exist it returns the english name
|
||||
"""
|
||||
|
||||
languages = {
|
||||
'JAPANESE': 'Japansk',
|
||||
'ENGLISH': 'Engelsk',
|
||||
@@ -87,6 +90,7 @@ class Anime(commands.Cog):
|
||||
'HEBREW': 'Hebraisk',
|
||||
'HUNGARIAN': 'Ungarsk'
|
||||
}
|
||||
|
||||
return languages.get(language_name, language_name)
|
||||
|
||||
def __convert_role_names(self, role_name: str) -> str:
|
||||
@@ -95,7 +99,7 @@ class Anime(commands.Cog):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
role_name: The english role name returned from the Anilist API
|
||||
role_name (str): The english role name returned from the Anilist API
|
||||
|
||||
Returns
|
||||
----------
|
||||
@@ -118,18 +122,20 @@ class Anime(commands.Cog):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
status: The english status name returned from the Anilist API
|
||||
status (str): The english status name returned from the Anilist API
|
||||
|
||||
Returns
|
||||
----------
|
||||
(str): The status name in norwegian. If a translation doesn't exist it returns the english name
|
||||
"""
|
||||
|
||||
statuses = {
|
||||
'FINISHED': 'Fullt utgitt',
|
||||
'RELEASING': 'Pågående',
|
||||
'NOT_YET_RELEASED': 'Ikke utgitt enda',
|
||||
'CANCELLED': 'Kansellert'
|
||||
}
|
||||
|
||||
return statuses.get(status, status)
|
||||
|
||||
def __remove_html(self, text: str) -> str:
|
||||
@@ -144,8 +150,10 @@ class Anime(commands.Cog):
|
||||
----------
|
||||
(str): The input string without HTML tags
|
||||
"""
|
||||
|
||||
compiled = re.compile(r'<.*?>')
|
||||
clean_text = re.sub(compiled, '', text)
|
||||
|
||||
return clean_text
|
||||
|
||||
async def __request_anilist(self, interaction: discord.Interaction, query: str, variables: dict, key: str) -> tuple[dict, str] | tuple[None, None]:
|
||||
@@ -154,14 +162,16 @@ class Anime(commands.Cog):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
query: The GraphQL query
|
||||
variables: The variables for the query
|
||||
key: The key to return from the response
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
query (str): The GraphQL query
|
||||
variables (str): The variables for the query
|
||||
key (str): The key to return from the response
|
||||
|
||||
Returns
|
||||
----------
|
||||
(dict): The response from the Anilist API
|
||||
(tuple[dict, str] | tuple[None, None]): The response from the Anilist API
|
||||
"""
|
||||
|
||||
try:
|
||||
url = 'https://graphql.anilist.co'
|
||||
response = requests.post(url, json={'query': query, 'variables': variables}, timeout=10)
|
||||
@@ -181,12 +191,13 @@ class Anime(commands.Cog):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
media: The list of media returned from the Anilist API
|
||||
media (list): The list of media returned from the Anilist API
|
||||
|
||||
Returns
|
||||
----------
|
||||
(str): The constructed string
|
||||
"""
|
||||
|
||||
favorite_media = []
|
||||
for node in media:
|
||||
try:
|
||||
@@ -196,6 +207,7 @@ class Anime(commands.Cog):
|
||||
favorite_media.append(f'[{anime_name}]({anime_url}){nsfwtag}')
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
return ' | '.join(favorite_media)
|
||||
|
||||
def __construct_favorite_entity_string(self, entities: list, studio: bool = False) -> str:
|
||||
@@ -204,23 +216,26 @@ class Anime(commands.Cog):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
entity: The list of entities returned from the Anilist API
|
||||
entities (list): The list of entities returned from the Anilist API
|
||||
studio (bool): Whether the entities are studios or not
|
||||
|
||||
Returns
|
||||
----------
|
||||
(str): The constructed string
|
||||
"""
|
||||
|
||||
favortie_entities = []
|
||||
for entity in entities:
|
||||
try:
|
||||
if studio:
|
||||
entity_name = entity['name']
|
||||
else:
|
||||
entity_name = entity['name']["full"]
|
||||
entity_name = entity['name']['full']
|
||||
entity_url = entity['siteUrl']
|
||||
favortie_entities.append(f'[{entity_name}]({entity_url})')
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
return ' | '.join(favortie_entities)
|
||||
|
||||
def __construct_release_schedule_string(self, numbers: dict) -> str:
|
||||
@@ -235,16 +250,17 @@ class Anime(commands.Cog):
|
||||
----------
|
||||
(str): The constructed string
|
||||
"""
|
||||
|
||||
# Release and end date formatting
|
||||
if numbers['start_day'] != '?' and numbers['start_month'] != '?' and numbers['start_year'] != '?':
|
||||
release_date = datetime(numbers['start_year'], numbers['start_month'], numbers['start_day'])
|
||||
release_date = discord.utils.format_dt(release_date, style="d")
|
||||
release_date = discord.utils.format_dt(release_date, style='d')
|
||||
else:
|
||||
release_date = f'{numbers["start_day"]}.{numbers["start_month"]}.{numbers["start_year"]}'
|
||||
|
||||
if numbers['end_day'] != '?' and numbers['end_month'] != '?' and numbers['end_year'] != '?':
|
||||
end_date = datetime(numbers['end_year'], numbers['end_month'], numbers['end_day'])
|
||||
end_date = discord.utils.format_dt(end_date, style="d")
|
||||
if numbers["end_day"] != '?' and numbers["end_month"] != '?' and numbers["end_year"] != '?':
|
||||
end_date = datetime(numbers["end_year"], numbers["end_month"], numbers["end_day"])
|
||||
end_date = discord.utils.format_dt(end_date, style='d')
|
||||
else:
|
||||
end_date = f'{numbers["end_day"]}.{numbers["end_month"]}.{numbers["end_year"]}'
|
||||
|
||||
@@ -259,6 +275,15 @@ class Anime(commands.Cog):
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@anilist_profile.command(name='generelt', description='Viser informasjon om en Anilistprofil')
|
||||
async def anilist_profile_general(self, interaction: discord.Interaction, bruker: str):
|
||||
"""
|
||||
Shows general information about a user's Anilist profile
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
bruker (str): The user to get information about
|
||||
"""
|
||||
|
||||
# GraphQL
|
||||
query = """
|
||||
query ($name: String) {
|
||||
@@ -388,6 +413,15 @@ class Anime(commands.Cog):
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@anilist_profile.command(name='anime', description='Se statistikk om animetittingen til en bruker')
|
||||
async def anilist_profile_anime_stats(self, interaction: discord.Interaction, bruker: str):
|
||||
"""
|
||||
Shows anime viewing statistics from a user's Anilist profile
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
bruker (str): The user to get information about
|
||||
"""
|
||||
|
||||
# GraphQL
|
||||
query = """
|
||||
query ($name: String) {
|
||||
@@ -487,6 +521,15 @@ class Anime(commands.Cog):
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@anilist_profile.command(name='manga', description='Se statistikk om mangalesingen til en bruker')
|
||||
async def anilist_profile_manga_stats(self, interaction: discord.Interaction, bruker: str):
|
||||
"""
|
||||
Shows manga reading statistics from a user's Anilist profile
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
bruker (str): The user to get information about
|
||||
"""
|
||||
|
||||
# GraphQL
|
||||
query = """
|
||||
query ($name: String) {
|
||||
@@ -588,8 +631,17 @@ class Anime(commands.Cog):
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@anilist.command(name='anime', description='Hent informasjon om en anime')
|
||||
async def anilist_anime(self, interaction: discord.Interaction, navn: str):
|
||||
"""
|
||||
Shows information about an anime
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
navn (str): The name of the anime to fetch information about
|
||||
"""
|
||||
|
||||
# GraphQL
|
||||
query = '''
|
||||
query = """
|
||||
query ($search: String, $isMain: Boolean) {
|
||||
Media (search: $search, type: ANIME) {
|
||||
siteUrl
|
||||
@@ -642,7 +694,7 @@ class Anime(commands.Cog):
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
"""
|
||||
variables = {
|
||||
'search': navn,
|
||||
'isMain': True
|
||||
@@ -747,7 +799,16 @@ class Anime(commands.Cog):
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@anilist.command(name='manga', description='Hent informasjon om en manga')
|
||||
async def anilist_manga(self, interaction: discord.Interaction, navn: str):
|
||||
query = '''
|
||||
"""
|
||||
Shows information about a manga
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
navn (str): The name of the manga to fetch information about
|
||||
"""
|
||||
|
||||
query = """
|
||||
query ($search: String) {
|
||||
Media (search: $search, type: MANGA) {
|
||||
siteUrl
|
||||
@@ -794,7 +855,7 @@ class Anime(commands.Cog):
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
"""
|
||||
variables = {
|
||||
'search': navn
|
||||
}
|
||||
@@ -880,7 +941,16 @@ class Anime(commands.Cog):
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@anilist.command(name='karakter', description='Hent informasjon om en karakter')
|
||||
async def anilist_character(self, interaction: discord.Interaction, navn: str):
|
||||
query = '''
|
||||
"""
|
||||
Shows information about a character
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
navn (str): The name of the character to fetch information about
|
||||
"""
|
||||
|
||||
query = """
|
||||
query ($search: String) {
|
||||
Character (search: $search) {
|
||||
name {
|
||||
@@ -915,7 +985,7 @@ class Anime(commands.Cog):
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
"""
|
||||
variables = {
|
||||
'search': navn
|
||||
}
|
||||
@@ -968,7 +1038,16 @@ class Anime(commands.Cog):
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@anilist.command(name='skaper', description='Hent informasjon om en skaper')
|
||||
async def anilist_creator(self, interaction: discord.Interaction, navn: str):
|
||||
query = '''
|
||||
"""
|
||||
Shows information about a creator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
navn (str): The name of the creator to fetch information about
|
||||
"""
|
||||
|
||||
query = """
|
||||
query ($search: String) {
|
||||
Staff(search: $search) {
|
||||
name {
|
||||
@@ -1007,7 +1086,7 @@ class Anime(commands.Cog):
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
"""
|
||||
variables = {
|
||||
'search': navn
|
||||
}
|
||||
@@ -1061,7 +1140,16 @@ class Anime(commands.Cog):
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@anilist.command(name='studio', description='Hent informasjon om et studio')
|
||||
async def anilist_studio(self, interaction: discord.Interaction, navn: str):
|
||||
query = '''
|
||||
"""
|
||||
Shows information about a studio
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
navn (str): The name of the studio to fetch information about
|
||||
"""
|
||||
|
||||
query = """
|
||||
query ($search: String) {
|
||||
Studio(search: $search) {
|
||||
name
|
||||
@@ -1081,7 +1169,7 @@ class Anime(commands.Cog):
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
"""
|
||||
variables = {
|
||||
'search': navn
|
||||
}
|
||||
@@ -1101,7 +1189,7 @@ class Anime(commands.Cog):
|
||||
popular_media.append(f'- [{media_name}]({media_url}){nsfwtag}')
|
||||
popular_media = '\n'.join(popular_media)
|
||||
|
||||
query2 = '''
|
||||
query2 = """
|
||||
query ($search: String) {
|
||||
Studio(search: $search) {
|
||||
media(sort: START_DATE_DESC) {
|
||||
@@ -1116,7 +1204,7 @@ class Anime(commands.Cog):
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
"""
|
||||
data = requests.post('https://graphql.anilist.co', json={'query': query2, 'variables': variables}, timeout=10).json()
|
||||
data = data['data']['Studio']
|
||||
|
||||
@@ -1146,4 +1234,12 @@ class Anime(commands.Cog):
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
await bot.add_cog(Anime(bot))
|
||||
+126
-41
@@ -10,12 +10,21 @@ from cogs.utils import discord_utils, embed_templates
|
||||
|
||||
|
||||
class Birthday(commands.Cog):
|
||||
"""Save the birthday of Discord users and allow them to see the birthdays of other users"""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): The bot instance
|
||||
"""
|
||||
|
||||
self.bot = bot
|
||||
self.cursor = self.bot.db_connection.cursor()
|
||||
|
||||
def init_db(self):
|
||||
"""Create the necessary tables for the birthday cog to work."""
|
||||
"""Create the necessary tables for the birthday cog to work"""
|
||||
|
||||
self.cursor.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS birthdays (
|
||||
@@ -27,22 +36,43 @@ class Birthday(commands.Cog):
|
||||
self.bot.db_connection.commit()
|
||||
|
||||
def __fetch_user_birthday(self, user_id: int) -> datetime | None:
|
||||
"""Fetch the birthday of a user from the database"""
|
||||
self.cursor.execute("SELECT birthday FROM birthdays WHERE discord_id = (%s)", (user_id,))
|
||||
"""
|
||||
Fetch the birthday of a user in the database
|
||||
|
||||
Parameters
|
||||
----------
|
||||
user_id (int): The Discord user ID
|
||||
|
||||
Returns
|
||||
----------
|
||||
(datetime | None): The birthday of the user
|
||||
"""
|
||||
|
||||
self.cursor.execute('SELECT birthday FROM birthdays WHERE discord_id = (%s)', (user_id,))
|
||||
result = self.cursor.fetchone()
|
||||
if result:
|
||||
birthday = result[0]
|
||||
return datetime(birthday.year, birthday.month, birthday.day)
|
||||
|
||||
def __fetch_user_next_birthday(self, user_id: int) -> datetime:
|
||||
"""Get date of next birthday of a user"""
|
||||
"""
|
||||
Get date of next birthday for a user
|
||||
|
||||
Parameters
|
||||
----------
|
||||
user_id (int): The Discord user ID
|
||||
|
||||
Returns
|
||||
----------
|
||||
(datetime): The date of the next birthday
|
||||
"""
|
||||
|
||||
self.cursor.execute(
|
||||
"""
|
||||
SELECT *, CAST(birthday + ((EXTRACT(YEAR FROM AGE(birthday)) + 1) * interval '1' YEAR) AS DATE) AS next_birthday
|
||||
FROM birthdays
|
||||
WHERE discord_id = %s
|
||||
""",
|
||||
(user_id,),
|
||||
""", (user_id,)
|
||||
)
|
||||
results = self.cursor.fetchone()
|
||||
if results:
|
||||
@@ -52,7 +82,14 @@ class Birthday(commands.Cog):
|
||||
return datetime.now() # This will never happen unless a database error occurs. Keeping the type checker happy
|
||||
|
||||
def __fetch_next_birthdays(self) -> list[tuple[int, datetime, datetime]]:
|
||||
"""Fetch the 5 first future birthdays of all users in the database"""
|
||||
"""
|
||||
Fetch the 5 first future birthdays of all users in the database
|
||||
|
||||
Returns
|
||||
----------
|
||||
(list[tuple[int, datetime, datetime]]): A list of tuples containing the user ID, the date of birth and the next birthday
|
||||
"""
|
||||
|
||||
self.cursor.execute(
|
||||
"""
|
||||
SELECT *, CAST(birthday + ((EXTRACT(YEAR FROM AGE(birthday)) + 1) * interval '1' YEAR) AS DATE) AS next_birthday
|
||||
@@ -71,8 +108,16 @@ class Birthday(commands.Cog):
|
||||
|
||||
return results
|
||||
|
||||
def __set_user_birthday(self, user_id: int, birthday: datetime) -> None:
|
||||
"""Iset the birthday of a user in the database. If it already exists, update it."""
|
||||
def __set_user_birthday(self, user_id: int, birthday: datetime):
|
||||
"""
|
||||
Set the birthday of a user in the database. If it already exists, update it.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
user_id (int): The Discord user ID
|
||||
birthday (datetime): The birthday of the user
|
||||
"""
|
||||
|
||||
try:
|
||||
self.cursor.execute(
|
||||
"""
|
||||
@@ -82,10 +127,10 @@ class Birthday(commands.Cog):
|
||||
self.bot.db_connection.commit()
|
||||
except psycopg2.errors.UniqueViolation:
|
||||
self.bot.db_connection.rollback()
|
||||
self.cursor.execute("UPDATE birthdays SET birthday = %s WHERE discord_id = %s", (birthday, user_id))
|
||||
self.cursor.execute('UPDATE birthdays SET birthday = %s WHERE discord_id = %s', (birthday, user_id))
|
||||
self.bot.db_connection.commit()
|
||||
|
||||
# @aiocron.crontab("0 0 * * *")
|
||||
# @aiocron.crontab('0 0 * * *')
|
||||
# async def __check_birthdays(self):
|
||||
# """Check if it's someone's birthday every day at midgnight and send a greeting if it is."""
|
||||
# await asyncio.sleep(1) # Prevent sending message before date has really changed
|
||||
@@ -106,54 +151,79 @@ class Birthday(commands.Cog):
|
||||
# for birthday in birthdays:
|
||||
# user = self.bot.get_user(birthday[0])
|
||||
# if user:
|
||||
# await channel.send(f"Gratulrer med dagen {user.mention}!")
|
||||
# await channel.send(f'Gratulrer med dagen {user.mention}!')
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@app_commands.command()
|
||||
async def settbursdag(self, interaction: discord.Interaction, dag: int, måned: int, år: int):
|
||||
"""Lagrer din bursdag i databasen"""
|
||||
@app_commands.command(name='settbursdag', description='Lagrer din bursdag i databasen')
|
||||
async def birthday_set(self, interaction: discord.Interaction, dag: int, måned: int, år: int):
|
||||
"""
|
||||
Allows the user to set their birthday in the database.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
dag (int): Day of the month
|
||||
måned (int): Month of the year
|
||||
år (int): Year
|
||||
"""
|
||||
|
||||
try:
|
||||
date = datetime(år, måned, dag)
|
||||
except ValueError:
|
||||
return await interaction.response.send_message(
|
||||
embed=embed_templates.error_fatal(interaction, text="ikke en gyldig dato, gjøk!"),
|
||||
embed=embed_templates.error_fatal(interaction, text='ikke en gyldig dato, gjøk!'),
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
if date.year < 1970:
|
||||
return await interaction.response.send_message(
|
||||
embed=embed_templates.error_fatal(interaction, text="Ok boomer, men nei. Hvorfor? Unix timestamps. Google it"),
|
||||
embed=embed_templates.error_fatal(interaction, text='Ok boomer, men nei. Hvorfor? Unix timestamps. Google it'),
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
if date > datetime.now():
|
||||
return await interaction.response.send_message(
|
||||
embed=embed_templates.error_fatal(interaction, text="Du kan ikke sette en fremtidig dato!"),
|
||||
embed=embed_templates.error_fatal(interaction, text='Du kan ikke sette en fremtidig dato!'),
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
self.__set_user_birthday(interaction.user.id, date)
|
||||
|
||||
embed = embed_templates.success(interaction, text=f"Bursdag satt til {discord.utils.format_dt(date, style='D')}")
|
||||
embed = embed_templates.success(interaction, text=f'Bursdag satt til {discord.utils.format_dt(date, style="D")}')
|
||||
await interaction.response.send_message(embed=embed)
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@app_commands.command()
|
||||
async def fjernbursdag(self, interaction: discord.Interaction):
|
||||
"""Fjerner bursdagen din fra databasen"""
|
||||
self.cursor.execute("DELETE FROM birthdays WHERE discord_id = (%s)", (interaction.user.id,))
|
||||
@app_commands.command(name='fjernbursdag', description='Fjerner bursdagen din fra databasen')
|
||||
async def birthday_remove(self, interaction: discord.Interaction):
|
||||
"""
|
||||
Removes the invoking user's birthday from the database
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
self.cursor.execute('DELETE FROM birthdays WHERE discord_id = (%s)', (interaction.user.id,))
|
||||
self.bot.db_connection.commit()
|
||||
|
||||
embed = embed_templates.success(interaction, text="Bursdag fjernet")
|
||||
embed = embed_templates.success(interaction, text='Bursdag fjernet')
|
||||
await interaction.response.send_message(embed=embed)
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@app_commands.command()
|
||||
async def bursdag(self, interaction: discord.Interaction, bruker: discord.Member | discord.User | None = None):
|
||||
"""Viser bursdagen til en bruker. Om ingen er gitt, vises din egen bursdag."""
|
||||
@app_commands.command(name='bursdag', description='Viser bursdagen til en bruker. Om ingen er gitt, vises din egen')
|
||||
async def birthday_show(self, interaction: discord.Interaction, bruker: discord.Member | discord.User | None = None):
|
||||
"""
|
||||
Shows the birthday of a user. If none is given, shows the invoking user's one.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
bruker (discord.Member | discord.User | None): The user to show the birthday of. Defaults to None.
|
||||
"""
|
||||
|
||||
if not bruker:
|
||||
bruker = interaction.user
|
||||
|
||||
@@ -161,7 +231,7 @@ class Birthday(commands.Cog):
|
||||
|
||||
if not user:
|
||||
return await interaction.response.send_message(
|
||||
embed=embed_templates.error_fatal(interaction, text="Brukeren har ikke registrert bursdagen sin")
|
||||
embed=embed_templates.error_fatal(interaction, text='Brukeren har ikke registrert bursdagen sin')
|
||||
)
|
||||
|
||||
# Current age information
|
||||
@@ -176,24 +246,31 @@ class Birthday(commands.Cog):
|
||||
embed = discord.Embed(description=bruker.mention, color=discord_utils.get_color(bruker))
|
||||
embed.set_thumbnail(url=bruker.display_avatar)
|
||||
embed.set_author(name=bruker.name, icon_url=bruker.display_avatar)
|
||||
embed.add_field(name="Bursdag", value=discord.utils.format_dt(birthday, style="D"))
|
||||
embed.add_field(name="Hvor gammel?", value=f"{years_old} år\n({days_old} dager)", inline=False)
|
||||
embed.add_field(name="Neste bursdag om", value=f"{next_birthday_days} dager", inline=False)
|
||||
embed.add_field(name='Bursdag', value=discord.utils.format_dt(birthday, style='D'))
|
||||
embed.add_field(name='Hvor gammel?', value=f'{years_old} år\n({days_old} dager)', inline=False)
|
||||
embed.add_field(name='Neste bursdag om', value=f'{next_birthday_days} dager', inline=False)
|
||||
embed_templates.default_footer(interaction, embed)
|
||||
await interaction.response.send_message(embed=embed)
|
||||
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@app_commands.command()
|
||||
async def kommendebursdager(self, interaction: discord.Interaction):
|
||||
"""Se opptil de 5 neste bursdagene i UiO Gaming"""
|
||||
@app_commands.command(name='kommendebursdager', description='Viser en liste over de opptil 5 kommende bursdager i serveren')
|
||||
async def birthdays_upcoming(self, interaction: discord.Interaction):
|
||||
"""
|
||||
Lists up to 5 upcoming birthdays of users in the server.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
next_birthdays = self.__fetch_next_birthdays()
|
||||
|
||||
if not next_birthdays:
|
||||
return await interaction.response.send_message(embed=embed_templates.error_fatal(interaction, text="Ingen bursdager"))
|
||||
return await interaction.response.send_message(embed=embed_templates.error_fatal(interaction, text='Ingen bursdager'))
|
||||
|
||||
birthday_string = ""
|
||||
birthday_string = ''
|
||||
for user in next_birthdays:
|
||||
user_id, _, next_birthday = user
|
||||
try:
|
||||
@@ -201,17 +278,25 @@ class Birthday(commands.Cog):
|
||||
except (discord.NotFound, discord.HTTPException):
|
||||
continue
|
||||
|
||||
timestamp = discord.utils.format_dt(next_birthday, style="D")
|
||||
relative_timestamp = discord.utils.format_dt(next_birthday, style="R")
|
||||
birthday_string += f"{discord_user.name}#{discord_user.discriminator} - {timestamp} ({relative_timestamp})\n"
|
||||
timestamp = discord.utils.format_dt(next_birthday, style='D')
|
||||
relative_timestamp = discord.utils.format_dt(next_birthday, style='R')
|
||||
birthday_string += f'{discord_user.name}#{discord_user.discriminator} - {timestamp} ({relative_timestamp})\n'
|
||||
|
||||
if not birthday_string:
|
||||
return await interaction.response.send_message(embed=embed_templates.error_fatal(interaction, text="Ingen bursdager"))
|
||||
return await interaction.response.send_message(embed=embed_templates.error_fatal(interaction, text='Ingen bursdager'))
|
||||
|
||||
embed = discord.Embed(title="Kommende bursdager", description=birthday_string)
|
||||
embed = discord.Embed(title='Kommende bursdager', description=birthday_string)
|
||||
embed_templates.default_footer(interaction, embed)
|
||||
await interaction.response.send_message(embed=embed)
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
await bot.add_cog(Birthday(bot))
|
||||
+45
-10
@@ -11,14 +11,29 @@ from cogs.utils import embed_templates
|
||||
|
||||
|
||||
class BotInfo(commands.Cog):
|
||||
"""View information about the bot"""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): The bot instance
|
||||
"""
|
||||
|
||||
self.bot = bot
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True, external_emojis=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@app_commands.command()
|
||||
@app_commands.command(name='botinfo', description='Se informajson om botten')
|
||||
async def botinfo(self, interaction: discord.Interaction):
|
||||
"""Viser informasjon om bot"""
|
||||
"""
|
||||
View information about the bot
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
# Dev user info
|
||||
dev = await self.bot.fetch_user(170506717140877312)
|
||||
|
||||
@@ -78,9 +93,15 @@ class BotInfo(commands.Cog):
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@app_commands.command()
|
||||
async def oppetid(self, interaction: discord.Interaction):
|
||||
"""Viser hvor lenge bot har vært kjørende"""
|
||||
@app_commands.command(name='oppetid', description='Se hvor lenge botten har kjørt')
|
||||
async def uptime(self, interaction: discord.Interaction):
|
||||
"""
|
||||
View the bot's uptime
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
embed = discord.Embed(color=interaction.client.user.color)
|
||||
embed.add_field(name='🔌 Oppetid', value=self.__get_uptime())
|
||||
@@ -89,9 +110,16 @@ class BotInfo(commands.Cog):
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@app_commands.command()
|
||||
@app_commands.command(name='ping', description='Se botten sin nåværende ping')
|
||||
async def ping(self, interaction: discord.Interaction):
|
||||
"""Viser bot sin ping"""
|
||||
"""
|
||||
View the bot's ping
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
embed = discord.Embed(color=interaction.client.user.color)
|
||||
embed.add_field(
|
||||
name='📶 Ping',
|
||||
@@ -108,19 +136,18 @@ class BotInfo(commands.Cog):
|
||||
----------
|
||||
(int) The bot's ping in milliseconds
|
||||
"""
|
||||
|
||||
return int(self.bot.latency * 1000)
|
||||
|
||||
def __get_uptime(self) -> str:
|
||||
"""
|
||||
Returns the current uptime of the bot in string format
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
Returns
|
||||
----------
|
||||
(str) The bot's uptime in human readable format
|
||||
"""
|
||||
|
||||
now = time()
|
||||
diff = int(now - self.bot.uptime)
|
||||
days, remainder = divmod(diff, 24 * 60 * 60)
|
||||
@@ -131,4 +158,12 @@ class BotInfo(commands.Cog):
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
await bot.add_cog(BotInfo(bot))
|
||||
@@ -69,7 +69,7 @@ class SocialCredit(commands.Cog):
|
||||
def add_new_citizen(func):
|
||||
async def wrapper(*args, **kwargs):
|
||||
self = args[0]
|
||||
self.cursor.execute("SELECT user_id FROM social_credit WHERE user_id = %s", (args[1],))
|
||||
self.cursor.execute('SELECT user_id FROM social_credit WHERE user_id = %s', (args[1],))
|
||||
if not self.cursor.fetchone():
|
||||
self._add_citizen(args[1])
|
||||
await func(*args, **kwargs)
|
||||
@@ -100,9 +100,9 @@ class SocialCredit(commands.Cog):
|
||||
async def get_leaderboard(self, ctx, page, worst=False):
|
||||
|
||||
if worst:
|
||||
keyword = "ASC"
|
||||
keyword = 'ASC'
|
||||
else:
|
||||
keyword = "DESC"
|
||||
keyword = 'DESC'
|
||||
|
||||
self.cursor.execute(
|
||||
f"""
|
||||
@@ -113,13 +113,13 @@ class SocialCredit(commands.Cog):
|
||||
result = self.cursor.fetchall()
|
||||
|
||||
if not result:
|
||||
return await ctx.send(embed=embed_templates.error_fatal(ctx, "Ingen brukere er registrert i databasen"))
|
||||
return await ctx.send(embed=embed_templates.error_fatal(ctx, 'Ingen brukere er registrert i databasen'))
|
||||
|
||||
output_list = []
|
||||
for i, row in enumerate(result):
|
||||
user = ctx.guild.get_member(row[0])
|
||||
if user:
|
||||
output_list.append(f"{i+1}. {user.name}#{user.discriminator} - `{row[1]}` poeng")
|
||||
output_list.append(f'{i+1}. {user.name}#{user.discriminator} - `{row[1]}` poeng')
|
||||
|
||||
return misc_utils.paginator(output_list, int(page))
|
||||
|
||||
@@ -134,7 +134,7 @@ class SocialCredit(commands.Cog):
|
||||
|
||||
@add_new_citizen
|
||||
async def social_punishment(self, user_id, points):
|
||||
print(f"{points} points deducted from {user_id}")
|
||||
print(f'{points} points deducted from {user_id}')
|
||||
self.cursor.execute(
|
||||
"""
|
||||
UPDATE social_credit
|
||||
@@ -147,7 +147,7 @@ class SocialCredit(commands.Cog):
|
||||
|
||||
@add_new_citizen
|
||||
async def social_reward(self, user_id, points):
|
||||
print(f"{points} points given to {user_id}")
|
||||
print(f'{points} points given to {user_id}')
|
||||
self.cursor.execute(
|
||||
"""
|
||||
UPDATE social_credit
|
||||
@@ -164,17 +164,17 @@ class SocialCredit(commands.Cog):
|
||||
if not bruker:
|
||||
bruker = ctx.author
|
||||
|
||||
self.cursor.execute("SELECT * FROM social_credit WHERE user_id = %s", (bruker.id,))
|
||||
self.cursor.execute('SELECT * FROM social_credit WHERE user_id = %s', (bruker.id,))
|
||||
result = self.cursor.fetchone()
|
||||
|
||||
if not result:
|
||||
return await ctx.send(
|
||||
embed=embed_templates.error_fatal(ctx, f"{bruker.mention} er ikke registrert i databasen")
|
||||
embed=embed_templates.error_fatal(ctx, f'{bruker.mention} er ikke registrert i databasen')
|
||||
)
|
||||
|
||||
db_user = CreditUser(*result)
|
||||
|
||||
embed = discord.Embed(description=(f"{bruker.mention} har `{db_user.credit_score}` social credits"))
|
||||
embed = discord.Embed(description=(f'{bruker.mention} har `{db_user.credit_score}` social credits'))
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command()
|
||||
@@ -185,13 +185,13 @@ class SocialCredit(commands.Cog):
|
||||
page = 0
|
||||
|
||||
page_data = await self.get_leaderboard(ctx, page)
|
||||
output_content = "\n".join(page_data["page_content"])
|
||||
output_content = '\n'.join(page_data['page_content'])
|
||||
|
||||
embed = discord.Embed(title="Social credit leaderboard", description=output_content)
|
||||
embed.set_footer(text=f"Side {page_data['page']}/{page_data['pagecount']}")
|
||||
embed = discord.Embed(title='Social credit leaderboard', description=output_content)
|
||||
embed.set_footer(text=f'Side {page_data['page']}/{page_data['pagecount']}')
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(aliases=["skammeliste"])
|
||||
@commands.command(aliases=['skammeliste'])
|
||||
async def shamelist(self, ctx, page=0):
|
||||
try:
|
||||
page = int(page)
|
||||
@@ -199,13 +199,13 @@ class SocialCredit(commands.Cog):
|
||||
page = 0
|
||||
|
||||
page_data = await self.get_leaderboard(ctx, page, worst=True)
|
||||
output_content = "\n".join(page_data["page_content"])
|
||||
output_content = '\n'.join(page_data['page_content'])
|
||||
|
||||
embed = discord.Embed(title="Social credit skammeliste", description=output_content)
|
||||
embed.set_footer(text=f"Side {page_data['page']}/{page_data['pagecount']}")
|
||||
embed = discord.Embed(title='Social credit skammeliste', description=output_content)
|
||||
embed.set_footer(text=f'Side {page_data['page']}/{page_data['pagecount']}')
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.Cog.listener("on_message")
|
||||
@commands.Cog.listener('on_message')
|
||||
async def on_message(self, message):
|
||||
if message.author.bot:
|
||||
return
|
||||
@@ -246,12 +246,12 @@ class SocialCredit(commands.Cog):
|
||||
for mention in message.mentions:
|
||||
await self.social_punishment(mention.id, 10)
|
||||
|
||||
@commands.Cog.listener("on_reaction_add")
|
||||
@commands.Cog.listener('on_reaction_add')
|
||||
async def on_star_add(self, reaction, user):
|
||||
if user.bot:
|
||||
return
|
||||
|
||||
if reaction.emoji == "⭐":
|
||||
if reaction.emoji == '⭐':
|
||||
if reaction.message.author == user:
|
||||
await self.social_punishment(user.id, 100)
|
||||
else:
|
||||
@@ -259,12 +259,12 @@ class SocialCredit(commands.Cog):
|
||||
await self.social_punishment(user.id, (len(reaction.message.reactions) - 1) * 25)
|
||||
await self.social_reward(user.id, 25 * len(reaction.message.reactions))
|
||||
|
||||
@commands.Cog.listener("on_reaction_remove")
|
||||
@commands.Cog.listener('on_reaction_remove')
|
||||
async def on_star_remove(self, reaction, user):
|
||||
if user.bot:
|
||||
return
|
||||
|
||||
if reaction.emoji == "⭐":
|
||||
if reaction.emoji == '⭐':
|
||||
if len(reaction.message.reactions) >= 3:
|
||||
await self.social_punishment(user.id, 25)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ class Vær(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@aiocron.crontab("0 6 * * *")
|
||||
@aiocron.crontab('0 6 * * *')
|
||||
async def forecast():
|
||||
|
||||
dev = await self.bot.fetch_user(162337748781367296)
|
||||
@@ -19,8 +19,8 @@ class Vær(commands.Cog):
|
||||
|
||||
weather = Yr(location_name='Norway/Oslo/Oslo/Oslo', forecast_link='forecast_hour_by_hour')
|
||||
|
||||
embed = discord.Embed(title=":white_sun_small_cloud: Værmelding for Oslo :white_sun_small_cloud:")
|
||||
embed.description = "*Værmeldingen levert til deg av Petter*"
|
||||
embed = discord.Embed(title=':white_sun_small_cloud: Værmelding for Oslo :white_sun_small_cloud:')
|
||||
embed.description = '*Værmeldingen levert til deg av Petter*'
|
||||
embed.set_author(name=dev.name, icon_url=dev.display_avatar)
|
||||
|
||||
half_hour = False
|
||||
@@ -35,11 +35,11 @@ class Vær(commands.Cog):
|
||||
rain = data['precipitation']
|
||||
regn = rain['@value']
|
||||
temperatur = temp['@value']
|
||||
embed.add_field(name=f"kl {klokkeslett}", value=f"{temperatur}°C - {regn}mm")
|
||||
embed.add_field(name=f'kl {klokkeslett}', value=f'{temperatur}°C - {regn}mm')
|
||||
klokkeslett += 1
|
||||
half_hour = True
|
||||
|
||||
await channel.send("RISE AND SHINE GAMERS!", embed=embed)
|
||||
await channel.send('RISE AND SHINE GAMERS!', embed=embed)
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
|
||||
@@ -6,7 +6,7 @@ class Wiki(commands.Cog):
|
||||
@commands.command()
|
||||
async def wiki_search(self, ctx, *search_term):
|
||||
|
||||
search_term = " ".join(search_term)
|
||||
search_term = ' '.join(search_term)
|
||||
|
||||
search = wikipedia.search(search_term)
|
||||
search = search[0]
|
||||
@@ -15,7 +15,7 @@ class Wiki(commands.Cog):
|
||||
summary = wikipedia.summary(search_term, sentences=5)
|
||||
url = search.url
|
||||
|
||||
embed = discord.Embed(title=f"Wikipediasøk for {search_term}", url=url)
|
||||
embed = discord.Embed(title=f'Wikipediasøk for {search_term}', url=url)
|
||||
embed.add_field(name=search_term, value=summary)
|
||||
|
||||
embed_templates.default_footer(ctx,embed)
|
||||
|
||||
+121
-26
@@ -9,14 +9,31 @@ from cogs.utils import embed_templates
|
||||
|
||||
|
||||
class DevTools(commands.Cog):
|
||||
"""Commands for developers to mangage cogs and other functionality of the bot"""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): The bot instance
|
||||
"""
|
||||
|
||||
self.bot = bot
|
||||
|
||||
@commands.is_owner()
|
||||
@commands.bot_has_permissions(embed_links=True)
|
||||
@commands.command()
|
||||
@commands.command(name='custommsg', description='Send en melding til hvilken som helst kanal på hvilken som helst server botten er i')
|
||||
async def custommsg(self, ctx: commands.Context, channel: int, *text: tuple[str]):
|
||||
"""Send a message to a specified channel"""
|
||||
"""
|
||||
Send a message to any channel on any server the bot is in
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
channel (int): The channel ID to send the message to
|
||||
text (tuple[str]): The text to send
|
||||
"""
|
||||
|
||||
# Send message to the requested channel
|
||||
channel = self.bot.get_channel(channel)
|
||||
custommessage = ' '.join(text)
|
||||
@@ -30,9 +47,19 @@ class DevTools(commands.Cog):
|
||||
@commands.is_owner()
|
||||
@commands.bot_has_permissions(embed_links=True)
|
||||
@commands.cooldown(1, 10, commands.BucketType.guild)
|
||||
@commands.command()
|
||||
@commands.command(name='changepresence', description='Endre botten sin nåværende status')
|
||||
async def changepresence(self, ctx: commands.Context, activity_type: str, message: str, status_type: str):
|
||||
"""Changes the bot's presence status"""
|
||||
"""
|
||||
Change the bot's presence status
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
activity_type (str): The type of activity to set the bot's status to
|
||||
message (str): The message to set the bot's status to
|
||||
status_type (str): The type of status to set the bot's status to
|
||||
"""
|
||||
|
||||
activities = {
|
||||
'playing': 0,
|
||||
'listening': 2,
|
||||
@@ -52,14 +79,23 @@ class DevTools(commands.Cog):
|
||||
status=status_type,
|
||||
activity=discord.Activity(type=activity_type, name=message)
|
||||
)
|
||||
|
||||
embed = discord.Embed(color=ctx.me.color, description='Endret Presence!')
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.is_owner()
|
||||
@commands.bot_has_permissions(embed_links=True, add_reactions=True)
|
||||
@commands.command()
|
||||
@commands.command(name='leave', description='Forlater en server. Om ingen er gitt, forlat der det ble sendt fra')
|
||||
async def leave(self, ctx: commands.Context, *guild_id: int):
|
||||
"""Leaves a specified guild"""
|
||||
"""
|
||||
Make bot leave a specified guild. If no guild is specified, leave the guild the command was sent from
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
guild_id (int): The ID of the guild to leave
|
||||
"""
|
||||
|
||||
# If no guild id is specified, leave the current guild
|
||||
guild_id = guild_id if guild_id else ctx.guild.id
|
||||
|
||||
@@ -75,7 +111,7 @@ class DevTools(commands.Cog):
|
||||
await confirmation_msg.add_reaction('✅')
|
||||
|
||||
# Check confirmation
|
||||
def comfirm(reaction, user):
|
||||
def comfirm(reaction: discord.Reaction, user: discord.Member):
|
||||
return user == ctx.author and str(reaction.emoji) == '✅'
|
||||
|
||||
try:
|
||||
@@ -93,9 +129,16 @@ class DevTools(commands.Cog):
|
||||
|
||||
@commands.is_owner()
|
||||
@commands.bot_has_permissions(embed_links=True)
|
||||
@commands.command()
|
||||
@commands.command(name='publicip', description='Hent den offentlige IP-adressen til serveren botten kjører på')
|
||||
async def publicip(self, ctx: commands.Context):
|
||||
"""Sends WAN IP-address. inb4 I leak my IP-address"""
|
||||
"""
|
||||
Sends WAN IP-address. Inb4 I leak my IP-address
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
data = requests.get('https://wtfismyip.com/json', timeout=10).json()
|
||||
ip = data['YourFuckingIPAddress']
|
||||
location = data['YourFuckingLocation']
|
||||
@@ -107,15 +150,30 @@ class DevTools(commands.Cog):
|
||||
|
||||
@commands.is_owner()
|
||||
@commands.bot_has_permissions(embed_links=True)
|
||||
@commands.group()
|
||||
@commands.group(name='cogs', description='Administrer cogs')
|
||||
async def cogs(self, ctx: commands.Context):
|
||||
"""Cog management commands"""
|
||||
"""
|
||||
Cog management commands
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
if not ctx.invoked_subcommand:
|
||||
await ctx.send_help(ctx.command)
|
||||
|
||||
@cogs.command()
|
||||
async def unload(self, ctx: commands.Context, cog: str):
|
||||
"""Disables a specified cog"""
|
||||
@cogs.command(name='unload', description='Avslutt en cog')
|
||||
async def cogs_unload(self, ctx: commands.Context, cog: str):
|
||||
"""
|
||||
Disables a specified cog
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
cog (str): The name of the cog to disable
|
||||
"""
|
||||
|
||||
for file in listdir('./src/cogs'):
|
||||
if file.endswith('.py'):
|
||||
name = file[:-3]
|
||||
@@ -127,9 +185,17 @@ class DevTools(commands.Cog):
|
||||
embed = embed_templates.error_fatal(ctx, text=f'{cog} does not exist')
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@cogs.command()
|
||||
async def load(self, ctx: commands.Context, cog: str):
|
||||
"""Enables a speicifed cog"""
|
||||
@cogs.command(name='load', description='Aktiver en cog')
|
||||
async def cogs_load(self, ctx: commands.Context, cog: str):
|
||||
"""
|
||||
Enables a speicifed cog
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
cog (str): The name of the cog to enable
|
||||
"""
|
||||
|
||||
for file in listdir('./src/cogs'):
|
||||
if file.endswith('.py'):
|
||||
name = file[:-3]
|
||||
@@ -141,9 +207,16 @@ class DevTools(commands.Cog):
|
||||
embed = embed_templates.error_fatal(ctx, text=f'{cog} does not exist')
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@cogs.command()
|
||||
async def reload(self, ctx: commands.Context, cog: str):
|
||||
"""Reloads a specified cog"""
|
||||
@cogs.command(name='reload', description='Last inn en cog på nytt')
|
||||
async def cogs_reload(self, ctx: commands.Context, cog: str):
|
||||
"""
|
||||
Reloads a specified cog
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
cog (str): The name of the cog to reload
|
||||
"""
|
||||
for file in listdir('./src/cogs'):
|
||||
if file.endswith('.py'):
|
||||
name = file[:-3]
|
||||
@@ -155,9 +228,16 @@ class DevTools(commands.Cog):
|
||||
embed = embed_templates.error_fatal(ctx, text=f'{cog} does not exist')
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@cogs.command()
|
||||
async def reloadunloaded(self, ctx: commands.Context):
|
||||
"""Reloads all cogs, including previously disabled ones"""
|
||||
@cogs.command(name='reloadunloaded', description='Last inn alle cogs på nytt, selv de som ikke er lastet inn')
|
||||
async def cogs_reloadunloaded(self, ctx: commands.Context):
|
||||
"""
|
||||
Reloads all cogs, including previously disabled ones
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
# Unload all cogs
|
||||
for file in listdir('./src/cogs'):
|
||||
if file.endswith('.py'):
|
||||
@@ -173,9 +253,16 @@ class DevTools(commands.Cog):
|
||||
embed = discord.Embed(color=ctx.me.color, description='Reloaded all cogs')
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@cogs.command()
|
||||
async def reloadall(self, ctx: commands.Context):
|
||||
"""Reloads all previously enabled cogs"""
|
||||
@cogs.command(name='reloadall', description='Last inn alle cogs på nytt')
|
||||
async def cogs_reloadall(self, ctx: commands.Context):
|
||||
"""
|
||||
Reloads all previously enabled cogs
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
for file in listdir('./src/cogs'):
|
||||
if file.endswith('.py'):
|
||||
name = file[:-3]
|
||||
@@ -186,4 +273,12 @@ class DevTools(commands.Cog):
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
await bot.add_cog(DevTools(bot))
|
||||
+53
-6
@@ -9,13 +9,28 @@ from cogs.utils.misc_utils import ignore_exception
|
||||
|
||||
|
||||
class Errors(commands.Cog):
|
||||
"""Error handlers for commands"""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): The bot instance
|
||||
"""
|
||||
|
||||
self.bot = bot
|
||||
bot.tree.on_error = self.on_app_command_error
|
||||
bot.tree.on_error = self.on_app_command_error # Set error handler for slash commands
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_command(self, ctx: commands.Context):
|
||||
"""Logs prefix command execution metadata"""
|
||||
"""
|
||||
Logs prefix command execution metadata
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
self.bot.logger.info(
|
||||
f'{"❌ " if ctx.command_failed else "✔ "} {ctx.command} | ' +
|
||||
f'{ctx.author.name}#{ctx.author.discriminator} ({ctx.author.id}) | ' +
|
||||
@@ -24,7 +39,15 @@ class Errors(commands.Cog):
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_app_command_completion(self, interaction: discord.Interaction, command: app_commands.Command | app_commands.ContextMenu):
|
||||
"""Logs slash command execution metadata"""
|
||||
"""
|
||||
Logs slash command execution metadata
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
command (app_commands.Command | app_commands.ContextMenu): Command object
|
||||
"""
|
||||
|
||||
self.bot.logger.info(
|
||||
f'{"❌ " if interaction.command_failed else "✔ "} {command.name} | ' +
|
||||
f'{interaction.user.name}#{interaction.user.discriminator} ({interaction.user.id}) | ' +
|
||||
@@ -33,7 +56,15 @@ class Errors(commands.Cog):
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_command_error(self, ctx: commands.Context, error: commands.CommandError):
|
||||
"""Handle prefix command errors"""
|
||||
"""
|
||||
Handle prefix command errors
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
error (commands.CommandError): Eror context object
|
||||
"""
|
||||
|
||||
# Reset cooldown if command throws AttributeError
|
||||
with ignore_exception(AttributeError):
|
||||
self.bot.get_command(f'{ctx.command}').reset_cooldown(ctx)
|
||||
@@ -83,7 +114,7 @@ class Errors(commands.Cog):
|
||||
text = 'Denne kommandoen kan bare utføres i servere'
|
||||
return await ctx.send(text)
|
||||
except discord.errors.Forbidden: # Thrown if bot is blocked by the user or if the user has closed their DMs
|
||||
print("DM Blocked!")
|
||||
print('DM Blocked!')
|
||||
|
||||
elif isinstance(error, commands.DisabledCommand):
|
||||
pass
|
||||
@@ -98,7 +129,15 @@ class Errors(commands.Cog):
|
||||
self.bot.logger.error(''.join(traceback.format_exception(type(error), error, error.__traceback__)))
|
||||
|
||||
async def on_app_command_error(self, interaction: discord.Interaction, error: app_commands.AppCommandError):
|
||||
"""Handle slash command errors"""
|
||||
"""
|
||||
Handle slash command errors
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
error (app_commands.AppCommandError): Eror context object
|
||||
"""
|
||||
|
||||
# Log command usage, just in case
|
||||
await self.on_app_command_completion(interaction, interaction.command)
|
||||
|
||||
@@ -131,4 +170,12 @@ class Errors(commands.Cog):
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
await bot.add_cog(Errors(bot))
|
||||
+68
-5
@@ -2,44 +2,107 @@ from discord.ext import commands
|
||||
|
||||
|
||||
class Fun(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
"""Simple commands that return short strings for the memes"""
|
||||
|
||||
@commands.cooldown(1, 2, commands.BucketType.guild)
|
||||
@commands.command()
|
||||
@commands.command(name='norskeuniversiteter')
|
||||
async def norskeuniversiteter(self, ctx: commands.Context):
|
||||
"""
|
||||
Sends a link to university meme image album
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
await ctx.send('<https://imgur.com/a/uGopaSq>')
|
||||
|
||||
@commands.cooldown(1, 2, commands.BucketType.guild)
|
||||
@commands.command()
|
||||
@commands.command(name='ifi')
|
||||
async def ifi(self, ctx: commands.Context):
|
||||
"""
|
||||
ifi meme 1
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
await ctx.send('https://i.imgur.com/ypyK1mi.jpg')
|
||||
|
||||
@commands.cooldown(1, 2, commands.BucketType.guild)
|
||||
@commands.command()
|
||||
@commands.command(name='ifi2')
|
||||
async def ifi2(self, ctx: commands.Context):
|
||||
"""
|
||||
ifi meme 2
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
await ctx.send('https://i.imgur.com/ZqgZEEA.jpg')
|
||||
|
||||
@commands.cooldown(1, 2, commands.BucketType.guild)
|
||||
@commands.command()
|
||||
async def ifi3(self, ctx: commands.Context):
|
||||
"""
|
||||
ifi meme 3
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
await ctx.send('https://i.imgur.com/Gx9DQE5.jpg')
|
||||
|
||||
@commands.cooldown(1, 2, commands.BucketType.guild)
|
||||
@commands.command()
|
||||
async def uio(self, ctx: commands.Context):
|
||||
"""
|
||||
uio meme 1
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
await ctx.send('https://i.imgur.com/188MoIV.jpg')
|
||||
|
||||
@commands.cooldown(1, 2, commands.BucketType.guild)
|
||||
@commands.command()
|
||||
async def ntnu(self, ctx: commands.Context):
|
||||
"""
|
||||
ntnu meme 1
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
await ctx.send('https://twitter.com/NTNU/status/970667413564993536')
|
||||
|
||||
@commands.cooldown(1, 2, commands.BucketType.guild)
|
||||
@commands.command()
|
||||
async def ntnu2(self, ctx: commands.Context):
|
||||
"""
|
||||
ntnu meme 2
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx (commands.Context): Context object
|
||||
"""
|
||||
|
||||
await ctx.send('https://i.imgur.com/h84fknj.jpg')
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
await bot.add_cog(Fun(bot))
|
||||
+24
-1
@@ -7,7 +7,15 @@ from discord.ext import commands
|
||||
|
||||
|
||||
class FunReplies(commands.Cog):
|
||||
"""Reply to messages that trigger certain key words/phrases"""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): The bot instance
|
||||
"""
|
||||
|
||||
self.bot = bot
|
||||
|
||||
# Cooldowns for trigger words
|
||||
@@ -24,7 +32,14 @@ class FunReplies(commands.Cog):
|
||||
}
|
||||
|
||||
async def reply_to_triggers(self, message: discord.Message):
|
||||
"""Replies to messages that trigger certain key words/phrases"""
|
||||
"""
|
||||
Replies to messages that trigger certain key words/phrases
|
||||
|
||||
Parameters
|
||||
----------
|
||||
message (discord.Message): Message object to check for triggers to
|
||||
"""
|
||||
|
||||
if message.author.bot:
|
||||
return
|
||||
|
||||
@@ -62,5 +77,13 @@ class FunReplies(commands.Cog):
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
bot.add_listener(FunReplies(bot).reply_to_triggers, 'on_message')
|
||||
await bot.add_cog(FunReplies(bot))
|
||||
+213
-28
@@ -8,24 +8,55 @@ from cogs.utils import discord_utils, embed_templates, misc_utils
|
||||
|
||||
|
||||
class Info(commands.Cog):
|
||||
"""View information about Discord object such as guilds, users, roles and channels"""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): The bot instance
|
||||
"""
|
||||
|
||||
self.bot = bot
|
||||
|
||||
guild_group = app_commands.Group(name="guild", description="Se ting om serveren")
|
||||
user_group = app_commands.Group(name="bruker", description="Se ting om brukeren")
|
||||
guild_group = app_commands.Group(name='guild', description='Se ting om serveren')
|
||||
user_group = app_commands.Group(name='bruker', description='Se ting om brukeren')
|
||||
|
||||
def __construct_role_string(self, roles: list[discord.Role]) -> str:
|
||||
"""Puts all roles except @everyone into a list and joins them to a string"""
|
||||
if not roles:
|
||||
return "**Ingen roller**"
|
||||
"""
|
||||
Puts all roles except @everyone into a list and joins them to a string
|
||||
|
||||
roles = [role.name for role in roles if role.name != "@everyone"]
|
||||
Parameters
|
||||
----------
|
||||
roles (list[discord.Role]): List of roles
|
||||
|
||||
Returns
|
||||
-------
|
||||
(str): String of roles
|
||||
"""
|
||||
|
||||
if not roles:
|
||||
return '**Ingen roller**'
|
||||
|
||||
roles = [role.name for role in roles if role.name != '@everyone']
|
||||
roles.reverse()
|
||||
|
||||
return ', '.join(roles)
|
||||
|
||||
def __construct_booster_string(self, interaction: discord.Interaction, join_method: callable = ', '.join) -> str:
|
||||
"""Joins all boosters into a string"""
|
||||
"""
|
||||
Joins all boosters into a string
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
join_method (callable): Function to join the boosters with
|
||||
|
||||
Returns
|
||||
-------
|
||||
(str): String of boosters
|
||||
"""
|
||||
|
||||
if not interaction.guild.premium_subscribers:
|
||||
return '**Ingen boostere**'
|
||||
|
||||
@@ -39,7 +70,18 @@ class Info(commands.Cog):
|
||||
return join_method(boosters)
|
||||
|
||||
def __construct_member_string(self, members: list[discord.Member]) -> str:
|
||||
"""Joins all name#discrim into a string"""
|
||||
"""
|
||||
Joins all name#discrim into a string
|
||||
|
||||
Parameters
|
||||
----------
|
||||
members (list[discord.Member]): List of members
|
||||
|
||||
Returns
|
||||
-------
|
||||
(str): String of members
|
||||
"""
|
||||
|
||||
if not members:
|
||||
return '**Ingen**'
|
||||
|
||||
@@ -48,7 +90,16 @@ class Info(commands.Cog):
|
||||
return ', '.join(members)
|
||||
|
||||
async def __send_as_txt_file(self, interaction: discord.Interaction, content: str, file_path: str):
|
||||
"""Sends a string as a txt file and deletes the file afterwards"""
|
||||
"""
|
||||
Sends a string as a txt file and deletes the file afterwards
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
content (str): String that's too long to send
|
||||
file_path (str): Path to file
|
||||
"""
|
||||
|
||||
# Create file
|
||||
with open(file_path, 'w', encoding='utf-8') as file:
|
||||
file.write(content)
|
||||
@@ -64,10 +115,18 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True, external_emojis=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@guild_group.command(name="info", description="Hent informasjon om en server")
|
||||
@guild_group.command(name='info', description='Hent informasjon om en server')
|
||||
async def guild_info(self, interaction: discord.Interaction):
|
||||
"""
|
||||
Sends general information about the guild
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
# Days since guild was created
|
||||
creation_date_timestamp = discord.utils.format_dt(interaction.guild.created_at, style="F")
|
||||
creation_date_timestamp = discord.utils.format_dt(interaction.guild.created_at, style='F')
|
||||
since_created_days = (interaction.created_at - interaction.guild.created_at).days
|
||||
days_ago = f'{since_created_days} dager' if since_created_days != 1 else f'{since_created_days} dag'
|
||||
|
||||
@@ -195,8 +254,16 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@guild_group.command(name="roller", description="Se rollene på serveren")
|
||||
@guild_group.command(name='roller', description='Se rollene på serveren')
|
||||
async def guild_roles(self, interaction: discord.Interaction):
|
||||
"""
|
||||
List all roles in the guild
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
roles = self.__construct_role_string(interaction.guild.roles)
|
||||
|
||||
# IF roles list is longer than 2048, create text file and send it
|
||||
@@ -211,8 +278,16 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@guild_group.command(name="boosters", description="Se boostere på serveren")
|
||||
@guild_group.command(name='boosters', description='Se boostere på serveren')
|
||||
async def guild_boosters(self, interaction: discord.Interaction):
|
||||
"""
|
||||
List all boosters in the guild
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
if len(interaction.guild.premium_subscribers) == 0:
|
||||
embed = embed_templates.error_warning(interaction, text='Serveren har ikke noen boosts :(')
|
||||
return await interaction.response.send_message(embed=embed)
|
||||
@@ -227,8 +302,16 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@guild_group.command(name="ikon", description="Hent serverens ikon")
|
||||
@guild_group.command(name='ikon', description='Hent serverens ikon')
|
||||
async def guild_icon(self, interaction: discord.Interaction):
|
||||
"""
|
||||
Get the guild icon
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
embed = discord.Embed(color=interaction.guild.me.color, description=f'[Lenke]({interaction.guild.icon})')
|
||||
embed.set_author(name=interaction.guild.name, icon_url=interaction.guild.icon)
|
||||
embed.set_image(url=interaction.guild.icon)
|
||||
@@ -238,8 +321,16 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@guild_group.command(name="splash", description="Hent serverens splash (bakgrunnsbilde på invitasjonsside)")
|
||||
@guild_group.command(name='splash', description='Hent serverens splash (bakgrunnsbilde på invitasjonsside)')
|
||||
async def guild_splash(self, interaction: discord.Interaction):
|
||||
"""
|
||||
Get the guild splash
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
if not interaction.guild.discovery_splash:
|
||||
embed = embed_templates.error_warning(interaction, text='Serveren har ikke en splash')
|
||||
return await interaction.response.send_message(embed=embed)
|
||||
@@ -253,8 +344,16 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@guild_group.command(name="banner", description="Hen serverens banner")
|
||||
@guild_group.command(name='banner', description='Hen serverens banner')
|
||||
async def guild_banner(self, interaction: discord.Interaction):
|
||||
"""
|
||||
Get the guild banner
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
if not interaction.guild.banner:
|
||||
embed = embed_templates.error_warning(interaction, text='Serveren har ikke et banner :(')
|
||||
return await interaction.response.send_message(embed=embed)
|
||||
@@ -268,14 +367,23 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@guild_group.command(name="rolle", description="Hent informasjon om en rolle på serveren")
|
||||
@guild_group.command(name='rolle', description='Hent informasjon om en rolle på serveren')
|
||||
async def guild_role(self, interaction: discord.Interaction, rolle: discord.Role):
|
||||
"""
|
||||
Get information about a role
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
rolle (discord.Role): Role to fetch information about
|
||||
"""
|
||||
|
||||
if rolle.name == '@everyone':
|
||||
embed = embed_templates.error_fatal(interaction, text='Skriv inn en annen rolle enn @everyone')
|
||||
return await interaction.response.send_message(embed=embed)
|
||||
|
||||
# Timestamp and days since creation
|
||||
created_at_timestamp = discord.utils.format_dt(rolle.created_at, style="F")
|
||||
created_at_timestamp = discord.utils.format_dt(rolle.created_at, style='F')
|
||||
since_created_days = (interaction.created_at - rolle.created_at).days
|
||||
|
||||
# List of members with the role
|
||||
@@ -302,8 +410,17 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@guild_group.command(name="tekstkanal", description="Hent informasjon om en tekstkanal")
|
||||
@guild_group.command(name='tekstkanal', description='Hent informasjon om en tekstkanal')
|
||||
async def guild_text_channel(self, interaction: discord.Interaction, kanal: discord.TextChannel):
|
||||
"""
|
||||
Get information about a text channel
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
kanal (discord.TextChannel): Text channel to fetch information about
|
||||
"""
|
||||
|
||||
members = self.__construct_member_string(kanal.members)
|
||||
if len(members) > 1024:
|
||||
members = 'For mange for å vise her'
|
||||
@@ -323,8 +440,17 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@guild_group.command(name="talekanal", description="Hent informasjon om en talekanal")
|
||||
@guild_group.command(name='talekanal', description='Hent informasjon om en talekanal')
|
||||
async def guild_voice_channel(self, interaction: discord.Interaction, kanal: discord.VoiceChannel):
|
||||
"""
|
||||
Get information about a voice channel
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
kanal (discord.VoiceChannel): Voice channel to fetch information about
|
||||
"""
|
||||
|
||||
embed = discord.Embed(color=interaction.guild.me.color, title=kanal.name, description=f'ID: {kanal.id}')
|
||||
embed.set_author(name=kanal.guild.name, icon_url=kanal.guild.icon)
|
||||
embed.add_field(name='Opprettet', value=discord.utils.format_dt(kanal.created_at, style='F'))
|
||||
@@ -352,17 +478,25 @@ class Info(commands.Cog):
|
||||
|
||||
# embed = discord.Embed(color=interaction.guild.me.color, title=emoji.name, description=f'ID: {emoji.id}')
|
||||
# embed.set_author(name=emoji.guild.name, icon_url=emoji.guild.icon)
|
||||
# embed.add_field(name='Opprettet', value=discord.utils.format_dt(emoji.created_at, style="F"))
|
||||
# embed.add_field(name='Opprettet', value=discord.utils.format_dt(emoji.created_at, style='F'))
|
||||
# embed.add_field(name='Animert', value='Ja' if emoji.animated else 'Nei')
|
||||
# embed.add_field(name='Lagt til av', value=emoji_creator)
|
||||
# embed.set_image(url=emoji.url)
|
||||
# embed_templates.default_footer(interaction, embed)
|
||||
# await interaction.response.send_message(embed=embed)
|
||||
|
||||
guild_oldest_group = app_commands.Group(name="eldst", description="Viser de eldste medlemmene på serveren", parent=guild_group)
|
||||
guild_oldest_group = app_commands.Group(name='eldst', description='Viser de eldste medlemmene på serveren', parent=guild_group)
|
||||
|
||||
def __construct_oldest_embed(self, paginator: misc_utils.Paginator, page: list, embed: discord.Embed) -> discord.Embed:
|
||||
"""Constructs the embed for the oldest commands"""
|
||||
"""
|
||||
Constructs the embed for the oldest commands
|
||||
|
||||
Parameters
|
||||
----------
|
||||
paginator (misc_utils.Paginator): Paginator dataclass
|
||||
page (list): List of members to display
|
||||
embed (discord.Embed): Embed to add fields to
|
||||
"""
|
||||
embed.description = '\n'.join(page)
|
||||
embed.set_footer(text=f'Side {paginator.current_page}/{paginator.total_page_count}')
|
||||
return embed
|
||||
@@ -370,8 +504,16 @@ class Info(commands.Cog):
|
||||
@commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@guild_oldest_group.command(name="lagd", description="Liste over de eldste brukerene på serveren basert på når de ble lagd")
|
||||
@guild_oldest_group.command(name='lagd', description='Liste over de eldste brukerene på serveren basert på når de ble lagd')
|
||||
async def guild_user_created_oldest(self, interaction: discord.Interaction):
|
||||
"""
|
||||
List the oldest users on the server based on when they were created
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
# Sort members by creation date
|
||||
members = sorted(interaction.guild.members, key=lambda m: m.created_at)
|
||||
|
||||
@@ -392,8 +534,16 @@ class Info(commands.Cog):
|
||||
@commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@guild_oldest_group.command(name="joined", description="Liste over de eldste brukerene på serveren basert på når de ble med")
|
||||
@guild_oldest_group.command(name='joined', description='Liste over de eldste brukerene på serveren basert på når de ble med')
|
||||
async def guild_user_joined_oldest(self, interaction: discord.Interaction):
|
||||
"""
|
||||
List the oldest users on the server based on when they joined
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
# Sort members by creation date
|
||||
members = sorted(interaction.guild.members, key=lambda m: m.joined_at)
|
||||
|
||||
@@ -414,8 +564,17 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True, external_emojis=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@user_group.command(name="info", description="Hent informasjon om en bruker")
|
||||
@user_group.command(name='info', description='Hent informasjon om en bruker')
|
||||
async def user_info(self, interaction: discord.Interaction, *, bruker: discord.Member | None = None):
|
||||
"""
|
||||
Get information about a user
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
bruker (discord.Member, optional): User to get information about. Defaults to None (invoker).
|
||||
"""
|
||||
|
||||
if not bruker:
|
||||
bruker = interaction.user
|
||||
|
||||
@@ -489,8 +648,17 @@ class Info(commands.Cog):
|
||||
@app_commands.guild_only()
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@user_group.command(name="roller", description="Hent roller til en bruker")
|
||||
@user_group.command(name='roller', description='Hent roller til en bruker')
|
||||
async def user_roles(self, interaction: discord.Interaction, bruker: discord.Member | None = None):
|
||||
"""
|
||||
Get roles of a user
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
bruker (discord.Member, optional): User to get roles of. Defaults to None (invoker).
|
||||
"""
|
||||
|
||||
if not bruker:
|
||||
bruker = interaction.user
|
||||
|
||||
@@ -507,8 +675,17 @@ class Info(commands.Cog):
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@user_group.command(name="avatar", description="Hent avatar til en bruker")
|
||||
@user_group.command(name='avatar', description='Hent avatar til en bruker')
|
||||
async def user_avatar(self, interaction: discord.Interaction, bruker: discord.User | discord.Member | None = None):
|
||||
"""
|
||||
Get avatar of a user
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
bruker (discord.User, optional): User to get avatar of. Defaults to None (invoker).
|
||||
"""
|
||||
|
||||
if not bruker:
|
||||
bruker = interaction.user
|
||||
|
||||
@@ -520,4 +697,12 @@ class Info(commands.Cog):
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
await bot.add_cog(Info(bot))
|
||||
+35
-11
@@ -8,13 +8,22 @@ from cogs.utils import embed_templates
|
||||
|
||||
|
||||
class MCWhitelist(commands.Cog):
|
||||
"""Stand alone cog for handling whitelisting of Discord users on the Minecraft server"""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): The bot instance
|
||||
"""
|
||||
|
||||
self.bot = bot
|
||||
self.cursor = self.bot.db_connection.cursor()
|
||||
self.init_db()
|
||||
|
||||
def init_db(self):
|
||||
"""Create the necessary tables for the mc_whitelist cog to work."""
|
||||
|
||||
self.cursor.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mc_whitelist (
|
||||
@@ -27,15 +36,22 @@ class MCWhitelist(commands.Cog):
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@app_commands.command()
|
||||
@app_commands.command(name='whitelist', description='Whitelist minecraftbrukeren din på serveren vår')
|
||||
async def whitelist(self, interaction: discord.Interaction, minecraftbrukernavn: str):
|
||||
"""Whitelist Minecraftbrukeren din på serveren vår"""
|
||||
"""
|
||||
Whitelist a minecraft user on the Minecraft server
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
minecraftbrukernavn (str): Minecraft username
|
||||
"""
|
||||
|
||||
# Fetch minecraft uuid from api
|
||||
data = requests.get(f"https://api.mojang.com/users/profiles/minecraft/{minecraftbrukernavn}", timeout=10).json()
|
||||
data = requests.get(f'https://api.mojang.com/users/profiles/minecraft/{minecraftbrukernavn}', timeout=10).json()
|
||||
if data.status_code != 200:
|
||||
return await interaction.response.send_message(
|
||||
embed=embed_templates.error_fatal(interaction, text=f"Brukeren `{minecraftbrukernavn}` finnes ikke på minecraft"),
|
||||
embed=embed_templates.error_fatal(interaction, text=f'Brukeren `{minecraftbrukernavn}` finnes ikke på minecraft'),
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
@@ -47,21 +63,21 @@ class MCWhitelist(commands.Cog):
|
||||
SELECT *
|
||||
FROM mc_whitelist
|
||||
WHERE minecraft_id = %s OR discord_id = %s
|
||||
""", (data["id"], interaction.user.id)
|
||||
""", (data['id'], interaction.user.id)
|
||||
)
|
||||
if self.cursor.fetchone():
|
||||
return await interaction.response.send_message(
|
||||
embed=embed_templates.error_fatal(
|
||||
interaction,
|
||||
text="Du har allerede whitelisted en bruker eller så er brukeren du oppga whitelisted"
|
||||
text='Du har allerede whitelisted en bruker eller så er brukeren du oppga whitelisted'
|
||||
)
|
||||
)
|
||||
|
||||
# Whitelist user on minecraft server
|
||||
# Unfortunately, this requires an active connection to the server, with correct credentials
|
||||
with MCRcon(host="127.0.0.1", password=self.bot.mc_rcon_password, port=25575) as mcr:
|
||||
mcr.command(f"whitelist add {data['name']}")
|
||||
mcr.command("whitelist reload")
|
||||
with MCRcon(host='127.0.0.1', password=self.bot.mc_rcon_password, port=25575) as mcr:
|
||||
mcr.command(f'whitelist add {data["name"]}')
|
||||
mcr.command('whitelist reload')
|
||||
|
||||
# Add user to db
|
||||
self.cursor.execute(
|
||||
@@ -69,16 +85,24 @@ class MCWhitelist(commands.Cog):
|
||||
INSERT INTO mc_whitelist (discord_id, minecraft_id)
|
||||
VALUES (%s, %s)
|
||||
""",
|
||||
(interaction.user.id, data["id"]),
|
||||
(interaction.user.id, data['id']),
|
||||
)
|
||||
self.bot.db_connection.commit()
|
||||
|
||||
await interaction.response.send_message(
|
||||
embed=embed_templates.success(
|
||||
interaction, text=f"`{data['name']}` er nå tilknyttet din discordbruker og whitelisted!"
|
||||
interaction, text=f'`{data["name"]}` er nå tilknyttet din discordbruker og whitelisted!'
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
await bot.add_cog(MCWhitelist(bot))
|
||||
+148
-70
@@ -14,21 +14,43 @@ from cogs.utils.misc_utils import ignore_exception
|
||||
|
||||
|
||||
class Misc(commands.Cog):
|
||||
"""Miscellaneous commands that don't fit anywhere else"""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): The bot instance
|
||||
"""
|
||||
|
||||
self.bot = bot
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@app_commands.command()
|
||||
@app_commands.command(name='weeb', description='Kjeft på weebs')
|
||||
async def weeb(self, interaction: discord.Interaction):
|
||||
"""Kjeft på weebs"""
|
||||
await interaction.response.send_message("<:sven:762725919604473866> Weebs 👉 <#803596668129509417>")
|
||||
"""
|
||||
Call out weebs
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
await interaction.response.send_message('<:sven:762725919604473866> Weebs 👉 <#803596668129509417>')
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@app_commands.command()
|
||||
@app_commands.command(name='kweeb', description='김정운, 최고도')
|
||||
async def kweeb(self, interaction: discord.Interaction):
|
||||
"""김정운, 최고도"""
|
||||
"""
|
||||
Call out kweebs
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
await interaction.response.send_message(
|
||||
"""
|
||||
Melding du nettopp sendte ga muligens følgende vibber for brukeren som brukte denne kommandoen:
|
||||
@@ -52,17 +74,24 @@ https://cdn.discordapp.com/attachments/674726496878723082/1042631569396990004/kw
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@app_commands.command()
|
||||
@app_commands.command(name='owo', description='Oversetter teksten din til owo (we_eb)')
|
||||
async def owo(self, interaction: discord.Interaction, tekst: str):
|
||||
"""Oversetter teksten din til owo (we_eb)"""
|
||||
"""
|
||||
Translate text into owo (we_eb)
|
||||
|
||||
owo_rules = {"r": "w", "l": "w", "R": "W", "L": "W", "n": "ny", "N": "Ny", "ove": "uv"}
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
tekst (str): Text to translate
|
||||
"""
|
||||
|
||||
owo_rules = {'r': 'w', 'l': 'w', 'R': 'W', 'L': 'W', 'n': 'ny', 'N': 'Ny', 'ove': 'uv'}
|
||||
for key, value in owo_rules.items():
|
||||
tekst = re.sub(key, value, tekst)
|
||||
# https://kaomoji.moe/
|
||||
|
||||
if len(tekst) >= 1000:
|
||||
embed = embed_templates.error_warning(interaction, text="Teksten er for lang")
|
||||
embed = embed_templates.error_warning(interaction, text='Teksten er for lang')
|
||||
return await interaction.response.send_message(embed=embed)
|
||||
|
||||
embed = discord.Embed(color=interaction.client.user.color, description=tekst)
|
||||
@@ -70,50 +99,74 @@ https://cdn.discordapp.com/attachments/674726496878723082/1042631569396990004/kw
|
||||
await interaction.response.send_message(embed=embed)
|
||||
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@app_commands.command()
|
||||
async def emne(self, interaction: discord.Interaction, emnekode: str):
|
||||
"""For NTNU'ere som ikke kan emnekoder på UiO"""
|
||||
data = requests.get(f"https://data.uio.no/studies/v1/course/{emnekode}", timeout=10)
|
||||
if data.status_code != 200:
|
||||
return await interaction.response.send_message(embed=embed_templates.error_fatal(interaction, text="Fant ikke emnekode"))
|
||||
@app_commands.command(name='emne', description='For NTNU\'ere som ikke kan emnekoder på UiO')
|
||||
async def course_code(self, interaction: discord.Interaction, emnekode: str):
|
||||
"""
|
||||
Translate UiO course codes to their respective course names
|
||||
|
||||
await interaction.response.send_message(data.json()["info"]["name"])
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
emnekode (str): UiO course code
|
||||
"""
|
||||
|
||||
data = requests.get(f'https://data.uio.no/studies/v1/course/{emnekode}', timeout=10)
|
||||
if data.status_code != 200:
|
||||
return await interaction.response.send_message(embed=embed_templates.error_fatal(interaction, text='Fant ikke emnekode'))
|
||||
|
||||
await interaction.response.send_message(data.json()['info']['name'])
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 2)
|
||||
@app_commands.command()
|
||||
async def klappifiser(self, interation: discord.Interaction, tekst: str):
|
||||
"""Klapppifiserer teksten din"""
|
||||
@app_commands.command(name='klappifiser', description='Klappifiser tekst')
|
||||
async def clapify(self, interation: discord.Interaction, tekst: str):
|
||||
"""
|
||||
Add clap emoji between every word of a string
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
tekst (str): Text to clapify
|
||||
"""
|
||||
|
||||
if len(tekst) >= 1000:
|
||||
embed = embed_templates.error_warning(interation, text="Teksten er for lang")
|
||||
embed = embed_templates.error_warning(interation, text='Teksten er for lang')
|
||||
return await interation.response.send_message(embed=embed)
|
||||
|
||||
tekst = re.sub(" ", "👏", tekst)
|
||||
tekst = re.sub(' ', '👏', tekst)
|
||||
|
||||
embed = discord.Embed(color=interation.client.user.color, description=f"**{tekst.upper()}**")
|
||||
embed = discord.Embed(color=interation.client.user.color, description=f'**{tekst.upper()}**')
|
||||
embed_templates.default_footer(interation, embed)
|
||||
await interation.response.send_message(embed=embed)
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@app_commands.command()
|
||||
@app_commands.command(name='imdb', description='Søk etter filmer på IMDB')
|
||||
async def imdb(self, interaction: discord.Interaction, tittel: str):
|
||||
"""Se informasjon om en film eller serie"""
|
||||
"""
|
||||
Search for movies on IMDB and displays information about the first result
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
tittel (str): Movie title
|
||||
"""
|
||||
|
||||
# Search for movie/show
|
||||
url = "http://www.omdbapi.com/?" + urllib.parse.urlencode({"s": tittel, "apikey": self.bot.api_keys["omdb"]})
|
||||
url = 'http://www.omdbapi.com/?' + urllib.parse.urlencode({'s': tittel, 'apikey': self.bot.api_keys['omdb']})
|
||||
search = requests.get(url, timeout=10).json()
|
||||
|
||||
try:
|
||||
best_result_id = search["Search"][0]["imdbID"]
|
||||
best_result_id = search['Search'][0]['imdbID']
|
||||
except KeyError:
|
||||
embed = embed_templates.error_fatal(interaction, text="Fant ikke filmen!")
|
||||
embed = embed_templates.error_fatal(interaction, text='Fant ikke filmen!')
|
||||
return await interaction.response.send_message(embed=embed)
|
||||
|
||||
# Get movie/show info
|
||||
data = requests.get(f'http://www.omdbapi.com/?i={best_result_id}&apikey={self.bot.api_keys["omdb"]}', timeout=10).json()
|
||||
acceptable_media_types = ["movie", "series", "episode"]
|
||||
if data["Type"] not in acceptable_media_types:
|
||||
embed = embed_templates.error_fatal(interaction, text="Fant ikke filmen!")
|
||||
acceptable_media_types = ['movie', 'series', 'episode']
|
||||
if data['Type'] not in acceptable_media_types:
|
||||
embed = embed_templates.error_fatal(interaction, text='Fant ikke filmen!')
|
||||
return await interaction.response.send_message(embed=embed)
|
||||
|
||||
embed = discord.Embed(
|
||||
@@ -122,61 +175,78 @@ https://cdn.discordapp.com/attachments/674726496878723082/1042631569396990004/kw
|
||||
url=f'https://www.imdb.com/title/{data["imdbID"]}/',
|
||||
)
|
||||
embed.set_author(name=interaction.user.name, icon_url=interaction.user.display_avatar)
|
||||
embed.add_field(name="Type", value=data["Type"].title())
|
||||
embed.add_field(name="Sjanger", value=data["Genre"])
|
||||
embed.add_field(name="Spilletid", value=data["Runtime"])
|
||||
embed.add_field(name="Vurdering på IMDb", value=f'{data["imdbRating"]}/10')
|
||||
release_date = datetime.strptime(data["Released"], "%d %b %Y")
|
||||
embed.add_field(name="Utgitt", value=discord.utils.format_dt(release_date, style="D"))
|
||||
embed.add_field(name='Type', value=data['Type'].title())
|
||||
embed.add_field(name='Sjanger', value=data['Genre'])
|
||||
embed.add_field(name='Spilletid', value=data['Runtime'])
|
||||
embed.add_field(name='Vurdering på IMDb', value=f'{data["imdbRating"]}/10')
|
||||
release_date = datetime.strptime(data['Released'], '%d %b %Y')
|
||||
embed.add_field(name='Utgitt', value=discord.utils.format_dt(release_date, style='D'))
|
||||
embed_templates.default_footer(interaction, embed)
|
||||
|
||||
if data["Poster"] != "N/A":
|
||||
embed.set_thumbnail(url=data["Poster"])
|
||||
if data["Director"] != "N/A":
|
||||
embed.description = data["Director"]
|
||||
if data["Plot"] != "N/A" and len(data["Plot"]) < 1024:
|
||||
embed.add_field(name="Sammendrag", value=data["Plot"], inline=False)
|
||||
if data['Poster'] != 'N/A':
|
||||
embed.set_thumbnail(url=data['Poster'])
|
||||
if data['Director'] != 'N/A':
|
||||
embed.description = data['Director']
|
||||
if data['Plot'] != 'N/A' and len(data['Plot']) < 1024:
|
||||
embed.add_field(name='Sammendrag', value=data['Plot'], inline=False)
|
||||
|
||||
await interaction.response.send_message(embed=embed)
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@app_commands.command()
|
||||
async def helligdager(self, interaction: discord.Interaction, *, land: str = "NO", år: int = None):
|
||||
"""Se hellidagene i et land"""
|
||||
@app_commands.command(name='helligdager', description='Se helligdager i et land for et år')
|
||||
async def holidays(self, interaction: discord.Interaction, *, land: str = 'NO', år: int = None):
|
||||
"""
|
||||
Get holidays for a country for a given year
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
land (str): Country code
|
||||
år (int): Year
|
||||
"""
|
||||
|
||||
land = land.upper()
|
||||
aar = datetime.now().year if not år else int(år)
|
||||
|
||||
data = requests.get(f"https://date.nager.at/api/v2/publicholidays/{aar}/{land}", timeout=10)
|
||||
data = requests.get(f'https://date.nager.at/api/v2/publicholidays/{aar}/{land}', timeout=10)
|
||||
if data.status_code != 200:
|
||||
embed = embed_templates.error_fatal(
|
||||
interaction, text="Ugyldig land\nHusk å bruke landskoder\n" + "For eksempel: `NO`"
|
||||
interaction, text='Ugyldig land\nHusk å bruke landskoder\n' + 'For eksempel: `NO`'
|
||||
)
|
||||
return await interaction.response.send_message(embed=embed)
|
||||
|
||||
data = data.json()
|
||||
|
||||
country = data[0]["countryCode"].lower()
|
||||
country = data[0]['countryCode'].lower()
|
||||
|
||||
# Construct output
|
||||
holiday_str = ""
|
||||
holiday_str = ''
|
||||
for day in data:
|
||||
date = discord.utils.format_dt(datetime.strptime(day["date"], "%Y-%m-%d"), style="D")
|
||||
date = discord.utils.format_dt(datetime.strptime(day['date'], '%Y-%m-%d'), style='D')
|
||||
holiday_str += f'**{date}**: {day["localName"]}\n'
|
||||
|
||||
embed = discord.Embed(color=interaction.client.user.color, title=f":flag_{country}: Helligdager {aar} :flag_{country}:")
|
||||
embed = discord.Embed(color=interaction.client.user.color, title=f':flag_{country}: Helligdager {aar} :flag_{country}:')
|
||||
embed.description = holiday_str
|
||||
embed_templates.default_footer(interaction, embed)
|
||||
await interaction.response.send_message(embed=embed)
|
||||
|
||||
@app_commands.checks.bot_has_permissions(embed_links=True)
|
||||
@app_commands.checks.cooldown(1, 5)
|
||||
@app_commands.command()
|
||||
@app_commands.command(name='match', description='Se hvor mye du matcher med en annen')
|
||||
async def match(self, interaction: discord.Interaction, bruker: discord.Member):
|
||||
"""Se hvor mye du matcher med en annen"""
|
||||
"""
|
||||
Get dating compatibility with another user
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
bruker (discord.Member): User to match with
|
||||
"""
|
||||
|
||||
if bruker == interaction.user:
|
||||
embed = embed_templates.error_warning(
|
||||
interaction, text="Jeg vet du er ensom, men du kan " "ikke matche med deg selv"
|
||||
interaction, text='Jeg vet du er ensom, men du kan ' 'ikke matche med deg selv'
|
||||
)
|
||||
return await interaction.response.send_message(embed=embed)
|
||||
|
||||
@@ -188,39 +258,47 @@ https://cdn.discordapp.com/attachments/674726496878723082/1042631569396990004/kw
|
||||
if bruker.id == self.bot.user.id:
|
||||
match_percent = 100
|
||||
|
||||
await interaction.user.display_avatar.save(fp=f"./src/assets/temp/{interaction.user.id}_raw.png")
|
||||
await bruker.display_avatar.save(fp=f"./src/assets/temp/{bruker.id}_raw.png")
|
||||
await interaction.user.display_avatar.save(fp=f'./src/assets/temp/{interaction.user.id}_raw.png')
|
||||
await bruker.display_avatar.save(fp=f'./src/assets/temp/{bruker.id}_raw.png')
|
||||
|
||||
invoker = Image.open(f"./src/assets/temp/{interaction.user.id}_raw.png").convert("RGBA")
|
||||
invoker = Image.open(f'./src/assets/temp/{interaction.user.id}_raw.png').convert('RGBA')
|
||||
invoker = invoker.resize((389, 389), Image.ANTIALIAS)
|
||||
user = Image.open(f"./src/assets/temp/{bruker.id}_raw.png").convert("RGBA")
|
||||
user = Image.open(f'./src/assets/temp/{bruker.id}_raw.png').convert('RGBA')
|
||||
user = user.resize((389, 389), Image.ANTIALIAS)
|
||||
heart = Image.open("./src/assets/misc/heart.png")
|
||||
mask = Image.open("./src/assets/misc/heart.png", "r")
|
||||
heart = Image.open('./src/assets/misc/heart.png')
|
||||
mask = Image.open('./src/assets/misc/heart.png', 'r')
|
||||
|
||||
image = Image.new("RGBA", (1024, 576))
|
||||
image = Image.new('RGBA', (1024, 576))
|
||||
image.paste(invoker, (0, 94))
|
||||
image.paste(user, (635, 94))
|
||||
image.paste(heart, (311, 94), mask=mask)
|
||||
draw = ImageDraw.Draw(image)
|
||||
font = ImageFont.truetype("./src/assets/fonts/RobotoMono-Medium.ttf", 86)
|
||||
font_size = font.getsize(f"{match_percent}%")
|
||||
font = ImageFont.truetype('./src/assets/fonts/RobotoMono-Medium.ttf', 86)
|
||||
font_size = font.getsize(f'{match_percent}%')
|
||||
font_size = ((image.size[0] - font_size[0]) / 2, (image.size[1] - font_size[1]) / 2)
|
||||
draw.text(font_size, f"{match_percent}%", font=font, fill=(255, 255, 255, 255))
|
||||
draw.text(font_size, f'{match_percent}%', font=font, fill=(255, 255, 255, 255))
|
||||
|
||||
image.save(f"./src/assets/temp/{interaction.user.id}_{bruker.id}_edit.png")
|
||||
image.save(f'./src/assets/temp/{interaction.user.id}_{bruker.id}_edit.png')
|
||||
|
||||
f = discord.File(f"./src/assets/temp/{interaction.user.id}_{bruker.id}_edit.png")
|
||||
f = discord.File(f'./src/assets/temp/{interaction.user.id}_{bruker.id}_edit.png')
|
||||
embed = discord.Embed()
|
||||
embed.set_image(url=f"attachment://{interaction.user.id}_{bruker.id}_edit.png")
|
||||
embed.set_image(url=f'attachment://{interaction.user.id}_{bruker.id}_edit.png')
|
||||
embed_templates.default_footer(interaction, embed)
|
||||
await interaction.response.send_message(embed=embed, file=f)
|
||||
|
||||
with ignore_exception(OSError):
|
||||
remove(f"./src/assets/temp/{bruker.id}_raw.png")
|
||||
remove(f"./src/assets/temp/{interaction.user.id}_raw.png")
|
||||
remove(f"./src/assets/temp/{interaction.user.id}_{bruker.id}_edit.png")
|
||||
remove(f'./src/assets/temp/{bruker.id}_raw.png')
|
||||
remove(f'./src/assets/temp/{interaction.user.id}_raw.png')
|
||||
remove(f'./src/assets/temp/{interaction.user.id}_{bruker.id}_edit.png')
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
await bot.add_cog(Misc(bot))
|
||||
@@ -3,34 +3,49 @@ from discord.ext import commands
|
||||
|
||||
|
||||
class RepeatedMessages(commands.Cog):
|
||||
"""Send messages at specific points of time"""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
self.uiog_server = self.bot.get_guild(747542543750660178)
|
||||
|
||||
@aiocron.crontab("0 0 * * 5")
|
||||
@aiocron.crontab('0 0 * * 5')
|
||||
async def fredag():
|
||||
"""Sends a message on Friday at 00:00"""
|
||||
|
||||
channel = await self.uiog_server.fetch_channel(747542544291987597)
|
||||
await channel.send(
|
||||
"NU ÄR DET FREDAG!\n" +
|
||||
"https://cdn.discordapp.com/attachments/750052141346979850/851216786259181578/video0.mp4"
|
||||
'NU ÄR DET FREDAG!\n' +
|
||||
'https://cdn.discordapp.com/attachments/750052141346979850/851216786259181578/video0.mp4'
|
||||
)
|
||||
|
||||
@aiocron.crontab("0 0 * * 1")
|
||||
@aiocron.crontab('0 0 * * 1')
|
||||
async def mandag():
|
||||
"""Sends a message on Monday at 00:00"""
|
||||
|
||||
channel = await self.uiog_server.fetch_channel(747542544291987597)
|
||||
await channel.send(
|
||||
"ENDELIG MANDAG!\n\n" +
|
||||
"https://cdn.discordapp.com/attachments/678396498089738250/862853827278929940/hvorfor_de_rike_br_spises.mp4"
|
||||
'ENDELIG MANDAG!\n\n' +
|
||||
'https://cdn.discordapp.com/attachments/678396498089738250/862853827278929940/hvorfor_de_rike_br_spises.mp4'
|
||||
)
|
||||
|
||||
@aiocron.crontab("0 0 1 1 *")
|
||||
@aiocron.crontab('0 0 1 1 *')
|
||||
async def new_year():
|
||||
"""Sends a message on New Year's Day at 00:00"""
|
||||
|
||||
channel = await self.uiog_server.fetch_channel(747542544291987597)
|
||||
await channel.send(
|
||||
"GODT NYTTÅR!\n\nNå, meld dere inn i UiO Gaming igjen <:ThisIsAThreat:874998234072903710>"
|
||||
'GODT NYTTÅR!\n\nNå, meld dere inn i UiO Gaming igjen <:ThisIsAThreat:874998234072903710>'
|
||||
)
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
"""
|
||||
Add the cog to the bot on extension load
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bot (commands.Bot): Bot instance
|
||||
"""
|
||||
|
||||
await bot.add_cog(RepeatedMessages(bot))
|
||||
@@ -15,27 +15,55 @@ def get_color(discord_object: discord.User | discord.Member | discord.Role) -> d
|
||||
-----------
|
||||
(discord.Color): The user's displayed color
|
||||
"""
|
||||
if hasattr(discord_object, "color") and str(discord_object.color) != '#000000':
|
||||
|
||||
if hasattr(discord_object, 'color') and str(discord_object.color) != '#000000':
|
||||
return discord_object.color
|
||||
|
||||
return discord.Colour(0x99AAB5)
|
||||
|
||||
|
||||
class ScrollerButton(discord.ui.Button):
|
||||
"""Button that scrolls through pages in a scroller view"""
|
||||
|
||||
def __init__(self, paginator: Paginator, button_action: callable, content_constructor: callable, label: str, disabled: bool = False):
|
||||
"""
|
||||
Parameters
|
||||
-----------
|
||||
paginator (Paginator): The paginator object that contains the data to be paginated
|
||||
button_action (callable): The function that returns the requested page
|
||||
content_constructor (callable): A function that takes a paginator object and a page number and returns an embed
|
||||
"""
|
||||
|
||||
super().__init__(label=label, disabled=disabled)
|
||||
self.paginator = paginator
|
||||
self.button_action = button_action
|
||||
self.content_constructor = content_constructor
|
||||
|
||||
async def callback(self, interaction: discord.Interaction):
|
||||
"""
|
||||
What to do when the button is pressed
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
"""
|
||||
|
||||
await interaction.response.defer()
|
||||
content = self.content_constructor(self.paginator, self.button_action(), interaction.message.embeds[0])
|
||||
await interaction.message.edit(embed=content, view=Scroller(self.paginator, self.content_constructor))
|
||||
|
||||
|
||||
class Scroller(discord.ui.View):
|
||||
"""View that allows scrolling through pages of data using the pagination module"""
|
||||
|
||||
def __init__(self, paginatior: Paginator, content_constructor: callable):
|
||||
"""
|
||||
Parameters
|
||||
-----------
|
||||
paginator (Paginator): The paginator object that contains the data to be paginated
|
||||
content_constructor (callable): A function that takes a paginator object and a page number and returns an embed
|
||||
"""
|
||||
|
||||
super().__init__()
|
||||
self.paginator = paginatior
|
||||
|
||||
|
||||
@@ -7,16 +7,17 @@ def default_footer(interaction: discord.Interaction, embed: discord.Embed) -> di
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
interaction (discord.Interaction): Discord interaction context
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
embed (discord.Embed): An embed object to add the footer to
|
||||
|
||||
Returns
|
||||
-----------
|
||||
(discord.Embed): The passed in embed + footer
|
||||
"""
|
||||
|
||||
return embed.set_footer(
|
||||
icon_url=interaction.user.avatar,
|
||||
text=f"{interaction.user.name}#{interaction.user.discriminator}"
|
||||
text=f'{interaction.user.name}#{interaction.user.discriminator}'
|
||||
)
|
||||
|
||||
|
||||
@@ -26,14 +27,15 @@ def error_warning(interaction: discord.Interaction, text: str) -> discord.Embed:
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
interaction (discord.Interaction): Discord interaction context
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
text (str): The error message
|
||||
|
||||
Returns
|
||||
-----------
|
||||
(discord.Embed): An embed object based on the template with the specified text
|
||||
"""
|
||||
embed = discord.Embed(color=discord.Color.gold(), description=f"⚠️ {text}")
|
||||
|
||||
embed = discord.Embed(color=discord.Color.gold(), description=f'⚠️ {text}')
|
||||
default_footer(interaction, embed)
|
||||
|
||||
return embed
|
||||
@@ -45,14 +47,15 @@ def error_fatal(interaction: discord.Interaction, text: str) -> discord.Embed:
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
interaction (discord.Interaction): Discord interaction context
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
text (str): The error message
|
||||
|
||||
Returns
|
||||
-----------
|
||||
(discord.Embed): An embed object based on the template with the specified text
|
||||
"""
|
||||
embed = discord.Embed(color=discord.Color.red(), description=f"❌ {text}")
|
||||
|
||||
embed = discord.Embed(color=discord.Color.red(), description=f'❌ {text}')
|
||||
default_footer(interaction, embed)
|
||||
|
||||
return embed
|
||||
@@ -64,14 +67,15 @@ def success(interaction: discord.Interaction, text: str) -> discord.Embed:
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
interaction (discord.Interaction): Discord interaction context
|
||||
interaction (discord.Interaction): Slash command context object
|
||||
text (str): The message
|
||||
|
||||
Returns
|
||||
-----------
|
||||
discord.Embed: An embed object based on the template with the specified text
|
||||
"""
|
||||
embed = discord.Embed(color=discord.Color.green(), description=f"✅ {text}")
|
||||
|
||||
embed = discord.Embed(color=discord.Color.green(), description=f'✅ {text}')
|
||||
default_footer(interaction, embed)
|
||||
|
||||
return embed
|
||||
@@ -3,18 +3,15 @@ from math import ceil
|
||||
|
||||
|
||||
@contextmanager
|
||||
def ignore_exception(*exceptions) -> None:
|
||||
def ignore_exception(*exceptions: Exception):
|
||||
"""
|
||||
Ignores the given exceptions
|
||||
|
||||
Parameters
|
||||
----------
|
||||
*exceptions: The exceptions you want to ignore
|
||||
|
||||
Returns
|
||||
----------
|
||||
None
|
||||
*exceptions tuple[Exception]: The exceptions you want to ignore
|
||||
"""
|
||||
|
||||
try:
|
||||
yield
|
||||
except exceptions:
|
||||
|
||||
@@ -3,6 +3,8 @@ import logging.handlers
|
||||
|
||||
|
||||
class BotLogger:
|
||||
"""Logging config for the bot"""
|
||||
|
||||
def __init__(self):
|
||||
logger = logging.getLogger('discord')
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
+34
-32
@@ -11,14 +11,16 @@ from logger import BotLogger
|
||||
|
||||
|
||||
# Load config file
|
||||
with codecs.open("./src/config/config.yaml", "r", encoding="utf8") as f:
|
||||
with codecs.open('./src/config/config.yaml', 'r', encoding='utf8') as f:
|
||||
config = yaml.load(f, Loader=yaml.SafeLoader)
|
||||
|
||||
|
||||
class Bot(commands.Bot):
|
||||
def __init__(self) -> None:
|
||||
"""UiO Gaming Bot"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
command_prefix=commands.when_mentioned_or(config["bot"]["prefix"]),
|
||||
command_prefix=commands.when_mentioned_or(config['bot']['prefix']),
|
||||
case_insensitive=True,
|
||||
intents=discord.Intents.all()
|
||||
)
|
||||
@@ -26,28 +28,28 @@ class Bot(commands.Bot):
|
||||
self.logger = BotLogger().logger # Initialize logger
|
||||
|
||||
# Connect to database
|
||||
db = config.get("database", {})
|
||||
db = config.get('database', {})
|
||||
self.db_connection = psycopg2.connect(
|
||||
host=db["host"],
|
||||
dbname=db["dbname"],
|
||||
user=db["username"],
|
||||
password=db["password"],
|
||||
host=db['host'],
|
||||
dbname=db['dbname'],
|
||||
user=db['username'],
|
||||
password=db['password'],
|
||||
)
|
||||
|
||||
# Fetch misc config values
|
||||
self.mc_rcon_password = config["minecraft"]["rcon_password"]
|
||||
self.presence = config["bot"].get("presence", {})
|
||||
self.api_keys = config.get("api", {})
|
||||
self.emoji = config.get("emoji", {})
|
||||
self.misc = config.get("misc", {})
|
||||
self.config_mode = config.get("mode")
|
||||
self.mc_rcon_password = config['minecraft']['rcon_password']
|
||||
self.presence = config['bot'].get('presence', {})
|
||||
self.api_keys = config.get('api', {})
|
||||
self.emoji = config.get('emoji', {})
|
||||
self.misc = config.get('misc', {})
|
||||
self.config_mode = config.get('mode')
|
||||
|
||||
async def setup_hook(self) -> None:
|
||||
async def setup_hook(self):
|
||||
# Load cogs
|
||||
for file in listdir("./src/cogs"):
|
||||
if file.endswith(".py"):
|
||||
for file in listdir('./src/cogs'):
|
||||
if file.endswith('.py'):
|
||||
name = file[:-3]
|
||||
await bot.load_extension(f"cogs.{name}")
|
||||
await bot.load_extension(f'cogs.{name}')
|
||||
|
||||
# Sync slash commands to Discord
|
||||
if self.config_mode == 'prod':
|
||||
@@ -63,33 +65,33 @@ bot = Bot()
|
||||
|
||||
@bot.event
|
||||
async def on_ready():
|
||||
if not hasattr(bot, "uptime"):
|
||||
if not hasattr(bot, 'uptime'):
|
||||
bot.uptime = time()
|
||||
|
||||
# Print bot info
|
||||
print(f"Username: {bot.user.name}")
|
||||
print(f"ID: {bot.user.id}")
|
||||
print(f"Version: {discord.__version__}")
|
||||
print("." * 50 + "\n")
|
||||
print(f'Username: {bot.user.name}')
|
||||
print(f'ID: {bot.user.id}')
|
||||
print(f'Version: {discord.__version__}')
|
||||
print('.' * 50 + '\n')
|
||||
|
||||
# Set initial presence
|
||||
# Presence status
|
||||
status_types = {
|
||||
"online": discord.Status.online,
|
||||
"dnd": discord.Status.dnd,
|
||||
"idle": discord.Status.idle,
|
||||
"offline": discord.Status.offline,
|
||||
'online': discord.Status.online,
|
||||
'dnd': discord.Status.dnd,
|
||||
'idle': discord.Status.idle,
|
||||
'offline': discord.Status.offline,
|
||||
}
|
||||
status_type = status_types.get(bot.presence["type"].lower(), discord.Status.online)
|
||||
status_type = status_types.get(bot.presence['type'].lower(), discord.Status.online)
|
||||
|
||||
# Presence actitivity
|
||||
activities = {"playing": 0, "listening": 2, "watching": 3}
|
||||
activity_type = activities.get(bot.presence["activity"].lower(), 0)
|
||||
activities = {'playing': 0, 'listening': 2, 'watching': 3}
|
||||
activity_type = activities.get(bot.presence['activity'].lower(), 0)
|
||||
|
||||
await bot.change_presence(
|
||||
activity=discord.Activity(type=activity_type, name=bot.presence["message"]),
|
||||
activity=discord.Activity(type=activity_type, name=bot.presence['message']),
|
||||
status=status_type
|
||||
)
|
||||
|
||||
|
||||
bot.run(config["bot"]["token"], reconnect=True, log_handler=None)
|
||||
bot.run(config['bot']['token'], reconnect=True, log_handler=None)
|
||||
Reference in new issue
Block a user