diff --git a/help/help.md b/help/help.md index b92fc7b..fa03eda 100644 --- a/help/help.md +++ b/help/help.md @@ -8,3 +8,5 @@ Standard diceroller which works with the 1dX notation. See `!help roll` for more `# GIF embeds` For servers that want to disable embeds for any reason (triggers, unwanted imagery, etc), this function will make sure that (for specific channels configured in the config) gif URLs are picked up by the bot and embedded. This whole functionality is used for a problem that shouldn't be there in the first place, but because GIFs are linked to the Embed setting in Discord, for some servers this might pose a solution. +`# LARP Platform Babbelbingo` +For the LARP Platform babbelbingo, you can use the `!bingo` command anywhere on the LARP Platform Discord Server. You will get a babbelbingo card in PM. You can use the `!bingo` command again for a new card if your old one is done or if you want a new one with other questions. diff --git a/jeeves.py b/jeeves.py index 33752e7..83cac7b 100755 --- a/jeeves.py +++ b/jeeves.py @@ -3,10 +3,7 @@ import discord from discord.ext import commands import logging -from jeevesbot import bothelp, functions, env -import gspread -from oauth2client.service_account import ServiceAccountCredentials -import asyncio +from jeevesbot import bothelp, functions, env, babbelbingo # setup logging logging.basicConfig(level=logging.INFO) @@ -15,18 +12,16 @@ logger.setLevel(logging.INFO) handler = logging.FileHandler(filename='jeeves.log', encoding='utf-8', mode='a') handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s')) logger.addHandler(handler) -# setup discord.py -client = discord.Client() -e = discord.Embed() -# setup gspread -scope = ['https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive'] -# creds = ServiceAccountCredentials.from_json_keyfile_name('jeevesbot/secret.json', scope) -# gclient = gspread.authorize(creds) -@client.event +# setup discord.py bot +intents = discord.Intents().all() +bot = commands.Bot(command_prefix='!', intents=intents) +e = discord.Embed() + +@bot.event async def on_message(message): # we do not want the bot to reply to itself - if message.author == client.user: + if message.author == bot.user: return if message.content.startswith('!help'): parameters = message.content.split(' ', 1) @@ -51,7 +46,7 @@ async def on_message(message): await message.channel.send(embed=embed) logline = (str(message.author) + ' requested a gif: ' + str(gif_url)) logger.info(logline) - if message.content.startswith('https://c.tenor.com/'): + if message.content.endswith('.gif'): roles = functions.checkrole(message.author.roles) channel = functions.checkchannel(message.channel.id) embed_url = message.content @@ -60,7 +55,7 @@ async def on_message(message): if roles is not True: await message.channel.send(embed=embed) logline = (str(message.author) + ' requested a gif: ' + str(embed_url)) - logger.info(logline) + logger.info(logline) if message.content.startswith('https://giphy.com/'): roles = functions.checkrole(message.author.roles) channel = functions.checkchannel(message.channel.id) @@ -80,12 +75,30 @@ async def on_message(message): roll,result = functions.roll(param) msg = 'Rolling %s for {0.author.mention}: `%s`'.format(message) % (param,roll) await message.channel.send(msg) - -@client.event + if message.content.startswith('!bingo'): + name = message.author.name + bingocard = babbelbingo.bingo(name) + guild_id = message.guild.id + guild = discord.utils.find(lambda g: g.id == guild_id, bot.guilds) + member = discord.utils.get(guild.members, id=message.author.id) + role = discord.utils.get(guild.roles , name='babbelbingo') + await message.author.send(file=discord.File(bingocard)) + await member.add_roles(role) + if message.content.startswith('!youtube'): + msg = 'https://www.youtube.com/channel/UCTAnkjUOud_HdKhY_hi2ISA' + await message.channel.send(msg) + if message.content.startswith('!blokkenschema'): + msg = 'https://www.larp-platform.nl/zomer-festival/blokkenschema/' + await message.channel.send(msg) + if message.content.startswith('!donatie'): + msg = 'https://bunq.me/larpzomerfestival' + await message.channel.send(msg) + +@bot.event async def on_ready(): - print('### Active with id %s as %s ###' % (client.user.id,client.user.name) ) + print('### Active with id %s as %s ###' % (bot.user.id,bot.user.name) ) activity = discord.Activity(name='!help', type=discord.ActivityType.listening) - await client.change_presence(activity=activity) + await bot.change_presence(activity=activity) if __name__ == '__main__': - client.run(env.TOKEN) + bot.run(env.TOKEN) diff --git a/jeevesbot/babbelbingo.py b/jeevesbot/babbelbingo.py new file mode 100644 index 0000000..8d2e63a --- /dev/null +++ b/jeevesbot/babbelbingo.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 + +import gspread +from oauth2client.service_account import ServiceAccountCredentials +import random +from PIL import Image, ImageFont, ImageDraw +import textwrap + +# setup gspread +scope = ['https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive'] +creds = ServiceAccountCredentials.from_json_keyfile_name('jeevesbot/secret.json', scope) +gclient = gspread.authorize(creds) + +# load babbelbingofile +def babbelbingo_file(): + file = gclient.open_by_key("1zdWl17fhdT2P96ZgjSwB_2wsCHi_ZVA42JroX5d1ylc") + babbelbingo = file.get_worksheet(1) + values = babbelbingo.get_all_values() + list_values = [item for sublist in values for item in sublist] + questions = random.sample(list_values, k=24) + return questions + +def make_bingocard(name, questions): + image = Image.open('jeevesbot/files/bingokaart.png') + font_name = ImageFont.truetype('jeevesbot/files/Overpass-regular.ttf', 13) + draw = ImageDraw.Draw(image) + wrapper = textwrap.TextWrapper(width=20, break_on_hyphens=True) + box01 = '\n'.join(wrapper.wrap(questions[0])) + box02 = '\n'.join(wrapper.wrap(questions[1])) + box03 = '\n'.join(wrapper.wrap(questions[2])) + box04 = '\n'.join(wrapper.wrap(questions[3])) + box05 = '\n'.join(wrapper.wrap(questions[4])) + box06 = '\n'.join(wrapper.wrap(questions[5])) + box07 = '\n'.join(wrapper.wrap(questions[6])) + box08 = '\n'.join(wrapper.wrap(questions[7])) + box09 = '\n'.join(wrapper.wrap(questions[8])) + box10 = '\n'.join(wrapper.wrap(questions[9])) + box11 = '\n'.join(wrapper.wrap(questions[10])) + box12 = '\n'.join(wrapper.wrap(questions[11])) + box13 = '\n'.join(wrapper.wrap(questions[12])) + box14 = '\n'.join(wrapper.wrap(questions[13])) + box15 = '\n'.join(wrapper.wrap(questions[14])) + box16 = '\n'.join(wrapper.wrap(questions[15])) + box17 = '\n'.join(wrapper.wrap(questions[16])) + box18 = '\n'.join(wrapper.wrap(questions[17])) + box19 = '\n'.join(wrapper.wrap(questions[18])) + box20 = '\n'.join(wrapper.wrap(questions[19])) + box21 = '\n'.join(wrapper.wrap(questions[20])) + box22 = '\n'.join(wrapper.wrap(questions[21])) + box23 = '\n'.join(wrapper.wrap(questions[22])) + box24 = '\n'.join(wrapper.wrap(questions[23])) + draw.multiline_text((95, 280.5), box01, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((229, 280.5), box02, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((363, 280.5), box03, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((497, 280.5), box04, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((631, 280.5), box05, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((95, 399.5), box06, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((229, 399.5), box07, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((363, 399.5), box08, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((497, 399.5), box09, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((631, 399.5), box10, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((95, 518.5), box11, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((229, 518.5), box12, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((497, 518.5), box13, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((631, 518.5), box14, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((95, 637.5), box15, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((229, 637.5), box16, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((363, 637.5), box17, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((497, 637.5), box18, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((631, 637.5), box19, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((95, 756.5), box20, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((229, 756.5), box21, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((363, 756.5), box22, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((497, 756.5), box23, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + draw.multiline_text((631, 756.5), box24, (0, 0, 0), font=font_name, align='center', anchor='mm', spacing=8) + table = str.maketrans({'(':None, ')':None, '/':None, ' ':'_'}) + image.save('jeevesbot/files/generated_bingocards/' + name.translate(table) + '.png') + +def bingo(name): + questions = babbelbingo_file() + make_bingocard(name, questions) + table = str.maketrans({'(':None, ')':None, '/':None, ' ':'_'}) + bingoimage = ('jeevesbot/files/generated_bingocards/' + name.translate(table) + '.png') + return bingoimage diff --git a/jeevesbot/files/Overpass-Regular.ttf b/jeevesbot/files/Overpass-Regular.ttf new file mode 100644 index 0000000..0deeda5 Binary files /dev/null and b/jeevesbot/files/Overpass-Regular.ttf differ diff --git a/jeevesbot/files/bingokaart.png b/jeevesbot/files/bingokaart.png new file mode 100644 index 0000000..5ca3687 Binary files /dev/null and b/jeevesbot/files/bingokaart.png differ diff --git a/jeevesbot/files/generated_bingocards/Rowena Tilia.png b/jeevesbot/files/generated_bingocards/Rowena Tilia.png new file mode 100644 index 0000000..e6cd300 Binary files /dev/null and b/jeevesbot/files/generated_bingocards/Rowena Tilia.png differ diff --git a/jeevesbot/functions.py b/jeevesbot/functions.py index 1a2bec2..f1af938 100644 --- a/jeevesbot/functions.py +++ b/jeevesbot/functions.py @@ -1,14 +1,9 @@ #!/usr/bin/env python 3 from jeevesbot import env -# import urllib import aiohttp import dice -# This function is necessary for tenor, because they do not allow linking directly to the gif and need resolving. -#def resolve(url): -# return urllib.request.urlopen(url).url - # This function is necessary for tenor, because they do not allow linking directly to the gif and need resolving. ASYNC VERSION async def resolve(url): async with aiohttp.ClientSession() as session: @@ -33,4 +28,5 @@ def checkchannel(channelid): if channelid in env.GIFCHANNELS: return True else: - return False \ No newline at end of file + return False + diff --git a/requirements.txt b/requirements.txt index 68c6b69..a094b1d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ aiohttp async-timeout dice -discord.py +discord.py[voice] docopt multidict pyparsing @@ -10,6 +10,7 @@ typing-extensions pylint gspread oauth2client +Pillow # needs this version, otherwise TypeErrors will break stuff -yarl==1.4.2 \ No newline at end of file +yarl==1.4.2 diff --git a/scripts/emojivvdd.py b/scripts/emojivvdd.py new file mode 100644 index 0000000..fcbc5dc --- /dev/null +++ b/scripts/emojivvdd.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 + +import time +import discord +from discord.ext import commands +import sys +import ast +from ..jeevesbot import env + +## Standalone script for emoji-vvdd + +# setup discord.py bot +intents = discord.Intents().all() +client = commands.Bot(command_prefix='!', intents=intents) + +if len(sys.argv) >= 2: + params = sys.argv[1:] +else: + print("Missing parameter input.") + +async def score(question, score): + e = discord.Embed(title='Emoji-VVDD', color=discord.Color.green()) + e.set_author(name='Jeeves', icon_url='https://cdn.hippogrief.nl/jeevesbot/jeeves.jpg') + e.add_field(name=question, value='\u200b', inline=False) + e.add_field(name='Hoogste score:', value=score, inline=False) + e.set_thumbnail(url='https://cdn.hippogrief.nl/jeevesbot/logo.jpg') + return score + +async def run_script(params): + params = params + channel = client.get_channel(729667183126511617) # vvdd 729667183126511617 # tech 790908319005933598 # test 749399756752814105 + emoji_numbers = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣'] + question = params[0] # string + answers = ast.literal_eval(params[1]) # list + number_of_responses = len(answers) # int + e = discord.Embed(title='Emoji-VVDD', description='Klik de emoji beneden dit bericht om te stemmen op het antwoord wat bij de emoji hoort.', color=discord.Color.blue()) + e.set_author(name='Jeeves', icon_url='https://cdn.hippogrief.nl/jeevesbot/jeeves.jpg') + e.add_field(name=question, value='\u200b', inline=False) + for emoji, answer in zip(emoji_numbers, answers): + e.add_field(name=emoji, value=answer, inline=False) + e.set_thumbnail(url='https://cdn.hippogrief.nl/jeevesbot/logo.jpg') + message = await channel.send(embed=e) + for i in range(number_of_responses): + await message.add_reaction(emoji_numbers[i]) + for i in range(24, -1, -1): + time.sleep(60) + message = await channel.fetch_message(message.id) + + values = {} + for i in message.reactions: + itervalues = {str(i): int(i.count)} + values.update(itervalues) + max_key = max(values, key=values.get) + all_values = values.values() + max_value = max(all_values) + highest_keys = [key for key in values if values[key] == max_value] + + if len(highest_keys) == 1: + max_key = highest_keys[0] + hoogste_score = 'Hoogste score:' + elif len(highest_keys) != 1: + max_key = highest_keys + print(max_key) + hoogste_score = 'Gelijkspel tussen:' + + score = (str(max_key) + ' met ' + str(max_value) + ' stemmen.') + f = discord.Embed(title='Emoji-VVDD', color=discord.Color.green()) + f.set_author(name='Jeeves', icon_url='https://cdn.hippogrief.nl/jeevesbot/jeeves.jpg') + f.add_field(name=question, value='\u200b', inline=False) + f.add_field(name=hoogste_score, value=score, inline=False) + f.set_footer(text="Je mag blijven doorstemmen, deze tussenstand zal niet worden bijgewerkt meer verder.") + f.set_thumbnail(url='https://cdn.hippogrief.nl/jeevesbot/logo.jpg') + message = await channel.send(embed=f) + + await client.close() + +@client.event +async def on_ready(): + print('### Active with id %s as %s ###' % (client.user.id,client.user.name) ) + activity = discord.Activity(name='!help', type=discord.ActivityType.listening) + await client.change_presence(activity=activity) + await run_script(params) + +if __name__ == '__main__': + client.run(env.TOKEN)