Example #1
0
async def make_room(race_info):
    # Find the races category
    race_channel_category = server.find_category(
        channel_name=Config.RACE_CHANNEL_CATEGORY_NAME)

    # Make a channel for the room
    race_channel = await server.guild.create_text_channel(
        get_raceroom_name(race_info), category=race_channel_category)

    if race_channel is None:
        console.warning('Failed to make a race channel.')
        return None

    # Make the actual RaceRoom and initialize it
    new_room = RaceRoom(race_discord_channel=race_channel, race_info=race_info)
    await new_room.initialize()

    Necrobot().register_bot_channel(race_channel, new_room)

    # Send PM alerts
    alert_pref = UserPrefs(daily_alert=None, race_alert=True)

    alert_string = 'A new race has been started:\nFormat: {1}\nChannel: {0}'.format(
        race_channel.mention, race_info.format_str)
    for member_id in await userdb.get_all_discord_ids_matching_prefs(alert_pref
                                                                     ):
        member = server.find_member(discord_id=member_id)
        if member is not None:
            try:
                await member.send(alert_string)
            except discord.errors.Forbidden:
                continue

    return race_channel
Example #2
0
    async def _do_execute(self, cmd):
        if len(cmd.args) < 2:
            await cmd.channel.send('Not enough arguments for `{0}`.'.format(
                self.mention))
            return

        username = cmd.args[0]
        user = server.find_member(discord_name=username)
        if user is None:
            await cmd.channel.send(
                "Couldn't find the user `{0}`.".format(username))
            return

        message_content = cmd.arg_string[(len(username) + 1):]
        await Necrobot().force_command(channel=cmd.channel,
                                       author=user,
                                       message_str=message_content)
Example #3
0
    async def on_new_daily(self) -> None:
        """Run when a new daily happens"""
        # Make the leaderboard message
        text = await self.leaderboard_text(self.today_number,
                                           display_seed=False)
        msg = await self.client.send_message(self._leaderboard_channel, text)
        await self.register_message(self.today_number, msg.id)

        # Update yesterday's leaderboard with the seed
        await self.update_leaderboard(self.today_number - 1, display_seed=True)

        # PM users with the daily_alert preference
        auto_pref = UserPrefs(daily_alert=True, race_alert=None)
        for member_id in await userdb.get_all_discord_ids_matching_prefs(
                auto_pref):
            member = server.find_member(discord_id=member_id)
            if member is not None:
                await self.register(self.today_number, member.id)
                await self.client.send_message(
                    member, "({0}) Today's {2} speedrun seed: {1}".format(
                        self.today_date.strftime("%d %b"), await
                        self.get_seed(self.today_number),
                        dailytype.character(self.daily_type,
                                            self.today_number)))
