Merge pull request #100 from stijndcl/new_commands

Command for deadlines, slash command for schedules
pull/102/head
Stijn De Clercq 2021-11-29 21:55:32 +01:00 committed by GitHub
commit 81bdde9632
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 233 additions and 8 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
files/lastTasks.json files/lastTasks.json
files/c4.json files/c4.json
files/deadlines.json
files/hangman.json files/hangman.json
files/stats.json files/stats.json
files/lost.json files/lost.json

View File

@ -32,7 +32,10 @@ class Corona(commands.Cog):
return return
# Vaccination stats # Vaccination stats
try:
vaccine = self.getVaccineData(country, dic["today"]["population"], dic["yesterday"]["population"]) vaccine = self.getVaccineData(country, dic["today"]["population"], dic["yesterday"]["population"])
except KeyError:
vaccine = None
await self.sendEmbed(ctx, dic, vaccine) await self.sendEmbed(ctx, dic, vaccine)
@ -210,6 +213,11 @@ class Corona(commands.Cog):
embed.add_field(name="Aantal toegediende vaccins:", embed.add_field(name="Aantal toegediende vaccins:",
value="{:,}".format(vaccines["today"]["vaccines"]), value="{:,}".format(vaccines["today"]["vaccines"]),
inline=False) inline=False)
else:
# Vaccine data is missing
embed.add_field(name="Aantal toegediende vaccins:",
value="?",
inline=False)
# Timestamp of last update # Timestamp of last update
timeFormatted = timeFormatters.epochToDate(int(dic["today"]["updated"]) / 1000) timeFormatted = timeFormatters.epochToDate(int(dic["today"]["updated"]) / 1000)

View File

@ -5,6 +5,7 @@ from data.snipe import Snipe, Action, should_snipe
import datetime import datetime
import discord import discord
from discord.ext import commands from discord.ext import commands
from dislash.application_commands.errors import InteractionCheckFailure
from functions import checks, easterEggResponses, stringFormatters from functions import checks, easterEggResponses, stringFormatters
from functions.database import stats, muttn, custom_commands, commands as command_stats from functions.database import stats, muttn, custom_commands, commands as command_stats
import pytz import pytz
@ -136,6 +137,9 @@ class Events(commands.Cog):
if self.client.user.id != int(constants.didierId): if self.client.user.id != int(constants.didierId):
raise err raise err
if isinstance(err, InteractionCheckFailure):
return await interaction.reply("Je hebt geen toegang tot dit commando.", ephemeral=True)
usage = stringFormatters.format_slash_command_usage(interaction) usage = stringFormatters.format_slash_command_usage(interaction)
await self.sendErrorEmbed(err, "Slash Command", usage) await self.sendErrorEmbed(err, "Slash Command", usage)

View File

@ -1,12 +1,13 @@
from data import schedule from data import schedule
from data.embeds.deadlines import Deadlines
from data.embeds.food import Menu from data.embeds.food import Menu
from decorators import help from decorators import help
import discord import discord
from discord.ext import commands from discord.ext import commands
from enums.help_categories import Category from enums.help_categories import Category
from functions import config, eten, les from functions import config, les
from functions.stringFormatters import capitalize from functions.stringFormatters import capitalize
from functions.timeFormatters import intToWeekday, skip_weekends from functions.timeFormatters import skip_weekends
class School(commands.Cog): class School(commands.Cog):
@ -70,6 +71,11 @@ class School(commands.Cog):
await message.pin(reason="Didier Pin door {}".format(ctx.author.display_name)) await message.pin(reason="Didier Pin door {}".format(ctx.author.display_name))
await ctx.message.add_reaction("") await ctx.message.add_reaction("")
@commands.command(name="Deadlines", aliases=["dl"])
@help.Category(category=Category.School)
async def deadlines(self, ctx):
await ctx.send(embed=Deadlines().to_embed())
def setup(client): def setup(client):
client.add_cog(School(client)) client.add_cog(School(client))

View File

