Example #1
0
def _get_user_from_db_row(user_row):
    user = NecroUser(commit_fn=userdb.write_user)
    console.debug('Getting user from data: {}'.format(user_row))
    user.set(discord_id=user_row[0],
             discord_name=user_row[1],
             twitch_name=user_row[2],
             rtmp_name=user_row[3],
             timezone=user_row[4],
             user_info=user_row[5],
             user_prefs=UserPrefs(daily_alert=bool(user_row[6]),
                                  race_alert=bool(user_row[7])),
             commit=False)
    user._user_id = int(user_row[8])
    _cache_user(user)
    return user
Example #2
0
            async def make_single_match(racers):
                console.debug('MakeMatchesFromFile: Making match {0}-{1}'.format(racers[0], racers[1]))
                racer_1 = all_racers[racers[0]]
                racer_2 = all_racers[racers[1]]
                if racer_1 is None or racer_2 is None:
                    console.warning('Couldn\'t find racers for match {0}-{1}.'.format(
                        racers[0], racers[1]
                    ))
                    not_found_matches.append('`{0}`-`{1}`'.format(racers[0], racers[1]))
                    return

                new_match = await matchutil.make_match(
                    register=True,
                    racer_1_id=racer_1.user_id,
                    racer_2_id=racer_2.user_id,
                    match_info=match_info,
                    autogenned=True
                )
                if new_match is None:
                    console.debug('MakeMatchesFromFile: Match {0}-{1} not created.'.format(racers[0], racers[1]))
                    not_found_matches.append('{0}-{1}'.format(racers[0], racers[1]))
                    return

                matches.append(new_match)
                console.debug('MakeMatchesFromFile: Created {0}-{1}'.format(
                    new_match.racer_1.rtmp_name, new_match.racer_2.rtmp_name)
                )
Example #3
0
        async def make_single_match(racers):
            console.debug(
                '_makematches_from_pairs: Making match {0}-{1}'.format(
                    racers[0], racers[1]))
            racer_1 = all_racers[racers[0]][0] if len(
                all_racers[racers[0]]) == 1 else None
            racer_2 = all_racers[racers[1]][0] if len(
                all_racers[racers[1]]) == 1 else None
            if racer_1 is None or racer_2 is None:
                console.warning(
                    'Couldn\'t find racers for match {0}-{1}.'.format(
                        racers[0], racers[1]))
                not_found_matches.append((racers[0], racers[1]))
                return

            new_match = await matchutil.make_match(register=True,
                                                   racer_1_id=racer_1.user_id,
                                                   racer_2_id=racer_2.user_id,
                                                   match_info=match_info,
                                                   league_tag=league.tag,
                                                   autogenned=True)
            if new_match is None:
                console.debug(
                    '_makematches_from_pairs: Match {0}-{1} not created.'.
                    format(racers[0], racers[1]))
                not_found_matches.append((racers[0], racers[1]))
                return

            matches.append(new_match)
            console.debug('_makematches_from_pairs: Created {0}-{1}'.format(
                new_match.racer_1.matchroom_name,
                new_match.racer_2.matchroom_name))
