Esempio n. 1
0
 async def background_task_rotation_hype(self) -> None:
     rotation_hype_channel_id = configuration.get_int(
         'rotation_hype_channel_id')
     if not rotation_hype_channel_id:
         logging.warning('rotation hype channel is not configured')
         return
     channel = self.get_channel(rotation_hype_channel_id)
     if not isinstance(channel, discord.abc.Messageable):
         logging.warning('rotation hype channel is not a text channel')
         return
     while self.is_ready():
         until_rotation = rotation.next_rotation() - dtutil.now()
         last_run_time = rotation.last_run_time()
         if until_rotation < datetime.timedelta(
                 7) and last_run_time is not None:
             if dtutil.now() - last_run_time < datetime.timedelta(
                     minutes=5):
                 hype = await rotation_hype_message()
                 if hype:
                     await channel.send(hype)
             timer = 5 * 60
         else:
             timer = int(
                 (until_rotation - datetime.timedelta(7)).total_seconds())
         await asyncio.sleep(timer)
Esempio n. 2
0
def lint(argv: List[str]) -> None:
    """
    Invoke Pylint with our preferred options
    """
    print('>>>> Running pylint')
    args = [
        '--rcfile=.pylintrc',  # Load rcfile first.
        '--ignored-modules=alembic,MySQLdb,flask_sqlalchemy,distutils.dist',  # override ignored-modules (codacy hack)
        '--load-plugins',
        'pylint_quotes,pylint_monolith',  # Plugins
        '-f',
        'parseable',  # Machine-readable output.
        '-j',
        str(configuration.get_int(
            'pylint_threads')),  # Use four cores for speed.
    ]
    args.extend(argv or find_files(file_extension='py'))
    # pylint: disable=import-outside-toplevel
    import pylint.lint
    try:
        linter = pylint.lint.Run(args, exit=False)
    except PicklingError:
        print('Error while running pylint with multiprocessing')
        configuration.write('pylint_threads', 1)
        lint(argv)
        return

    if linter.linter.msg_status:
        raise TestFailedException(linter.linter.msg_status)
Esempio n. 3
0
    async def background_task_tournaments(self) -> None:
        try:
            await self.wait_until_ready()
            tournament_channel_id = configuration.get_int(
                'tournament_channel_id')
            if not tournament_channel_id:
                return
            channel = self.get_channel(tournament_channel_id)
            while not self.is_closed:
                info = tournaments.next_tournament_info()
                diff = info['next_tournament_time_precise']
                if info['sponsor_name']:
                    message = 'A {sponsor} sponsored tournament'.format(
                        sponsor=info['sponsor_name'])
                else:
                    message = 'A free tournament'
                embed = discord.Embed(title=info['next_tournament_name'],
                                      description=message)
                if diff <= 0:
                    embed.add_field(
                        name='Starting now',
                        value=
                        'Check <#334220558159970304> for further annoucements')
                elif diff <= 14400:
                    embed.add_field(name='Starting in:',
                                    value=dtutil.display_time(diff, 2))
                    embed.add_field(name='Pre-register now:',
                                    value='https://gatherling.com')

                if diff <= 14400:
                    embed.set_image(
                        url=fetcher.decksite_url('/favicon-152.png'))
                    # See #2809.
                    # pylint: disable=no-value-for-parameter,unexpected-keyword-arg
                    await channel.send(embed=embed)

                if diff <= 300:
                    # Five minutes, final warning.  Sleep until the tournament has started.
                    timer = 301
                elif diff <= 1800:
                    # Half an hour. Sleep until 5 minute warning.
                    timer = diff - 300
                elif diff <= 3600:
                    # One hour.  Sleep until half-hour warning.
                    timer = diff - 1800
                else:
                    # Wait until four hours before tournament.
                    timer = 3600 + diff % 3600
                    if diff > 3600 * 6:
                        # The timer can afford to get off-balance by doing other background work.
                        await self.background_task_spoiler_season()
                        multiverse.update_bugged_cards()

                if timer < 300:
                    timer = 300
                print('diff={0}, timer={1}'.format(diff, timer))
                await asyncio.sleep(timer)
        except Exception:  # pylint: disable=broad-except
            await self.on_error('background_task_tournaments')
Esempio n. 4
0
    async def background_task_league_end(self) -> None:
        tournament_channel_id = configuration.get_int(
            'tournament_reminders_channel_id')
        if not tournament_channel_id:
            logging.warning('tournament channel is not configured')
            return
        channel = self.get_channel(tournament_channel_id)
        if not isinstance(channel, discord.abc.Messageable):
            logging.warning('tournament channel could not be found')
            return

        while self.is_ready:
            try:
                league = await fetch_tools.fetch_json_async(
                    fetcher.decksite_url('/api/league'))
            except fetch_tools.FetchException as e:
                logging.error(
                    "Couldn't reach decksite or decode league json with error message(s) {e}",
                    e='; '.join(str(x) for x in e.args))
                logging.info('Sleeping for 5 minutes and trying again.')
                await asyncio.sleep(300)
                continue

            if not league:
                await asyncio.sleep(300)
                continue

            diff = round((dtutil.parse_rfc3339(league['end_date']) -
                          datetime.datetime.now(tz=datetime.timezone.utc)) /
                         datetime.timedelta(seconds=1))

            embed = discord.Embed(
                title=league['name'],
                description=
                'League ending soon - any active runs will be cut short.')
            if diff <= 60 * 60 * 24:
                embed.add_field(name='Ending in:',
                                value=dtutil.display_time(diff, 2))
                embed.set_image(url=fetcher.decksite_url('/favicon-152.png'))
                # See #2809.
                # pylint: disable=no-value-for-parameter,unexpected-keyword-arg
                await channel.send(embed=embed)
            if diff <= 5 * 60:
                # Five minutes, final warning.
                timer = 301
            elif diff <= 1 * 60 * 60:
                # 1 hour. Sleep until five minute warning.
                timer = diff - 300
            elif diff <= 24 * 60 * 60:
                # 1 day.  Sleep until one hour warning.
                timer = diff - 1800
            else:
                # Sleep for 1 day, plus enough to leave us with a whole number of days
                timer = 24 * 60 * 60 + diff % (24 * 60 * 60)

            if timer < 300:
                timer = 300
            await asyncio.sleep(timer)
        logging.warning('naturally stopping league reminders')
