Newer
Older
import io
import uuid
import discord
from peewee import *
from peewee import ModelSelect
db = SqliteDatabase("db.sqlite3")
class BaseModel(Model):
class Meta:
database = db
legacy_table_names = False
class Settings(BaseModel):
guild_id = IntegerField(default=0)
greeting_channel_id = IntegerField(default=0)
modmail_channel_id = IntegerField(default=0)
news_url = CharField()
news_channel_id = IntegerField(default=0)
news_role_id = IntegerField(default=0)
command_approval_channel_id = IntegerField(default=0)
learninggroup_voice_category_id = IntegerField(default=0)
voice_bitrate = IntegerField(default=0)
thread_notification_role_id = IntegerField(default=0)
class LinkCategory(BaseModel):
channel = IntegerField()
name = CharField()
@classmethod
def get_categories(cls, channel: int, category: str = None) -> ModelSelect:
categories: ModelSelect = cls.select().where(LinkCategory.channel == channel)
return categories.where(LinkCategory.name == category) if category else categories
@classmethod
def has_links(cls, channel: int, category: str = None) -> bool:
for category in cls.get_categories(channel, category=category):
if category.links.count() > 0:
return True
return False
class Link(BaseModel):
url = CharField()
title = CharField()
category = ForeignKeyField(LinkCategory, backref='links')
class NewsFeed(BaseModel):
settings = ForeignKeyField(Settings)
url = CharField()
type = CharField()
class NewsArticle(BaseModel):
news_feed = ForeignKeyField(NewsFeed)
title = CharField(null=True)
description = CharField(null=True)
link = CharField()
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
class Poll(BaseModel):
question = CharField()
author = IntegerField()
channel = IntegerField()
message = IntegerField()
def get_embed(self) -> discord.Embed:
embed = discord.Embed(title="Umfrage", description=self.question)
embed.add_field(name="Erstellt von", value=f'<@!{self.author}>', inline=False)
embed.add_field(name="\u200b", value="\u200b", inline=False)
for choice in self.choices:
name = f'{choice.emoji} {choice.text}'
value = f'{len(choice.participants)}'
embed.add_field(name=name, value=value, inline=False)
participants = {str(participant.member_id): 1 for participant in
PollParticipant.select().join(PollChoice, on=PollParticipant.poll_choice).where(
PollChoice.poll == self)}
embed.add_field(name="\u200b", value="\u200b", inline=False)
embed.add_field(name="Anzahl der Teilnehmer an der Umfrage", value=f"{len(participants)}", inline=False)
return embed
class PollChoice(BaseModel):
poll = ForeignKeyField(Poll, backref='choices')
text = CharField()
emoji = CharField()
class PollParticipant(BaseModel):
poll_choice = ForeignKeyField(PollChoice, backref='participants')
member_id = IntegerField()
class Command(BaseModel):
guild_id = IntegerField()
command = CharField(unique=True)
description = CharField()
class CommandText(BaseModel):
text = CharField()
command = ForeignKeyField(Command, backref="texts")
class Appointment(BaseModel):
channel = IntegerField()
message = IntegerField()
date_time = DateTimeField()
reminder = IntegerField()
title = CharField()
description = CharField()
author = IntegerField()
recurring = IntegerField()
reminder_sent = BooleanField()
uuid = UUIDField(default=uuid.uuid4())
def get_embed(self, state: int) -> discord.Embed:
attendees = self.attendees
description = (f"- Durch Klicken auf Anmelden erhältst du eine Benachrichtigung zum Beginn des Termins"
f"{f', sowie {self.reminder} Minuten vorher' if self.reminder > 0 else f''}.\n"
f"- Durch Klicken auf Abmelden nimmst du deine vorherige Anmeldung wieder zurück und wirst "
emoji = "📅" if state == 0 else ("📣" if state == 1 else "✅")
embed = discord.Embed(title=f"{emoji} __{self.title}__ {'findet jetzt statt.' if state == 2 else ''}",
description=description)
embed.color = Colour.green() if state == 0 else Colour.yellow() if state == 1 else 19607
if len(self.description) > 0:
embed.add_field(name="Beschreibung", value=self.description, inline=False)
embed.add_field(name="Startzeitpunkt", value=self.get_start_time(state), inline=False)
if self.reminder > 0 and state == 0:
embed.add_field(name="Erinnerung", value=f"{self.reminder} Minuten vor dem Start", inline=False)
if self.recurring > 0:
embed.add_field(name="Wiederholung", value=f"Alle {self.recurring} Tage", inline=False)
if len(attendees) > 0:
embed.add_field(name=f"Teilnehmerinnen ({len(attendees)})",
value=",".join([f"<@{attendee.member_id}>" for attendee in attendees]))
return embed
def remind_at(self) -> datetime:
if self.reminder_sent:
return self.date_time
elif datetime.now() >= self.date_time:
Appointment.update(reminder_sent=True).where(Appointment.id == self.id).execute()
self.reminder_sent = True
return self.date_time
else:
return self.date_time - timedelta(minutes=self.reminder)
def get_start_time(self, state) -> str:
if state == 0:
return f"<t:{int(self.date_time.timestamp())}:F>"
return f"<t:{int(self.date_time.timestamp())}:F> (<t:{int(self.date_time.timestamp())}:R>)"
def get_ics_file(self):
fmt = "%Y%m%dT%H%M"
appointment = f"BEGIN:VCALENDAR\n" \
f"PRODID:Boty McBotface\n" \
f"VERSION:2.0\n" \
f"BEGIN:VTIMEZONE\n" \
f"TZID:Europe/Berlin\n" \
f"BEGIN:DAYLIGHT\n" \
f"TZOFFSETFROM:+0100\n" \
f"TZOFFSETTO:+0200\n" \
f"TZNAME:CEST\n" \
f"DTSTART:19700329T020000\n" \
f"RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3\n" \
f"END:DAYLIGHT\n" \
f"BEGIN:STANDARD\n" \
f"TZOFFSETFROM:+0200\n" \
f"TZOFFSETTO:+0100\n" \
f"TZNAME:CET\n" \
f"DTSTART:19701025T030000\n" \
f"RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\n" \
f"END:STANDARD\n" \
f"END:VTIMEZONE\n" \
f"BEGIN:VEVENT\n" \
f"DTSTAMP:{datetime.now().strftime(fmt)}00Z\n" \
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
f"UID:{self.uuid}\n" \
f"SUMMARY:{self.title}\n"
appointment += f"RRULE:FREQ=DAILY;INTERVAL={self.recurring}\n" if self.recurring else f""
appointment += f"DTSTART;TZID=Europe/Berlin:{self.date_time.strftime(fmt)}00\n" \
f"DTEND;TZID=Europe/Berlin:{self.date_time.strftime(fmt)}00\n" \
f"TRANSP:OPAQUE\n" \
f"BEGIN:VALARM\n" \
f"ACTION:DISPLAY\n" \
f"TRIGGER;VALUE=DURATION:-PT{self.reminder}M\n" \
f"DESCRIPTION:{self.description}\n" \
f"END:VALARM\n" \
f"END:VEVENT\n" \
f"END:VCALENDAR"
ics_file = io.BytesIO(appointment.encode("utf-8"))
return ics_file
class Attendee(BaseModel):
appointment = ForeignKeyField(Appointment, backref='attendees')
member_id = IntegerField()
class Course(BaseModel):
name = CharField()
short = CharField()
url = CharField()
role_id = IntegerField()
class Module(BaseModel):
number = IntegerField(primary_key=True)
title = CharField()
url = CharField()
ects = CharField(null=True)
effort = CharField(null=True)
duration = CharField(null=True)
interval = CharField(null=True)
notes = CharField(null=True)
requirements = CharField(null=True)
class Event(BaseModel):
name = CharField()
number = CharField()
url = CharField()
module = ForeignKeyField(Module, backref='events')
class Support(BaseModel):
title = CharField()
city = CharField()
url = CharField()
module = ForeignKeyField(Module, backref='support')
class Exam(BaseModel):
name = CharField()
type = CharField(null=True)
requirements = CharField(null=True)
weight = CharField(null=True)
hard_requirements = CharField(null=True)
module = ForeignKeyField(Module, backref='exams')
class Download(BaseModel):
title = CharField()
url = CharField()
module = ForeignKeyField(Module, backref='downloads')
class Contact(BaseModel):
name = CharField()
module = ForeignKeyField(Module, backref='contacts')
db.create_tables(
[Settings, LinkCategory, Link, NewsFeed, NewsArticle, Poll, PollChoice, PollParticipant, Command, CommandText, Appointment,
Attendee, Course, Module, Event, Support, Exam, Download, Contact], safe=True)