From 25f4ac5314c3f4da7d51293400d3f786a314549b Mon Sep 17 00:00:00 2001 From: Stijn De Clercq Date: Sun, 24 Jan 2021 21:49:06 +0100 Subject: [PATCH 01/11] Disable Translate until a fix for the module is found (#16) --- cogs/translate.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cogs/translate.py b/cogs/translate.py index 548a7ae..7330673 100644 --- a/cogs/translate.py +++ b/cogs/translate.py @@ -15,8 +15,8 @@ class Translate(commands.Cog): def cog_check(self, ctx): return not self.client.locked - @commands.command(name="Translate", aliases=["Tl", "Trans"], usage="[Tekst] [Van]* [Naar]*") - @help.Category(Category.Words) + # @commands.command(name="Translate", aliases=["Tl", "Trans"], usage="[Tekst] [Van]* [Naar]*") + # @help.Category(Category.Words) async def translate(self, ctx, query=None, to="nl", fr="auto"): if query is None: return await ctx.send("Controleer je argumenten.") @@ -57,8 +57,8 @@ class Translate(commands.Cog): raise e - @commands.command(name="Detect", aliases=["Ld"], usage="[Tekst]") - @help.Category(Category.Words) + # @commands.command(name="Detect", aliases=["Ld"], usage="[Tekst]") + # @help.Category(Category.Words) async def detect(self, ctx, query=None): if query is None: return await ctx.send("Controleer je argumenten.") From d9d8c6a842f15ba066429e144fc8de524e1bad80 Mon Sep 17 00:00:00 2001 From: Stijn De Clercq Date: Sun, 24 Jan 2021 22:00:24 +0100 Subject: [PATCH 02/11] Fix incorrect sorting in stats ca --- cogs/stats.py | 2 +- cogs/tasks.py | 4 ++++ functions/scraping.py | 7 +++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cogs/stats.py b/cogs/stats.py index 0c45151..7a20d56 100644 --- a/cogs/stats.py +++ b/cogs/stats.py @@ -102,7 +102,7 @@ class Stats(commands.Cog): embed.set_author(name="Channel Activity - {}".format(ctx.guild)) description = "" - for c in sorted(res, key=lambda x: int(x[1]), reverse=True): + for c in sorted(res, key=lambda x: float(x[1]), reverse=True): if not any(tc.id == int(c[0]) for tc in ctx.guild.text_channels): continue diff --git a/cogs/tasks.py b/cogs/tasks.py index 2771335..b57a87d 100644 --- a/cogs/tasks.py +++ b/cogs/tasks.py @@ -218,6 +218,10 @@ class Tasks(commands.Cog): async def beforeSendReminders(self): await self.client.wait_until_ready() + # TODO + async def updateMatchweek(self): + pass + def getCurrentHour(self): return timeFormatters.dateTimeNow().hour diff --git a/functions/scraping.py b/functions/scraping.py index cde779f..fcb2b3a 100644 --- a/functions/scraping.py +++ b/functions/scraping.py @@ -43,3 +43,10 @@ def google_search(query): divs = bs.find_all("div", attrs={"class": "g"}) return list(getContent(d) for d in divs), 200 + + +def getMatchweek(): + """ + Parses the current JPL matchweek out of Sporza's site + """ + pass From 2b96f3ec413dac33916fa3df46d8378dbf9d023f Mon Sep 17 00:00:00 2001 From: Stijn De Clercq Date: Sun, 24 Jan 2021 22:31:09 +0100 Subject: [PATCH 03/11] Scrape current jpl matchweek every few hours --- cogs/tasks.py | 20 ++++++++++++++++++-- files/config.json | 2 +- functions/scraping.py | 28 +++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/cogs/tasks.py b/cogs/tasks.py index b57a87d..d38e14c 100644 --- a/cogs/tasks.py +++ b/cogs/tasks.py @@ -3,7 +3,9 @@ from data.remind import Reminders from discord.ext import commands, tasks from enums.numbers import Numbers from functions import timeFormatters +from functions.config import config from functions.database import currency, poke, prison, birthdays, stats +from functions.scraping import getMatchweek import json import random import requests @@ -21,6 +23,7 @@ class Tasks(commands.Cog): self.checkBirthdays.start() self.updateMessageCounts.start() self.sendReminders.start() + self.updateMatchweek.start() @tasks.loop(hours=1.0) async def bankInterest(self): @@ -218,9 +221,22 @@ class Tasks(commands.Cog): async def beforeSendReminders(self): await self.client.wait_until_ready() - # TODO + @tasks.loop(hours=2.0) async def updateMatchweek(self): - pass + """ + Task that checks the current JPL matchweek & changes the dict value + """ + matchweek = getMatchweek() + + if matchweek is None: + return + + # Change the setting in the config + config("jpl_day", int(matchweek)) + + @updateMatchweek.before_loop + async def beforeUpdateMatchweek(self): + await self.client.wait_until_ready() def getCurrentHour(self): return timeFormatters.dateTimeNow().hour diff --git a/files/config.json b/files/config.json index 6ef40bc..d2a501a 100644 --- a/files/config.json +++ b/files/config.json @@ -1 +1 @@ -{"semester": "1", "year": "2", "years": 2, "jpl": 161733, "jpl_day": 4} \ No newline at end of file +{"semester": "1", "year": "2", "years": 2, "jpl": 161733, "jpl_day": 21} \ No newline at end of file diff --git a/functions/scraping.py b/functions/scraping.py index fcb2b3a..aef771a 100644 --- a/functions/scraping.py +++ b/functions/scraping.py @@ -1,3 +1,5 @@ +import re + from requests import get from urllib.parse import urlencode from bs4 import BeautifulSoup @@ -49,4 +51,28 @@ def getMatchweek(): """ Parses the current JPL matchweek out of Sporza's site """ - pass + resp = get("https://sporza.be/nl/categorie/voetbal/jupiler-pro-league/") + + if resp.status_code != 200: + return None + + bs = BeautifulSoup(resp.text, "html.parser") + matchdays = bs.find_all("section", attrs={"class": "sc-matchdays"}) + + if len(matchdays) < 2: + return None + + # Table header + header = matchdays[1] + + # Regex to find current matchday + r = re.compile(r"speeldag\s*\d+", flags=re.I) + + match = r.search(str(header)) + + # Something went wrong, just ignore + if match is None: + return None + + # "Speeldag DD" -> split on space & take second + return match[0].split(" ")[1] From 8238bdf6dea8d7dccdafacaf05df004763d23712 Mon Sep 17 00:00:00 2001 From: Stijn De Clercq Date: Mon, 25 Jan 2021 00:16:38 +0100 Subject: [PATCH 04/11] Clean up Football matches a lot --- cogs/football.py | 34 ++--------- functions/football.py | 134 ++++++++++++++++++++++++++++++++++++++++++ functions/scraping.py | 13 ++++ 3 files changed, 152 insertions(+), 29 deletions(-) create mode 100644 functions/football.py diff --git a/cogs/football.py b/cogs/football.py index b025543..fbe4b98 100644 --- a/cogs/football.py +++ b/cogs/football.py @@ -1,9 +1,9 @@ from bs4 import BeautifulSoup -import datetime from decorators import help from discord.ext import commands from enums.help_categories import Category from functions import checks, config +from functions.football import getMatches import requests import tabulate @@ -25,37 +25,13 @@ class Football(commands.Cog): @jpl.command(name="Matches", aliases=["M"], usage="[Week]*") async def matches(self, ctx, *args): args = list(args) + + # Default is current day if not args: args = [str(config.get("jpl_day"))] + if all(letter.isdigit() for letter in args[0]): - current_day = requests.get("https://api.sporza.be/web/soccer/matchdays/161733/{}".format(args[0])).json() - current_day = current_day["groupedMatches"][0]["matches"] - - # Create dictionaries for every match - matches_formatted = {} - for i, match in enumerate(current_day): - matchDic = {"home": match["homeTeam"]["name"], "away": match["awayTeam"]["name"]} - - # Add date - matchDate = datetime.datetime.strptime(match["startDateTime"].split("+")[0], "%Y-%m-%dT%H:%M:%S.%f") - matchDic["date"] = matchDate.strftime("%d/%m") - matchDic["day"] = self.get_weekday(matchDate.weekday()) - - # TODO check back when there's active games (to find the key in the dict) & add the current time if not over - # Add scores - if match["status"] == "END": # Status != [not_yet_started] whatever it is - matchDic["score"] = "{} - {}".format(match["homeScore"], match["awayScore"]) - else: - # If there's no score, show when the match starts - matchDic["score"] = "{}:{}".format( - ("" if len(str(matchDate.hour)) == 2 else "0") + str(matchDate.hour), # Leading Zero - ("" if len(str(matchDate.minute)) == 2 else "0") + str(matchDate.minute)) # Leading Zero - - matches_formatted[i] = matchDic - - # Put every formatted version of the matches in a list - matchList = list([self.format_match(matches_formatted[match]) for match in matches_formatted]) - await ctx.send("```Jupiler Pro League - Speeldag {}\n\n{}```".format(args[0], tabulate.tabulate(matchList, headers=["Dag", "Datum", "Thuis", "Stand", "Uit", "Tijd"]))) + await ctx.send(getMatches(int(args[0]))) else: return await ctx.send("Dit is geen geldige speeldag.") diff --git a/functions/football.py b/functions/football.py new file mode 100644 index 0000000..47b2efe --- /dev/null +++ b/functions/football.py @@ -0,0 +1,134 @@ +from enum import Enum +from attr import dataclass, field +from functions.timeFormatters import fromString +from functions.scraping import getJPLMatches +from functions.stringFormatters import leadingZero +from datetime import datetime +import tabulate + + +class Status(Enum): + AfterToday = "--:--" + NotStarted = "--:--" + Over = "Einde" + HalfTime = "Rust" + + +@dataclass +class Match: + """ + Class representing a football match between two teams + """ + matchDict: dict + home: str = field(init=False) + homeScore: int = 0 + away: str = field(init=False) + awayScore: int = 0 + start: datetime = field(init=False) + date: str = field(init=False) + weekDay: str = field(init=False) + status: Status = field(init=False) + + def __attrs_post_init__(self): + """ + Parse class attributes out of a dictionary returned from an API request + """ + # The API isn't public, so every single game state is differently formatted + self.status = self._getStatus(self.matchDict[Navigation.Status.value]) + self.home = self.matchDict[Navigation.HomeTeam.value][Navigation.Name.value] + self.away = self.matchDict[Navigation.AwayTeam.value][Navigation.Name.value] + + if self._hasStarted(): + self.homeScore = self.matchDict[Navigation.HomeScore.value] + self.awayScore = self.matchDict[Navigation.AwayScore.value] + + self.start = fromString(self.matchDict["startDateTime"], formatString="%Y-%m-%dT%H:%M:%S.%f%z") + self.date = self.start.strftime("%d/%m") + self.weekDay = self._getWeekday() + + def _getStatus(self, status: str): + """ + Gets the string representation for the status of this match + """ + # LiveTime only exists if the status is live + # Avoids KeyErrors + if status.lower() == "live": + # Half time + if Navigation.LiveMatchPhase.value in self.matchDict and \ + Navigation.LiveMatchPhase.value == Navigation.HalfTime.value: + return Status.HalfTime.value + + # Current time + return self.matchDict[Navigation.LiveTime.value] + + # If no special status, pull it out of this dict + statusses: dict = { + "after_today": Status.AfterToday.value, + "not_started": Status.NotStarted.value, + "end": Status.Over.value + } + + return statusses[status.lower()] + + def _getWeekday(self): + """ + Gets the day of the week this match is played on + """ + day = self.start.weekday() + days = ["Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"] + return days[day] + + def getInfo(self): + """ + Returns a list of all the info of this class in order to create a table + """ + return [self.weekDay, self.date, self.home, self._getScore(), self.away, self.status] + + def _getScore(self): + """ + Returns a string representing the scoreboard + """ + # No score to show yet, show time when the match starts + if not self._hasStarted(): + return "{}:{}".format(leadingZero(str(self.start.hour)), leadingZero(str(self.start.minute))) + + return "{} - {}".format(self.homeScore, self.awayScore) + + def _hasStarted(self): + return self.status not in [Status.AfterToday.value, Status.NotStarted.value] + + +class Navigation(Enum): + """ + Enum to navigate through the matchdict, + seeing as the API is private the keys of the dict could change every now and then + so this makes sure a key only has to be changed once. + """ + AwayTeam = "awayTeam" + HomeTeam = "homeTeam" + AwayScore = "awayScore" + HomeScore = "homeScore" + LiveTime = "liveTime" + LiveMatchPhase = "liveMatchPhase" + HalfTime = "HALF_TIME" + Status = "status" + Name = "name" + + +def getMatches(matchweek: int): + """ + Function that constructs the table for a given matchweek + """ + current_day = getJPLMatches(matchweek) + + # API request failed + if current_day is None: + return "Er ging iets mis. Probeer het later opnieuw." + + matches = list(map(Match, current_day)) + matches = list(map(lambda x: x.getInfo(), matches)) + + header = "Jupiler Pro League - Speeldag {}".format(matchweek) + table = tabulate.tabulate(matches, headers=["Dag", "Datum", "Thuis", "Stand", "Uit", "Tijd"]) + + return "```{}\n\n{}```".format(header, table) diff --git a/functions/scraping.py b/functions/scraping.py index aef771a..a389bdd 100644 --- a/functions/scraping.py +++ b/functions/scraping.py @@ -76,3 +76,16 @@ def getMatchweek(): # "Speeldag DD" -> split on space & take second return match[0].split(" ")[1] + + +def getJPLMatches(week: int): + """ + JPL matches for a given matchweek + """ + current_day = get("https://api.sporza.be/web/soccer/matchdays/161733/{}".format(week)) + + # Something went wrong + if current_day.status_code != 200: + return None + + return current_day.json()["groupedMatches"][0]["matches"] From f2b62c3ce7885b6e0c26893dcb7dc06cdbee1400 Mon Sep 17 00:00:00 2001 From: Stijn De Clercq Date: Mon, 25 Jan 2021 23:21:40 +0100 Subject: [PATCH 05/11] Clean up memegen code a bit --- cogs/fun.py | 12 ++++++------ cogs/modCommands.py | 2 +- functions/database/memes.py | 12 +++++++----- functions/memes.py | 0 4 files changed, 14 insertions(+), 12 deletions(-) create mode 100644 functions/memes.py diff --git a/cogs/fun.py b/cogs/fun.py index f546aa6..d5b9e42 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -94,22 +94,22 @@ class Fun(commands.Cog): result = memes.getMeme(name) # No meme found - if not result[0]: - return await ctx.send(result[1]) + if result is None: + return await ctx.send("Deze meme staat niet in de database.") # Convert to list to support item assignment fields = list(fields) # If there's only one field, the user isn't required to use quotes - if result[1][2] == 1: + if result[2] == 1: fields = [" ".join(fields)] # Apply mock to mocking spongebob memes - if result[1][1] == "mocking spongebob": + if result[1] == "mocking spongebob": fields = list(map(mock.mock, fields)) # X, X everywhere only takes X as an argument - if result[1][1] == "x, x everywhere": + if result[1] == "x, x everywhere": fields[0] = " ".join(fields) fields.append(fields[0] + " everywhere") @@ -127,7 +127,7 @@ class Fun(commands.Cog): if req["success"]: caption = { - "template_id": result[1][0], + "template_id": result[0], "username": os.getenv("IMGFLIPNAME"), "password": os.getenv("IMGFLIPPASSWORD"), "boxes[0][text]": boxes[0]["text"], diff --git a/cogs/modCommands.py b/cogs/modCommands.py index 274d7fe..70a6077 100644 --- a/cogs/modCommands.py +++ b/cogs/modCommands.py @@ -130,7 +130,7 @@ class ModCommands(commands.Cog): # Adds a meme into the database @add.command(name="Meme", aliases=["Mem"], usage="[Id] [Name] [Aantal Velden]") async def meme(self, ctx, memeid, meme, fields): - await ctx.send(memes.insert(memeid, meme, fields)[1]) + await ctx.send(memes.insert(memeid, meme, fields)) # Adds a person's GitHub into the database @add.command(name="GitHub", aliases=["Gh", "Git"], usage="[Id] [Link]") diff --git a/functions/database/memes.py b/functions/database/memes.py index ab55c1e..1385651 100644 --- a/functions/database/memes.py +++ b/functions/database/memes.py @@ -2,13 +2,15 @@ from functions.database import utils def insert(id, name, fields): - if getMeme(name)[0]: - return [False, "Deze meme staat al in de database."] + if getMeme(name) is not None: + return "Deze meme staat al in de database." + connection = utils.connect() cursor = connection.cursor() cursor.execute("INSERT INTO memes(id, name, fields) VALUES (%s, %s, %s)", [int(id), name.lower(), int(fields)]) connection.commit() - return [True, "{} is toegevoegd aan de database.".format(name[0].upper() + name[1:].lower())] + + return "{} is toegevoegd aan de database.".format(name[0].upper() + name[1:].lower()) def getMeme(name): @@ -17,8 +19,8 @@ def getMeme(name): cursor.execute("SELECT * FROM memes WHERE name like %s", ["%" + name.lower() + "%"]) result = cursor.fetchall() if len(result) == 0: - return [False, "Deze meme staat niet in de database."] - return [True, result[0]] + return None + return result[0] def getAllMemes(): diff --git a/functions/memes.py b/functions/memes.py new file mode 100644 index 0000000..e69de29 From 77addbc30c90abbc94610a135bb426c3535bc1af Mon Sep 17 00:00:00 2001 From: Stijn De Clercq Date: Mon, 25 Jan 2021 23:30:52 +0100 Subject: [PATCH 06/11] Use meme class --- cogs/fun.py | 10 +++++----- functions/database/memes.py | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/cogs/fun.py b/cogs/fun.py index d5b9e42..961609e 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -91,7 +91,7 @@ class Fun(commands.Cog): return await ctx.send("Controleer je argumenten.") # Get the meme info that corresponds to this name - result = memes.getMeme(name) + result: memes.Meme = memes.getMeme(name) # No meme found if result is None: @@ -101,15 +101,15 @@ class Fun(commands.Cog): fields = list(fields) # If there's only one field, the user isn't required to use quotes - if result[2] == 1: + if result.fields == 1: fields = [" ".join(fields)] # Apply mock to mocking spongebob memes - if result[1] == "mocking spongebob": + if result.name == "mocking spongebob": fields = list(map(mock.mock, fields)) # X, X everywhere only takes X as an argument - if result[1] == "x, x everywhere": + if result.name == "x, x everywhere": fields[0] = " ".join(fields) fields.append(fields[0] + " everywhere") @@ -127,7 +127,7 @@ class Fun(commands.Cog): if req["success"]: caption = { - "template_id": result[0], + "template_id": result.meme_id, "username": os.getenv("IMGFLIPNAME"), "password": os.getenv("IMGFLIPPASSWORD"), "boxes[0][text]": boxes[0]["text"], diff --git a/functions/database/memes.py b/functions/database/memes.py index 1385651..2c2a443 100644 --- a/functions/database/memes.py +++ b/functions/database/memes.py @@ -1,3 +1,5 @@ +from attr import dataclass + from functions.database import utils @@ -18,9 +20,23 @@ def getMeme(name): cursor = connection.cursor() cursor.execute("SELECT * FROM memes WHERE name like %s", ["%" + name.lower() + "%"]) result = cursor.fetchall() + if len(result) == 0: return None - return result[0] + + meme = Meme(result[0][0], result[0][1], result[0][2]) + + return meme + + +@dataclass +class Meme: + """ + Dataclass to represent a meme in order to avoid having to use [] on tuples all the time + """ + meme_id: int + name: str + fields: int def getAllMemes(): From 7c47c6af73527516b05022a0d6d8912f2d6139c2 Mon Sep 17 00:00:00 2001 From: Stijn De Clercq Date: Tue, 26 Jan 2021 00:05:44 +0100 Subject: [PATCH 07/11] Clean memegen code up more, add more memes (#15) --- cogs/fun.py | 56 ++++-------------------- functions/memes.py | 105 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 48 deletions(-) diff --git a/cogs/fun.py b/cogs/fun.py index 961609e..ca4338f 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -3,10 +3,10 @@ from decorators import help import discord from discord.ext import commands from enums.help_categories import Category -from functions import checks, mock, stringFormatters +from functions import checks, stringFormatters from functions.database import memes, trump, dadjoke +from functions.memes import generate import json -import os import random import requests @@ -100,54 +100,14 @@ class Fun(commands.Cog): # Convert to list to support item assignment fields = list(fields) - # If there's only one field, the user isn't required to use quotes - if result.fields == 1: - fields = [" ".join(fields)] + generated = generate(result, fields) - # Apply mock to mocking spongebob memes - if result.name == "mocking spongebob": - fields = list(map(mock.mock, fields)) + # If the request was successful, remove the message calling it + if generated["success"]: + await self.utilsCog.removeMessage(ctx.message) - # X, X everywhere only takes X as an argument - if result.name == "x, x everywhere": - fields[0] = " ".join(fields) - fields.append(fields[0] + " everywhere") - - # List of fields to send to the API - boxes = [{"text": ""}, {"text": ""}, {"text": ""}, {"text": ""}] - - # Add all fields required & ignore the excess ones - for i in range(len(fields)): - if i > 3: - break - boxes[i]["text"] = fields[i] - - # Check server status - req = requests.get('https://api.imgflip.com/get_memes').json() - - if req["success"]: - caption = { - "template_id": result.meme_id, - "username": os.getenv("IMGFLIPNAME"), - "password": os.getenv("IMGFLIPPASSWORD"), - "boxes[0][text]": boxes[0]["text"], - "boxes[1][text]": boxes[1]["text"], - "boxes[2][text]": boxes[2]["text"], - "boxes[3][text]": boxes[3]["text"] - } - - # Send the POST to the API - memeReply = requests.post('https://api.imgflip.com/caption_image', caption).json() - - if memeReply['success']: - await ctx.send(str(memeReply['data']['url'])) - await self.utilsCog.removeMessage(ctx.message) - else: - await ctx.send( - "Error! Controleer of je de juiste syntax hebt gebruikt. Gebruik het commando " - "\"memes\" voor een lijst aan geaccepteerde meme-namen.") - else: - await ctx.send("Er is een fout opgetreden.") + # Send the meme's url or the error message + await ctx.send(generated["message"]) @commands.command(name="Memes") @commands.check(checks.allowedChannels) diff --git a/functions/memes.py b/functions/memes.py index e69de29..4b3255e 100644 --- a/functions/memes.py +++ b/functions/memes.py @@ -0,0 +1,105 @@ +import os + +import requests + +from functions.database.memes import Meme +from functions.mock import mock + + +def generate(meme: Meme, fields): + """ + Main function that takes a Meme as input & generates an image. + """ + # If there's only one field, the user isn't required to use quotes + if meme.fields == 1: + fields = [" ".join(fields)] + + fields = _applyMeme(meme, fields) + + # List of fields to send to the API + boxes = [{"text": ""}, {"text": ""}, {"text": ""}, {"text": ""}] + + # Add all fields required & ignore the excess ones + for i in range(len(fields)): + if i > 3: + break + boxes[i]["text"] = fields[i] + + # Check server status + req = requests.get('https://api.imgflip.com/get_memes').json() + + # Server is down + if not req["success"]: + return {"success": False, "message": "Er is een fout opgetreden."} + + # Post meme + reply = _postMeme(meme, boxes) + + # Adding a message parameter makes the code in the cog a lot cleaner + if not reply["success"]: + reply["message"] = "Error! Controleer of je de juiste syntax hebt gebruikt. Gebruik het commando " \ + "\"memes\" voor een lijst aan geaccepteerde meme-namen." + else: + reply["message"] = reply["data"]["url"] + + return reply + + +def _postMeme(meme: Meme, boxes): + """ + Performs API request to generate the meme + """ + caption = { + "template_id": meme.meme_id, + "username": os.getenv("IMGFLIPNAME"), + "password": os.getenv("IMGFLIPPASSWORD"), + "boxes[0][text]": boxes[0]["text"], + "boxes[1][text]": boxes[1]["text"], + "boxes[2][text]": boxes[2]["text"], + "boxes[3][text]": boxes[3]["text"] + } + + # Send the POST to the API + memeReply = requests.post('https://api.imgflip.com/caption_image', caption).json() + + return memeReply + + +def _applyMeme(meme: Meme, fields): + """ + Some memes are in a special format that only requires + a few words to be added, or needs the input to be changed. + This function handles all that. + + Callbacks contains a function that modifies the input + """ + memeDict = { + 102156234: _mockingSpongebob, + 91538330: _xXEverywhere, + 252600902: _alwaysHasBeen + } + + # Meme needs no special treatment + if meme.meme_id not in memeDict: + return fields + + return memeDict[meme.meme_id](fields) + + +def _mockingSpongebob(fields): + for i, field in enumerate(fields): + fields[i] = mock(field) + + return fields + + +def _xXEverywhere(fields): + word = fields[0] + + return ["{}".format(word), "{} everywhere".format(word)] + + +def _alwaysHasBeen(fields): + word = fields[0] + + return ["Wait, it's all {}?".format(word), "Always has been"] From 89fdc70813c9760d00f223d2e593a44e0ea301ac Mon Sep 17 00:00:00 2001 From: Stijn De Clercq Date: Tue, 26 Jan 2021 21:58:49 +0100 Subject: [PATCH 08/11] Clean up jpl table --- cogs/football.py | 27 ++------------------------- files/config.json | 2 +- functions/football.py | 33 ++++++++++++++++++++++++++++++--- functions/memes.py | 5 +---- functions/scraping.py | 14 ++++++++++++++ 5 files changed, 48 insertions(+), 33 deletions(-) diff --git a/cogs/football.py b/cogs/football.py index fbe4b98..dc27334 100644 --- a/cogs/football.py +++ b/cogs/football.py @@ -1,11 +1,8 @@ -from bs4 import BeautifulSoup from decorators import help from discord.ext import commands from enums.help_categories import Category from functions import checks, config -from functions.football import getMatches -import requests -import tabulate +from functions.football import getMatches, getTable class Football(commands.Cog): @@ -35,30 +32,10 @@ class Football(commands.Cog): else: return await ctx.send("Dit is geen geldige speeldag.") - # TODO check back when there's active games & add the timestamp instead of EINDE - def format_match(self, match): - return [match["day"], match["date"], match["home"], match["score"], match["away"], "Einde"] - - def get_weekday(self, day: int): - days = ["Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"] - return days[day] - @jpl.command(name="Table", aliases=["Ranking", "Rankings", "Ranks", "T"]) async def table(self, ctx, *args): - page_html = requests.get("https://sporza.be/nl/categorie/voetbal/jupiler-pro-league/").text - bs_parsed = BeautifulSoup(page_html, "html.parser") - rows = bs_parsed.find(summary="algemeen klassement").find_all("tr")[1:] - rowsFormatted = [] - for row in rows: - rowsFormatted.append(self.createRowList(row)) - await ctx.send("```Jupiler Pro League Klassement\n\n{}```".format(tabulate.tabulate(rowsFormatted, headers=["#", "Ploeg", "Punten", "M", "M+", "M-", "M="]))) + await ctx.send(getTable()) - # Formats the row into an list that can be passed to Tabulate - def createRowList(self, row): - scoresArray = list([td.renderContents().decode("utf-8") for td in row.find_all("td")])[:6] - # Insert the team name into the list - scoresArray.insert(1, row.find_all("a")[0].renderContents().decode("utf-8").split("