Esempio n. 5
0
def decksite_url(path: str = '/') -> str:
    hostname = configuration.get_str('decksite_hostname')
    port = configuration.get_int('decksite_port')
    if port != 80:
        hostname = '{hostname}:{port}'.format(hostname=hostname, port=port)
    url = parse.urlunparse((configuration.get_str('decksite_protocol'), hostname, path, '', '', ''))
    assert url is not None
    return url
 def __init__(self, db: str) -> None:
     warnings.filterwarnings('error', category=MySQLdb.Warning)
     self.name = db
     self.host = configuration.get_str('mysql_host')
     self.port = configuration.get_int('mysql_port')
     self.user = configuration.get_str('mysql_user')
     self.passwd = configuration.get_str('mysql_passwd')
     self.connect()
Esempio n. 7
0
    async def background_task_tournaments(self) -> None:
        tournament_channel_id = configuration.get_int(
            'tournament_reminders_channel_id')
        if not tournament_channel_id:
            logging.warning('tournament channel is not configured')
            return
        channel = self.get_channel(tournament_channel_id)
        if not isinstance(channel, discord.abc.Messageable):
            logging.warning('ERROR: could not find tournament_channel_id {id}',
                            id=tournament_channel_id)
            return
        while self.is_ready:
            info = tournaments.next_tournament_info()
            diff = info['next_tournament_time_precise']
            if info['sponsor_name']:
                message = 'A {sponsor} sponsored tournament'.format(
                    sponsor=info['sponsor_name'])
            else:
                message = 'A free tournament'
            embed = discord.Embed(title=info['next_tournament_name'],
                                  description=message)
            if diff <= 1:
                embed.add_field(
                    name='Starting now',
                    value='Check <#334220558159970304> for further annoucements'
                )
            elif diff <= 14400:
                embed.add_field(name='Starting in:',
                                value=dtutil.display_time(diff, 2))
                embed.add_field(name='Pre-register now:',
                                value='https://gatherling.com')

            if diff <= 14400:
                embed.set_image(url=fetcher.decksite_url('/favicon-152.png'))
                # See #2809.
                # pylint: disable=no-value-for-parameter,unexpected-keyword-arg
                await channel.send(embed=embed)

            if diff <= 300:
                # Five minutes, final warning.  Sleep until the tournament has started.
                timer = 301
            elif diff <= 1800:
                # Half an hour. Sleep until 5 minute warning.
                timer = diff - 300
            elif diff <= 3600:
                # One hour.  Sleep until half-hour warning.
                timer = diff - 1800
            else:
                # Sleep for one hour plus enough to have a whole number of hours left.
                timer = 3600 + diff % 3600
                if diff > 3600 * 6:
                    # The timer can afford to get off-balance by doing other background work.
                    await multiverse.update_bugged_cards_async()

            if timer < 300:
                timer = 300
            await asyncio.sleep(timer)
        logging.warning('naturally stopping tournament reminders')
Esempio n. 8
0
def run() -> None:
    """Make a 'safe' (no personal info) copy of the current prod db for download by devs."""
    host = configuration.get_str('mysql_host')
    port = configuration.get_int('mysql_port')
    usr = configuration.get_str('mysql_user')
    pwd = configuration.get_str('mysql_passwd')
    db = configuration.get_str('decksite_database')
    if not (host or port or usr or pwd or db):
        safe_pwd = 'PRESENT' if pwd else 'MISSING'
        raise InvalidArgumentException(f'Unable to dump dev db with {host} {port} {usr} pwd:{safe_pwd} {db}')
    base_command = ['mysqldump', '-h', host, '-P', str(port), '-u', usr, f'-p{pwd}']
    structure = subprocess.check_output(base_command + ['--no-data', db])
    data = subprocess.check_output(base_command + [f'--ignore-table={db}.person_note', db])
    with gzip.open('shared_web/static/dev-db.sql.gz', 'wb') as f:
        f.write(structure)
        f.write(data)
Esempio n. 9
0
def is_tournament_channel(channel: TextChannel) -> bool:
    tournament_channel_id = configuration.get_int('tournament_channel_id')
    if not tournament_channel_id:
        return False
    return channel.id == tournament_channel_id
def logsite_url(path: str = '/') -> str:
    return site_url(configuration.get_str('logsite_protocol'), configuration.get_str('logsite_hostname'), configuration.get_int('logsite_port'), path)