@ -0,0 +1,87 @@
import datetime
import json
from discord.ext import commands
from dislash import SlashInteraction, slash_command, Option, OptionType, check
from functions.checks import isMe
from functions.timeFormatters import fromString
from startup.didier import Didier
class Slash(commands.Cog):
def __init__(self, client: Didier):
self.client: Didier = client
@slash_command(name="db")
@check(isMe)
async def _db_slash(self, interaction: SlashInteraction):
pass
@_db_slash.sub_command_group(name="add")
async def _add_slash(self, interaction: SlashInteraction):
pass
@_add_slash.sub_command(
name="deadline",
options=[
Option(
"year",
description="Year (1-based)",
type=OptionType.INTEGER,
required=True
),
Option(
"course",
description="Course (abbreviated)",
type=OptionType.STRING,
required=True
),
Option(
"name",
description="Name of the deadline/project",
type=OptionType.STRING,
required=True
),
Option(
"date",
description="Date (DD/MM)",
type=OptionType.STRING,
required=True
),
Option(
"time",
description="Timestamp (HH:MM or HH:MM:SS)",
type=OptionType.STRING,
required=False
)
]
)
async def _add_deadline_slash(self, interaction: SlashInteraction, year: int, course: str, name: str, date: str, time: str = "00:00:00"):
with open("files/deadlines.json", "r") as f:
deadlines = json.load(f)
date += "/" + str(datetime.datetime.now().year)
# Fix format
if time.count(":") == 1:
time += ":00"
dt = fromString(f"{date} {time}", formatString="%d/%m/%Y %H:%M:%S")
# Add year & course if necessary
if str(year) not in deadlines:
deadlines[str(year)] = {}
if course not in deadlines[str(year)]:
deadlines[str(year)][course] = {}
deadlines[str(year)][course][name] = round(dt.timestamp())
with open("files/deadlines.json", "w") as f:
json.dump(deadlines, f)
await interaction.reply("Addition successful", ephemeral=True)
def setup(client: Didier):
client.add_cog(Slash(client))

View File

@ -1,7 +1,12 @@
from discord.ext import commands from discord.ext import commands
from dislash import SlashInteraction, slash_command, Option, OptionType from dislash import SlashInteraction, slash_command, Option, OptionType
from data import schedule
from data.embeds.food import Menu from data.embeds.food import Menu
from data.embeds.deadlines import Deadlines
from functions import les, config
from functions.stringFormatters import capitalize
from functions.timeFormatters import skip_weekends
from startup.didier import Didier from startup.didier import Didier
@ -24,6 +29,48 @@ class SchoolSlash(commands.Cog):
embed = Menu(dag).to_embed() embed = Menu(dag).to_embed()
await interaction.reply(embed=embed) await interaction.reply(embed=embed)
@slash_command(name="deadlines", description="Aanstaande deadlines")
async def _deadlines_slash(self, interaction: SlashInteraction):
embed = Deadlines().to_embed()
await interaction.reply(embed=embed)
@slash_command(
name="les",
description="Lessenrooster voor [Dag] (default vandaag)",
options=[
Option(
"dag",
description="dag",
type=OptionType.STRING,
required=False
)
]
)
async def _schedule_slash(self, interaction: SlashInteraction, day: str = None):
"""It's late and I really don't want to refactor the original right now"""
if day is not None:
day = day.lower()
date = les.find_target_date(day)
# Person explicitly requested a weekend-day
if day is not None and day.lower() in ("morgen", "overmorgen") and date.weekday() > 4:
return await interaction.reply(f"{capitalize(day)} is het weekend.", ephemeral=True)
date = skip_weekends(date)
s = schedule.Schedule(date, int(config.get("year")), int(config.get("semester")), day is not None)
if s.semester_over:
return await interaction.reply("Het semester is afgelopen.", ephemeral=True)
# DM only shows user's own minor
if interaction.guild is None:
minor_roles = [*schedule.find_minor(self.client, interaction.author.id)]
return await interaction.reply(embed=s.create_schedule(minor_roles=minor_roles).to_embed())
return await interaction.reply(embed=s.create_schedule().to_embed())
def setup(client: Didier): def setup(client: Didier):
client.add_cog(SchoolSlash(client)) client.add_cog(SchoolSlash(client))

View File

@ -0,0 +1,68 @@
import json
import time
from dataclasses import dataclass
from discord import Embed, Colour
from functions.stringFormatters import get_edu_year
from typing import Dict
"""
Sample json structure:
{
"1": {
"ad1": {
"proj1": 123456789
}
}
}
"""
@dataclass
class Deadline:
course: str
name: str
t: int
passed: bool
def __str__(self) -> str:
v = f"{self.course} - {self.name}: <t:{self.t}:R>"
if self.passed:
v = f"~~v~~"
return v
class Deadlines:
data: Dict
def __init__(self):
with open("files/deadlines.json") as f:
self.data = json.load(f)
def to_embed(self) -> Embed:
embed = Embed(colour=Colour.dark_gold())
embed.set_author(name="Aanstaande Deadlines")
now = time.time()
if not self.data:
embed.description = "Er staan geen deadlines gepland."
return embed
courses: Dict
for year, courses in self.data.items():
content = []
deadlines: Dict[str, int]
for course, deadlines in courses.items():
for deadline, t in deadlines.items():
content.append(Deadline(course, deadline, t, t < now))
content.sort(key=lambda x: x.t)
content = map(lambda x: str(x), content)
embed.add_field(name=get_edu_year(int(year)), value="\n".join(content))
return embed