Example #4
0
    async def get_matches(self, **kwargs):
        """Read racer names and match types from the GSheet; create corresponding matches.
        
        Parameters
        ----------
        kwargs:
            Parameters to be passed to matchutil.make_match for every match made.
        
        Returns
        -------
        list[Match]
            The list of created Matches.
        """
        console.debug('get_matches begin...')
        await self.column_data.refresh_footer()

        matches = []
        self._not_found_matches = []
        write_match_ids = self.column_data.match_id is not None and 'register' in kwargs and kwargs[
            'register']
        match_ids = []

        async with Spreadsheets() as spreadsheets:
            value_range = await self.column_data.get_values(spreadsheets)
            console.debug('get_matches: Got values from spreadsheets.')

            if 'values' not in value_range:
                console.debug('get_matches: Values is empty.')
                return matches
            else:
                console.debug('get_matches: Values: {0}'.format(
                    value_range['values']))

            for row_idx, row_values in enumerate(value_range['values']):
                try:
                    racer_1_name = row_values[self.column_data.racer_1].rstrip(
                        ' ')
                    racer_2_name = row_values[self.column_data.racer_2].rstrip(
                        ' ')
                except IndexError:
                    console.warning(
                        'Failed to make match from sheet row: <{}>'.format(
                            row_values))
                    continue

                if not racer_1_name or not racer_2_name:
                    continue

                # if racer_1_name[0] not in string.ascii_letters or racer_2_name[0] not in string.ascii_letters:
                #     self._not_found_matches.append('{0}-{1}'.format(racer_1_name, racer_2_name))
                #     continue

                console.debug('get_matches: Creating {0}-{1}'.format(
                    racer_1_name, racer_2_name))

                racer_1 = await userlib.get_user(any_name=racer_1_name,
                                                 register=True)
                racer_2 = await userlib.get_user(any_name=racer_2_name,
                                                 register=True)
                if racer_1 is None or racer_2 is None:
                    console.warning(
                        'Couldn\'t find racers for match {0}-{1}.'.format(
                            racer_1_name, racer_2_name))
                    self._not_found_matches.append('{0}-{1}'.format(
                        racer_1_name, racer_2_name))
                    continue

                sheet_info = MatchGSheetInfo()
                sheet_info.wks_id = self.wks_id
                sheet_info.row = row_idx

                kwarg_copy = kwargs.copy()
                if self.column_data.type is not None:
                    match_info = kwarg_copy[
                        'match_info'] if 'match_info' in kwargs else matchinfo.MatchInfo(
                        )
                    try:
                        parsed_args = shlex.split(
                            row_values[self.column_data.type])
                        kwarg_copy['match_info'] = matchinfo.parse_args_modify(
                            parsed_args, match_info)
                    except IndexError:
                        pass

                new_match = await matchutil.make_match(
                    racer_1_id=racer_1.user_id,
                    racer_2_id=racer_2.user_id,
                    gsheet_info=sheet_info,
                    **kwarg_copy)
                matches.append(new_match)
                console.debug('get_matches: Created {0}-{1}'.format(
                    new_match.racer_1.rtmp_name, new_match.racer_2.rtmp_name))

                if write_match_ids:
                    match_ids.append([new_match.match_id])

        if write_match_ids:
            ids_range = self.column_data.get_range_for_column(
                self.column_data.match_id)
            await self.column_data.update_cells(sheet_range=ids_range,
                                                values=match_ids,
                                                raw_input=True)

        console.debug('get_matches: Returning Matches=<{}>'.format(matches))
        return matches
Example #5
0
    async def _do_execute(self, cmd: Command):
        if len(cmd.args) != 1:
            await self.client.send_message(
                cmd.channel,
                'Wrong number of arguments for `{0}`.'.format(self.mention))
            return

        wks_name = cmd.args[0]
        await self.client.send_message(
            cmd.channel,
            'Creating matches from worksheet `{0}`...'.format(wks_name))
        await self.client.send_typing(cmd.channel)

        match_info = LeagueMgr().league.match_info

        console.info('MakeFromSheet: Getting GSheet info...')
        try:
            matchup_sheet = await sheetlib.get_sheet(
                gsheet_id=LeagueMgr().league.gsheet_id,
                wks_name=wks_name,
                sheet_type=sheetlib.SheetType.MATCHUP)  # type: MatchupSheet
            matches = await matchup_sheet.get_matches(register=False,
                                                      match_info=match_info)
        except (googleapiclient.errors.Error,
                necrobot.exception.NecroException) as e:
            await self.client.send_message(
                cmd.channel, 'Error while making matchups: `{0}`'.format(e))
            return

        console.info('MakeFromSheet: Creating Match objects...')
        not_found_matches = matchup_sheet.uncreated_matches()
        matches_with_channels = await matchutil.get_matches_with_channels()
        channeled_matchroom_names = dict()
        for match in matches_with_channels:
            if match.matchroom_name in channeled_matchroom_names:
                channeled_matchroom_names[match.matchroom_name] += 1
            else:
                channeled_matchroom_names[match.matchroom_name] = 1

        console.info('MakeFromSheet: Removing duplicate matches...')
        # Remove matches that have the same name as current channels (but only one per channel)
        unchanneled_matches = []
        for match in matches:
            channeled_name = match.matchroom_name in channeled_matchroom_names
            if not channeled_name or channeled_matchroom_names[
                    match.matchroom_name] <= 0:
                unchanneled_matches.append(match)
            if channeled_name:
                channeled_matchroom_names[match.matchroom_name] -= 1

        console.info('MakeFromSheet: Sorting matches...')
        # Sort the remaining matches
        unchanneled_matches = sorted(unchanneled_matches,
                                     key=lambda m: m.matchroom_name)

        console.debug(
            'MakeFromSheet: Matches to make: {0}'.format(unchanneled_matches))
        console.info('MakeFromSheet: Creating match channels...')
        for match in unchanneled_matches:
            console.info('MakeFromSheet: Creating {0}...'.format(
                match.matchroom_name))
            new_room = await matchutil.make_match_room(match=match,
                                                       register=True)
            await new_room.send_channel_start_text()

        uncreated_str = ''
        for match_str in not_found_matches:
            uncreated_str += match_str + ', '
        if uncreated_str:
            uncreated_str = uncreated_str[:-2]

        if uncreated_str:
            report_str = 'Done creating matches. The following matches were not made: {0}'.format(
                uncreated_str)
        else:
            report_str = 'All matches created successfully.'

        await self.client.send_message(cmd.channel, report_str)
