mirror of https://github.com/stijndcl/didier
commit
2bfd507bce
|
@ -1,11 +1,8 @@
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
import datetime
|
|
||||||
from decorators import help
|
from decorators import help
|
||||||
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 checks, config
|
from functions import checks, config
|
||||||
import requests
|
from functions.football import getMatches, getTable
|
||||||
import tabulate
|
|
||||||
|
|
||||||
|
|
||||||
class Football(commands.Cog):
|
class Football(commands.Cog):
|
||||||
|
@ -14,7 +11,7 @@ class Football(commands.Cog):
|
||||||
|
|
||||||
# Don't allow any commands to work when locked
|
# Don't allow any commands to work when locked
|
||||||
def cog_check(self, ctx):
|
def cog_check(self, ctx):
|
||||||
return checks.isMe(ctx) and not self.client.locked
|
return not self.client.locked
|
||||||
|
|
||||||
@commands.group(name="Jpl", case_insensitive=True, invoke_without_command=True)
|
@commands.group(name="Jpl", case_insensitive=True, invoke_without_command=True)
|
||||||
@commands.check(checks.allowedChannels)
|
@commands.check(checks.allowedChannels)
|
||||||
|
@ -25,64 +22,19 @@ class Football(commands.Cog):
|
||||||
@jpl.command(name="Matches", aliases=["M"], usage="[Week]*")
|
@jpl.command(name="Matches", aliases=["M"], usage="[Week]*")
|
||||||
async def matches(self, ctx, *args):
|
async def matches(self, ctx, *args):
|
||||||
args = list(args)
|
args = list(args)
|
||||||
|
|
||||||
|
# Default is current day
|
||||||
if not args:
|
if not args:
|
||||||
args = [str(config.get("jpl_day"))]
|
args = [str(config.get("jpl_day"))]
|
||||||
|
|
||||||
if all(letter.isdigit() for letter in args[0]):
|
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()
|
await ctx.send(getMatches(int(args[0])))
|
||||||
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"])))
|
|
||||||
else:
|
else:
|
||||||
return await ctx.send("Dit is geen geldige speeldag.")
|
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"])
|
@jpl.command(name="Table", aliases=["Ranking", "Rankings", "Ranks", "T"])
|
||||||
async def table(self, ctx, *args):
|
async def table(self, ctx, *args):
|
||||||
page_html = requests.get("https://sporza.be/nl/categorie/voetbal/jupiler-pro-league/").text
|
await ctx.send(getTable())
|
||||||
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="])))
|
|
||||||
|
|
||||||
# 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("<!--")[0])
|
|
||||||
return scoresArray
|
|
||||||
|
|
||||||
|
|
||||||
def setup(client):
|
def setup(client):
|
||||||
|
|
62
cogs/fun.py
62
cogs/fun.py
|
@ -3,10 +3,10 @@ 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 checks, mock, stringFormatters
|
from functions import checks, stringFormatters
|
||||||
from functions.database import memes, trump, dadjoke
|
from functions.database import memes, trump, dadjoke
|
||||||
|
from functions.memes import generate
|
||||||
import json
|
import json
|
||||||
import os
|
|
||||||
import random
|
import random
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
@ -91,63 +91,23 @@ class Fun(commands.Cog):
|
||||||
return await ctx.send("Controleer je argumenten.")
|
return await ctx.send("Controleer je argumenten.")
|
||||||
|
|
||||||
# Get the meme info that corresponds to this name
|
# Get the meme info that corresponds to this name
|
||||||
result = memes.getMeme(name)
|
result: memes.Meme = memes.getMeme(name)
|
||||||
|
|
||||||
# No meme found
|
# No meme found
|
||||||
if not result[0]:
|
if result is None:
|
||||||
return await ctx.send(result[1])
|
return await ctx.send("Deze meme staat niet in de database.")
|
||||||
|
|
||||||
# Convert to list to support item assignment
|
# Convert to list to support item assignment
|
||||||
fields = list(fields)
|
fields = list(fields)
|
||||||
|
|
||||||
# If there's only one field, the user isn't required to use quotes
|
generated = generate(result, fields)
|
||||||
if result[1][2] == 1:
|
|
||||||
fields = [" ".join(fields)]
|
|
||||||
|
|
||||||
# Apply mock to mocking spongebob memes
|
# If the request was successful, remove the message calling it
|
||||||
if result[1][1] == "mocking spongebob":
|
if generated["success"]:
|
||||||
fields = list(map(mock.mock, fields))
|
|
||||||
|
|
||||||
# X, X everywhere only takes X as an argument
|
|
||||||
if result[1][1] == "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[1][0],
|
|
||||||
"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)
|
await self.utilsCog.removeMessage(ctx.message)
|
||||||
else:
|
|
||||||
await ctx.send(
|
# Send the meme's url or the error message
|
||||||
"Error! Controleer of je de juiste syntax hebt gebruikt. Gebruik het commando "
|
await ctx.send(generated["message"])
|
||||||
"\"memes\" voor een lijst aan geaccepteerde meme-namen.")
|
|
||||||
else:
|
|
||||||
await ctx.send("Er is een fout opgetreden.")
|
|
||||||
|
|
||||||
@commands.command(name="Memes")
|
@commands.command(name="Memes")
|
||||||
@commands.check(checks.allowedChannels)
|
@commands.check(checks.allowedChannels)
|
||||||
|
|
|
@ -130,7 +130,7 @@ class ModCommands(commands.Cog):
|
||||||
# Adds a meme into the database
|
# Adds a meme into the database
|
||||||
@add.command(name="Meme", aliases=["Mem"], usage="[Id] [Name] [Aantal Velden]")
|
@add.command(name="Meme", aliases=["Mem"], usage="[Id] [Name] [Aantal Velden]")
|
||||||
async def meme(self, ctx, memeid, meme, fields):
|
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
|
# Adds a person's GitHub into the database
|
||||||
@add.command(name="GitHub", aliases=["Gh", "Git"], usage="[Id] [Link]")
|
@add.command(name="GitHub", aliases=["Gh", "Git"], usage="[Id] [Link]")
|
||||||
|
|
|
@ -102,7 +102,7 @@ class Stats(commands.Cog):
|
||||||
embed.set_author(name="Channel Activity - {}".format(ctx.guild))
|
embed.set_author(name="Channel Activity - {}".format(ctx.guild))
|
||||||
|
|
||||||
description = ""
|
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):
|
if not any(tc.id == int(c[0]) for tc in ctx.guild.text_channels):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,9 @@ from data.remind import Reminders
|
||||||
from discord.ext import commands, tasks
|
from discord.ext import commands, tasks
|
||||||
from enums.numbers import Numbers
|
from enums.numbers import Numbers
|
||||||
from functions import timeFormatters
|
from functions import timeFormatters
|
||||||
|
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
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
import requests
|
import requests
|
||||||
|
@ -21,6 +23,7 @@ class Tasks(commands.Cog):
|
||||||
self.checkBirthdays.start()
|
self.checkBirthdays.start()
|
||||||
self.updateMessageCounts.start()
|
self.updateMessageCounts.start()
|
||||||
self.sendReminders.start()
|
self.sendReminders.start()
|
||||||
|
self.updateMatchweek.start()
|
||||||
|
|
||||||
@tasks.loop(hours=1.0)
|
@tasks.loop(hours=1.0)
|
||||||
async def bankInterest(self):
|
async def bankInterest(self):
|
||||||
|
@ -218,6 +221,23 @@ class Tasks(commands.Cog):
|
||||||
async def beforeSendReminders(self):
|
async def beforeSendReminders(self):
|
||||||
await self.client.wait_until_ready()
|
await self.client.wait_until_ready()
|
||||||
|
|
||||||
|
@tasks.loop(hours=2.0)
|
||||||
|
async def updateMatchweek(self):
|
||||||
|
"""
|
||||||
|
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):
|
def getCurrentHour(self):
|
||||||
return timeFormatters.dateTimeNow().hour
|
return timeFormatters.dateTimeNow().hour
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@ class Translate(commands.Cog):
|
||||||
def cog_check(self, ctx):
|
def cog_check(self, ctx):
|
||||||
return not self.client.locked
|
return not self.client.locked
|
||||||
|
|
||||||
@commands.command(name="Translate", aliases=["Tl", "Trans"], usage="[Tekst] [Van]* [Naar]*")
|
# @commands.command(name="Translate", aliases=["Tl", "Trans"], usage="[Tekst] [Van]* [Naar]*")
|
||||||
@help.Category(Category.Words)
|
# @help.Category(Category.Words)
|
||||||
async def translate(self, ctx, query=None, to="nl", fr="auto"):
|
async def translate(self, ctx, query=None, to="nl", fr="auto"):
|
||||||
if query is None:
|
if query is None:
|
||||||
return await ctx.send("Controleer je argumenten.")
|
return await ctx.send("Controleer je argumenten.")
|
||||||
|
@ -57,8 +57,8 @@ class Translate(commands.Cog):
|
||||||
|
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
@commands.command(name="Detect", aliases=["Ld"], usage="[Tekst]")
|
# @commands.command(name="Detect", aliases=["Ld"], usage="[Tekst]")
|
||||||
@help.Category(Category.Words)
|
# @help.Category(Category.Words)
|
||||||
async def detect(self, ctx, query=None):
|
async def detect(self, ctx, query=None):
|
||||||
if query is None:
|
if query is None:
|
||||||
return await ctx.send("Controleer je argumenten.")
|
return await ctx.send("Controleer je argumenten.")
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"semester": "1", "year": "2", "years": 2, "jpl": 161733, "jpl_day": 4}
|
{"semester": "1", "year": "2", "years": 2, "jpl": 161733, "jpl_day": 22}
|
|
@ -1,14 +1,18 @@
|
||||||
|
from attr import dataclass
|
||||||
|
|
||||||
from functions.database import utils
|
from functions.database import utils
|
||||||
|
|
||||||
|
|
||||||
def insert(id, name, fields):
|
def insert(id, name, fields):
|
||||||
if getMeme(name)[0]:
|
if getMeme(name) is not None:
|
||||||
return [False, "Deze meme staat al in de database."]
|
return "Deze meme staat al in de database."
|
||||||
|
|
||||||
connection = utils.connect()
|
connection = utils.connect()
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("INSERT INTO memes(id, name, fields) VALUES (%s, %s, %s)", [int(id), name.lower(), int(fields)])
|
cursor.execute("INSERT INTO memes(id, name, fields) VALUES (%s, %s, %s)", [int(id), name.lower(), int(fields)])
|
||||||
connection.commit()
|
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):
|
def getMeme(name):
|
||||||
|
@ -16,9 +20,23 @@ def getMeme(name):
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("SELECT * FROM memes WHERE name like %s", ["%" + name.lower() + "%"])
|
cursor.execute("SELECT * FROM memes WHERE name like %s", ["%" + name.lower() + "%"])
|
||||||
result = cursor.fetchall()
|
result = cursor.fetchall()
|
||||||
|
|
||||||
if len(result) == 0:
|
if len(result) == 0:
|
||||||
return [False, "Deze meme staat niet in de database."]
|
return None
|
||||||
return [True, 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():
|
def getAllMemes():
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
from enum import Enum
|
||||||
|
from attr import dataclass, field
|
||||||
|
from functions.timeFormatters import fromString
|
||||||
|
from functions.scraping import getJPLMatches, getJPLTable
|
||||||
|
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 list of matches for a given matchweek
|
||||||
|
"""
|
||||||
|
current_day = getJPLMatches(matchweek)
|
||||||
|
|
||||||
|
# API request failed
|
||||||
|
if current_day is None:
|
||||||
|
return "Er ging iets fout. 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)
|
||||||
|
|
||||||
|
|
||||||
|
def getTable():
|
||||||
|
"""
|
||||||
|
Function that constructs the current table of the JPL
|
||||||
|
"""
|
||||||
|
rows = getJPLTable()
|
||||||
|
|
||||||
|
if rows is None:
|
||||||
|
return "Er ging iets fout. Probeer het later opnieuw."
|
||||||
|
|
||||||
|
# Format every row to work for Tabulate
|
||||||
|
formatted = [_formatRow(row) for row in rows]
|
||||||
|
|
||||||
|
header = "Jupiler Pro League Klassement"
|
||||||
|
table = tabulate.tabulate(formatted, headers=["#", "Ploeg", "Punten", "M", "M+", "M-", "M="])
|
||||||
|
|
||||||
|
return "```{}\n\n{}```".format(header, table)
|
||||||
|
|
||||||
|
|
||||||
|
def _formatRow(row):
|
||||||
|
"""
|
||||||
|
Function that formats a row into a list for Tabulate to use
|
||||||
|
"""
|
||||||
|
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("<!--")[0])
|
||||||
|
|
||||||
|
return scoresArray
|
|
@ -0,0 +1,102 @@
|
||||||
|
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.
|
||||||
|
|
||||||
|
Links certain meme id's to functions that need to be applied first.
|
||||||
|
"""
|
||||||
|
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):
|
||||||
|
return list(map(mock, 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"]
|
|
@ -1,3 +1,5 @@
|
||||||
|
import re
|
||||||
|
|
||||||
from requests import get
|
from requests import get
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
@ -43,3 +45,62 @@ def google_search(query):
|
||||||
divs = bs.find_all("div", attrs={"class": "g"})
|
divs = bs.find_all("div", attrs={"class": "g"})
|
||||||
|
|
||||||
return list(getContent(d) for d in divs), 200
|
return list(getContent(d) for d in divs), 200
|
||||||
|
|
||||||
|
|
||||||
|
def getMatchweek():
|
||||||
|
"""
|
||||||
|
Parses the current JPL matchweek out of Sporza's site
|
||||||
|
"""
|
||||||
|
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]
|
||||||
|
|
||||||
|
|
||||||
|
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"]
|
||||||
|
|
||||||
|
|
||||||
|
def getJPLTable():
|
||||||
|
"""
|
||||||
|
JPL table
|
||||||
|
"""
|
||||||
|
page_html = get("https://sporza.be/nl/categorie/voetbal/jupiler-pro-league/")
|
||||||
|
|
||||||
|
# Something went wrong
|
||||||
|
if page_html.status_code != 200:
|
||||||
|
return None
|
||||||
|
|
||||||
|
bs_parsed = BeautifulSoup(page_html.text, "html.parser")
|
||||||
|
rows = bs_parsed.find(summary="algemeen klassement").find_all("tr")[1:]
|
||||||
|
return rows
|
||||||
|
|
Loading…
Reference in New Issue