<commit_before>from datetime import datetime
import asyncio
import re

from discord.ext import commands
import discord

from db.dbase import DBase
from cogs.utils.messages import delete_all, MessageManager
from cogs.utils.checks import is_event, is_int
from cogs.utils import constants


class Events:

    def __init__(self, bot):
        self.bot = bot


    @commands.command()
    @commands.guild_only()
    @commands.has_permissions(administrator=True)
    async def event(self, ctx):
        """
        Create an event (admin only)

        After invoking the command, the bot will ask
        you to enter the event details. Once the event
        is created, it will appear in the upcoming-events
        channel. The upcoming-events channel is designed
        the assumption that it isn't used for anything but
        displaying events.

        Users will be able to accept and decline the
        event by adding reactions. If a maximum number
        of attendees is set and the event is full,
        additional attendees will be placed in a standby
        section. If a spot opens up, the user at the
        top of the standby section will be automatically
        moved into the event.

        Administrators can delete events by reacting to
        the event message with \U0001f480
        """
        manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])
        await manager.say('Event creation instructions have been messaged to you')

        res = await manager.say_and_wait("Enter event title:", dm=True)
        if not res:
            return
        title = res.content

        description = ""
        res = await manager.say_and_wait("Enter event description (type 'none' for no description):", dm=True)
        if not res:
            return
        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):", dm=True)
            if not res:
                return
            if res.content.upper() == 'NONE':
                break
            elif is_int(res.content) and int(res.content) > 0:
                max_members = int(res.content)
            else:
                await manager.say("That is not a a valid entry.", dm=True)

        start_time = None
        while not start_time:
            res = await manager.say_and_wait("Enter event time (YYYY-MM-DD HH:MM AM/PM):", dm=True)
            if not res:
                return
            start_time_format = '%Y-%m-%d %I:%M %p'
            try:
                start_time = datetime.strptime(res.content, start_time_format)
            except ValueError:
                await manager.say("Invalid event time!", dm=True)

        time_zone = None
        while not time_zone:
            res = await manager.say_and_wait("Enter the time zone (PST, EST, etc):", dm=True)
            if not res:
                return
            if res.content.upper() not in constants.TIME_ZONES:
                await manager.say("Unsupported time zone", dm=True)
            else:
                time_zone = res.content.upper()

        with DBase() as db:
            res = db.create_event(title, start_time, time_zone, ctx.guild.id, description, max_members)
        if res == 0:
            await manager.say("An event with that name already exists!", dm=True)
            return await manager.clear()

        event_channel = await self.get_events_channel(ctx.guild)
        await manager.say("Event created! The " + event_channel.mention + " channel will be updated momentarily.", dm=True)
        await self.list_events(ctx.guild)
        await manager.clear()


    async def list_events(self, guild):
        """Clear the event channel and display all upcoming events"""
        events_channel = await self.get_events_channel(guild)
        await events_channel.purge(limit=999, check=delete_all)
        with DBase() as db:
            events = db.get_events(guild.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], row[6])
                msg = await events_channel.send(embed=event_embed)
                await msg.add_reaction("\N{WHITE HEAVY CHECK MARK}")
                await msg.add_reaction("\N{CROSS MARK}")
        else:
            await events_channel.send("There are no upcoming events.")


    async def on_raw_reaction_add(self, emoji, message_id, channel_id, user_id):
        """If a reaction represents a user RSVP, update the DB and event message"""
        channel = self.bot.get_channel(channel_id)
        message = await channel.get_message(message_id)
        user = self.bot.get_user(user_id)
        guild = channel.guild
        manager = MessageManager(self.bot, user, channel)

        # We check that the user is not the message author as to not count
        # the initial reactions added by the bot as being indicative of attendance
        if is_event(message) and user != message.author:
            title = message.embeds[0].title
            if emoji.name == "\N{WHITE HEAVY CHECK MARK}":
                await self.set_attendance(str(user), guild.id, 1, title, message)
            elif emoji.name == "\N{CROSS MARK}":
                await self.set_attendance(str(user), guild.id, 0, title, message)
            elif emoji.name == "\N{SKULL}":
                if user.permissions_in(channel).administrator:
                    return await self.delete_event(guild, title)
                else:
                    await manager.say("You must be an administrator to do that.")

            await message.remove_reaction(emoji, user)
            await manager.clear()


    async def set_attendance(self, username, server_id, attending, title, message):
        """Send updated event attendance info to db and update the event"""<commit_msg>event reaction listener was creating a user object instead of a member object<commit_after>from datetime import datetime
import asyncio
import re

from discord.ext import commands
import discord