Example #6
0
    async def _do_execute(self, cmd: Command):
        if len(cmd.args) != 1:
            await cmd.channel.send(
                'Wrong number of arguments for `{0}`.'.format(self.mention))
            return

        wks_name = cmd.args[0]
        status_message = await cmd.channel.send(
            'Creating matches from worksheet `{0}`... (Getting GSheet info)'.
            format(wks_name))

        async with cmd.channel.typing():
            match_info = LeagueMgr().league.match_info

            console.info('MakeFromSheet: Getting GSheet info...')
            try:
                matchup_sheet = await sheetlib.get_sheet(
                    gsheet_id=LeagueMgr().league.gsheet_id,
                    wks_name=wks_name,
                    sheet_type=sheetlib.SheetType.MATCHUP
                )  # type: MatchupSheet
                matches = await matchup_sheet.get_matches(
                    register=True, match_info=match_info)
            except (googleapiclient.errors.Error,
                    necrobot.exception.NecroException) as e:
                await cmd.channel.send(
                    'Error while making matchups: `{0}`'.format(e))
                return

            console.info('MakeFromSheet: Creating Match objects...')
            await status_message.edit(
                content=
                'Creating matches from worksheet `{0}`... (Creating match list)'
                .format(wks_name))
            not_found_matches = matchup_sheet.uncreated_matches()
            matches_with_channels = await matchchannelutil.get_matches_with_channels(
            )

            console.info('MakeFromSheet: Removing duplicate matches...')
            # Remove matches from the list that already have channels
            unchanneled_matches = []
            for match in matches:
                found = False
                for channeled_match in matches_with_channels:
                    if match.match_id == channeled_match.match_id:
                        found = True
                if not found:
                    unchanneled_matches.append(match)

            console.info('MakeFromSheet: Sorting matches...')
            # Sort the remaining matches
            unchanneled_matches = sorted(unchanneled_matches,
                                         key=lambda m: m.matchroom_name)

            await status_message.edit(
                content=
                'Creating matches from worksheet `{0}`... (Creating race rooms)'
                .format(wks_name))
            console.debug('MakeFromSheet: Matches to make: {0}'.format(
                unchanneled_matches))
            console.info('MakeFromSheet: Creating match channels...')
            for match in unchanneled_matches:
                console.info('MakeFromSheet: Creating {0}...'.format(
                    match.matchroom_name))
                new_room = await matchchannelutil.make_match_room(
                    match=match, register=False)
                await new_room.send_channel_start_text()

            uncreated_str = ''
            for match_str in not_found_matches:
                uncreated_str += match_str + ', '
            if uncreated_str:
                uncreated_str = uncreated_str[:-2]

            if uncreated_str:
                report_str = 'The following matches were not made: {0}'.format(
                    uncreated_str)
            else:
                report_str = 'All matches created successfully.'

        await status_message.edit(
            content='Creating matches from worksheet `{0}`... done. {1}'.
            format(wks_name, report_str))
