mirror of https://github.com/stijndcl/didier
commit
2bc949de83
|
@ -8,6 +8,7 @@ files/stats.json
|
||||||
files/lost.json
|
files/lost.json
|
||||||
files/locked.json
|
files/locked.json
|
||||||
files/database.json
|
files/database.json
|
||||||
|
files/ufora_notifications.json
|
||||||
.idea/
|
.idea/
|
||||||
__pycache__
|
__pycache__
|
||||||
.env
|
.env
|
|
@ -8,6 +8,7 @@ import pytz
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
# Temporarily disabled because of API (setup @ bottom)
|
||||||
class Launch(commands.Cog):
|
class Launch(commands.Cog):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
self.client = client
|
self.client = client
|
||||||
|
@ -51,4 +52,5 @@ class Launch(commands.Cog):
|
||||||
|
|
||||||
|
|
||||||
def setup(client):
|
def setup(client):
|
||||||
client.add_cog(Launch(client))
|
pass
|
||||||
|
# client.add_cog(Launch(client))
|
||||||
|
|
|
@ -6,6 +6,7 @@ from discord.ext import commands
|
||||||
from enums.help_categories import Category
|
from enums.help_categories import Category
|
||||||
from functions import checks, clap, mock, sunrise, timeFormatters
|
from functions import checks, clap, mock, sunrise, timeFormatters
|
||||||
import pytz
|
import pytz
|
||||||
|
from requests import get
|
||||||
import time
|
import time
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
|
@ -101,7 +102,7 @@ class Oneliners(commands.Cog):
|
||||||
|
|
||||||
@commands.command(name="Todo", aliases=["List", "Td"])
|
@commands.command(name="Todo", aliases=["List", "Td"])
|
||||||
@help.Category(category=Category.Didier)
|
@help.Category(category=Category.Didier)
|
||||||
async def todo(self, ctx, *args):
|
async def todo(self, ctx):
|
||||||
await ctx.send("https://trello.com/b/PdtsAJea/didier-to-do-list")
|
await ctx.send("https://trello.com/b/PdtsAJea/didier-to-do-list")
|
||||||
|
|
||||||
@commands.command(name="LMGTFY", aliases=["Dsfr"], usage="[Query]")
|
@commands.command(name="LMGTFY", aliases=["Dsfr"], usage="[Query]")
|
||||||
|
@ -130,7 +131,7 @@ class Oneliners(commands.Cog):
|
||||||
await ctx.send("Shut, it already is.")
|
await ctx.send("Shut, it already is.")
|
||||||
|
|
||||||
@commands.command()
|
@commands.command()
|
||||||
async def sc(self, ctx, *args):
|
async def sc(self, ctx):
|
||||||
await ctx.send("http://take-a-screenshot.org/")
|
await ctx.send("http://take-a-screenshot.org/")
|
||||||
|
|
||||||
@commands.command(aliases=["os", "sauce", "src"])
|
@commands.command(aliases=["os", "sauce", "src"])
|
||||||
|
@ -144,9 +145,19 @@ class Oneliners(commands.Cog):
|
||||||
await ctx.send(":sunny:: **{}**\n:crescent_moon:: **{}**".format(s.sunrise(), s.sunset()))
|
await ctx.send(":sunny:: **{}**\n:crescent_moon:: **{}**".format(s.sunrise(), s.sunset()))
|
||||||
|
|
||||||
@commands.command(name="Tias", aliases=["TryIt"])
|
@commands.command(name="Tias", aliases=["TryIt"])
|
||||||
async def tias(self, ctx, *args):
|
async def tias(self, ctx):
|
||||||
await ctx.send("***Try it and see***")
|
await ctx.send("***Try it and see***")
|
||||||
|
|
||||||
|
@commands.command(name="Inspire")
|
||||||
|
@help.Category(Category.Other)
|
||||||
|
async def inspire(self, ctx):
|
||||||
|
image = get("http://inspirobot.me/api?generate=true")
|
||||||
|
|
||||||
|
if image.status_code == 200:
|
||||||
|
await ctx.send(image.text)
|
||||||
|
else:
|
||||||
|
await ctx.send("Uh oh API down.")
|
||||||
|
|
||||||
|
|
||||||
def setup(client):
|
def setup(client):
|
||||||
client.add_cog(Oneliners(client))
|
client.add_cog(Oneliners(client))
|
||||||
|
|
|
@ -6,6 +6,7 @@ from functions import timeFormatters
|
||||||
from functions.config import config
|
from functions.config import config
|
||||||
from functions.database import currency, poke, prison, birthdays, stats
|
from functions.database import currency, poke, prison, birthdays, stats
|
||||||
from functions.scraping import getMatchweek
|
from functions.scraping import getMatchweek
|
||||||
|
from functions import ufora_notifications
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
import requests
|
import requests
|
||||||
|
@ -24,6 +25,7 @@ class Tasks(commands.Cog):
|
||||||
self.updateMessageCounts.start()
|
self.updateMessageCounts.start()
|
||||||
self.sendReminders.start()
|
self.sendReminders.start()
|
||||||
self.updateMatchweek.start()
|
self.updateMatchweek.start()
|
||||||
|
self.uforaAnnouncements.start()
|
||||||
|
|
||||||
@tasks.loop(hours=1.0)
|
@tasks.loop(hours=1.0)
|
||||||
async def bankInterest(self):
|
async def bankInterest(self):
|
||||||
|
@ -238,6 +240,24 @@ class Tasks(commands.Cog):
|
||||||
async def beforeUpdateMatchweek(self):
|
async def beforeUpdateMatchweek(self):
|
||||||
await self.client.wait_until_ready()
|
await self.client.wait_until_ready()
|
||||||
|
|
||||||
|
@tasks.loop(minutes=30.0)
|
||||||
|
async def uforaAnnouncements(self):
|
||||||
|
"""
|
||||||
|
Task that checks for new Ufora announcements every few minutes
|
||||||
|
"""
|
||||||
|
# Get new notifications
|
||||||
|
announcements = ufora_notifications.run()
|
||||||
|
|
||||||
|
if announcements:
|
||||||
|
announcements_channel = self.client.get_channel(816724500136591380)
|
||||||
|
|
||||||
|
for an in announcements:
|
||||||
|
await announcements_channel.send(embed=an.to_embed())
|
||||||
|
|
||||||
|
@uforaAnnouncements.before_loop
|
||||||
|
async def beforeUforaAnnouncements(self):
|
||||||
|
await self.client.wait_until_ready()
|
||||||
|
|
||||||
def getCurrentHour(self):
|
def getCurrentHour(self):
|
||||||
return timeFormatters.dateTimeNow().hour
|
return timeFormatters.dateTimeNow().hour
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,13 @@ botIDs = [
|
||||||
"728361496874057812"
|
"728361496874057812"
|
||||||
]
|
]
|
||||||
BugReports = "762668401960812554"
|
BugReports = "762668401960812554"
|
||||||
|
BotTesting = "679701786189103106"
|
||||||
CallOfCode = "626699611192688641"
|
CallOfCode = "626699611192688641"
|
||||||
CoCGeneral = "626699611813314561"
|
CoCGeneral = "626699611813314561"
|
||||||
DeZandbak = "728361030404538488"
|
DeZandbak = "728361030404538488"
|
||||||
ErrorLogs = "762668505455132722"
|
ErrorLogs = "762668505455132722"
|
||||||
FeatureRequests = "762668473313787964"
|
FeatureRequests = "762668473313787964"
|
||||||
|
ZandbakSpeeltuin = "769248992957038612"
|
||||||
|
|
||||||
mods = {
|
mods = {
|
||||||
626699611192688641: [384457911377854467, 171671190631481345],
|
626699611192688641: [384457911377854467, 171671190631481345],
|
||||||
|
@ -53,7 +55,12 @@ faq_channels = {
|
||||||
727876797458284584: "funcprog",
|
727876797458284584: "funcprog",
|
||||||
727876819264733244: "statprob",
|
727876819264733244: "statprob",
|
||||||
727876836587208714: "sysprog",
|
727876836587208714: "sysprog",
|
||||||
676713433567199232: "didier"
|
676713433567199232: "didier",
|
||||||
|
807566495550013460: "comparch",
|
||||||
|
807567007355895838: "multimedia",
|
||||||
|
807567261216538644: "sel1",
|
||||||
|
807567345484169237: "webdev",
|
||||||
|
807567387775336499: "wetrek"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
from .ufora import UforaNotification
|
|
@ -0,0 +1,95 @@
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from discord import Embed, Colour
|
||||||
|
from functions.stringFormatters import leadingZero as lz
|
||||||
|
from functions.timeFormatters import intToWeekday
|
||||||
|
import pytz
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class UforaNotification:
|
||||||
|
def __init__(self, content: dict, course, notif_id, course_id):
|
||||||
|
self._content: dict = content
|
||||||
|
self._course = course
|
||||||
|
self._notif_id, self._course_id = notif_id, course_id
|
||||||
|
self._view_url = self._create_url()
|
||||||
|
self._title = self._clean_content(self._content["title"])
|
||||||
|
self._description = self._get_description()
|
||||||
|
self._published = self._get_published()
|
||||||
|
|
||||||
|
def to_embed(self):
|
||||||
|
embed = Embed(colour=Colour.from_rgb(30, 100, 200))
|
||||||
|
|
||||||
|
embed.set_author(name=self._course)
|
||||||
|
embed.title = self._title
|
||||||
|
embed.url = self._view_url
|
||||||
|
embed.description = self._description
|
||||||
|
embed.set_footer(text=self._published)
|
||||||
|
|
||||||
|
return embed
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return int(self._notif_id) if self._notif_id is not None else self._content["id"]
|
||||||
|
|
||||||
|
def _create_url(self):
|
||||||
|
if self._notif_id is None or self._course_id is None:
|
||||||
|
return self._content["link"]
|
||||||
|
|
||||||
|
return "https://ufora.ugent.be/d2l/le/news/{0}/{1}/view?ou={0}".format(self._course_id, self._notif_id)
|
||||||
|
|
||||||
|
def _get_description(self):
|
||||||
|
desc = self._clean_content(self._content["summary"])
|
||||||
|
|
||||||
|
if len(desc) > 500:
|
||||||
|
return desc[:497] + "..."
|
||||||
|
|
||||||
|
return desc
|
||||||
|
|
||||||
|
def _clean_content(self, text: str):
|
||||||
|
# Dict with HTML & markdown tags to replace
|
||||||
|
html_table = {
|
||||||
|
# CHARACTERS:
|
||||||
|
"&": '&',
|
||||||
|
""": '"',
|
||||||
|
"apos;": "'",
|
||||||
|
">": ">",
|
||||||
|
"<": "<",
|
||||||
|
# MARKDOWN SUPPORT:
|
||||||
|
"<b>": "**",
|
||||||
|
"</b>": "**",
|
||||||
|
"<strong>": "**",
|
||||||
|
"</strong>": "**",
|
||||||
|
"<i>": "*",
|
||||||
|
"</i>": "*",
|
||||||
|
"<em>": "*",
|
||||||
|
"</em>": "*",
|
||||||
|
"<del>": "~~",
|
||||||
|
"</del>": "~~",
|
||||||
|
"<ins>": "__",
|
||||||
|
"</ins>": "__",
|
||||||
|
# Represent paragraphs with newlines
|
||||||
|
"</p>": "\n",
|
||||||
|
"<br>": "\n",
|
||||||
|
"<br/>": "\n",
|
||||||
|
"<br />": "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Unescape HTML
|
||||||
|
for key, value in html_table.items():
|
||||||
|
text = text.replace(key, value)
|
||||||
|
|
||||||
|
# Remove HTML tags
|
||||||
|
return re.sub(r"<[^>]*>", "", text)
|
||||||
|
|
||||||
|
def _get_published(self):
|
||||||
|
time_string = "%a, %d %b %Y %H:%M:%S %Z"
|
||||||
|
dt = datetime.strptime(self._content["published"], time_string)\
|
||||||
|
.astimezone(pytz.timezone("Europe/Brussels"))
|
||||||
|
|
||||||
|
# Apply timezone offset
|
||||||
|
dt = dt + timedelta(hours=dt.utcoffset().seconds//3600)
|
||||||
|
|
||||||
|
return "{} {}/{}/{} om {}:{}:{}".format(
|
||||||
|
intToWeekday(dt.weekday()),
|
||||||
|
lz(dt.day), lz(dt.month), lz(dt.year),
|
||||||
|
lz(dt.hour), lz(dt.minute), lz(dt.second)
|
||||||
|
)
|
|
@ -46,12 +46,12 @@
|
||||||
"hangman start": "Start een nieuwe Hangman game indien er nog geen bezig is. Indien je geen woord opgeeft, wordt er een willekeurig woord gekozen.\n**Indien je wel een woord opgeeft, werkt dit enkel in DM.**",
|
"hangman start": "Start een nieuwe Hangman game indien er nog geen bezig is. Indien je geen woord opgeeft, wordt er een willekeurig woord gekozen.\n**Indien je wel een woord opgeeft, werkt dit enkel in DM.**",
|
||||||
"hangman guess": "Probeer het woord te raden.",
|
"hangman guess": "Probeer het woord te raden.",
|
||||||
"claim": "Claim [Aantal] Didier Dinks uit je profit.\nIndien je geen aantal opgeeft (of \"all\"), claim je alles, inclusief je investering.",
|
"claim": "Claim [Aantal] Didier Dinks uit je profit.\nIndien je geen aantal opgeeft (of \"all\"), claim je alles, inclusief je investering.",
|
||||||
|
"inspire": "Generate quotes via [InspiroBot](https://inspirobot.me/).",
|
||||||
"inventory": "Bekijk de items in jouw inventory.",
|
"inventory": "Bekijk de items in jouw inventory.",
|
||||||
"invest": "Investeer [Aantal] Didier Dinks in jouw Didier Bank om rente te vergaren.",
|
"invest": "Investeer [Aantal] Didier Dinks in jouw Didier Bank om rente te vergaren.",
|
||||||
"jpl": "Informatie over de Jupiler Pro League.",
|
"jpl": "Informatie over de Jupiler Pro League.",
|
||||||
"jpl matches": "Bekijk de wedstrijden die gespeeld worden op [Week]. Default naar de huidige speeldag.",
|
"jpl matches": "Bekijk de wedstrijden die gespeeld worden op [Week]. Default naar de huidige speeldag.",
|
||||||
"jpl table": "De huidige stand van het klassement.",
|
"jpl table": "De huidige stand van het klassement.",
|
||||||
"launch": "Tijdstip van de volgende SpaceX lancering.",
|
|
||||||
"leaderboard": "Bekijk de Top 10 van [Categorie].\nIndien je geen categorie opgeeft krijg je een lijst van categorieën.",
|
"leaderboard": "Bekijk de Top 10 van [Categorie].\nIndien je geen categorie opgeeft krijg je een lijst van categorieën.",
|
||||||
"les": "Bekijk het lessenrooster voor [Dag] in het [Jaargang]-de jaar.\nIndien je geen dag opgeeft, is dit standaard vandaag. De jaargang is standaard 2.\nLes Morgen/Overmorgen werkt ook.",
|
"les": "Bekijk het lessenrooster voor [Dag] in het [Jaargang]-de jaar.\nIndien je geen dag opgeeft, is dit standaard vandaag. De jaargang is standaard 2.\nLes Morgen/Overmorgen werkt ook.",
|
||||||
"lmgtfy": "Stuur iemand een LMGTFY link wanneer ze je een domme vraag stellen in plaats van het zelf op te zoeken.\nQueries met spaties moeten **niet** tussen aanhalingstekens staan.",
|
"lmgtfy": "Stuur iemand een LMGTFY link wanneer ze je een domme vraag stellen in plaats van het zelf op te zoeken.\nQueries met spaties moeten **niet** tussen aanhalingstekens staan.",
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
|
||||||
|
|
||||||
import dateutil.relativedelta
|
import dateutil.relativedelta
|
||||||
import pytz
|
import pytz
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
def epochToDate(epochTimeStamp, strFormat="%d/%m/%Y om %H:%M:%S"):
|
def epochToDate(epochTimeStamp, strFormat="%d/%m/%Y om %H:%M:%S"):
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
import re
|
||||||
|
|
||||||
|
import feedparser
|
||||||
|
from data.embeds import UforaNotification
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
course_urls = {
|
||||||
|
"Algoritmen en Datastructuren 2": "https://ufora.ugent.be/d2l/le/news/rss/222018/course?token=aehhv6utkf46t8cc102e0&ou=222018",
|
||||||
|
"Communicatienetwerken": "https://ufora.ugent.be/d2l/le/news/rss/221184/course?token=aehhv6utkf46t8cc102e0&ou=221184",
|
||||||
|
"Computerarchitectuur": "https://ufora.ugent.be/d2l/le/news/rss/228912/course?token=aehhv6utkf46t8cc102e0&ou=228912",
|
||||||
|
"Functioneel Programmeren": "https://ufora.ugent.be/d2l/le/news/rss/236396/course?token=aehhv6utkf46t8cc102e0&ou=236396",
|
||||||
|
"Multimedia": "https://ufora.ugent.be/d2l/le/news/rss/236949/course?token=aehhv6utkf46t8cc102e0&ou=236949",
|
||||||
|
"Software Engineering Lab 1": "https://ufora.ugent.be/d2l/le/news/rss/235800/course?token=aehhv6utkf46t8cc102e0&ou=235800",
|
||||||
|
"Statistiek en Probabiliteit": "https://ufora.ugent.be/d2l/le/news/rss/236398/course?token=aehhv6utkf46t8cc102e0&ou=236398",
|
||||||
|
"Systeemprogrammeren": "https://ufora.ugent.be/d2l/le/news/rss/222035/course?token=aehhv6utkf46t8cc102e0&ou=222035",
|
||||||
|
"Webdevelopment": "https://ufora.ugent.be/d2l/le/news/rss/223449/course?token=aehhv6utkf46t8cc102e0&ou=223449",
|
||||||
|
"Wetenschappelijk Rekenen": "https://ufora.ugent.be/d2l/le/news/rss/236404/course?token=aehhv6utkf46t8cc102e0&ou=236404"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
"""
|
||||||
|
Check for new notifications
|
||||||
|
"""
|
||||||
|
# List of new notifications
|
||||||
|
new_notifications = []
|
||||||
|
|
||||||
|
# List of old notifications
|
||||||
|
with open("files/ufora_notifications.json", "r") as fp:
|
||||||
|
notifications = json.load(fp)
|
||||||
|
|
||||||
|
for course, url in course_urls.items():
|
||||||
|
# Automatically append new/missing courses
|
||||||
|
if course not in notifications:
|
||||||
|
notifications[course] = []
|
||||||
|
|
||||||
|
# Get the updated feed
|
||||||
|
feed = feedparser.parse(url)
|
||||||
|
|
||||||
|
# Filter out old notifications
|
||||||
|
feed = list(filter(lambda f: _parse_ids(f["id"])[0] not in notifications[course], feed.entries))
|
||||||
|
|
||||||
|
if feed:
|
||||||
|
for item in feed:
|
||||||
|
notif_id, course_id = _parse_ids(item["id"])
|
||||||
|
new_notifications.append(UforaNotification(item, course, notif_id, course_id))
|
||||||
|
|
||||||
|
notifications[course].append(notif_id)
|
||||||
|
|
||||||
|
# Update list of notifications
|
||||||
|
if new_notifications:
|
||||||
|
with open("files/ufora_notifications.json", "w") as fp:
|
||||||
|
json.dump(notifications, fp)
|
||||||
|
|
||||||
|
return new_notifications
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_ids(url: str):
|
||||||
|
match = re.search(r"[0-9]+-[0-9]+$", url)
|
||||||
|
|
||||||
|
if not match:
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
spl = match[0].split("-")
|
||||||
|
|
||||||
|
return spl[0], spl[1]
|
19
ignored.md
19
ignored.md
|
@ -103,3 +103,22 @@ Contains the stats to track for gambling games. Weren't made as a PSQL table bec
|
||||||
Contains Didier's status message for when he logs in. Keep in mind that his activity is set to `Playing `. This was first used in Didier V1 to show whether or not he was in sandbox mode.
|
Contains Didier's status message for when he logs in. Keep in mind that his activity is set to `Playing `. This was first used in Didier V1 to show whether or not he was in sandbox mode.
|
||||||
|
|
||||||
with your Didier Dinks.
|
with your Didier Dinks.
|
||||||
|
|
||||||
|
### files/ufora_notifications.json
|
||||||
|
|
||||||
|
Stores ID's of all received Ufora notifications.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"Algoritmen en Datastructuren 2": [],
|
||||||
|
"Communicatienetwerken": [],
|
||||||
|
"Computerarchitectuur": [],
|
||||||
|
"Functioneel Programmeren": [],
|
||||||
|
"Multimedia": [],
|
||||||
|
"Software Engineering Lab 1": [],
|
||||||
|
"Statistiek en Probabiliteit": [],
|
||||||
|
"Systeemprogrammeren": [],
|
||||||
|
"Webdevelopment": [],
|
||||||
|
"Wetenschappelijk Rekenen": []
|
||||||
|
}
|
||||||
|
```
|
Loading…
Reference in New Issue