Example #4
0
    async def _do_execute(self, cmd: Command):
        send = self.get_send_func(cmd.channel)

        alice = server.find_member(discord_name='incnone_testing')
        bob = server.find_member(discord_name='condorbot_alpha')
        carol = server.find_member(discord_name='condorbot')
        admin = server.find_member(discord_name='incnone')

        if alice is None or bob is None or carol is None or admin is None:
            await cmd.channel.send(
                "Can't find one of the racers (as a Discord member) in this match."
            )
            return

        # Race 1: some common stuff
        await send(alice, '.r', wait_for='Waiting on')
        await send(bob, '.e', wait_for='2 entrants')
        await send(alice, '.ready', wait_for='is already ready')
        await send(bob, '.ready', wait_for='The race will begin')
        await send(alice, '.unready', wait_for='is no longer ready')
        await send(alice, '.r', wait_for='GO!')
        await send(carol, '.notify', wait_for='will be alerted')
        await send(alice, '.f', wait_for='has forfeit')
        await send(alice, '.unforfeit', wait_for='no longer forfeit')
        await send(bob, '.death 3-2', wait_for='has forfeit')
        await send(bob, '.c spirits are fair')
        await asyncio.sleep(2)
        await send(alice, '.d', wait_for='The race is over')
        await send(alice, '.igt 4:20.69')
        await send(bob, '.re', wait_for='Race number')
        await send(alice, '.c i did it')

        # Race 2: admin stuff
        await send(alice, '.join')
        await send(carol, '.j')
        await send(admin, '.e', wait_for='3 entrants')
        await send(alice, '.missing', wait_for='Unentered')
        await send(bob, '.r')
        await send(alice, '.r')
        await send(carol, '.r', wait_for='1 remaining')
        await send(alice, '.poke')
        await send(bob, '.poke')
        await send(admin,
                   '.kick "{0}"'.format(alice.display_name),
                   wait_for='no longer entered')
        await send(alice, '.r', wait_for='is ready')
        await send(admin, '.reseed', wait_for='Changed seed')
        await send(admin,
                   '.changerules Diamond u custom have a blast with diamond',
                   wait_for="Couldn't parse")
        await send(admin,
                   '.changerules Diamond u custom "have a blast with diamond"',
                   wait_for="Changed rules")
        await send(admin, '.reseed', wait_for='This is not a seeded race')
        await send(admin, '.unenter', wait_for='GO!')
        await send(admin, '.pause', wait_for='Race paused')
        await send(bob, '.time', wait_for='The current race time')
        await asyncio.sleep(1)
        await send(carol, '.time', wait_for='The current race time')
        await send(admin,
                   '.forceforfeit "{0}"'.format(carol.display_name),
                   wait_for='has forfeit')
        await send(alice, '.missing', wait_for='Still racing')
        await send(alice, '.d')
        await asyncio.sleep(1)
        await send(admin, '.unpause', wait_for='GO!')
        await send(carol, '.d', wait_for='has finished')
        await send(bob, '.d 5-4 i can\'t deep blues', wait_for='has forfeit')
        await send(bob, '.notify off', wait_for='not be alerted')
        await send(carol, '.undone', wait_for='continues to race')
        await send(alice, '.d', wait_for='has finished')
        await send(carol, '.d', wait_for='The race is over')

        # Race 3
        await send(alice, '.re', wait_for='Race number')
        await send(alice, '.r')
        await send(carol, '.r', wait_for='GO!')
        await send(admin, '.forceforfeitall', wait_for='The race is over')
Example #5
0
 def discord_member(self) -> discord.Member or None:
     if self._discord_member is None and \
             (self._discord_id is not None or self._discord_name is not None):
         self._discord_member = server.find_member(
             discord_name=self._discord_name, discord_id=self._discord_id)
     return self._discord_member
Example #6
0
    def set(self,
            discord_member: discord.Member = None,
            discord_id: int = None,
            discord_name: str = None,
            twitch_name: str = None,
            rtmp_name: str = None,
            timezone: str = None,
            user_info: str = None,
            user_prefs: UserPrefs = None,
            commit: bool = True) -> None:
        """Set all non-None values and optionally commit the change to the database.
        
        Parameters
        ----------
        discord_member: discord.Member
            The discord.Member corresponding to this necrobot user.
        discord_id: int
            The user's discord ID. Not necessary if discord_member is not None.
        discord_name: str
            The user's discord name. Not necessary if discord_member is not None.
        twitch_name: str
            This user's twitch name. Case-insensitive.
        rtmp_name: str
            This user's RTMP name. Case-insensitive.
        timezone: str
            The user's timezone as a string, e.g., 'Asia/Tokyo'.
        user_info: str
            The user's custom info (shown on .userinfo).
        user_prefs: UserPrefs  
            The user's preferences.
        commit: bool
            If False, will not commit changes to the database.
        """

        changed_any = False
        if discord_member is not None and discord_member != self.discord_member:
            self._discord_id = int(discord_member.id)
            self._discord_name = discord_member.name
            self._discord_member = discord_member
            changed_any = True
        elif discord_id is not None and discord_id != self.discord_id:
            self._discord_id = discord_id
            member = server.find_member(discord_id=discord_id)
            if member is not None:
                self._discord_member = member
                self._discord_name = member.name
            elif discord_name is not None:
                self._discord_name = discord_name
            changed_any = True
        elif discord_name is not None and discord_name != self.discord_name:
            self._discord_name = discord_name
            member = server.find_member(discord_name=discord_name)
            if member is not None:
                self._discord_member = member
                self._discord_id = int(member.id)
            changed_any = True

        if twitch_name is not None and twitch_name != self._twitch_name:
            self._twitch_name = twitch_name
            changed_any = True
        if rtmp_name is not None and rtmp_name != self._rtmp_name:
            self._rtmp_name = rtmp_name
            changed_any = True
        if timezone is not None:
            if timezone not in pytz.common_timezones:
                console.warning(
                    'Tried to set timezone to {0}.'.format(timezone))
            elif str(self.timezone) != timezone:
                self._timezone = pytz.timezone(timezone)
                changed_any = True
        if user_info is not None and user_info != self._user_info:
            self._user_info = user_info
            changed_any = True
        if user_prefs is not None and user_prefs != self._user_prefs:
            self._user_prefs.merge_prefs(user_prefs)
            changed_any = True

        if changed_any and commit:
            asyncio.ensure_future(self.commit())