Example #7
0
    async def _do_execute(self, cmd):
        if len(cmd.args) != 1:
            await cmd.channel.send(
                'Wrong number of arguments for `{0}`.'.format(self.mention)
            )
            return

        filename = cmd.args[0]
        if not filename.endswith('.csv'):
            await cmd.channel.send(
                'Matchup file should be a `.csv` file.'
            )
            return
        file_path = os.path.join(filename)
        if not os.path.isfile(file_path):
            await cmd.channel.send(
                'Cannot find file `{}`.'.format(filename)
            )
            return

        match_info = LeagueMgr().league.match_info
        status_message = await cmd.channel.send(
            'Creating matches from file `{0}`... (Reading file)'.format(filename)
        )

        async with cmd.channel.typing():
            # Store file data
            desired_match_pairs = []
            with open(file_path) as file:
                for line in file:
                    racernames = line.rstrip('\n').split(',')
                    desired_match_pairs.append((racernames[0].lower(), racernames[1].lower(),))

            # Find all racers
            all_racers = dict()
            for racerpair in desired_match_pairs:
                all_racers[racerpair[0]] = None
                all_racers[racerpair[1]] = None

            await userlib.fill_user_dict(all_racers)
            console.debug('MakeMatchesFromFile: Filled user dict: {}'.format(all_racers))

            # Create Match objects
            matches = []
            not_found_matches = []

            async def make_single_match(racers):
                console.debug('MakeMatchesFromFile: Making match {0}-{1}'.format(racers[0], racers[1]))
                racer_1 = all_racers[racers[0]]
                racer_2 = all_racers[racers[1]]
                if racer_1 is None or racer_2 is None:
                    console.warning('Couldn\'t find racers for match {0}-{1}.'.format(
                        racers[0], racers[1]
                    ))
                    not_found_matches.append('`{0}`-`{1}`'.format(racers[0], racers[1]))
                    return

                new_match = await matchutil.make_match(
                    register=True,
                    racer_1_id=racer_1.user_id,
                    racer_2_id=racer_2.user_id,
                    match_info=match_info,
                    autogenned=True
                )
                if new_match is None:
                    console.debug('MakeMatchesFromFile: Match {0}-{1} not created.'.format(racers[0], racers[1]))
                    not_found_matches.append('{0}-{1}'.format(racers[0], racers[1]))
                    return

                matches.append(new_match)
                console.debug('MakeMatchesFromFile: Created {0}-{1}'.format(
                    new_match.racer_1.rtmp_name, new_match.racer_2.rtmp_name)
                )

            for racer_pair in desired_match_pairs:
                await make_single_match(racer_pair)

            matches = sorted(matches, key=lambda m: m.matchroom_name)

            await status_message.edit(
                content='Creating matches from file `{0}`... (Creating race rooms)'.format(filename)
            )
            console.debug('MakeMatchesFromFile: Matches to make: {0}'.format(matches))

            # Create match channels
            for match in matches:
                console.info('MakeMatchesFromFile: Creating {0}...'.format(match.matchroom_name))
                new_room = await matchchannelutil.make_match_room(match=match, register=False)
                await new_room.send_channel_start_text()

            # Report on uncreated matches
            uncreated_str = ''
            for match_str in not_found_matches:
                uncreated_str += match_str + ', '
            if uncreated_str:
                uncreated_str = uncreated_str[:-2]

            if uncreated_str:
                report_str = 'The following matches were not made: {0}'.format(uncreated_str)
            else:
                report_str = 'All matches created successfully.'

        await status_message.edit(
            content='Creating matches from file `{0}`... done. {1}'.format(filename, report_str)
        )
Example #8
0
 def execute(self, operation, *args, **kwargs):
     console.debug('Execute SQL: <{0}> <args={1}> <kwargs={2}>'.format(
         operation, args, kwargs))
     return self.cursor.execute(operation, *args, **kwargs)