from db.dbase import DBase
from cogs.utils.messages import delete_all, MessageManager
from cogs.utils.checks import is_event, is_int
from cogs.utils import constants


class Events:

    def __init__(self, bot):
        self.bot = bot


    @commands.command()
    @commands.guild_only()
    @commands.has_permissions(administrator=True)
    async def event(self, ctx):
        """
        Create an event (admin only)

        After invoking the command, the bot will ask
        you to enter the event details. Once the event
        is created, it will appear in the upcoming-events
        channel. The upcoming-events channel is designed
        the assumption that it isn't used for anything but
        displaying events.

        Users will be able to accept and decline the
        event by adding reactions. If a maximum number
        of attendees is set and the event is full,
        additional attendees will be placed in a standby
        section. If a spot opens up, the user at the
        top of the standby section will be automatically
        moved into the event.

        Administrators can delete events by reacting to
        the event message with \U0001f480
        """
        manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])
        await manager.say('Event creation instructions have been messaged to you')

        res = await manager.say_and_wait("Enter event title:", dm=True)
        if not res:
            return
        title = res.content

        description = ""
        res = await manager.say_and_wait("Enter event description (type 'none' for no description):", dm=True)
        if not res:
            return
        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):", dm=True)
            if not res:
                return
            if res.content.upper() == 'NONE':
                break
            elif is_int(res.content) and int(res.content) > 0:
                max_members = int(res.content)
            else:
                await manager.say("That is not a a valid entry.", dm=True)

        start_time = None
        while not start_time:
            res = await manager.say_and_wait("Enter event time (YYYY-MM-DD HH:MM AM/PM):", dm=True)
            if not res:
                return
            start_time_format = '%Y-%m-%d %I:%M %p'
            try:
                start_time = datetime.strptime(res.content, start_time_format)
            except ValueError:
                await manager.say("Invalid event time!", dm=True)

        time_zone = None
        while not time_zone:
            res = await manager.say_and_wait("Enter the time zone (PST, EST, etc):", dm=True)
            if not res:
                return
            if res.content.upper() not in constants.TIME_ZONES:
                await manager.say("Unsupported time zone", dm=True)
            else:
                time_zone = res.content.upper()

        with DBase() as db:
            res = db.create_event(title, start_time, time_zone, ctx.guild.id, description, max_members)
        if res == 0:
            await manager.say("An event with that name already exists!", dm=True)
            return await manager.clear()

        event_channel = await self.get_events_channel(ctx.guild)
        await manager.say("Event created! The " + event_channel.mention + " channel will be updated momentarily.", dm=True)
        await self.list_events(ctx.guild)
        await manager.clear()


    async def list_events(self, guild):
        """Clear the event channel and display all upcoming events"""
        events_channel = await self.get_events_channel(guild)
        await events_channel.purge(limit=999, check=delete_all)
        with DBase() as db:
            events = db.get_events(guild.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], row[6])
                msg = await events_channel.send(embed=event_embed)
                await msg.add_reaction("\N{WHITE HEAVY CHECK MARK}")
                await msg.add_reaction("\N{CROSS MARK}")
        else:
            await events_channel.send("There are no upcoming events.")


    async def on_raw_reaction_add(self, emoji, message_id, channel_id, user_id):
        """If a reaction represents a user RSVP, update the DB and event message"""
        channel = self.bot.get_channel(channel_id)
        guild = channel.guild
        user = guild.get_member(user_id)
        message = await channel.get_message(message_id)
        manager = MessageManager(self.bot, user, channel)

        # We check that the user is not the message author as to not count
        # the initial reactions added by the bot as being indicative of attendance
        if is_event(message) and user != message.author:
            title = message.embeds[0].title
            if emoji.name == "\N{WHITE HEAVY CHECK MARK}":
                await self.set_attendance(str(user), guild.id, 1, title, message)
            elif emoji.name == "\N{CROSS MARK}":
                await self.set_attendance(str(user), guild.id, 0, title, message)
            elif emoji.name == "\N{SKULL}":
                if user.permissions_in(channel).administrator:
                    return await self.delete_event(guild, title)
                else:
                    await manager.say("You must be an administrator to do that.")

            await message.remove_reaction(emoji, user)
            await manager.clear()


    async def set_attendance(self, username, server_id, attending, title, message):
        """Send updated event attendance info to db and update the event"""
{'fraction_non_alphanumeric': 0.08522114347357065, 'fraction_numerical': 0.003983071944236993, 'mean_word_length': 2.1883597883597883, 'pattern_counts': {'":': 6, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2170286', 'n_tokens_mistral': 3356, 'n_tokens_neox': 3222, 'n_words': 1111}