Example #7
0
async def get_user(discord_id: int = None,
                   discord_name: str = None,
                   twitch_name: str = None,
                   rtmp_name: str = None,
                   user_id: int = None,
                   any_name: str = None,
                   register: bool = False) -> NecroUser or None:
    """Search for a NecroUser satisfying the given parameter. Behavior only guaranteed when exactly one of the
    parameters other than register is non-None.

    Parameters
    ----------
    discord_id: int
        The user's discord ID.
    discord_name: str
        The user's discord name. Case-insensitve.
    twitch_name: str
        The user's twitch name. Case-insensitve.
    rtmp_name: str
        The user's RTMP name. Case-insensitve.
    user_id: int
        The user's database ID.
    any_name: str
        Will search for a user, if possible, whose rtmp_name, discord_name, or twitch_name is equal to that name, 
        case-insensitive. If multiple users, prioritize by name type (1=rtmp, 2=discord, 3=twitch), then randomly.
        Providing this field means that the above fields will be ignored.
    register: bool
        If True, will register a new user if none is found matching the given parameters. This requires that either
        discord_id, rtmp_name, or any_name is not None. (If any_name is given, it will be registered as an RTMP name.)

    Returns
    -------
    NecroUser or None
        The found NecroUser object.
    """
    if any_name is not None:
        return await _get_user_any_name(any_name, register)

    if discord_id is None and discord_name is None and twitch_name is None \
            and rtmp_name is None and user_id is None:
        return None

    cached_user = _get_cached_user(discord_id=discord_id, user_id=user_id)
    if cached_user is not None:
        return cached_user

    raw_db_data = await userdb.get_users_with_all(discord_id=discord_id,
                                                  discord_name=discord_name,
                                                  twitch_name=twitch_name,
                                                  rtmp_name=rtmp_name,
                                                  user_id=user_id)

    # If no user found, register if asked, otherwise return None
    if not raw_db_data:
        if not register:
            return None
        elif rtmp_name is not None:
            user = NecroUser(commit_fn=userdb.write_user)
            user.set(rtmp_name=rtmp_name, commit=False)
            await user.commit()
            _cache_user(user)
            return user
        elif discord_id is not None:
            discord_member = server.find_member(discord_id=discord_id)
            if discord_member is not None:
                user = NecroUser(commit_fn=userdb.write_user)
                user.set(discord_member=discord_member, commit=False)
                await user.commit()
                _cache_user(user)
                return user
        else:
            console.warning(
                'Tried to register a NecroUser without providing a name or ID.'
            )
            return None

    # If more than one user is found, raise an exception
    elif len(raw_db_data) > 1:
        raise necrobot.exception.DuplicateUserException(
            'Two or more users found satisfying discord_id={0}, discord_name={1}, twitch_name={2}, '
            'rtmp_name={3}, user_id={4}.'.format(discord_id, discord_name,
                                                 twitch_name, rtmp_name,
                                                 user_id))

    # Exactly one user was found; convert into a NecroUser and return it
    for row in raw_db_data:
        return _get_user_from_db_row(row)

    return None