From 3c8d34acdd57ec664e392ffec1f8bf5c721ae72a Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Thu, 3 Nov 2022 23:28:14 +0100 Subject: [PATCH 01/40] eerste opzet testje --- tests.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests.py diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..f2c3082 --- /dev/null +++ b/tests.py @@ -0,0 +1,37 @@ +import unittest +import configparser +import praw +import random + +import General + +class TestTest(unittest.TestCase): + def test_a(self): + self.assertEqual(1, 1) + def test_b(self): + self.assertEqual("ab", "a" + "b") + +class TestGeneral(unittest.TestCase): + def setUp(self): + config = configparser.ConfigParser() + config.read('stroopwafel.ini') + self.tokens = config["tokens"] + self.r = praw.Reddit( + user_agent='StroopwafelBot', + client_secret=self.tokens["redditSecret"], + client_id=self.tokens["redditId"] + ) + self.r.read_only = True + + def test_aww(self): + # Duplicate code is tijdelijk!!!11one + raww = self.r.subreddit('aww+catloaf+tuckedinkitties+babyelephantgifs+babybigcatgifs+blep+holdmynip+gingerkitty+cathighfive+catsstandingup+catsareassholes+eyebleach') + post = raww.top('month', limit=250) + listing = list(post) + random.shuffle(listing) + post = listing[0] + print(post) + self.assertIsInstance(post,praw.models.Submission) + + def test_playlist(self): + pass \ No newline at end of file From f89889fc48f28738ec86da03c3e9c108fe42da3d Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Fri, 4 Nov 2022 23:25:36 +0100 Subject: [PATCH 02/40] refactors en echte tests ofzo --- General.py | 14 ++++++++------ tests.py | 25 ++++++++++++++++++------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/General.py b/General.py index 6d8bfda..9e7e9a8 100644 --- a/General.py +++ b/General.py @@ -8,7 +8,6 @@ import json, requests from discord.ext import commands from sympy import latex, symbols, preview, Symbol #for LaTeX images import youtube_dl -import ffmpeg class General(commands.Cog): """Overal toegestaan.""" @@ -16,6 +15,7 @@ class General(commands.Cog): def __init__(self, bot): self.bot = bot self.voice_states = {} + self.muzak_url = 'https://hdcon-muzak.herokuapp.com' self.r = praw.Reddit( user_agent='StroopwafelBot', client_secret=self.bot.tokens["redditSecret"], @@ -85,7 +85,7 @@ class General(commands.Cog): rkopieerpasta = self.r.subreddit('kopieerpasta') post = rkopieerpasta.random() - # Subreddits kunnen de random functie uitzetten, dus dit is de fallback: + # Subreddits kunnen de random functie uitzetten, dus dit is de fallback: if post == None: post = rkopieerpasta.top('month', limit=250) listing = list(post) @@ -121,15 +121,17 @@ Op kunt u bijvoorbeeld via een web-interface gifjes maken Namens de directie van Stroopwafel B.V. onze excuses voor dit ongemak.""") + def get_playlist_json(self): + return requests.get(self.muzak_url + '/stroopwafel') + @commands.command(pass_context=True) @asyncio.coroutine def playlist(self, ctx): """HDcon2021 playlist""" - muzak_url = 'https://hdcon-muzak.herokuapp.com' - data = json.loads(requests.get(muzak_url + '/stroopwafel').content) # als dit faalt yolo no catch - msg = 'Stemmen en nomineren kan hier: {}\n'.format(muzak_url) + data = json.loads(self.get_playlist_json().content) + msg = 'Stemmen en nomineren kan hier: {}\n'.format(self.muzak_url) msg += '*Er zijn al {} nummers genomineerd*\n'.format(data['stemCount']) - yield from ctx.channel.send(msg) + yield from ctx.channel.send(self.get_playlist_msg()) @commands.command(pass_context=True, hidden=True) @asyncio.coroutine diff --git a/tests.py b/tests.py index f2c3082..ea64811 100644 --- a/tests.py +++ b/tests.py @@ -2,15 +2,14 @@ import unittest import configparser import praw import random +import requests +import json + +import discord +from discord.ext import commands import General -class TestTest(unittest.TestCase): - def test_a(self): - self.assertEqual(1, 1) - def test_b(self): - self.assertEqual("ab", "a" + "b") - class TestGeneral(unittest.TestCase): def setUp(self): config = configparser.ConfigParser() @@ -22,6 +21,12 @@ class TestGeneral(unittest.TestCase): client_id=self.tokens["redditId"] ) self.r.read_only = True + intents = discord.Intents.default() + intents.message_content = True + intents.members = True + bot = commands.Bot(command_prefix=commands.when_mentioned_or('!'), description='Stroopwafel. Shitpost bot extraordinaire.', pm_help=True, intents=intents) + bot.tokens = self.tokens + self.cog = General.General(bot) def test_aww(self): # Duplicate code is tijdelijk!!!11one @@ -34,4 +39,10 @@ class TestGeneral(unittest.TestCase): self.assertIsInstance(post,praw.models.Submission) def test_playlist(self): - pass \ No newline at end of file + data = self.cog.get_playlist_json() + with self.subTest(msg="Reddit doesn't return 200"): + self.assertEqual(data.status_code, 200) + with self.subTest(msg="Not a good response"): + self.assertIsInstance(data, requests.Response) + with self.subTest(msg="Does not convert to json"): + self.assertIsInstance(json.loads(data.content), dict) \ No newline at end of file From 67bb071305c3d4034211e951b999588a53a7bce6 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 13 Nov 2022 19:58:27 +0100 Subject: [PATCH 03/40] adds requirements for pip --- .gitignore | 3 ++- requirements.txt | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index b15dfb2..b0771d7 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,6 @@ stroopwafel.ini Stroopwafel.sln Stroopwafel.pyproj *.txt +!requirements.txt *.sh -*.npy \ No newline at end of file +*.npy diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5959dba --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +caldav +discord.py +praw +sympy +numpy +youtube_dl +python-ffmpeg From 7e9e88eee7896b51e0f1d7f06cfadc08967e1a4f Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 13 Nov 2022 20:00:31 +0100 Subject: [PATCH 04/40] adds drone config nog wel de vraag hoe het gaat zonder ini en hoe we die er in krijgen, maar dat moeten we maar even zien --- .drone.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .drone.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..98a22ef --- /dev/null +++ b/.drone.yml @@ -0,0 +1,9 @@ +kind: pipeline +name: default + +steps: +- name: test + image: python:3.10 + commands: + - pip install -r requirements.txt + - python -m unittest tests From fc0d59964d4a88210054a77bad5f3a453d21325c Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 13 Nov 2022 20:02:07 +0100 Subject: [PATCH 05/40] alleen builden op push, niet op PR --- .drone.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.drone.yml b/.drone.yml index 98a22ef..2719268 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,3 +7,7 @@ steps: commands: - pip install -r requirements.txt - python -m unittest tests +trigger: + event: + exclude: + - pull_request From da7262307d9550d3e50d0390c124bcf660a2c067 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Mon, 14 Nov 2022 16:13:44 +0100 Subject: [PATCH 06/40] fix domme bug waar we niet voor testen --- General.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/General.py b/General.py index 9e7e9a8..d7134c1 100644 --- a/General.py +++ b/General.py @@ -131,7 +131,7 @@ Namens de directie van Stroopwafel B.V. onze excuses voor dit ongemak.""") data = json.loads(self.get_playlist_json().content) msg = 'Stemmen en nomineren kan hier: {}\n'.format(self.muzak_url) msg += '*Er zijn al {} nummers genomineerd*\n'.format(data['stemCount']) - yield from ctx.channel.send(self.get_playlist_msg()) + yield from ctx.channel.send(msg) @commands.command(pass_context=True, hidden=True) @asyncio.coroutine From 2c69b13f3dd9ea8bd91e7e563a099b9c6a5eb4f5 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Mon, 14 Nov 2022 16:18:42 +0100 Subject: [PATCH 07/40] vervangt ini file met dotenv Maakt het makkelijker om te testen, en is sowieso betere manier denk ik --- .gitignore | 3 ++- General.py | 6 +++--- Points.py | 3 ++- Shitpost.py | 18 +++++++++--------- Stroopwafel.py | 26 +++++--------------------- requirements.txt | 1 + tests.py | 25 +++---------------------- 7 files changed, 25 insertions(+), 57 deletions(-) diff --git a/.gitignore b/.gitignore index b0771d7..4a5ac38 100644 --- a/.gitignore +++ b/.gitignore @@ -5,10 +5,11 @@ tijd/ test.png UpgradeLog\.htm markov_dict.npy -stroopwafel.ini +*.ini Stroopwafel.sln Stroopwafel.pyproj *.txt !requirements.txt *.sh *.npy +.env diff --git a/General.py b/General.py index d7134c1..ad4296e 100644 --- a/General.py +++ b/General.py @@ -18,8 +18,8 @@ class General(commands.Cog): self.muzak_url = 'https://hdcon-muzak.herokuapp.com' self.r = praw.Reddit( user_agent='StroopwafelBot', - client_secret=self.bot.tokens["redditSecret"], - client_id=self.bot.tokens["redditId"] + client_secret=os.getenv("STROOP_REDDIT_SECRET"), + client_id=os.getenv("STROOP_REDDIT_ID") ) self.r.read_only = True @@ -137,7 +137,7 @@ Namens de directie van Stroopwafel B.V. onze excuses voor dit ongemak.""") @asyncio.coroutine def reboot(self, ctx, password=""): """ Reboot.. """ - if password == self.bot.passwords["resetpassword"]: + if password == os.getenv("STROOP_RESET_PASSWORD"): yield from ctx.channel.send("Rebooting.. brb!") os.execv(sys.executable, ['python3'] + sys.argv) else: diff --git a/Points.py b/Points.py index 934d18b..f65827e 100644 --- a/Points.py +++ b/Points.py @@ -5,6 +5,7 @@ from pprint import pprint import time import numpy as np import random +import os from datetime import datetime class Points(commands.Cog): @@ -264,7 +265,7 @@ class Points(commands.Cog): np.save("pointscount.npy", pointsCount) # Add new/unknown members: - list_channel = self.bot.get_channel(self.bot.hdChannels["shitpost"]) + list_channel = self.bot.get_channel(int(os.getenv('STROOP_CHANNEL_SHITPOST'))) memberList = list_channel.members if list_channel else [] for member in memberList: # Give new members 100 points diff --git a/Shitpost.py b/Shitpost.py index 949e2cd..4ac8781 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -27,7 +27,7 @@ class Shitpost(commands.Cog): 'knoeier','sufferd','slaapkop','onbenul','enorme nerf herder','geinponem', 'clownsfiguur','krotenkoker','hansworst','grappenmaker','flapdrol','oen', 'achterlijk gebakje','demente dibbes','geitenbreier','koekwous','sufkop'] - self.caldav_client = caldav.DAVClient(url=self.bot.tokens['caldav_url']) + self.caldav_client = caldav.DAVClient(url=os.getenv('STROOP_CALDAV_HOST')) def __check(self, ctx): #Todo: Is dit het shitpost kanaal? return True @@ -218,7 +218,7 @@ class Shitpost(commands.Cog): Ja of Nee.. kom op nou. """ #We halen dit op van de twitter account @gietitaloan die vertrouwen wij als de ultieme waarheid - consumer = oauth.Consumer(key=self.bot.tokens["twitterKey"], secret=self.bot.tokens["twitterSecret"]) + consumer = oauth.Consumer(key=os.getenv('STROOP_TWITTER_KEY'), secret=os.getenv('STROOP_TWITTER_SECRET')) client = oauth.Client(consumer) resp, content = client.request("https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=gietitaloan&count=1", "GET") #TODO kijken of resp iets zinnigs teruggeeft.. of iets doen met een try of catch ofzow @@ -266,7 +266,7 @@ class Shitpost(commands.Cog): params = dict( template_id = '78416340', #party hard username = 'Stroopwafel', - password = self.bot.passwords["imgflip"], + password = os.getenv("STROOP_IMGFLIP_PASSWORD"), text0 = boven, text1 = onder ) @@ -291,7 +291,7 @@ class Shitpost(commands.Cog): params = dict( template_id = '112898841', #de marku username = 'Stroopwafel', - password = self.bot.passwords["imgflip"], + password = os.getenv("STROOP_IMGFLIP_PASSWORD"), text0 = boven, text1 = onder ) @@ -317,7 +317,7 @@ class Shitpost(commands.Cog): params = dict( template_id = '93296473', #de eriku username = 'Stroopwafel', - password = self.bot.passwords["imgflip"], + password = os.getenv('STROOP_IMGFLIP_PASSWORD'), text0 = boven, text1 = onder ) @@ -344,7 +344,7 @@ class Shitpost(commands.Cog): params = { 'template_id': '121572521', #delfts blauw 'username': 'Stroopwafel', - 'password': self.bot.passwords["imgflip"], + 'password': os.getenv('STROOP_IMGFLIP_PASSWORD'), 'text0': 'dummy0', 'text1': 'dummy1', 'font': 'arial', @@ -417,7 +417,7 @@ class Shitpost(commands.Cog): params = dict( template_id = '116231806', #de martijn username = 'Stroopwafel', - password = self.bot.passwords["imgflip"], + password = os.getenv('STROOP_IMGFLIP_PASSWORD'), text0 = boven, text1 = onder ) @@ -545,7 +545,7 @@ class Shitpost(commands.Cog): else: v = True - url = f"http://weerlive.nl/api/json-data-10min.php?key={self.bot.tokens['weerLive']}&locatie={location}" + url = f"http://weerlive.nl/api/json-data-10min.php?key={os.getenv('STROOP_WEERLIVE')}&locatie={location}" response = requests.get(url) #Oant Moarn @@ -710,7 +710,7 @@ class Shitpost(commands.Cog): def watspelenweecht(self): """Geeft een paar terug, met de titel en omschrijving van het eerstvolgende event uit de kalender""" - calendar = self.caldav_client.calendar(url=self.bot.tokens["calendar"]) # refresh kalender + calendar = self.caldav_client.calendar(url=os.getenv('STROOP_CALDAV_CAL')) # refresh kalender # geen errorchecking hier, de caller doet dat maar gewoon ofzo, yolo events = calendar.date_search( diff --git a/Stroopwafel.py b/Stroopwafel.py index 43807a8..d00fc68 100644 --- a/Stroopwafel.py +++ b/Stroopwafel.py @@ -7,14 +7,15 @@ import Cryptocoin import Chatbot import Points import logging -import importlib -import configparser -import base64 +import dotenv +import os from discord.ext import commands logging.basicConfig(level=logging.INFO) +dotenv.load_dotenv() + async def add_cogs(bot): await bot.add_cog(Shitpost.Shitpost(bot)) await bot.add_cog(General.General(bot)) @@ -28,26 +29,9 @@ intents.members = True bot = commands.Bot(command_prefix=commands.when_mentioned_or('!'), description='Stroopwafel. Shitpost bot extraordinaire.', pm_help=True, intents=intents) -#Read configuration file: -config = configparser.ConfigParser() -config.read('stroopwafel.ini') -bot.tokens = config["tokens"] -bot.hdChannels = {} -for channel in config["channels"]: #channelIDs must be integers - bot.hdChannels[channel] = int(config["channels"][channel]) - -#passwords are base64 encoded, which makes it like 1% safer -bot.passwords = {} -for pw in config["passwords"]: - try: - bot.passwords[pw] = (base64.standard_b64decode(config["passwords"][pw])).decode() - except: - print("Problem with decoding password!") - bot.passwords[pw] = config["passwords"][pw] - @bot.event async def on_ready(): await add_cogs(bot) print('Logged in as:\n{0} (ID: {0.id})'.format(bot.user)) -bot.run(bot.tokens["discordbot"]) +bot.run(os.getenv("STROOP_DISCORD_TOKEN")) diff --git a/requirements.txt b/requirements.txt index 5959dba..2556519 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ sympy numpy youtube_dl python-ffmpeg +python-dotenv diff --git a/tests.py b/tests.py index ea64811..f932b25 100644 --- a/tests.py +++ b/tests.py @@ -1,9 +1,9 @@ import unittest -import configparser import praw import random import requests import json +import dotenv import discord from discord.ext import commands @@ -12,32 +12,13 @@ import General class TestGeneral(unittest.TestCase): def setUp(self): - config = configparser.ConfigParser() - config.read('stroopwafel.ini') - self.tokens = config["tokens"] - self.r = praw.Reddit( - user_agent='StroopwafelBot', - client_secret=self.tokens["redditSecret"], - client_id=self.tokens["redditId"] - ) - self.r.read_only = True + dotenv.load_dotenv() intents = discord.Intents.default() intents.message_content = True intents.members = True bot = commands.Bot(command_prefix=commands.when_mentioned_or('!'), description='Stroopwafel. Shitpost bot extraordinaire.', pm_help=True, intents=intents) - bot.tokens = self.tokens self.cog = General.General(bot) - def test_aww(self): - # Duplicate code is tijdelijk!!!11one - raww = self.r.subreddit('aww+catloaf+tuckedinkitties+babyelephantgifs+babybigcatgifs+blep+holdmynip+gingerkitty+cathighfive+catsstandingup+catsareassholes+eyebleach') - post = raww.top('month', limit=250) - listing = list(post) - random.shuffle(listing) - post = listing[0] - print(post) - self.assertIsInstance(post,praw.models.Submission) - def test_playlist(self): data = self.cog.get_playlist_json() with self.subTest(msg="Reddit doesn't return 200"): @@ -45,4 +26,4 @@ class TestGeneral(unittest.TestCase): with self.subTest(msg="Not a good response"): self.assertIsInstance(data, requests.Response) with self.subTest(msg="Does not convert to json"): - self.assertIsInstance(json.loads(data.content), dict) \ No newline at end of file + self.assertIsInstance(json.loads(data.content), dict) From b0901cb2e960a286da9d95b6132f5447c22e0254 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Wed, 16 Nov 2022 12:58:17 +0100 Subject: [PATCH 08/40] get secrets from drone --- .drone.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.drone.yml b/.drone.yml index 2719268..83f140a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -4,6 +4,29 @@ name: default steps: - name: test image: python:3.10 + environment: + STROOP_DISCORD_TOKEN: + from_secret: STROOP_DISCORD_TOKEN + STROOP_TWITTER_KEY: + from_secret: STROOP_TWITTER_KEY + STROOP_TWITTER_SECRET: + from_secret: STROOP_TWITTER_SECRET + STROOP_REDDIT_ID: + from_secret: STROOP_REDDIT_ID + STROOP_REDDIT_SECRET: + from_secret: STROOP_REDDIT_SECRET + STROOP_WEERLIVE: + from_secret: STROOP_WEERLIVE + STROOP_CALDAV_HOST: + from_secret: STROOP_CALDAV_HOST + STROOP_CALDAV_CAL: + from_secret: STROOP_CALDAV_CAL + STROOP_IMGFLIP_PASSWORD: + from_secret: STROOP_IMGFLIP_PASSWORD + STROOP_RESET_PASSWORD: + from_secret: STROOP_RESET_PASSWORD + STROOP_CHANNEL_SHITPOST: + from_secret: STROOP_CHANNEL_SHITPOST commands: - pip install -r requirements.txt - python -m unittest tests From 3ef817c6aa1129777310d250a9de71d93925c81e Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Fri, 2 Dec 2022 19:35:29 +0100 Subject: [PATCH 09/40] Expected failure for server down Was even een les om te leren. Nu checkt hij eerst voor een 5xx response. --- tests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests.py b/tests.py index f932b25..cf7dd14 100644 --- a/tests.py +++ b/tests.py @@ -21,7 +21,9 @@ class TestGeneral(unittest.TestCase): def test_playlist(self): data = self.cog.get_playlist_json() - with self.subTest(msg="Reddit doesn't return 200"): + if data.status_code >= 500: + self.skipTest(f"Server at {self.cog.muzak_url} has an error") + with self.subTest(msg=f"{self.cog.muzak_url} doesn't return 200"): self.assertEqual(data.status_code, 200) with self.subTest(msg="Not a good response"): self.assertIsInstance(data, requests.Response) From 54b3dfd290367aa082fe30b20d90bf4b43ed1838 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Fri, 2 Dec 2022 21:07:55 +0100 Subject: [PATCH 10/40] tests voor aww --- General.py | 13 ++++++------- tests.py | 6 ++++++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/General.py b/General.py index ad4296e..c86b601 100644 --- a/General.py +++ b/General.py @@ -61,17 +61,16 @@ class General(commands.Cog): print("No permission to delete message") yield from ctx.channel.send(ctx.author.mention, file=discord.File('test.png', 'tex.png')) + def get_aww_post(self): + raww = self.r.subreddit('aww+catloaf+tuckedinkitties+babyelephantgifs+babybigcatgifs+blep+holdmynip+gingerkitty+cathighfive+catsstandingup+catsareassholes+eyebleach') + listing = list(raww.top(time_filter='month')) + return random.choice(listing) + @commands.command(pass_context=True) @asyncio.coroutine def aww(self, ctx): """ iets schattigs... """ - print(type(ctx.message.channel)) - raww = self.r.subreddit('aww+catloaf+tuckedinkitties+babyelephantgifs+babybigcatgifs+blep+holdmynip+gingerkitty+cathighfive+catsstandingup+catsareassholes+eyebleach') - post = raww.top('month', limit=250) - listing = list(post) - random.shuffle(listing) - post = listing[0] - + post = self.get_aww_post() try: yield from ctx.message.delete() except: diff --git a/tests.py b/tests.py index cf7dd14..22ebc82 100644 --- a/tests.py +++ b/tests.py @@ -29,3 +29,9 @@ class TestGeneral(unittest.TestCase): self.assertIsInstance(data, requests.Response) with self.subTest(msg="Does not convert to json"): self.assertIsInstance(json.loads(data.content), dict) + + def test_aww(self): + if not isinstance(self.cog.r, praw.Reddit): + self.skipTest("PRAW Reddit instance failed to create") + post = self.cog.get_aww_post() + self.assertIsInstance(post.url, str) From 009d64ef160050e88f02cf882c42e992c48cb047 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Fri, 2 Dec 2022 21:50:20 +0100 Subject: [PATCH 11/40] Test voor kopieerpasta --- General.py | 38 ++++++++++++++++++++++++-------------- tests.py | 7 +++++++ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/General.py b/General.py index c86b601..b11f33d 100644 --- a/General.py +++ b/General.py @@ -5,6 +5,7 @@ import praw import random import re import json, requests +import warnings from discord.ext import commands from sympy import latex, symbols, preview, Symbol #for LaTeX images import youtube_dl @@ -22,6 +23,7 @@ class General(commands.Cog): client_id=os.getenv("STROOP_REDDIT_ID") ) self.r.read_only = True + warnings.simplefilter("ignore") def __check(self, ctx): #Todo: Is dit het porno kanaal? return True @@ -77,30 +79,38 @@ class General(commands.Cog): print("No permission to delete message") yield from ctx.channel.send(ctx.author.mention + ' ' + post.url) + def get_kopieerpasta(self): + rkopieerpasta = self.r.subreddit('kopieerpasta') + post = rkopieerpasta.random() + + # Subreddits kunnen de random functie uitzetten, dus dit is de fallback: + if post == None: + listing = list(rkopieerpasta.top('month', limit=250)) + post = random.choice(listing) + + return post + @commands.command(pass_context=True) @asyncio.coroutine def kopieerpasta(self, ctx): """Een willekeurige shitpost""" - rkopieerpasta = self.r.subreddit('kopieerpasta') - post = rkopieerpasta.random() - - # Subreddits kunnen de random functie uitzetten, dus dit is de fallback: - if post == None: - post = rkopieerpasta.top('month', limit=250) - listing = list(post) - random.shuffle(listing) - post = listing[0] + post = self.get_kopieerpasta() + print(post.url) + ATTEMPTS = 10 + a = 0 + while len(post.selftext + post.title) >= 1990 and a < ATTEMPTS: + post = self.get_kopieerpasta() + print(post.url) + a += 1 try: yield from ctx.message.delete() except: print("No permission to delete message") - # Er is een 2000 karakter limiet wat met sommige pastas overschreden kan worden. - # eigenlijk willen we het dan opnieuw proberen maar dat is lastiger, dus maar gewoon berichtje. - if (len(post.selftext)+len(post.title)) >= 1990: - yield from ctx.channel.send('Sorry, kopieerpasta te lang. Probeer het maar opnieuw .') - else: + if len(post.selftext + post.title) < 1990: yield from ctx.channel.send('**'+post.title+'**```'+post.selftext+'```') + else: + yield from ctx.channel.send("Geen kopieerpasta voor jou vandaag.") @commands.command(pass_context=True) @asyncio.coroutine diff --git a/tests.py b/tests.py index 22ebc82..e57ed51 100644 --- a/tests.py +++ b/tests.py @@ -35,3 +35,10 @@ class TestGeneral(unittest.TestCase): self.skipTest("PRAW Reddit instance failed to create") post = self.cog.get_aww_post() self.assertIsInstance(post.url, str) + + def test_kopieerpasta(self): + if not isinstance(self.cog.r, praw.Reddit): + self.skipTest("PRAW Reddit instance failed to create") + post = self.cog.get_kopieerpasta() + self.assertIsInstance(post.url, str) + From 074545f965f76e791105906fdcce090b9ce15bb0 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 4 Dec 2022 15:10:26 +0100 Subject: [PATCH 12/40] Verwijder gif functie Als het het niet doet en we het niet testen, dan moet het weg. --- General.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/General.py b/General.py index b11f33d..92cba0e 100644 --- a/General.py +++ b/General.py @@ -112,24 +112,6 @@ class General(commands.Cog): else: yield from ctx.channel.send("Geen kopieerpasta voor jou vandaag.") - @commands.command(pass_context=True) - @asyncio.coroutine - def gif(self, ctx, yt: str, start: str="0", duration: str="5", res: str="320", fps: int=10): - """ Giffify. Tijdelijk uitgeschakeld. - """ - try: - yield from ctx.message.delete() - except: - print("No permission to delete message") - yield from ctx.channel.send( - ctx.author.mention + - """ -Welkom bij de stroopwafel GIF hotline! -Deze functionaliteit is momenteel helaas offline voor onderhoud. Gelukkig is vergelijkbare functionaliteit ook elders beschikbaar: -Op kunt u bijvoorbeeld via een web-interface gifjes maken van youtube-filmpjes. Geavanceerde gebruikers kunnen u ook proberen, waarna u gifjes kan genereren via bijvoorbeeld . - -Namens de directie van Stroopwafel B.V. onze excuses voor dit ongemak.""") - def get_playlist_json(self): return requests.get(self.muzak_url + '/stroopwafel') From b376191cd82bd801e4f2d191b5f34565e4522005 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 4 Dec 2022 16:28:38 +0100 Subject: [PATCH 13/40] Verwijder reboot functie is alleen maar gewoon gezeik, en restarten kan ook vanuit de server --- General.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/General.py b/General.py index 92cba0e..628e199 100644 --- a/General.py +++ b/General.py @@ -123,13 +123,3 @@ class General(commands.Cog): msg = 'Stemmen en nomineren kan hier: {}\n'.format(self.muzak_url) msg += '*Er zijn al {} nummers genomineerd*\n'.format(data['stemCount']) yield from ctx.channel.send(msg) - - @commands.command(pass_context=True, hidden=True) - @asyncio.coroutine - def reboot(self, ctx, password=""): - """ Reboot.. """ - if password == os.getenv("STROOP_RESET_PASSWORD"): - yield from ctx.channel.send("Rebooting.. brb!") - os.execv(sys.executable, ['python3'] + sys.argv) - else: - yield from ctx.channel.send(ctx.author.mention + " What's the magic word?") From b08933b9f1f4a961b0290ceb27e81238d7a6ab2c Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 4 Dec 2022 16:31:04 +0100 Subject: [PATCH 14/40] Verwijder tex Gebruikt niemand, en vergt 10 gigabyte installs om lokaal te testen --- General.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/General.py b/General.py index 628e199..d433f05 100644 --- a/General.py +++ b/General.py @@ -45,24 +45,6 @@ class General(commands.Cog): print("No permission to delete message") yield from ctx.channel.send(ctx.author.mention, embed=em) - @commands.command() - @asyncio.coroutine - def tex(self, ctx, *, arg): - """Geeft een mooi LaTeX plaatje terug. - Bijvoorbeeld: - !tex Je moeder is lelijk! $a^b b^c \\rightarrow d$ - """ - preamble = "\\documentclass[10pt]{article}\\pagestyle{empty}\\usepackage[margin=1in]{geometry}\\usepackage{amsmath, amsfonts}\\begin{document}" #\\usepackage{CJKutf8}\\usepackage[T1]{fontenc}\\usepackage[english]{babel} - options = ["-T", "tight", "-z", "9", "--truecolor", "-D", "512"] - preview(r''+arg+'', viewer='file', filename='test.png', dvioptions=options, preamble=preamble) - #file = open('test.png', 'rb') - #yield from ctx.channel.send(file, filename ='test.png', content='') - try: - yield from ctx.message.delete() - except: - print("No permission to delete message") - yield from ctx.channel.send(ctx.author.mention, file=discord.File('test.png', 'tex.png')) - def get_aww_post(self): raww = self.r.subreddit('aww+catloaf+tuckedinkitties+babyelephantgifs+babybigcatgifs+blep+holdmynip+gingerkitty+cathighfive+catsstandingup+catsareassholes+eyebleach') listing = list(raww.top(time_filter='month')) From f3dfca14c235e1e748cf30e6c34e40823c7b37c5 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 4 Dec 2022 17:47:49 +0100 Subject: [PATCH 15/40] Test voor huge emoji Test alleen de parsing van de emoji en dat er een embed wordt gemaakt. --- General.py | 13 +++++++++---- tests.py | 5 +++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/General.py b/General.py index d433f05..9486453 100644 --- a/General.py +++ b/General.py @@ -28,6 +28,14 @@ class General(commands.Cog): def __check(self, ctx): #Todo: Is dit het porno kanaal? return True + def get_emoji_embed(self, tag: str): + emoji = re.search(".*\<\:([A-z]*)\:(\d*)\>.*", tag) + embed = discord.Embed(title=emoji.group(1), type='photo') + hugemoji = 'https://cdn.discordapp.com/emojis/' + emoji.group(2) + '.png' + embed.set_image(url=hugemoji) + return embed + + @commands.command() @asyncio.coroutine def huge(self, ctx, *, arg): @@ -35,10 +43,7 @@ class General(commands.Cog): Bijvoorbeeld: !huge :ancilla: """ - id = re.search("\<\:([A-z]*)\:(\d*)\>", arg) - hugemoji = 'https://cdn.discordapp.com/emojis/' + id.group(2) + '.png' - em = discord.Embed(title=id.group(1), type='photo') - em.set_image(url=hugemoji) + em = self.get_emoji_embed(arg) try: yield from ctx.message.delete() except: diff --git a/tests.py b/tests.py index e57ed51..a958bdb 100644 --- a/tests.py +++ b/tests.py @@ -4,6 +4,7 @@ import random import requests import json import dotenv +import re import discord from discord.ext import commands @@ -42,3 +43,7 @@ class TestGeneral(unittest.TestCase): post = self.cog.get_kopieerpasta() self.assertIsInstance(post.url, str) + def test_huge(self): + embed = self.cog.get_emoji_embed("<:test:123456789>") + self.assertIsInstance(embed, discord.Embed) + From 4b5e4cf40741a4f09786fe3dabd19b28afa3aefa Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 4 Dec 2022 19:25:00 +0100 Subject: [PATCH 16/40] Verwijdert enkele requirements Onder andere youtubedl en ffmpeg voor de gif, en de latex sympy. Deze changes zijn ook doorgevoerd in de readme. --- General.py | 2 -- README.md | 14 +------------- requirements.txt | 2 -- 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/General.py b/General.py index 9486453..2a5b73d 100644 --- a/General.py +++ b/General.py @@ -7,8 +7,6 @@ import re import json, requests import warnings from discord.ext import commands -from sympy import latex, symbols, preview, Symbol #for LaTeX images -import youtube_dl class General(commands.Cog): """Overal toegestaan.""" diff --git a/README.md b/README.md index 0203486..bf57b4f 100644 --- a/README.md +++ b/README.md @@ -13,18 +13,6 @@ Vragen en/of opmerkingen kunnen in onderstaande suggestiebox:\ ## Zelf deze bot runnen? -Deze link legt uit hoe je een bot token maakt: -[https://github.com/reactiflux/discord-irc/wiki/Creating-a-discord-bot-&-getting-a-token](https://github.com/reactiflux/discord-irc/wiki/Creating-a-discord-bot-&-getting-a-token) - -Requirements: - -* `discord.py` -* `praw` -* `sympy` -* `asyncio` -* `numpy` -* `youtube_dl` -* `ffmpeg-python` -* `caldav` +Maak een bot token aan, vul wat dingen in in de `.env`, installeer requirements.txt en gaan met de banaan. Verder zoek je het zelf maar uit. \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2556519..a463a10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,4 @@ discord.py praw sympy numpy -youtube_dl -python-ffmpeg python-dotenv From 47ae62afa9cfcd8ac754cf3c044795baff038b59 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 4 Dec 2022 19:32:57 +0100 Subject: [PATCH 17/40] Moves tests to module --- tests/__init__.py | 1 + tests.py => tests/general.py | 0 2 files changed, 1 insertion(+) create mode 100644 tests/__init__.py rename tests.py => tests/general.py (100%) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..ac22dce --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +from .general import TestGeneral \ No newline at end of file diff --git a/tests.py b/tests/general.py similarity index 100% rename from tests.py rename to tests/general.py From e8df92be23cd7dc435b0795380178cfee79b90eb Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 4 Dec 2022 20:40:30 +0100 Subject: [PATCH 18/40] Voegt test voor review toe --- Shitpost.py | 18 ++++++++++-------- tests/__init__.py | 1 + tests/shitpost.py | 27 +++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 tests/shitpost.py diff --git a/Shitpost.py b/Shitpost.py index 4ac8781..55e0986 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -861,15 +861,8 @@ class Shitpost(commands.Cog): except: print("No permission to delete message") yield from ctx.channel.send(message) - - @commands.command(pass_context=True) - @asyncio.coroutine - def review(self, ctx, *args): - """Stroop heeft (bijna) overal een mening over. Vraag het hem! - """ - - topic = " ".join(args) + def get_review_string(self, topic = ""): if topic == "": random.seed(datetime.now()) else: @@ -916,6 +909,15 @@ class Shitpost(commands.Cog): emoj = random.choice(EMOJI) message += str(rating) + " " + emoj*rating + " out of " + str(maxRating) + "." + return message + + @commands.command(pass_context=True) + @asyncio.coroutine + def review(self, ctx, *args): + """Stroop heeft (bijna) overal een mening over. Vraag het hem! + """ + topic = " ".join(args) + message = self.get_review_string(topic) yield from ctx.channel.send(message) diff --git a/tests/__init__.py b/tests/__init__.py index ac22dce..8d7ef16 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1,2 @@ +from .shitpost import TestShitpost from .general import TestGeneral \ No newline at end of file diff --git a/tests/shitpost.py b/tests/shitpost.py new file mode 100644 index 0000000..f9e6a89 --- /dev/null +++ b/tests/shitpost.py @@ -0,0 +1,27 @@ +import unittest +import dotenv +import discord +from discord.ext import commands + +import Shitpost + +class TestShitpost(unittest.TestCase): + def setUp(self): + dotenv.load_dotenv() + intents = discord.Intents.default() + intents.message_content = True + intents.members = True + bot = commands.Bot(command_prefix=commands.when_mentioned_or('!'), description='Stroopwafel. Shitpost bot extraordinaire.', pm_help=True, intents=intents) + self.cog = Shitpost.Shitpost(bot) + + def test_review(self): + TOPIC = "qpwoeirut12" + topic_review = self.cog.get_review_string(TOPIC) + with self.subTest(msg=f"Topic review does not return a string"): + self.assertIsInstance(topic_review, str) + with self.subTest(msg=f"Topic review does not contain the topic"): + self.assertIn(TOPIC, topic_review) + + basic_review = self.cog.get_review_string() + with self.subTest(msg=f"Review does not return a string"): + self.assertIsInstance(basic_review, str) \ No newline at end of file From 7c29180ca41d046b215f7a152c1ed0b6884080ba Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 4 Dec 2022 21:07:59 +0100 Subject: [PATCH 19/40] Adds test watspelenwe Test het martijn en het mark gedeelte los. --- Shitpost.py | 33 ++++++++++++++++----------------- tests/shitpost.py | 23 ++++++++++++++++++++++- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index 55e0986..fa5d845 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -10,6 +10,7 @@ import sys import os import random import caldav +import warnings class Shitpost(commands.Cog): """Schijtpaal commando's. Alleen bruikbaar in de daarvoor toegewezen schijtpaal kanalen.""" @@ -28,6 +29,7 @@ class Shitpost(commands.Cog): 'clownsfiguur','krotenkoker','hansworst','grappenmaker','flapdrol','oen', 'achterlijk gebakje','demente dibbes','geitenbreier','koekwous','sufkop'] self.caldav_client = caldav.DAVClient(url=os.getenv('STROOP_CALDAV_HOST')) + warnings.simplefilter("ignore") def __check(self, ctx): #Todo: Is dit het shitpost kanaal? return True @@ -708,7 +710,7 @@ class Shitpost(commands.Cog): yield from ctx.channel.send(member.mention+ ", " + ctx.author.mention + " vindt jou een " + random.choice(self.insult) + "! :angry:") yield from ctx.message.delete() - def watspelenweecht(self): + def get_watspelenwe_cal(self): """Geeft een paar terug, met de titel en omschrijving van het eerstvolgende event uit de kalender""" calendar = self.caldav_client.calendar(url=os.getenv('STROOP_CALDAV_CAL')) # refresh kalender @@ -720,14 +722,7 @@ class Shitpost(commands.Cog): ) return (events[0].vobject_instance.vevent.summary.value, events[0].vobject_instance.vevent.description.value) - - @commands.command(pass_context=True) - @asyncio.coroutine - def watspelenwe(self, ctx): - """Stroop weet wat we spelen op vrijdag. - Geeft elke week een pseudo-random antwoord. - Geseed op weeknummer + jaar. - """ + def get_watspelenwe_sass(self): SASS = [ "Pathfinder. Nee lmao wie speelt er nu nog pathfinder?", "Midfloat. Oh wacht dat is? Oh in Apeldoorn zeg je? Jeetje.", @@ -850,8 +845,19 @@ class Shitpost(commands.Cog): else: message = "We spelen " + DAG + random.choice(SPELLEN) + " " + random.choice(PLAATSEN) + ", aanvang " + random.choice(AANVANG) + return message + + @commands.command(pass_context=True) + @asyncio.coroutine + def watspelenwe(self, ctx): + """Stroop weet wat we spelen op vrijdag. + Geeft elke week een pseudo-random antwoord. + Geseed op weeknummer + jaar. + """ + message = self.get_watspelenwe_sass() + try: - (activiteit, reden) = self.watspelenweecht() + (activiteit, reden) = self.get_watspelenwe_cal() message += f"\nNee, we doen eigenlijk {activiteit} want {reden}" except: message += ". En wilt iemand even aan Mark vragen of hij de kalender bijhoudt?" @@ -919,10 +925,3 @@ class Shitpost(commands.Cog): topic = " ".join(args) message = self.get_review_string(topic) yield from ctx.channel.send(message) - - - - - -def setup(bot): - bot.add_cog(Shitpost(bot)) diff --git a/tests/shitpost.py b/tests/shitpost.py index f9e6a89..75e0db2 100644 --- a/tests/shitpost.py +++ b/tests/shitpost.py @@ -1,6 +1,8 @@ import unittest import dotenv +import os import discord +import requests from discord.ext import commands import Shitpost @@ -24,4 +26,23 @@ class TestShitpost(unittest.TestCase): basic_review = self.cog.get_review_string() with self.subTest(msg=f"Review does not return a string"): - self.assertIsInstance(basic_review, str) \ No newline at end of file + self.assertIsInstance(basic_review, str) + + def test_watspelenwe_sass(self): + once = self.cog.get_watspelenwe_sass() + twice = self.cog.get_watspelenwe_sass() + with self.subTest(msg="Watspelenwe does not seed correctly"): + self.assertEqual(once, twice) + with self.subTest(msg="Watspelenwe does not return a string"): + self.assertIsInstance(once, str) + + def test_watspelenwe_cal(self): + data = requests.get(os.getenv('STROOP_CALDAV_CAL')) + if not data: + self.skipTest(f"Server at {self.cog.muzak_url} has an error, or is unavailable") + + (activiteit, reden) = self.cog.get_watspelenwe_cal() + with self.subTest(msg="Watspelenwe activiteit does not return a string"): + self.assertIsInstance(activiteit, str) + with self.subTest(msg="Watspelenwe reden does not return a string"): + self.assertIsInstance(reden, str) \ No newline at end of file From 39ec30a048428b9e34e8ed79b21d2c39a60521ef Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 4 Dec 2022 21:16:44 +0100 Subject: [PATCH 20/40] Maakt een klein beetje schoon hier en daar Oude comments, verdwaalde warnings, ongebruikte imports --- General.py | 7 +------ Shitpost.py | 53 +++++++++-------------------------------------------- 2 files changed, 10 insertions(+), 50 deletions(-) diff --git a/General.py b/General.py index 2a5b73d..ee9d122 100644 --- a/General.py +++ b/General.py @@ -1,6 +1,6 @@ import asyncio import discord -import sys, os +import os import praw import random import re @@ -13,7 +13,6 @@ class General(commands.Cog): def __init__(self, bot): self.bot = bot - self.voice_states = {} self.muzak_url = 'https://hdcon-muzak.herokuapp.com' self.r = praw.Reddit( user_agent='StroopwafelBot', @@ -23,9 +22,6 @@ class General(commands.Cog): self.r.read_only = True warnings.simplefilter("ignore") - def __check(self, ctx): #Todo: Is dit het porno kanaal? - return True - def get_emoji_embed(self, tag: str): emoji = re.search(".*\<\:([A-z]*)\:(\d*)\>.*", tag) embed = discord.Embed(title=emoji.group(1), type='photo') @@ -33,7 +29,6 @@ class General(commands.Cog): embed.set_image(url=hugemoji) return embed - @commands.command() @asyncio.coroutine def huge(self, ctx, *, arg): diff --git a/Shitpost.py b/Shitpost.py index fa5d845..4a7ad6c 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -2,11 +2,9 @@ import asyncio import discord from discord.ext import commands from urllib import request -import requests import json, requests import math from datetime import datetime, timedelta -import sys import os import random import caldav @@ -17,10 +15,11 @@ class Shitpost(commands.Cog): def __init__(self, bot): self.bot = bot - self.voice_states = {} self.hdConImpatientEvents = [] - self.zwarte_lijst = [line.rstrip('\n') for line in open('black.txt')] - self.witte_lijst = [line.rstrip('\n') for line in open('white.txt')] # nihao + with open('black.txt') as zwart: + self.zwarte_lijst = [line.rstrip('\n') for line in zwart] + with open('white.txt') as wit: + self.witte_lijst = [line.rstrip('\n') for line in wit] self.insult = ['koekenbakker','stumperd','knurft','oelewapper','klungel','stoethaspel', 'onnozelaar','beunhaas','uilskuiken','bamibal','zwakzinnige','oenemeloen', 'klaphark','rompeknonker','bal gehakt','ongewassen vlerk','droeftoeter','omgedraaid pak hagelslag', @@ -30,14 +29,11 @@ class Shitpost(commands.Cog): 'achterlijk gebakje','demente dibbes','geitenbreier','koekwous','sufkop'] self.caldav_client = caldav.DAVClient(url=os.getenv('STROOP_CALDAV_HOST')) warnings.simplefilter("ignore") - - def __check(self, ctx): #Todo: Is dit het shitpost kanaal? - return True @commands.command(pass_context=True, hidden=False) @asyncio.coroutine def ishetalhdcon(self, ctx): - """Hoe lang nog tot Hoestende Dranken Con 2022? + """Hoe lang nog tot Hoestende Draken Con 2022? Gebruik: !ishetalhdcon """ @@ -246,7 +242,7 @@ class Shitpost(commands.Cog): !inspire """ r = requests.get(url='http://inspirobot.me/api?generate=true') - if r.status_code is 200: + if r.status_code == 200: url = r.text em = discord.Embed(title='Uw wijze woorden:', type='photo') em.set_image(url=url) @@ -297,7 +293,6 @@ class Shitpost(commands.Cog): text0 = boven, text1 = onder ) - #self.bot.say("deed ik het ding?") resp = requests.get(url='https://api.imgflip.com/caption_image', params=params) #todo check for success photourl = resp.json()['data']['url'] @@ -323,7 +318,6 @@ class Shitpost(commands.Cog): text0 = boven, text1 = onder ) - #self.bot.say("deed ik het ding?") resp = requests.get(url='https://api.imgflip.com/caption_image', params=params) #todo check for success photourl = resp.json()['data']['url'] @@ -385,8 +379,6 @@ class Shitpost(commands.Cog): Bijvoorbeeld: !relevantxkcd python """ - - #self.bot.say("deed ik het ding?") response = requests.get("https://relevantxkcd.appspot.com/process?action=xkcd&query=" + query) splitResponse = response.text.split(" ") @@ -423,7 +415,6 @@ class Shitpost(commands.Cog): text0 = boven, text1 = onder ) - #self.bot.say("deed ik het ding?") resp = requests.get(url='https://api.imgflip.com/caption_image', params=params) #todo check for success photourl = resp.json()['data']['url'] @@ -438,7 +429,6 @@ class Shitpost(commands.Cog): @commands.command(pass_context=True, hidden=True) @asyncio.coroutine def nihao(self,ctx): - #yield from self.bot.say("Kankerlauw") yield from ctx.channel.send("kankerlauw") @commands.command(pass_context=True) @@ -454,8 +444,6 @@ class Shitpost(commands.Cog): for argument in args: time = argument filepath = '' - #filejpg = './tijd/' + time + '.jpg' - #filepng = './tijd/' + time + '.png' filejpg = os.path.join('tijd', time) + '.jpg' filepng = os.path.join('tijd', time) + '.png' filegif = os.path.join('tijd', time) + '.gif' @@ -469,9 +457,7 @@ class Shitpost(commands.Cog): yield from ctx.message.delete() except: print("No permission to delete message") - if filepath is not '': - #file = open(filepath, 'rb') - #yield from self.bot.upload(file, filename = filepath) + if filepath != '': yield from ctx.channel.send(ctx.author.mention + ' Het is nu ' + datetime.now().strftime('%H:%M'), file=discord.File(filepath, 'tijd.png')) else: yield from ctx.channel.send(ctx.author.mention + ' Het is nu ' + datetime.now().strftime('%H:%M')) @@ -738,26 +724,17 @@ class Shitpost(commands.Cog): ] SPELLEN = [ "DND", "Ars Magica", - #"5e", "4e", - #"Pathfinder", "Pathfinder 2", - #"CoC", "Delta Green", "een one-shot", "Kaarten tegen de Mensheid", - #"Midfloat", "Isle of Arden", "Cyberpunk 2020", "Star Wars", - "Blades in the Dark", #"Vampire the Masquerade", + "Blades in the Dark", "Expeditie Acquisitie", "Starfinder" - #"MAGE the Ascension" ] PLAATSEN = [ - # het is de na-lockdown-voor-de-volgende-lockdown-patch "bij Mark thuis", "bij Freek thuis", "bij JP thuis", "bij Erik thuis", "bij Lourens thuis", "in de Vrouwensteeg", "bij Martijn thuis", "bij je moeder thuis", "bij de Privรฉ2000", "Vakantiepark Landal Kasteeldomein de Cauberg" - #"op Roll-20", "op Roll-20, bij jezelf thuis, het is lockdown immers", - #"op de digitale vrouwensteeg, te weten Roll-20", "op tabletop simulator? Oh maar dit is bizar kut, toch maar weer Roll-20", - #"bij Freek thuis. Echt. Heus" ] AANVANG = [ "17:00.", "17:30.", @@ -767,10 +744,7 @@ class Shitpost(commands.Cog): "nadat iedereen tot 20:30 het uitgebreid over databases \"bij ons op het werk\" heeft gehad en de DM er een sarcastische opmerking over maakt.", "na een flinke portie slap gelul.", "nadat Mark tenminste 20 plaatjes in #tiger-girls heeft gepost.", "wanneer iedereen thuis is van zijn werk.", "nadat JP met de klantenservice heeft gebeld.", - #"als Martijn aanbelt.", "als iedereen heeft gekookt.", "ongeveer een uur voordat JP's trein gaat." - #"als Guus zijn GPU werkend heeft gekregen.", - #"wanneer Martijn klaar is met nakijken.", "als Mark klaar is met zijn dailies." ] PERSONEN = [ "Mark", "Lourens", "JP", @@ -786,21 +760,14 @@ class Shitpost(commands.Cog): "Minecraft met een of andere kutmodpack die Martijn gevonden heeft waardoor je de meeste troep niet zo maar kunt craften.", "Golf with y- oh het werkt niet op Linux? Oh jeetje oh nee, ja wat moeten we? Misschien kunnen we een ander spelletje - ja echt sorry ik weet het ook niet.", "Warcraft 3 met een hamachi-server.", #Martijn poogt onironisch dit idee te pushen - #"dat ene flavour-of-the-week lockdown spel leuk jongens.", "allemaal afzonderlijk Dark Souls omdat we het JP hebben zien spelen en nu begint het toch weer te kriebelen heh? Toch weer een spelletje wat over het algemeen als moeilijk wordt ervaren even opnieuw doen zodat je je goed voelt over jezelf. Oh je doet het voor de achievements? Uhuh ja die heb ik ook. Alsjeblieft JP mag ik je invaden? JP stop niet zo goed zijn in het spel toe.", "Subnautica. Te weten: we kijken hoe Martijn zijn broek volpoept op stream.", "SOMA. Lmao knul niemand speelt SOMA. We gaan Minecraft doen en je gaat het maar naar je zin hebben.", "een best wel okee spel wat net uit is. Misschien hebben we het nog eens naar ons zin." - #"Barotrauma.", "Among Us.", #alsjeblieft zeg - #"Elder Scrolls Online." - #"Monster Hunter.", "Grim Dawn.", - #"Diablo.", "PoE.", - #"dat ene spel dat net uit is gekomen in de Humble Bundle waar we na 2 dagen klaar mee zijn precies wanneer Martijn wel tijd heeft mee te spelen." ] GEBEURTENIS = [ "is ziek. We spelen", "moet overwerken want ze hebben het weer verneukt. Iets met IT. De rest speelt", - #"moet overwerken want ze hebben het weer verneukt. Iets met IT. Of parkieten op Teams. De rest speelt", "heeft mogelijk corona en we zijn toch een risicogroep. We spelen", "zijn kat is van de trap gekankerd. De rest speelt", "heeft best wel hard zijn teen gestoten. De rest doet", @@ -840,8 +807,6 @@ class Shitpost(commands.Cog): message = "We spelen " + DAG + random.choice(SPELLEN) + " " + random.choice(PLAATSEN) + ", aanvang " + random.choice(AANVANG) + random.choice(EXTRA) elif KEUZEMOGELIJKHEDEN == 6: message = "We spelen " + DAG + random.choice(VIDYA) + " Ja, ik weet het, eigenlijk \"D&D\"-avond maar ja. Wees nou eerlijk heh. Aanvang " + random.choice(AANVANG) - #elif KEUZEMOGELIJKHEDEN > 2: - # message = "We spelen " + DAG + "omwille van de lockdown " + random.choice(VIDYA) + " Aanvang op discord " + random.choice(AANVANG) else: message = "We spelen " + DAG + random.choice(SPELLEN) + " " + random.choice(PLAATSEN) + ", aanvang " + random.choice(AANVANG) @@ -870,7 +835,7 @@ class Shitpost(commands.Cog): def get_review_string(self, topic = ""): if topic == "": - random.seed(datetime.now()) + random.seed(datetime.now().timestamp()) else: random.seed(topic.lower().replace(" ", "")) From 19d71e3b4cf37d0d4582e102928e5a0a3f310a96 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sun, 4 Dec 2022 23:30:47 +0100 Subject: [PATCH 21/40] Fixes error on missing black and white txt --- Shitpost.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index 4a7ad6c..886a767 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -16,10 +16,14 @@ class Shitpost(commands.Cog): def __init__(self, bot): self.bot = bot self.hdConImpatientEvents = [] - with open('black.txt') as zwart: - self.zwarte_lijst = [line.rstrip('\n') for line in zwart] - with open('white.txt') as wit: - self.witte_lijst = [line.rstrip('\n') for line in wit] + try: + with open('black.txt') as zwart: + self.zwarte_lijst = [line.rstrip('\n') for line in zwart] + with open('white.txt') as wit: + self.witte_lijst = [line.rstrip('\n') for line in wit] + except: + self.zwarte_lijst = ["___", "___, ___", "___, ___, ___"] + self.witte_lijst = ["A", "B", "C"] self.insult = ['koekenbakker','stumperd','knurft','oelewapper','klungel','stoethaspel', 'onnozelaar','beunhaas','uilskuiken','bamibal','zwakzinnige','oenemeloen', 'klaphark','rompeknonker','bal gehakt','ongewassen vlerk','droeftoeter','omgedraaid pak hagelslag', From a9de2ab7538c13a913a62949a84d0c2958018216 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Mon, 5 Dec 2022 02:11:56 +0100 Subject: [PATCH 22/40] ktdm test En refactor, want hoe het stond was niet heel testbaar --- Shitpost.py | 66 +++++++++++++++++++++-------------------------- tests/shitpost.py | 18 ++++++++++++- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index 886a767..0ec60b0 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -648,49 +648,43 @@ class Shitpost(commands.Cog): return -1.0 return max(1.0, min(10.0, grade)) + + def get_ktdm(self, wit = []): + if not wit: + zwarte_kaart = random.choice(self.zwarte_lijst) + aantal_wit = zwarte_kaart.count("___") + if aantal_wit == 0: # Soms staat er geen ___ in de kaart + zwarte_kaart = zwarte_kaart + " ___" + aantal_wit = 1 + wit = random.sample(self.witte_lijst, k=aantal_wit) + else: + if len(wit) > 3: + return None + zwarte_kaart = None + random.shuffle(self.zwarte_lijst) + for zwart in self.zwarte_lijst: + if zwart.count("___") == len(wit): + zwarte_kaart = zwart + break + if not zwarte_kaart: + return None + + return zwarte_kaart.replace("___", "**{}**").format(*wit) @commands.command(pass_context=True) @asyncio.coroutine def ktdm(self, ctx, *args): '''Speel Kaarten Tegen De Mensheid! Genereer een kaart of geef zelf opties. Bijvoorbeeld: !ktdm <"1"><"2"><"3"> (aanbevolen 1 of 2, max 3)''' - random.shuffle(self.witte_lijst) # schudden voor gebruik - zwarte_kaart = random.choice(self.zwarte_lijst).replace("___", "**{}**") # kies en maak het juiste format - aantal_wit = zwarte_kaart.count("{}") # tel hoeveel witte kaarten er nodig zijn - if aantal_wit == 0: # Soms staat er geen ___ in de kaart - zwarte_kaart = zwarte_kaart + " **{}**" - aantal_wit = 1 - arg_count = len(args) - if arg_count > 3: - yield from ctx.channel.send(ctx.author.mention + ", " + random.choice(insult) + ", 3 is het maximum.") - elif arg_count > 0: - for elem in args: - self.witte_lijst.append(elem) - - if arg_count != 0: # Indien extra args gegeven - while arg_count != aantal_wit: # Match het aantal args aan het aantal dat nodig is - zwarte_kaart = random.choice(self.zwarte_lijst).replace("___", "**{}**") - aantal_wit = zwarte_kaart.count("{}") - - wit={} # maak dynamisch dict aan met de witte kaarten die ingevuld worden - for x in range(aantal_wit, 0, -1): - key = "wit" + str(x) - wit[key] = self.witte_lijst.pop() - - # Dit gedeelte print de zwarte kaart mooi af - if aantal_wit == 1: - print(zwarte_kaart.format(wit['wit1'])) - yield from ctx.channel.send(ctx.author.mention + "\n" + zwarte_kaart.format(wit['wit1'])) - elif aantal_wit == 2: - print(zwarte_kaart.format(wit['wit1'],wit['wit2'])) - yield from ctx.channel.send(ctx.author.mention + "\n" + zwarte_kaart.format(wit['wit1'],wit['wit2'])) - elif aantal_wit == 3: - print(zwarte_kaart.format(wit['wit1'],wit['wit2'],wit['wit3'])) - yield from ctx.channel.send(ctx.author.mention + "\n" + zwarte_kaart.format(wit['wit1'],wit['wit2'],wit['wit3'])) + try: + yield from ctx.message.delete() + except: + print("No permission to delete message") + resultaat = self.get_ktdm(args) + if resultaat: + yield from ctx.channel.send(f"{ctx.author.mention}\n{resultaat}") else: - print("Dit is een vreemd aantal witte kaarten: " + str(aantal_wit) + "\nDe boosdoener: " + zwarte_kaart) - yield from ctx.channel.send("Arme " + random.choice(insult) + ", er is iets foutgegaan!") - yield from ctx.message.delete() + yield from ctx.channel.send(f"{ctx.author.mention}\nIets ging niet helemaal lekker") @commands.command(pass_context=True) @asyncio.coroutine diff --git a/tests/shitpost.py b/tests/shitpost.py index 75e0db2..37d7af3 100644 --- a/tests/shitpost.py +++ b/tests/shitpost.py @@ -45,4 +45,20 @@ class TestShitpost(unittest.TestCase): with self.subTest(msg="Watspelenwe activiteit does not return a string"): self.assertIsInstance(activiteit, str) with self.subTest(msg="Watspelenwe reden does not return a string"): - self.assertIsInstance(reden, str) \ No newline at end of file + self.assertIsInstance(reden, str) + + def test_ktdm(self): + with self.subTest(): + wit = ["qwerty", "yuiop"] + kaart = self.cog.get_ktdm(wit) + self.assertIn(wit[0], kaart) + self.assertIn(wit[1], kaart) + with self.subTest(): + wit = ["a", "b", "c", "d"] + kaart = self.cog.get_ktdm(wit) + self.assertEqual(kaart, None) + with self.subTest(): + wit = ["a", "b", "c"] + self.cog.zwarte_lijst = ["___"] + kaart = self.cog.get_ktdm(wit) + self.assertEqual(kaart, None) \ No newline at end of file From fc532086bb793fc6c14a082b671babaa24060a78 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Mon, 5 Dec 2022 12:34:53 +0100 Subject: [PATCH 23/40] Adds Dockerfile for easy testing Moet up-to-date worden gehouden met drone. Maar emuleert een pull van de repo met een .env file erin. --- .dockerignore | 15 +++++++++++++++ Dockerfile | 9 +++++++++ 2 files changed, 24 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..27c8b63 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +__pycache__/ +discord.py-rewrite/ +tijd/ +.vs/ +test.png +UpgradeLog\.htm +markov_dict.npy +*.ini +Stroopwafel.sln +Stroopwafel.pyproj +*.txt +!requirements.txt +*.sh +*.npy +#.env \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1a755b2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.10 + +WORKDIR /opt/stroopwafel + +COPY . ./ + +RUN pip install -r requirements.txt + +CMD python -m unittest tests \ No newline at end of file From 1cfd3d0decfe0df1a1b98175cc482fe25e81960a Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Mon, 5 Dec 2022 14:51:25 +0100 Subject: [PATCH 24/40] Haalt sympy uit de requirements Was alleen nodig voor de LaTeX functie, en die is geschrapt --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a463a10..156e39b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ caldav discord.py praw -sympy numpy python-dotenv From 1361d9c0832e2a27d4003fd2c8965ff73ad7b013 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Mon, 5 Dec 2022 14:51:53 +0100 Subject: [PATCH 25/40] Refactor weer Omwille van het zo beter te kunnen maken om voor te kunnen testen. --- Shitpost.py | 128 ++++++++++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index 0ec60b0..fadcc8c 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -521,76 +521,78 @@ class Shitpost(commands.Cog): returnText += " = __**" + str(total) + "**__" yield from ctx.channel.send(returnText) + + def get_weerbericht(self, wData, verbose=None): + if not wData: + return None + message = "" + # Weather alert: + alertCode, alertMessage = self.getWeerAlarm(wData) + if (verbose and alertCode): + message += alertMessage + "\n\n" + elif (not verbose and alertCode): + if (alertCode == "rood"): + message += alertMessage + "\n\n" + else: + message += ":warning: Er is een weeralarm van kracht. Code " + alertCode + ".\n\n" + # Today: + message += self.getWeatherIconTranslation( wData["image"] ) + message += " Het is " + wData["temp"] + " graden " + message += "en het weer is: " + wData["samenv"] + ". " + message += "De verwachting: " + wData["verw"] + + if (verbose): + # Only print tomorrow, the day after and the BBQ grade if verbose is on: + message += "\n\nMorgen: " + self.getWeatherIconTranslation( wData["d1weer"] ) + message += " " + wData["d1tmin"] + " tot " + message += wData["d1tmax"] + " graden. " + if (wData["d1neerslag"] == "0"): + message += "Geen neerslag. " + else: + message += "Kans op neerslag: " + wData["d1neerslag"] + "%. " + if (int(wData["d1windk"]) > 5): + message += "Windkracht " + wData["d1windk"] + ". Blow it." + + message += "\n\nOvermorgen: "+ self.getWeatherIconTranslation( wData["d2weer"] ) + message += " " + wData["d2tmin"] + " tot " + message += wData["d2tmax"] + " graden. " + if (wData["d2neerslag"] == "0"): + message += "Geen neerslag. " + else: + message += "Kans op neerslag: " + wData["d2neerslag"] + "%. " + if (int(wData["d2windk"]) > 5): + message += "Windkracht " + wData["d2windk"] + ". " + + bbqGrade = self.getBbqGrade(wData) + message += "\n\nHet BBQ cijfer voor vandaag is: " + '{0:g}'.format(round(bbqGrade, 1)) + + message += "\n\nOant Moarn!" + return message + + + def get_weer_json(self, location=None): + if not location: + location = "Leiden" + url = f"http://weerlive.nl/api/json-data-10min.php?key={os.getenv('STROOP_WEERLIVE')}&locatie={location}" + response = requests.get(url) + if response: + return json.loads(response.content.decode('utf-8'))["liveweer"][0] + return None @commands.command(pass_context=True) @asyncio.coroutine - def weer(self, ctx, location="Leiden", verbose="False"): + def weer(self, ctx, location="Leiden", verbose=None): """Vertelt je het weer. Omdat je te lui bent om naar buiten te kijken. Oant Moarn! """ - if(location == ""): - location = "Leiden" - if(str(verbose).lower() == "false"): - v = False - else: - v = True - - url = f"http://weerlive.nl/api/json-data-10min.php?key={os.getenv('STROOP_WEERLIVE')}&locatie={location}" - response = requests.get(url) - #Oant Moarn - - if (response.ok): - wData = json.loads(response.content.decode('utf-8')) - message = "" - - # Weather alert: - alertCode, alertMessage = self.getWeerAlarm(wData["liveweer"][0]) - if (v and alertCode != None): - message += alertMessage + "\n\n" - elif (not v and alertCode != None): - if (alertCode == "rood"): - message += alertMessage + "\n\n" - else: - message += ":warning: Er is een weeralarm van kracht. Code " + alertCode + ".\n\n" - - # Today: - message += self.getWeatherIconTranslation( wData["liveweer"][0]["image"] ) - message += " Het is " + wData["liveweer"][0]["temp"] + " graden " - message += "en het weer is: " + wData["liveweer"][0]["samenv"] + ". " - message += "De verwachting: " + wData["liveweer"][0]["verw"] - - if (v): - # Only print tomorrow, the day after and the BBQ grade if verbose is on: - message += "\n\nMorgen: " + self.getWeatherIconTranslation( wData["liveweer"][0]["d1weer"] ) - message += " " + wData["liveweer"][0]["d1tmin"] + " tot " - message += wData["liveweer"][0]["d1tmax"] + " graden. " - if (wData["liveweer"][0]["d1neerslag"] == "0"): - message += "Geen neerslag. " - else: - message += "Kans op neerslag: " + wData["liveweer"][0]["d1neerslag"] + "%. " - if (int(wData["liveweer"][0]["d1windk"]) > 5): - message += "Windkracht " + wData["liveweer"][0]["d1windk"] + ". Blow it." - - message += "\n\nOvermorgen: "+ self.getWeatherIconTranslation( wData["liveweer"][0]["d2weer"] ) - message += " " + wData["liveweer"][0]["d2tmin"] + " tot " - message += wData["liveweer"][0]["d2tmax"] + " graden. " - if (wData["liveweer"][0]["d2neerslag"] == "0"): - message += "Geen neerslag. " - else: - message += "Kans op neerslag: " + wData["liveweer"][0]["d2neerslag"] + "%. " - if (int(wData["liveweer"][0]["d2windk"]) > 5): - message += "Windkracht " + wData["liveweer"][0]["d2windk"] + ". " - - bbqGrade = self.getBbqGrade(wData["liveweer"][0]) - message += "\n\nHet BBQ cijfer voor vandaag is: " + '{0:g}'.format(round(bbqGrade, 1)) - - message += "\n\nOant Moarn!" - - yield from ctx.channel.send(message) - else: - print("API ERROR. :robot:") + wData = self.get_weer_json(location) + if wData: + message = self.get_weerbericht(wData, verbose) + if not wData or not message: + message = "Weer ophalen niet gelukt. Probeer het later nogmaals.." + yield from ctx.channel.send(message) #returns a nice weather icon. Sometimes the API uses non-documented icons, so we return something else def getWeatherIconTranslation(self, iconKey): @@ -613,10 +615,8 @@ class Shitpost(commands.Cog): try: return WEATHER_ICONS[iconKey] except KeyError: - print("WARN Unknown iconKey:", str(iconKey)) return ":park:" - #returns which the current weatheralert code and returns a message def getWeerAlarm(self, weatherObj): if (weatherObj["alarm"] != "1"): return None, "" From 088d86f4dd724ea30ced7a52013bc0dd3a6fd42b Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Mon, 5 Dec 2022 14:52:16 +0100 Subject: [PATCH 26/40] Adds tests for weer --- tests/shitpost.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/tests/shitpost.py b/tests/shitpost.py index 37d7af3..5d734fd 100644 --- a/tests/shitpost.py +++ b/tests/shitpost.py @@ -61,4 +61,56 @@ class TestShitpost(unittest.TestCase): wit = ["a", "b", "c"] self.cog.zwarte_lijst = ["___"] kaart = self.cog.get_ktdm(wit) - self.assertEqual(kaart, None) \ No newline at end of file + self.assertEqual(kaart, None) + + def test_weer(self): + data = requests.get("http://weerlive.nl/api/json-data-10min.php") + if not data: + self.skipTest(f"Weerlive has an error, or is unavailable") + weerJson = self.cog.get_weer_json() + with self.subTest("Weer does not correctly convert from json"): + self.assertIsInstance(weerJson, dict) + + icon = self.cog.getWeatherIconTranslation(weerJson["d2weer"]) + with self.subTest("Weericon not available"): + self.assertNotEqual(icon, ":park:") + with self.subTest("Weericon incorrect"): + self.assertRegex(icon, ":[A-z]+:") + with self.subTest("No weericon for unknown weather"): + icon = self.cog.getWeatherIconTranslation("sniezelig") # Bestaat niet natuurlijk + self.assertRegex(icon, ":[A-z]+:") + + bbq = self.cog.getBbqGrade(weerJson) + with self.subTest("BBQ cijfer incorrect"): + self.assertIsInstance(bbq, float) + self.assertGreaterEqual(bbq, 1.0) + self.assertLessEqual(bbq, 10.0) + + with self.subTest("False positive alarm"): + weerMock = { "alarm": 0} + alertCode, alertMessage = self.cog.getWeerAlarm(weerMock) + self.assertEqual(alertCode, None) + self.assertEqual(alertMessage, "") + with self.subTest("False negative rood alarm"): + weerMock = { "alarm": "1", "alarmtxt": "qwerty code rood yuiop"} + alertCode, alertMessage = self.cog.getWeerAlarm(weerMock) + self.assertEqual(alertCode, "rood") + self.assertIsInstance(alertMessage, str) + with self.subTest("False negative oranje alarm"): + weerMock = { "alarm": "1", "alarmtxt": "qwerty code oranje yuiop"} + alertCode, alertMessage = self.cog.getWeerAlarm(weerMock) + self.assertEqual(alertCode, "oranje") + self.assertIsInstance(alertMessage, str) + with self.subTest("False negative geel alarm"): + weerMock = { "alarm": "1", "alarmtxt": "lorem ipsum dolor sit amet"} + alertCode, alertMessage = self.cog.getWeerAlarm(weerMock) + self.assertEqual(alertCode, "geel") + self.assertIsInstance(alertMessage, str) + + wb = self.cog.get_weerbericht(weerJson) + wb_v = self.cog.get_weerbericht(weerJson, "verbose pls") + with self.subTest("Can't render message from json"): + self.assertIsInstance(wb, str) + self.assertIsInstance(wb_v, str) + with self.subTest("Verbose isn't actually verbose"): + self.assertTrue(len(wb_v) > len(wb)) From ba5958fb77883666de9664f711a9d1ce06f0bd07 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Tue, 6 Dec 2022 01:39:17 +0100 Subject: [PATCH 27/40] more efficient caching of images --- Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1a755b2..2a204d3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,11 @@ FROM python:3.10 WORKDIR /opt/stroopwafel -COPY . ./ +# Do the requirements first for better caching +COPY requirements.txt . RUN pip install -r requirements.txt +COPY . ./ + CMD python -m unittest tests \ No newline at end of file From 3760d8cb0257c1eed432cc17c5a929628aaa0785 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Tue, 6 Dec 2022 01:39:28 +0100 Subject: [PATCH 28/40] Refactors roll En flink ook. Nu met regex en meer pythonic one-liners die niet of nauwelijks leesbaar zijn. Eindeloos plezier. --- Shitpost.py | 97 ++++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index fadcc8c..797eac2 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -9,6 +9,7 @@ import os import random import caldav import warnings +import re class Shitpost(commands.Cog): """Schijtpaal commando's. Alleen bruikbaar in de daarvoor toegewezen schijtpaal kanalen.""" @@ -466,61 +467,59 @@ class Shitpost(commands.Cog): else: yield from ctx.channel.send(ctx.author.mention + ' Het is nu ' + datetime.now().strftime('%H:%M')) - + def get_dice_roll(self, nrOfDice, dieType, modifier=None): + if nrOfDice > 99 or dieType > 9999 or dieType < 2 or (modifier and abs(modifier) > 9999): + return None + + # Do the rolling + random.seed(datetime.now()) + total = 0 + rolls = [] + for x in range(0, nrOfDice): + roll = random.randint(1, dieType) + total += roll + rolls.append(roll) + total += modifier if modifier else 0 + + #Tally results + modifierText = "%+d" % modifier if modifier else "" # print modifier with sign + returnText = f"Rolling {nrOfDice}d{dieType}{modifierText}...\n" + rolls = [f"[**{roll}**]" if dieType >= 10 and (roll == 1 or roll == dieType) else f"[{roll}]" for roll in rolls] + returnText += "+".join(rolls) + returnText += modifierText + if nrOfDice > 1 or modifier: # only show calculation if it makes sense: + returnText += " = **" + str(total) + "**" + return returnText + + def get_dice_parameters(self, dice): + match = re.match(r"(\d+)d(\d+)(\s*([+-])\s*(\d+))?\s*", dice.lower()) + if not match: + return None + numDice = int(match.group(1)) + die = int(match.group(2)) + modifier = None + + modified = match.group(3) + if modified: + modifierType = match.group(4) + modifier = int(match.group(5)) + if "-" in modifierType: + modifier = -modifier + return (numDice, die, modifier) + @commands.command(pass_context=True) @asyncio.coroutine - def roll(self, ctx, dice="1d20", modifier1="", modifier2=""): + def roll(self, ctx, *, dice): """Roll een dobbelsteen. Of een paar. Bijvoorbeeld: !roll 4d20 !roll 1d6 + 5 """ - diceSplit = dice.lower().split('d') - if len(diceSplit) != 2: - return - modifier1 = modifier1.replace("+", "") #this is both possible: "1d20 + 1" and "1d20 +1" - modifier2 = modifier2.replace("+", "") - if modifier1 == "-": - modifier1 = ""; #this is also possible: "1d20 - 1" - modifier2 = "-" + modifier2 - try: #check if they are numbers: - nrOfDice = 1 if (diceSplit[0]=="") else int(diceSplit[0]) #allow input like: "!roll d20" - dieType = int(diceSplit[1]) - mod1 = 0 if (modifier1=="") else int(modifier1) - mod2 = 0 if (modifier2=="") else int(modifier2) - except ValueError: - return - #validate values: - if nrOfDice < 1 or nrOfDice > 99 or dieType < 2 or dieType > 100: - return - if mod1 < -999 or mod1 > 999 or mod2 < -999 or mod2 > 999: - return - - #roll: - random.seed(datetime.now()) - total = 0 - returnText = "Rolling " + str(nrOfDice) + "d" + str(dieType) + "...\n" - for x in range(0, nrOfDice): - if x != 0: - returnText += "+ " - roll = random.randint(1, dieType) - total += roll - if dieType >= 10 and (roll == 1 or roll == dieType): - returnText += "[**" + str(roll) + "**] " #make significant numbers bold - else: - returnText += "[" + str(roll) + "] " - total += mod1 + mod2 - if mod1 != 0: - if mod1 > 0: - returnText += "+" - returnText += str(mod1) + " " - if mod2 != 0: - if mod2 > 0: - returnText += "+" - returnText += str(mod2) + " " - if nrOfDice > 1 or mod1 != 0 or mod2 != 0: #only show calculation if it makes sense: - returnText += " = __**" + str(total) + "**__" - - yield from ctx.channel.send(returnText) + (nrOfDice, dieType, modifier) = self.get_dice_parameters(dice) + message = self.get_dice_roll(nrOfDice, dieType, modifier) + if message: + yield from ctx.channel.send(message) + else: + yield from ctx.channel.send("Die roll vind ik echt een beetje te mal..") def get_weerbericht(self, wData, verbose=None): if not wData: From a14d446e824a1804657ebe957d725a160ff304b7 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Tue, 6 Dec 2022 01:40:09 +0100 Subject: [PATCH 29/40] Tests roll En vrij grondig ook nog, al zeg ik het zelf --- tests/shitpost.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/shitpost.py b/tests/shitpost.py index 5d734fd..7a4d7a3 100644 --- a/tests/shitpost.py +++ b/tests/shitpost.py @@ -114,3 +114,34 @@ class TestShitpost(unittest.TestCase): self.assertIsInstance(wb_v, str) with self.subTest("Verbose isn't actually verbose"): self.assertTrue(len(wb_v) > len(wb)) + + def test_roll(self): + with self.subTest("Incorrect acceptance of malformed string"): + self.assertIsNone(self.cog.get_dice_parameters("1 d 20 ")) + with self.subTest("Incorrect parsing of capital D"): + self.assertEqual((1, 20, None), self.cog.get_dice_parameters("1D20")) + with self.subTest("Incorrect parsing of die-string"): + self.assertEqual((1, 20, None), self.cog.get_dice_parameters("1d20")) + with self.subTest("Incorrect parsing of die modifier"): + self.assertEqual((2, 20, 3), self.cog.get_dice_parameters("2d20+3")) + with self.subTest("Incorrect parsing of spacing in die-string"): + self.assertEqual((1, 20, 5), self.cog.get_dice_parameters("1d20 + 5")) + with self.subTest("Incorrect parsing of negative modifier"): + self.assertEqual((1, 12, -3), self.cog.get_dice_parameters("1d12 - 3")) + with self.subTest("Incorrect parsing of unbalanced spacing"): + self.assertEqual((1, 12, -3), self.cog.get_dice_parameters("1d12 -3")) + with self.subTest("Incorrect parsing of largest values"): + self.assertEqual((99, 9999, 9999), self.cog.get_dice_parameters("99d9999 + 9999")) + + with self.subTest("Incorrect acceptance of too many dice"): + self.assertIsNone(self.cog.get_dice_roll(100, 20, None)) + with self.subTest("Incorrect acceptance of too big die"): + self.assertIsNone(self.cog.get_dice_roll(4, 10000, None)) + with self.subTest("Incorrect acceptance of too large modifier"): + self.assertIsNone(self.cog.get_dice_roll(1, 20, 999999)) + with self.subTest("Incorrect acceptance of too large negative modifier"): + self.assertIsNone(self.cog.get_dice_roll(1, 20, -999999)) + with self.subTest("Critical fail/success not marked"): + self.assertIn("**10**", self.cog.get_dice_roll(99, 10, None)) + self.assertIn("**1**", self.cog.get_dice_roll(99, 10, None)) + self.assertTrue(True) From 5ad7512fa895f22d67a1eb530d8d0d54378cbcde Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Wed, 7 Dec 2022 21:43:43 +0100 Subject: [PATCH 30/40] byebye relevantxkcd. gbnf --- Shitpost.py | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index 797eac2..1cb1300 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -377,35 +377,6 @@ class Shitpost(commands.Cog): print("No permission to delete message") yield from ctx.channel.send(ctx.author.mention, embed=em) - @commands.command(pass_context=True) - @asyncio.coroutine - def relevantxkcd(self, ctx, query: str): - """There is always a relevant XKCD - Bijvoorbeeld: - !relevantxkcd python - """ - response = requests.get("https://relevantxkcd.appspot.com/process?action=xkcd&query=" + query) - - splitResponse = response.text.split(" ") - - if (float(splitResponse[0]) == 0.0): - yield from ctx.channel.send('Ik kan helaas geen XKCD vinden met als onderwerp "' + query + '".') - return - - photoUrl = "http://www.explainxkcd.com" + splitResponse[3] - - print(photoUrl) - - em = discord.Embed(title='', type='photo') - em.set_image(url=photoUrl) - - try: - yield from ctx.message.delete() - except: - print("No permission to delete message") - yield from ctx.channel.send(ctx.author.mention + - ' een XKCD over "' + query + '"', embed=em) - @commands.command(pass_context=True, hidden=True) @asyncio.coroutine def zout(self, ctx, boven: str, onder: str): From e1b18661cb60de7f7d997832f8cc78dcd22fc703 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Wed, 7 Dec 2022 22:04:08 +0100 Subject: [PATCH 31/40] refactor imgflip calls --- Shitpost.py | 121 ++++++++++++++++++++++------------------------------ 1 file changed, 51 insertions(+), 70 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index 1cb1300..b963f18 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -33,6 +33,13 @@ class Shitpost(commands.Cog): 'clownsfiguur','krotenkoker','hansworst','grappenmaker','flapdrol','oen', 'achterlijk gebakje','demente dibbes','geitenbreier','koekwous','sufkop'] self.caldav_client = caldav.DAVClient(url=os.getenv('STROOP_CALDAV_HOST')) + self.imgflips = { + 'tering': '78416340', + 'mark': '112898841', + 'eriku': '93296473', + 'tegeltje': '121572521', + 'zout': '116231806' + } warnings.simplefilter("ignore") @commands.command(pass_context=True, hidden=False) @@ -259,6 +266,25 @@ class Shitpost(commands.Cog): else: yield from ctx.channel.send(ctx.author.mention + ' helaas, geen quote gevonden.') + def get_imgflip_embed(self, template: str, boven: str, onder: str, extra_options: dict = None): + params = dict( + template_id = template, + username = 'Stroopwafel', + password = os.getenv("STROOP_IMGFLIP_PASSWORD"), + text0 = boven, + text1 = onder + ) + if extra_options: + params.update(extra_options) + resp = requests.get(url='https://api.imgflip.com/caption_image', params=params) + if resp: + photourl = resp.json()['data']['url'] + em = discord.Embed(type='photo') + em.set_image(url=photourl) + return em + return None + + @commands.command(pass_context=True, hidden=True) @asyncio.coroutine def tering(self, ctx, boven: str, onder: str): @@ -266,23 +292,13 @@ class Shitpost(commands.Cog): Bijvoorbeeld: !tering \"Vanavond\" \"gaan we helemaal naar de tering\" """ - params = dict( - template_id = '78416340', #party hard - username = 'Stroopwafel', - password = os.getenv("STROOP_IMGFLIP_PASSWORD"), - text0 = boven, - text1 = onder - ) - resp = requests.get(url='https://api.imgflip.com/caption_image', params=params) - #todo check for success - photourl = resp.json()['data']['url'] - em = discord.Embed(type='photo') - em.set_image(url=photourl) + em = self.get_imgflip_embed(self.imgflips['tering'], boven, onder) try: yield from ctx.message.delete() except: print("No permission to delete message") - yield from ctx.channel.send(ctx.author.mention, embed=em) + if em: + yield from ctx.channel.send(ctx.author.mention, embed=em) @commands.command(pass_context=True, hidden=True) @asyncio.coroutine @@ -291,23 +307,13 @@ class Shitpost(commands.Cog): Bijvoorbeeld: !mark \"je moeder\" \"is een hoer\" """ - params = dict( - template_id = '112898841', #de marku - username = 'Stroopwafel', - password = os.getenv("STROOP_IMGFLIP_PASSWORD"), - text0 = boven, - text1 = onder - ) - resp = requests.get(url='https://api.imgflip.com/caption_image', params=params) - #todo check for success - photourl = resp.json()['data']['url'] - em = discord.Embed(title='De Mark heeft gesproken.', type='photo') - em.set_image(url=photourl) + em = self.get_imgflip_embed(self.imgflips['mark'], boven, onder) try: yield from ctx.message.delete() except: print("No permission to delete message") - yield from ctx.channel.send(ctx.author.mention, embed=em) + if em: + yield from ctx.channel.send(ctx.author.mention, embed=em) @commands.command(pass_context=True, hidden=True) @asyncio.coroutine @@ -316,36 +322,16 @@ class Shitpost(commands.Cog): Bijvoorbeeld: !eriku \"je moeder\" \"is een hoer\" """ - params = dict( - template_id = '93296473', #de eriku - username = 'Stroopwafel', - password = os.getenv('STROOP_IMGFLIP_PASSWORD'), - text0 = boven, - text1 = onder - ) - resp = requests.get(url='https://api.imgflip.com/caption_image', params=params) - #todo check for success - photourl = resp.json()['data']['url'] - em = discord.Embed(title='De Eriku heeft gesproken. Prijs hem!', type='photo') - em.set_image(url=photourl) + em = self.get_imgflip_embed(self.imgflips['eriku'], boven, onder) try: yield from ctx.message.delete() except: print("No permission to delete message") - yield from ctx.channel.send(ctx.author.mention, embed=em) - - @commands.command(pass_context=True, hidden=True) - @asyncio.coroutine - def tegeltje(self, ctx, tekst: str, auteur: str=" "): - """Maak een mooi tegeltje met volkswijsheid - Bijvoorbeeld: - !tegeltje \"Oost west, 420 best\" \"Lourens\" - """ + if em: + yield from ctx.channel.send(ctx.author.mention, embed=em) + def get_tegeltje(self, tekst, auteur): params = { - 'template_id': '121572521', #delfts blauw - 'username': 'Stroopwafel', - 'password': os.getenv('STROOP_IMGFLIP_PASSWORD'), 'text0': 'dummy0', 'text1': 'dummy1', 'font': 'arial', @@ -365,17 +351,22 @@ class Shitpost(commands.Cog): 'boxes[1][color]': '#0044cc', 'boxes[1][outline_color]': '#ffffff' } - - resp = requests.get(url='https://api.imgflip.com/caption_image', params=params) - #todo check for success - photourl = resp.json()['data']['url'] - em = discord.Embed(title='Tegeltjeswijsheid:', type='photo') - em.set_image(url=photourl) + return self.get_imgflip_embed(self.imgflips['tegeltje'], "", "", params) + + @commands.command(pass_context=True, hidden=True) + @asyncio.coroutine + def tegeltje(self, ctx, tekst: str, auteur: str=" "): + """Maak een mooi tegeltje met volkswijsheid + Bijvoorbeeld: + !tegeltje \"Oost west, 420 best\" \"Lourens\" + """ + em = get_tegeltje(tekst, auteur) try: yield from ctx.message.delete() except: print("No permission to delete message") - yield from ctx.channel.send(ctx.author.mention, embed=em) + if em: + yield from ctx.channel.send(ctx.author.mention, embed=em) @commands.command(pass_context=True, hidden=True) @asyncio.coroutine @@ -384,23 +375,13 @@ class Shitpost(commands.Cog): Bijvoorbeeld: !zout \"je moeder\" \"is een hoer\" """ - params = dict( - template_id = '116231806', #de martijn - username = 'Stroopwafel', - password = os.getenv('STROOP_IMGFLIP_PASSWORD'), - text0 = boven, - text1 = onder - ) - resp = requests.get(url='https://api.imgflip.com/caption_image', params=params) - #todo check for success - photourl = resp.json()['data']['url'] - em = discord.Embed(title='De Martijn heeft gesproken.', type='photo') - em.set_image(url=photourl) + em = self.get_imgflip_embed(self.imgflips['zout'], boven, onder) try: yield from ctx.message.delete() except: print("No permission to delete message") - yield from ctx.channel.send(ctx.author.mention, embed=em) + if em: + yield from ctx.channel.send(ctx.author.mention, embed=em) @commands.command(pass_context=True, hidden=True) @asyncio.coroutine From f89418c5870522ea9c4c12a40872d1fccac20c32 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Wed, 7 Dec 2022 22:04:22 +0100 Subject: [PATCH 32/40] tests imgflips --- tests/shitpost.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/shitpost.py b/tests/shitpost.py index 7a4d7a3..dd63da6 100644 --- a/tests/shitpost.py +++ b/tests/shitpost.py @@ -145,3 +145,9 @@ class TestShitpost(unittest.TestCase): self.assertIn("**10**", self.cog.get_dice_roll(99, 10, None)) self.assertIn("**1**", self.cog.get_dice_roll(99, 10, None)) self.assertTrue(True) + + def test_imgflips(self): + eriku = self.cog.get_imgflip_embed(self.cog.imgflips['eriku'], "a", "b") + tegeltje = self.cog.get_tegeltje("Man who put penis in peanut butter is fucking nuts", "Confucius") + self.assertIsInstance(eriku, discord.Embed) + self.assertIsInstance(tegeltje, discord.Embed) From 90e0dc5bab279670d2fe1bfc86bd8c641410b106 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Wed, 7 Dec 2022 22:12:54 +0100 Subject: [PATCH 33/40] test inspire --- Shitpost.py | 14 ++++++++++---- tests/shitpost.py | 5 +++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index b963f18..d0e6842 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -245,6 +245,13 @@ class Shitpost(commands.Cog): if 'nee' in answer: reactie += 'Nee helaas..' yield from ctx.channel.send(ctx.author.mention + ' ' + reactie) + + def get_inspiration(self): + inspiration = requests.get(url='http://inspirobot.me/api?generate=true') + if inspiration: + return inspiration.text + return None + @commands.command(pass_context=True, hidden=False) @asyncio.coroutine @@ -253,11 +260,10 @@ class Shitpost(commands.Cog): Bijvoorbeeld: !inspire """ - r = requests.get(url='http://inspirobot.me/api?generate=true') - if r.status_code == 200: - url = r.text + inspo = self.get_inspiration() + if inspo: em = discord.Embed(title='Uw wijze woorden:', type='photo') - em.set_image(url=url) + em.set_image(url=inspo) try: yield from ctx.message.delete() except: diff --git a/tests/shitpost.py b/tests/shitpost.py index dd63da6..aa53cd0 100644 --- a/tests/shitpost.py +++ b/tests/shitpost.py @@ -151,3 +151,8 @@ class TestShitpost(unittest.TestCase): tegeltje = self.cog.get_tegeltje("Man who put penis in peanut butter is fucking nuts", "Confucius") self.assertIsInstance(eriku, discord.Embed) self.assertIsInstance(tegeltje, discord.Embed) + + def test_inspire(self): + inspo = self.cog.get_inspiration() + self.assertIn("https://", inspo) + self.assertIn(".jpg", inspo) \ No newline at end of file From 09477f3c4ddbcb247ff6b738a70444908b250157 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Wed, 7 Dec 2022 22:19:12 +0100 Subject: [PATCH 34/40] Tests giet het al oan Vooral om de testcount te padden lmao --- Shitpost.py | 13 +++++-------- tests/shitpost.py | 5 ++++- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index d0e6842..1518474 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -220,6 +220,10 @@ class Shitpost(commands.Cog): Message = "Nee. :frowning2: Nog even geduld..." yield from ctx.channel.send(ctx.author.mention + ' ' + str(Message)) + + def get_giet_het_oan(self): + # Alsof we ooit nog een elfstedentocht gaan krijgen. + return "nee" @commands.command(pass_context=True, hidden=False) @asyncio.coroutine @@ -227,14 +231,7 @@ class Shitpost(commands.Cog): """Giet het al oan? Ja of Nee.. kom op nou. """ - #We halen dit op van de twitter account @gietitaloan die vertrouwen wij als de ultieme waarheid - consumer = oauth.Consumer(key=os.getenv('STROOP_TWITTER_KEY'), secret=os.getenv('STROOP_TWITTER_SECRET')) - client = oauth.Client(consumer) - resp, content = client.request("https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=gietitaloan&count=1", "GET") - #TODO kijken of resp iets zinnigs teruggeeft.. of iets doen met een try of catch ofzow - content_str = content.decode('utf-8') #converteren naar str voor welke stomme reden dan ook - answer = json.loads(content_str)[0]["text"] #inhoud van de tweet - answer = answer.lower() + answer = self.get_giet_het_oan() reactie = "" if 'ja' in answer: if 'nee' in answer: diff --git a/tests/shitpost.py b/tests/shitpost.py index aa53cd0..c78bb05 100644 --- a/tests/shitpost.py +++ b/tests/shitpost.py @@ -155,4 +155,7 @@ class TestShitpost(unittest.TestCase): def test_inspire(self): inspo = self.cog.get_inspiration() self.assertIn("https://", inspo) - self.assertIn(".jpg", inspo) \ No newline at end of file + self.assertIn(".jpg", inspo) + + def test_giethetaloan(self): + self.assertIn("nee", self.cog.get_giet_het_oan().lower()) \ No newline at end of file From 8395a0b4a6498fee80e371e00a44b214229dba1d Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Wed, 7 Dec 2022 22:26:55 +0100 Subject: [PATCH 35/40] Tests corona Beetje slappe test wel, maar je moet iets. --- Shitpost.py | 50 ++++++++++++++--------------------------------- tests/shitpost.py | 6 +++++- 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index 1518474..3f2b7a2 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -131,26 +131,20 @@ class Shitpost(commands.Cog): print("No permission to delete message") yield from ctx.channel.send(ctx.author.mention + ' ' + str(message)) - @commands.command(pass_context=True, hidden=False) - @asyncio.coroutine - def coronaold(self, ctx): - try: - yield from ctx.message.delete() - except: - print("No permission to delete message") - params = ( - ('minimal/', 'true'), - ('format/', 'json') - ) - response = requests.get('https://corona-stats.online/NL/?format=json&source=2') - answer = json.loads(response.content.decode('utf-8')) - answer = answer["data"] - message = "Er zijn in Nederland " + str(answer[0]["cases"]) + " bevestigde gevallen ๐Ÿ˜ท" - message += " dat is ๐Ÿ”บ" + str(answer[0]["todayCases"]) + "๐Ÿ”บ meer dan gisteren! " - message += "Er zijn ondertussen " + str(answer[0]["deaths"]) + " mensen dood ๐Ÿ’€" - message += " waarvan " + str(answer[0]["todayDeaths"]) + " โ˜ ๏ธ in de afgelopen 24 uur. " - message += "Ook liggen er " + str(answer[0]["critical"]) + " mensen op de IC ๐Ÿฅ" - yield from ctx.channel.send(ctx.author.mention + ' ' + str(message)) + def get_corona_message(self): + response = requests.get('https://covid.ourworldindata.org/data/latest/owid-covid-latest.json') + if response: + answer = json.loads(response.content.decode('utf-8')) + d = answer["NLD"] + message = f"Dit is mijn informatie van **{d['last_updated_date']}**: \n\n" + message += f"Er zijn in Nederland {d['total_cases']:.0f} bevestigde gevallen ๐Ÿ˜ท" + message += f" dat is ๐Ÿ”บ{d['new_cases']:.0f}๐Ÿ”บ meer dan de dag er voor! \n" + message += f"Er zijn ondertussen {d['total_deaths']:.0f} mensen dood ๐Ÿ’€" + message += f" waarvan {d['new_deaths']:.0f} โ˜ ๏ธ in de meest recente 24 uur. \n" + message += f"En het r-getal is {d['reproduction_rate']}!\n\n" + message += "*Data van https://ourworldindata.org/coronavirus*" + return message + return None @commands.command(pass_context=True, hidden=False) @asyncio.coroutine @@ -159,21 +153,7 @@ class Shitpost(commands.Cog): yield from ctx.message.delete() except: print("No permission to delete message") - params = ( - ('minimal/', 'true'), - ('format/', 'json') - ) - response = requests.get('https://covid.ourworldindata.org/data/latest/owid-covid-latest.json') - answer = json.loads(response.content.decode('utf-8')) - d = answer["NLD"] - message = f"Dit is mijn informatie van **{d['last_updated_date']}**: \n\n" - message += f"Er zijn in Nederland {d['total_cases']:.0f} bevestigde gevallen ๐Ÿ˜ท" - message += f" dat is ๐Ÿ”บ{d['new_cases']:.0f}๐Ÿ”บ meer dan de dag er voor! \n" - message += f"Er zijn ondertussen {d['total_deaths']:.0f} mensen dood ๐Ÿ’€" - message += f" waarvan {d['new_deaths']:.0f} โ˜ ๏ธ in de meest recente 24 uur. \n" - message += f"Er zijn ondertussen {d['people_vaccinated']:.0f} mensen gevaccineerd! ๐Ÿ’‰ " - message += f"En het r-getal is {d['reproduction_rate']}!\n\n" - message += "*Data van https://ourworldindata.org/coronavirus*" + message = self.get_corona_message() yield from ctx.channel.send(ctx.author.mention + ' ' + str(message)) @commands.command(pass_context=True, hidden=False) diff --git a/tests/shitpost.py b/tests/shitpost.py index c78bb05..b487658 100644 --- a/tests/shitpost.py +++ b/tests/shitpost.py @@ -158,4 +158,8 @@ class TestShitpost(unittest.TestCase): self.assertIn(".jpg", inspo) def test_giethetaloan(self): - self.assertIn("nee", self.cog.get_giet_het_oan().lower()) \ No newline at end of file + self.assertIn("nee", self.cog.get_giet_het_oan().lower()) + + def test_corona(self): + message = self.cog.get_corona_message() + self.assertIsInstance(message, str) From 055f170f62f68f23a7e1a5bd355527b9f6337f77 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Wed, 7 Dec 2022 22:36:39 +0100 Subject: [PATCH 36/40] Tests zalgo Soort van. Kijkt iig of de conversie misschien goed gaat. --- Shitpost.py | 20 ++++++++++++-------- tests/shitpost.py | 6 ++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Shitpost.py b/Shitpost.py index 3f2b7a2..6e8034b 100644 --- a/Shitpost.py +++ b/Shitpost.py @@ -108,6 +108,16 @@ class Shitpost(commands.Cog): yield from ctx.channel.send(ctx.author.mention + ' ' + str(Message)) + def zalgofy(self, sentence, factor = 4): + random.seed(datetime.now().timestamp()) + message = '' + #from https://github.com/Aethylia/zalgo-cli: + for letter in sentence: + for i in range(factor): + letter += random.randint(0x300, 0x36f).to_bytes(2, byteorder='big').decode('utf-16be') + message += letter + return message + @commands.command(pass_context=True, hidden=False) @asyncio.coroutine def zalgo(self, ctx, *, arg): @@ -118,18 +128,12 @@ class Shitpost(commands.Cog): Gebruik: !zalgo [text] Bijv: !zalgo "Je moeder" """ - factor = 4 - message = '' - #from https://github.com/Aethylia/zalgo-cli: - for letter in arg: - for i in range(factor): - letter += random.randint(0x300, 0x36f).to_bytes(2, byteorder='big').decode('utf-16be') - message += letter + message = self.zalgofy(arg) try: yield from ctx.message.delete() except: print("No permission to delete message") - yield from ctx.channel.send(ctx.author.mention + ' ' + str(message)) + yield from ctx.channel.send(str(message)) def get_corona_message(self): response = requests.get('https://covid.ourworldindata.org/data/latest/owid-covid-latest.json') diff --git a/tests/shitpost.py b/tests/shitpost.py index b487658..f10fc25 100644 --- a/tests/shitpost.py +++ b/tests/shitpost.py @@ -163,3 +163,9 @@ class TestShitpost(unittest.TestCase): def test_corona(self): message = self.cog.get_corona_message() self.assertIsInstance(message, str) + + def test_zalgo(self): + inmsg = "lorem ipsum" + message = self.cog.zalgofy(inmsg) + self.assertIsInstance(message, str) + self.assertEqual(len(message), len(inmsg)*5) From 9119ac3171839e155892b96e8bbc2d0d23fc1e65 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sat, 10 Dec 2022 21:21:09 +0100 Subject: [PATCH 37/40] example env file --- example.env | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 example.env diff --git a/example.env b/example.env new file mode 100644 index 0000000..9b1ff1d --- /dev/null +++ b/example.env @@ -0,0 +1,16 @@ +STROOP_DISCORD_TOKEN= +STROOP_TWITTER_KEY= +STROOP_TWITTER_SECRET= +STROOP_REDDIT_ID= +STROOP_REDDIT_SECRET= +STROOP_SPOTIFY_ID= +STROOP_SPOTIFY_SECRET= +STROOP_SPOTIFY_USER= +STROOP_SPOTIFY_PLAYLIST= +STROOP_WEERLIVE= +STROOP_CALDAV_HOST= +STROOP_CALDAV_CAL= +STROOP_IMGFLIP_PASSWORD= +STROOP_RESET_PASSWORD= +STROOP_CHANNEL_SHITPOST= +STROOP_CHANNEL_BELANGRIJK= From c70bb1284fbb6a4c98f629529e2b6361e7666c0e Mon Sep 17 00:00:00 2001 From: Jan-Paul van Osta Date: Sat, 10 Dec 2022 22:26:13 +0100 Subject: [PATCH 38/40] eerste test voor chatbot --- tests/chatbot.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/chatbot.py diff --git a/tests/chatbot.py b/tests/chatbot.py new file mode 100644 index 0000000..d5cf629 --- /dev/null +++ b/tests/chatbot.py @@ -0,0 +1,36 @@ +import unittest +import praw +import dotenv +import re + +import discord +from discord.ext import commands + +import Chatbot + +class TestGeneral(unittest.TestCase): + def setUp(self): + dotenv.load_dotenv() + intents = discord.Intents.default() + intents.message_content = True + intents.members = True + bot = commands.Bot(command_prefix=commands.when_mentioned_or('!'), description='Stroopwafel. Shitpost bot extraordinaire.', pm_help=True, intents=intents) + self.cog = Chatbot.Chatbot(bot) + + def test_countsyllables(self): + with self.subTest("1 syllable word"): + self.assertEqual(1, self.cog.countSyllables("big")) + with self.subTest("1 syllable word (longer)"): + self.assertEqual(1, self.cog.countSyllables("Paard")) + with self.subTest("2 syllable word"): + self.assertEqual(2, self.cog.countSyllables("Bakfiets")) + with self.subTest("2 syllable word (more complex)"): + self.assertEqual(2, self.cog.countSyllables("Skiรซn")) + with self.subTest("3 syllable word"): + self.assertEqual(3, self.cog.countSyllables("Spookpoeper")) + with self.subTest("4 syllable word"): + self.assertEqual(4, self.cog.countSyllables("Papzakprobleem")) + with self.subTest("8 syllable word"): + self.assertEqual(8, self.cog.countSyllables("zuremattenvampirisme")) + with self.subTest("OMG"): + self.assertEqual(3, self.cog.countSyllables("OMG")) From c4ba63b83b3130de9ebd9a1231c884eb70ede6cc Mon Sep 17 00:00:00 2001 From: Jan-Paul van Osta Date: Sun, 11 Dec 2022 16:15:39 +0100 Subject: [PATCH 39/40] chatbot and points unittests toegevoegd aan init --- tests/__init__.py | 4 +++- tests/chatbot.py | 2 +- tests/points.py | 21 +++++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 tests/points.py diff --git a/tests/__init__.py b/tests/__init__.py index 8d7ef16..4c7fb26 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,2 +1,4 @@ from .shitpost import TestShitpost -from .general import TestGeneral \ No newline at end of file +from .general import TestGeneral +from .chatbot import TestChatbot +from .points import TestPoints \ No newline at end of file diff --git a/tests/chatbot.py b/tests/chatbot.py index d5cf629..ed6e21f 100644 --- a/tests/chatbot.py +++ b/tests/chatbot.py @@ -8,7 +8,7 @@ from discord.ext import commands import Chatbot -class TestGeneral(unittest.TestCase): +class TestChatbot(unittest.TestCase): def setUp(self): dotenv.load_dotenv() intents = discord.Intents.default() diff --git a/tests/points.py b/tests/points.py new file mode 100644 index 0000000..0d5b7fd --- /dev/null +++ b/tests/points.py @@ -0,0 +1,21 @@ +import unittest +import praw +import dotenv +from datetime import datetime + +import discord +from discord.ext import commands + +import Points + +class TestPoints(unittest.TestCase): + def setUp(self): + dotenv.load_dotenv() + intents = discord.Intents.default() + intents.message_content = True + intents.members = True + bot = commands.Bot(command_prefix=commands.when_mentioned_or('!'), description='Stroopwafel. Shitpost bot extraordinaire.', pm_help=True, intents=intents) + self.cog = Points.Points(bot) + + def test_getUserBalance(self): + self.assertEqual(2, 1+1) \ No newline at end of file From 25e38b6b5f5cb86d636dc00732780538f53ea2e4 Mon Sep 17 00:00:00 2001 From: Jan-Paul van Osta Date: Sun, 11 Dec 2022 16:19:05 +0100 Subject: [PATCH 40/40] refactor Points class + tests --- Points.py | 97 ++++++++++++++++++++-------------- tests/points.py | 138 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 193 insertions(+), 42 deletions(-) diff --git a/Points.py b/Points.py index f65827e..7292e71 100644 --- a/Points.py +++ b/Points.py @@ -18,6 +18,9 @@ class Points(commands.Cog): self.BANK_ID = 42 self.init() + self.pointsCount = {} + self.reloadPointsCount() + def __check(self, ctx): return True @@ -31,6 +34,8 @@ class Points(commands.Cog): De eerste 10 punten zijn on the house. (Als er genoeg in de bank zit.) """ + self.reloadPointsCount() + if points == 0: yield from ctx.channel.send("0 punten? Gul hoor.") return @@ -58,21 +63,26 @@ class Points(commands.Cog): return # Execute the transaction: - # First, try to give a away (at most 10) bankpoints - areBeingGivenFromBank = min(points, self.getUsersRemainingBankPointsToGiveAwayToday(ctx.author.id)) - areBeingGivenFromBank = min(areBeingGivenFromBank, self.getBankBalance()) - if areBeingGivenFromBank > 0: - self.transferPoints(self.BANK_ID, userObj.id, areBeingGivenFromBank) - self.increaseUsersBankPointGivenAwayToday(ctx.author.id, areBeingGivenFromBank) - remainingPointsToGive = points - areBeingGivenFromBank - else: - remainingPointsToGive = points - # The remaining points come out of your own pocket - if remainingPointsToGive > 0: - self.transferPoints(ctx.author.id, userObj.id, remainingPointsToGive) + self.execute_geefpunten(ctx.author.id, userObj.id, points) + + self.savePointsCount() message = self.getMessageForAwardingPoints(ctx.author.name, userObj.name, points) yield from ctx.channel.send(message) + + def execute_geefpunten(self, giverId, recieverId, points): + # First, try to give away (at most 10) bankpoints + areBeingGivenFromBank = min(points, self.getUsersRemainingBankPointsToGiveAwayToday(giverId)) + areBeingGivenFromBank = min(areBeingGivenFromBank, self.getBankBalance()) + if areBeingGivenFromBank > 0: + self.transferPoints(self.BANK_ID, recieverId, areBeingGivenFromBank) + self.increaseUsersBankPointGivenAwayToday(giverId, areBeingGivenFromBank) + remainingPointsToGive = points - areBeingGivenFromBank + else: + remainingPointsToGive = points + # The remaining points come out of your own pocket + if remainingPointsToGive > 0: + self.transferPoints(giverId, recieverId, remainingPointsToGive) @commands.command(pass_context=True, hidden=False) @@ -85,6 +95,8 @@ class Points(commands.Cog): Let op: je moet iemand taggen om punten weg te nemen. """ + self.reloadPointsCount() + if points < 1: yield from ctx.channel.send("Volgens mij snap je het niet.") return @@ -110,11 +122,16 @@ class Points(commands.Cog): return # Execute the transaction: - self.increaseUsersPointTakenOnDate(ctx.author.id, points) - self.transferPoints(userObj.id, self.BANK_ID, points) + self.execute_neempunten(ctx.author.id, userObj.id, points); + + self.savePointsCount() message = self.getMessageForTakingPoints(userObj.name, ctx.author.name, points) yield from ctx.channel.send(message) + + def execute_neempunten(self, takerId, victimId, points): + self.increaseUsersPointTakenOnDate(takerId, points) + self.transferPoints(victimId, self.BANK_ID, points) @commands.command(pass_context=True, hidden=False) @@ -123,14 +140,14 @@ class Points(commands.Cog): """Hoeveel punten heeft iedereen? """ + self.reloadPointsCount() + message = "**De puntentelling:** \n```" - pointsCount = np.load('pointscount.npy', allow_pickle=True).item() - pointsCountSorted = sorted(pointsCount.items(), key=lambda i: i[1]['points'], reverse=True) + pointsCountSorted = sorted(self.pointsCount.items(), key=lambda i: i[1]['points'], reverse=True) for user in pointsCountSorted: if user[0] != self.BANK_ID: message += str(user[1]["points"]).rjust(4) + " " + user[1]["name"] + "\n" - message += str(pointsCount[self.BANK_ID]["points"]).rjust(4) + " " + pointsCount[self.BANK_ID]["name"] + "```" - #message += "```" + message += str(self.pointsCount[self.BANK_ID]["points"]).rjust(4) + " " + self.pointsCount[self.BANK_ID]["name"] + "```" yield from ctx.channel.send(message) @@ -146,40 +163,42 @@ class Points(commands.Cog): except: print("No permission to send DM") + + # Get the points count object from the file + def reloadPointsCount(self): + self.pointsCount = np.load('pointscount.npy', allow_pickle=True).item() + + # Save the points count to the file + def savePointsCount(self): + np.save("pointscount.npy", self.pointsCount) + # Transfer points form one user to another def transferPoints(self, fromUserId, toUserId, points): - pointsCount = np.load('pointscount.npy', allow_pickle=True).item() - pointsCount[fromUserId]["points"] -= points - pointsCount[toUserId]["points"] += points - np.save("pointscount.npy", pointsCount) + self.pointsCount[fromUserId]["points"] -= points + self.pointsCount[toUserId]["points"] += points # Do we know this user? def isUserOnList(self, user): - pointsCount = np.load('pointscount.npy', allow_pickle=True).item() - return user.id in pointsCount.keys() + return user.id in self.pointsCount.keys() # Get a user's point balance def getUserBalance(self, user): - pointsCount = np.load('pointscount.npy', allow_pickle=True).item() - return pointsCount[user.id]["points"] + return self.pointsCount[user.id]["points"] # Get the balance of the bank def getBankBalance(self): - pointsCount = np.load('pointscount.npy', allow_pickle=True).item() - return pointsCount[self.BANK_ID]["points"] + return self.pointsCount[self.BANK_ID]["points"] # To keep track if a user used some points today, we look at when the last time was he/she used them # If this was in the past: reset # Also, return the updated object. Why not. def refreshDateVarsAndReturnUserVars(self, userId): - pointsCount = np.load('pointscount.npy', allow_pickle=True).item() currentDateStr = datetime.now().strftime("%Y%m%d") - if pointsCount[userId]["theDate"] != currentDateStr: - pointsCount[userId]["theDate"] = currentDateStr - pointsCount[userId]["pointTakenOnDate"] = 0 - pointsCount[userId]["bankPointsGivenOnDate"] = 0 - np.save("pointscount.npy", pointsCount) - return pointsCount[userId] + if self.pointsCount[userId]["theDate"] != currentDateStr: + self.pointsCount[userId]["theDate"] = currentDateStr + self.pointsCount[userId]["pointTakenOnDate"] = 0 + self.pointsCount[userId]["bankPointsGivenOnDate"] = 0 + return self.pointsCount[userId] # How many points can this user still take away today? def getUsersRemainingPointsToTakeToday(self, userId): @@ -194,16 +213,12 @@ class Points(commands.Cog): # Increase the number of points this user has taken away today. # Warning: assumes you executed refreshDateVarsAndReturnUserVars() def increaseUsersPointTakenOnDate(self, userId, points): - pointsCount = np.load('pointscount.npy', allow_pickle=True).item() - pointsCount[userId]["pointTakenOnDate"] += points - np.save("pointscount.npy", pointsCount) + self.pointsCount[userId]["pointTakenOnDate"] += points # Increase the number of bank points this user has given today # Warning: assumes you executed refreshDateVarsAndReturnUserVars() def increaseUsersBankPointGivenAwayToday(self, userId, points): - pointsCount = np.load('pointscount.npy', allow_pickle=True).item() - pointsCount[userId]["bankPointsGivenOnDate"] += points - np.save("pointscount.npy", pointsCount) + self.pointsCount[userId]["bankPointsGivenOnDate"] += points # Generate a semi-random text to tell somebody they got some shiny new points diff --git a/tests/points.py b/tests/points.py index 0d5b7fd..9f79f2a 100644 --- a/tests/points.py +++ b/tests/points.py @@ -8,6 +8,11 @@ from discord.ext import commands import Points +class User: + def __init__(self, id, name): + self.id = id + self.name = name + class TestPoints(unittest.TestCase): def setUp(self): dotenv.load_dotenv() @@ -16,6 +21,137 @@ class TestPoints(unittest.TestCase): intents.members = True bot = commands.Bot(command_prefix=commands.when_mentioned_or('!'), description='Stroopwafel. Shitpost bot extraordinaire.', pm_help=True, intents=intents) self.cog = Points.Points(bot) + + self.user1 = User(10001, "Alice") + self.user2 = User(10002, "Bob") def test_getUserBalance(self): - self.assertEqual(2, 1+1) \ No newline at end of file + self.cog.pointsCount = {} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 69} + self.assertEqual(69, self.cog.getUserBalance(self.user1)) + + def test_getBankBalance(self): + self.cog.pointsCount = {} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 1} + self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 999} + self.assertEqual(999, self.cog.getBankBalance()) + + def test_isUserOnList(self): + self.cog.pointsCount = {} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 1} + self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 999} + self.assertTrue(self.cog.isUserOnList(self.user1)) + self.assertFalse(self.cog.isUserOnList(self.user2)) + + def test_transferPoints(self): + self.cog.pointsCount = {} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 50} + self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 30} + self.cog.transferPoints(self.user1.id, self.user2.id, 4) + self.assertEqual(46, self.cog.getUserBalance(self.user1)) + self.assertEqual(34, self.cog.getUserBalance(self.user2)) + + def test_given_bankHasBalanceAndUserHasNotGivenPointsYetToday_when_givingPoints_then_tenPointComeFromBank(self): + self.cog.pointsCount = {} + self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 1000} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 200, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"} + self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"} + self.cog.execute_geefpunten(self.user1.id, self.user2.id, 12) + self.assertEqual(990, self.cog.getBankBalance()) + self.assertEqual(198, self.cog.getUserBalance(self.user1)) + self.assertEqual(112, self.cog.getUserBalance(self.user2)) + + def test_given_bankHasBalanceButUserHasNoBalanceAndUserHasNotGivenPointsYetToday_when_givingPoints_then_pointComeFromBank(self): + currentDateStr = datetime.now().strftime("%Y%m%d") + self.cog.pointsCount = {} + self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 1000} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 0, "pointTakenOnDate":10, "bankPointsGivenOnDate":0, "theDate":currentDateStr} + self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":10, "bankPointsGivenOnDate":10, "theDate":currentDateStr} + self.cog.execute_geefpunten(self.user1.id, self.user2.id, 5) + self.assertEqual(995, self.cog.getBankBalance()) + self.assertEqual(0, self.cog.getUserBalance(self.user1)) + self.assertEqual(105, self.cog.getUserBalance(self.user2)) + + def test_given_bankIsEmpty_when_givingPoints_then_AllPointsComeFromUser(self): + self.cog.pointsCount = {} + self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 0} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 200, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"} + self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"} + self.cog.execute_geefpunten(self.user1.id, self.user2.id, 15) + self.assertEqual(0, self.cog.getBankBalance()) + self.assertEqual(185, self.cog.getUserBalance(self.user1)) + self.assertEqual(115, self.cog.getUserBalance(self.user2)) + + def test_given_userHasAlreadyGivenSomeBankPointsToday_when_givingPoints_then_NotAllPointsComeFromBank(self): + currentDateStr = datetime.now().strftime("%Y%m%d") + self.cog.pointsCount = {} + self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 1000} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 200, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":currentDateStr} + self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"} + # First a normal transaction: + self.cog.execute_geefpunten(self.user1.id, self.user2.id, 5) + self.assertEqual(995, self.cog.getBankBalance()) + self.assertEqual(200, self.cog.getUserBalance(self.user1)) + self.assertEqual(105, self.cog.getUserBalance(self.user2)) + # Then another one: + self.cog.execute_geefpunten(self.user1.id, self.user2.id, 8) + self.assertEqual(990, self.cog.getBankBalance()) # Only the first 5 come from the bank + self.assertEqual(197, self.cog.getUserBalance(self.user1)) + self.assertEqual(113, self.cog.getUserBalance(self.user2)) + # One more: + self.cog.execute_geefpunten(self.user1.id, self.user2.id, 3) + self.assertEqual(990, self.cog.getBankBalance()) # All points come out of the user's pocket now + self.assertEqual(194, self.cog.getUserBalance(self.user1)) + self.assertEqual(116, self.cog.getUserBalance(self.user2)) + + def test_given_usersWithPoints_when_takingPoints_then_pointsGoToTheBank(self): + self.cog.pointsCount = {} + self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 1000} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 200, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"} + self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"} + self.cog.refreshDateVarsAndReturnUserVars(self.user1.id) #usually happens in !neempunten, so this unittest is a bit poor + self.cog.execute_neempunten(self.user1.id, self.user2.id, 2) + self.assertEqual(1002, self.cog.getBankBalance()) + self.assertEqual(200, self.cog.getUserBalance(self.user1)) + self.assertEqual(98, self.cog.getUserBalance(self.user2)) + # The user should only have 8 points left to give away today: + self.assertEqual(8, self.cog.getUsersRemainingPointsToTakeToday(self.user1.id)) + + def test_given_user_when_takingPoints_then_pointsToTakeAreLimited(self): + self.cog.pointsCount = {} + self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 1000} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 200, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"} + self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"} + self.cog.refreshDateVarsAndReturnUserVars(self.user1.id) #usually happens in !neempunten, so this unittest is a bit poor + self.cog.execute_neempunten(self.user1.id, self.user2.id, 6) + self.assertEqual(94, self.cog.getUserBalance(self.user2)) + # The user should only have 4 points left to give away today: + self.assertEqual(4, self.cog.getUsersRemainingPointsToTakeToday(self.user1.id)) + self.cog.execute_neempunten(self.user1.id, self.user2.id, 3) + self.assertEqual(91, self.cog.getUserBalance(self.user2)) + # The user should only have 1 point left to give away today: + self.assertEqual(1, self.cog.getUsersRemainingPointsToTakeToday(self.user1.id)) + self.cog.execute_neempunten(self.user1.id, self.user2.id, 1) + self.assertEqual(90, self.cog.getUserBalance(self.user2)) + # The user should have 0 points left to take away: + self.assertEqual(0, self.cog.getUsersRemainingPointsToTakeToday(self.user1.id)) + # The actual check whether or not a user can keep on taking points away happens in !neempunten and is not tested here + + def test_refreshDateVarsAndReturnUserVars(self): + with self.subTest("Should not be updated yet. Update was just today."): + currentDateStr = datetime.now().strftime("%Y%m%d") + self.cog.pointsCount = {} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 100, "pointTakenOnDate":2, "bankPointsGivenOnDate":1, "theDate":currentDateStr} + self.cog.refreshDateVarsAndReturnUserVars(self.user1.id) + # Still today. Values should stay the same: + self.assertEqual(2, self.cog.pointsCount[self.user1.id]["pointTakenOnDate"]) + self.assertEqual(1, self.cog.pointsCount[self.user1.id]["bankPointsGivenOnDate"]) + with self.subTest("Should be reset. Update was in the past."): + currentDateStr = datetime.now().strftime("%Y%m%d") + self.cog.pointsCount = {} + self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 100, "pointTakenOnDate":2, "bankPointsGivenOnDate":1, "theDate":"20150101"} + self.cog.refreshDateVarsAndReturnUserVars(self.user1.id) + # A new day. Values should be set to 0 again: + self.assertEqual(0, self.cog.pointsCount[self.user1.id]["pointTakenOnDate"]) + self.assertEqual(0, self.cog.pointsCount[self.user1.id]["bankPointsGivenOnDate"]) + self.assertNotEqual("20150101", self.cog.pointsCount[self.user1.id]["theDate"])