diff --git a/CHANGELOG.md b/CHANGELOG.md index 03de4f8..ce4805e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## Unreleased +## [0.3.0] - 2017-08-07 +### Added +- A maximum number of attendees can be specified for an event +- A 'standby' section has been added to events that have more attendees than the event permits ### Changed - Events are now sorted in the events channel by their start time -- Event attendees are now sorted by when they RSVP'd +- Event attendees are now sorted by when they accepted the invitation ## [0.2.0] - 2017-08-02 ### Added diff --git a/cogs/events.py b/cogs/events.py index 7cb4a61..23352e7 100644 --- a/cogs/events.py +++ b/cogs/events.py @@ -7,7 +7,7 @@ import discord from cogs.utils.messages import delete_all, get_server_from_dm, MessageManager -from cogs.utils.checks import is_event, is_admin +from cogs.utils.checks import is_event, is_admin, is_int from cogs.utils import constants @@ -44,6 +44,19 @@ async def event(self, ctx): if res.content.upper() != 'NONE': description = res.content + max_members = 0 + while not max_members: + res = await manager.say_and_wait("Enter the maximum numbers of attendees (type 'none' for no maximum)") + if not res: + return + if res.content.upper() == 'NONE': + break + elif is_int(res.content) and int(res.content) > 0: + print(int(res.content)) + max_members = int(res.content) + else: + await manager.say("That is not a a valid entry.") + start_time = None while not start_time: res = await manager.say_and_wait("Enter event time (YYYY-MM-DD HH:MM AM/PM)") @@ -66,7 +79,7 @@ async def event(self, ctx): time_zone = res.content.upper() with DBase() as db: - res = db.create_event(title, start_time, time_zone, server.id, description) + res = db.create_event(title, start_time, time_zone, server.id, description, max_members) if res == 0: await manager.say("An event with that name already exists.") return await manager.clear() @@ -85,7 +98,7 @@ async def list_events(self, server): events = db.get_events(server.id) if len(events) > 0: for row in events: - event_embed = self.create_event_embed(row[0], row[1], row[2], row[3], row[4], row[5]) + event_embed = self.create_event_embed(row[0], row[1], row[2], row[3], row[4], row[5], row[6]) msg = await self.bot.send_message(events_channel, embed=event_embed) await self.bot.add_reaction(msg, "\N{WHITE HEAVY CHECK MARK}") await self.bot.add_reaction(msg, "\N{CROSS MARK}") @@ -131,7 +144,7 @@ async def set_attendance(self, username, server_id, attending, title, message): with DBase() as db: event = db.get_event(server_id, title) event_embed = self.create_event_embed(event[0][0], event[0][1], event[0][2], - event[0][3], event[0][4], event[0][5]) + event[0][3], event[0][4], event[0][5], event[0][6]) await self.bot.edit_message(message, embed=event_embed) @@ -156,7 +169,7 @@ async def get_events_channel(self, server): return channel - def create_event_embed(self, title, description, time, time_zone, accepted=None, declined=None): + def create_event_embed(self, title, description, time, time_zone, accepted=None, declined=None, max_members=None): """Create and return a Discord Embed object that represents an upcoming event""" embed_msg = discord.Embed(color=constants.BLUE) embed_msg.set_footer(text="React with {} to remove this event".format('\U0001f480')) @@ -168,22 +181,41 @@ def create_event_embed(self, title, description, time, time_zone, accepted=None, embed_msg.add_field(name="Time", value=time_str + " " + time_zone, inline=False) if accepted: - accepted = accepted.split(',') - accepted_list = "" - for member in accepted: - accepted_list += "{}\n".format(member.split("#")[0]) - embed_msg.add_field(name="Accepted", value=accepted_list) + accepted_list = None + if max_members: + accepted_list = accepted.split(',')[:max_members] + else: + accepted_list = accepted.split(',') + text = "" + for member in accepted_list: + text += "{}\n".format(member.split("#")[0]) + if max_members: + embed_msg.add_field(name="Accepted ({}/{})".format(len(accepted_list), max_members), value=text) + else: + embed_msg.add_field(name="Accepted", value=text) else: - embed_msg.add_field(name="Accepted", value="-") + if max_members: + embed_msg.add_field(name="Accepted (0/{})".format(max_members), value="-") + else: + embed_msg.add_field(name="Accepted", value="-") if declined: - declined = declined.split(',') - declined_list = "" - for member in declined: - declined_list += "{}\n".format(member.split("#")[0]) - embed_msg.add_field(name="Declined", value=declined_list) + declined_list = declined.split(',') + text = "" + for member in declined_list: + text += "{}\n".format(member.split("#")[0]) + embed_msg.add_field(name="Declined", value=text) else: embed_msg.add_field(name="Declined", value="-") + + if accepted and max_members: + standby_list = accepted.split(',')[max_members:] + if standby_list: + text = "" + for member in standby_list: + text += "{}\n".format(member.split("#")[0]) + embed_msg.add_field(name="Standby", value=text, inline=False) + return embed_msg diff --git a/cogs/utils/checks.py b/cogs/utils/checks.py index 5b2bf33..af96d3e 100644 --- a/cogs/utils/checks.py +++ b/cogs/utils/checks.py @@ -8,11 +8,20 @@ def is_event(message): and 'name' in embed['fields'][1] and 'name' in embed['fields'][2] and embed['fields'][0].get("name") == "Time" - and embed['fields'][1].get("name") == "Accepted" - and embed['fields'][2].get("name") == "Declined") + and embed['fields'][1].get("name").startswith("Accepted") + and embed['fields'][2].get("name").startswith("Declined")) def is_admin(user, channel): """Check if the user has admin privileges""" if channel.permissions_for(user).administrator: return True + +def is_int(x): + try: + a = float(x) + b = int(a) + except ValueError: + return False + else: + return a == b diff --git a/cogs/utils/constants.py b/cogs/utils/constants.py index 3c2c65c..bf5ce35 100644 --- a/cogs/utils/constants.py +++ b/cogs/utils/constants.py @@ -1,6 +1,6 @@ import discord - +VERSION = "0.3.0" BLUE = discord.Colour(3381759) SPAM_DELAY = 4 REACTION_DELAY = 0.5 diff --git a/db/dbase.py b/db/dbase.py index ae11af9..fd76abc 100644 --- a/db/dbase.py +++ b/db/dbase.py @@ -46,13 +46,13 @@ def update_roster(self, username, role, server_id): self.cur.execute(sql, (role, username, server_id)) self.conn.commit() - def create_event(self, title, start_time, time_zone, server_id, description): + def create_event(self, title, start_time, time_zone, server_id, description, max_members): sql = """ - INSERT INTO events (title, start_time, time_zone, server_id, description) - VALUES (%s, %s, %s, %s, %s) + INSERT INTO events (title, start_time, time_zone, server_id, description, max_members) + VALUES (%s, %s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE title = %s; """ - rows = self.cur.execute(sql, (title, start_time, time_zone, server_id, description, title)) + rows = self.cur.execute(sql, (title, start_time, time_zone, server_id, description, max_members, title)) self.conn.commit() return rows @@ -70,7 +70,8 @@ def get_events(self, server_id): WHERE user_event.server_id = %s AND user_event.title = e AND user_event.attending = 0) - AS declined + AS declined, + max_members FROM events WHERE events.server_id = %s GROUP BY title, description, start_time, time_zone @@ -102,7 +103,8 @@ def get_event(self, server_id, title): WHERE user_event.server_id = %s AND user_event.title = %s AND user_event.attending = 0) - AS declined + AS declined, + max_members FROM events WHERE server_id = %s AND title = %s; diff --git a/db/schema.sql b/db/schema.sql index 478aad9..9986e6d 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -20,6 +20,7 @@ CREATE TABLE events ( time_zone VARCHAR(5) NOT NULL, title VARCHAR(256) NOT NULL, description VARCHAR(1000), + max_members INT NOT NULL DEFAULT 0, PRIMARY KEY (server_id, title), FOREIGN KEY (server_id) REFERENCES servers(server_id) ON DELETE CASCADE diff --git a/spirit.py b/spirit.py index d94c51c..bda688d 100644 --- a/spirit.py +++ b/spirit.py @@ -5,6 +5,7 @@ from discord.ext import commands from db.dbase import DBase +from cogs.utils import constants from cogs.events import Events from cogs.roster import Roster from cogs.help import Help @@ -34,7 +35,7 @@ async def _prefix_callable(bot, message): @bot.event async def on_ready(): """Display startup information""" - print('Spirit v0.2.0') + print('Spirit v{}'.format(constants.VERSION)) print('Username: {}'.format(bot.user.name)) print('------')