commit eb0f3cec07021357fb28aa0ac3c22fe6f703ee43 Author: Danila Fedorin Date: Thu Dec 3 03:21:00 2020 -0800 Save requirements. diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..ec66f41 --- /dev/null +++ b/bot.py @@ -0,0 +1,95 @@ +import discord +from discord.ext import tasks +import os +import sqlite3 +from aiohttp import ClientSession +import json + +client = discord.Client() +conn = sqlite3.connect('data.db') + +def setup(): + conn.execute(''' + CREATE TABLE IF NOT EXISTS + guild(id int primary key, channel int, leaderboard int, last_sync text) + ''') + +@client.event +async def on_ready(): + print('We have logged in as {0.user}'.format(client)) + +@client.event +async def on_message(message): + if message.content.startswith("!setup"): + leaderboard = int(message.content[7:]) + conn.execute(''' + insert into guild(id, channel, leaderboard, last_sync) + values (?, ?, ?, ?) on conflict(id) do + update set channel=excluded.channel, leaderboard=excluded.leaderboard''', + (message.guild.id, message.channel.id, leaderboard, None)) + conn.commit() + await message.channel.send( + 'Updated {0.guild} to use channel {0.channel} and leaderboard {1}!' + .format(message, leaderboard)) + +def gather_stars(member): + star_list = [] + for day in member['completion_day_level']: + stars = member['completion_day_level'][day] + if "1" in stars: + star_list.append((member['name'], int(day), 1, stars['1']['get_star_ts'])) + if "2" in stars: + star_list.append((member['name'], int(day), 2, stars["2"]['get_star_ts'])) + return star_list + +def perform_member_diff(old_member, new_member): + old_stars = gather_stars(old_member) + new_stars = gather_stars(new_member) + return [star for star in new_stars if star not in old_stars] + +def perform_diff(old_json, new_json): + if old_json is None: + old_json = {'members': {}} + else: + old_json = json.loads(old_json) + new_json = json.loads(new_json) + diff = { 'join': [], 'new_stars': [] } + for new_member in new_json['members'].keys(): + if new_member not in old_json['members']: + diff['join'].append(new_json['members'][new_member]['name']) + continue + member_diff = perform_member_diff(old_json['members'][new_member], new_json['members'][new_member]) + diff['new_stars'] += member_diff + return diff + +async def send_diff(id, channel, diff): + announcements = [] + for user in diff['join']: + full_text = "User {0} joined the leaderboard!".format(user) + announcements.append(full_text) + for (user, day, star, ts) in diff['new_stars']: + star_name = "silver" if star == 1 else "gold" + full_text = "{0} won the {1} star from day {2}!".format(user, star_name, day) + announcements.append(full_text) + + if len(announcements) != 0: + channel = await client.fetch_channel(channel) + await channel.send("\n".join(announcements)) + +@tasks.loop(minutes=1.0) +async def update_aoc(): + url_string = "https://adventofcode.com/2020/leaderboard/private/view/{0}.json" + cookies = { 'session': os.getenv("AOC_SESSION") } + + async with ClientSession(cookies=cookies) as session: + for (id, channel, leaderboard, json) in conn.execute('select * from guild'): + async with session.get(url_string.format(leaderboard)) as resp: + new_json = await resp.text() + diff = perform_diff(json, new_json) + await send_diff(id, channel, diff) + conn.execute('update guild set last_sync=? where id=?', (new_json, id)) + conn.commit() + +setup() +update_aoc.start() +client.run(os.environ['AOC_BOT_TOKEN']) diff --git a/required.txt b/required.txt new file mode 100644 index 0000000..ee5ea35 --- /dev/null +++ b/required.txt @@ -0,0 +1,9 @@ +aiohttp==3.6.3 +async-timeout==3.0.1 +attrs==20.3.0 +chardet==3.0.4 +discord==1.0.1 +discord.py==1.5.1 +idna==2.10 +multidict==4.7.6 +yarl==1.5.1