Example #9
0
async def _makematches_from_pairs(cmd, league, desired_match_pairs):
    status_message = await cmd.channel.send(
        'Creating matches... (Checking usernames)')

    match_info = league.match_info
    async with cmd.channel.typing():
        # Find all racers
        all_racers = dict()  # type: Dict[str, List[NecroUser]]
        for racerpair in desired_match_pairs:
            all_racers[racerpair[0]] = []
            all_racers[racerpair[1]] = []

        await userlib.fill_user_dict(all_racers)
        console.debug(
            '_makematches_from_pairs: Filled user dict: {}'.format(all_racers))

        not_found_racers = []
        doublename_racers = []
        for username, userlist in all_racers.items():
            if len(userlist) == 0:
                not_found_racers.append(username)
            elif len(userlist) > 1:
                doublename_racers.append(username)

        # Create Match objects
        matches = []
        not_found_matches = []  # type: List[Tuple[str, str]]

        async def make_single_match(racers):
            console.debug(
                '_makematches_from_pairs: Making match {0}-{1}'.format(
                    racers[0], racers[1]))
            racer_1 = all_racers[racers[0]][0] if len(
                all_racers[racers[0]]) == 1 else None
            racer_2 = all_racers[racers[1]][0] if len(
                all_racers[racers[1]]) == 1 else None
            if racer_1 is None or racer_2 is None:
                console.warning(
                    'Couldn\'t find racers for match {0}-{1}.'.format(
                        racers[0], racers[1]))
                not_found_matches.append((racers[0], racers[1]))
                return

            new_match = await matchutil.make_match(register=True,
                                                   racer_1_id=racer_1.user_id,
                                                   racer_2_id=racer_2.user_id,
                                                   match_info=match_info,
                                                   league_tag=league.tag,
                                                   autogenned=True)
            if new_match is None:
                console.debug(
                    '_makematches_from_pairs: Match {0}-{1} not created.'.
                    format(racers[0], racers[1]))
                not_found_matches.append((racers[0], racers[1]))
                return

            matches.append(new_match)
            console.debug('_makematches_from_pairs: Created {0}-{1}'.format(
                new_match.racer_1.matchroom_name,
                new_match.racer_2.matchroom_name))

        for racer_pair in desired_match_pairs:
            await make_single_match(racer_pair)
            await asyncio.sleep(0)

        matches = sorted(matches, key=lambda m: m.matchroom_name)

        await status_message.edit(
            content='Creating matches... (Creating race rooms)')
        console.debug(
            '_makematches_from_pairs: Matches to make: {0}'.format(matches))

        # Create match channels
        for match in matches:
            console.info('MakeMatchesFromFile: Creating {0}...'.format(
                match.matchroom_name))
            new_room = await matchchannelutil.make_match_room(match=match,
                                                              register=False)
            await new_room.send_channel_start_text()

        # Report on uncreated matches
        if not_found_matches:
            filename = leagueutil.get_unmade_matches_filename(
                league_tag=league.tag)
            with open(filename, 'w') as file:
                for r1, r2 in not_found_matches:
                    file.write(f'{r1},{r2}\n')

            uncreated_str = ', '.join(f'`{t[0]}-{t[1]}`'
                                      for t in not_found_matches)
            report_str = f'The following matches were not made: {uncreated_str}. These matches were written to ' \
                         f'`{filename}`. Call `.make-unmade-matches` to attempt to remake these easily.'
        else:
            report_str = 'All matches created successfully.'

    unfound_racers_str = ', '.join(f'`{n}`' for n in not_found_racers)
    doubled_racers_str = ', '.join(f'`{n}`' for n in doublename_racers)
    if not_found_racers:
        report_str += \
            f'\n\nThe following racers could not be found: {unfound_racers_str}.'
    if doubled_racers_str:
        report_str += \
            f'\n\nThe following names were associated to more than one Discord account: {doubled_racers_str}.'

    await status_message.edit(
        content=f'Creating matches... done.\n\n{report_str}')