View File

@ -0,0 +1 @@
{}

View File

@ -35,10 +35,12 @@
"corona vaccinations": "Vaccinatiecijfers voor België.", "corona vaccinations": "Vaccinatiecijfers voor België.",
"custom": "Geeft een lijst van custom commands. Didier > Dyno confirmed once more.", "custom": "Geeft een lijst van custom commands. Didier > Dyno confirmed once more.",
"dadjoke": "Didier vertelt een dad joke.", "dadjoke": "Didier vertelt een dad joke.",
"deadlines": "Toont de (gekende) deadlines voor dit semester.",
"define": "Geeft de definitie van [Woord] zoals het in de Urban Dictionary staat.\nZoektermen met spaties moeten **niet** tussen aanhalingstekens staan.", "define": "Geeft de definitie van [Woord] zoals het in de Urban Dictionary staat.\nZoektermen met spaties moeten **niet** tussen aanhalingstekens staan.",
"detect": "Didier probeert de taal van [Tekst] te detecteren.", "detect": "Didier probeert de taal van [Tekst] te detecteren.",
"dice": "Gok op de uitkomst van een dobbelsteen.", "dice": "Gok op de uitkomst van een dobbelsteen.",
"dinks": "Bekijk jouw huidige aantal Dinks.", "dinks": "Bekijk jouw huidige aantal Dinks.",
"eten": "Geeft het menu voor [dag] weer in de UGent resto's.",
"faq": "Stuurt een lijst van alle FAQ's in [Categorie] naar jouw DM's.\nGeef geen categorie op om een lijst van categorieën te krijgen.\nIndien je een of meerdere personen tagt, wordt de lijst naar hun DM's gestuurd in plaats van de jouwe.", "faq": "Stuurt een lijst van alle FAQ's in [Categorie] naar jouw DM's.\nGeef geen categorie op om een lijst van categorieën te krijgen.\nIndien je een of meerdere personen tagt, wordt de lijst naar hun DM's gestuurd in plaats van de jouwe.",
"faq add": "Voegt een vraag & antwoord toe aan FAQ [Categorie].\nIndien je geen vraag & antwoord opgeeft, maakt het een categorie aan.", "faq add": "Voegt een vraag & antwoord toe aan FAQ [Categorie].\nIndien je geen vraag & antwoord opgeeft, maakt het een categorie aan.",
"faq quote": "Stuurt een specifieke entry uit de FAQ in het huidige channel in plaats van de hele lijst naar iemand's DM's.", "faq quote": "Stuurt een specifieke entry uit de FAQ in het huidige channel in plaats van de hele lijst naar iemand's DM's.",

View File

@ -167,12 +167,8 @@
}, },
"6": { "6": {
"canceled": true "canceled": true
},
"10,11,12": {
"online_only": true
} }
}, },
"online": "zoom",
"location": { "location": {
"campus": "Ardoyen", "campus": "Ardoyen",
"building": "iGent 125", "building": "iGent 125",

View File

@ -44,6 +44,7 @@ def format_command_usage(ctx: Context) -> str:
def format_slash_command_usage(interaction: SlashInteraction) -> str: def format_slash_command_usage(interaction: SlashInteraction) -> str:
# Create a string with the options used # Create a string with the options used
# TODO look into the format used by the lib because it's terrible
options = " ".join(list(map( options = " ".join(list(map(
lambda option: f"{option.name}: \"{option.value}\"", lambda option: f"{option.name}: \"{option.value}\"",
interaction.data.options.values() interaction.data.options.values()
@ -51,3 +52,7 @@ def format_slash_command_usage(interaction: SlashInteraction) -> str:
command = f"{interaction.slash_command.name} {options or ''}" command = f"{interaction.slash_command.name} {options or ''}"
return f"{interaction.author.display_name} in {_format_error_location(interaction)}: /{command}" return f"{interaction.author.display_name} in {_format_error_location(interaction)}: /{command}"
def get_edu_year(index: int) -> str:
return ["1ste Bachelor", "2de Bachelor", "3de Bachelor", "1ste Master", "2de Master"][index - 1]

View File

@ -3,7 +3,7 @@ from os import path
def check_all(): def check_all():
files = ["hangman", "lastTasks", "locked", "lost", "stats", "ufora_notifications"] files = ["deadlines", "hangman", "lastTasks", "locked", "lost", "stats", "ufora_notifications"]
for f in files: for f in files:
if not path.isfile(path.join(f"files/{f}.json")): if not path.isfile(path.join(f"files/{f}.json")):