Ejemplo n.º 1
0
async def deadline(ctx, timezone='America/New_York'):
    await ctx.message.add_reaction('⌚')

    sbdb = db.SpoilerBotDatabase(loop)
    await sbdb.connect()
    deadline = await sbdb.get_current_deadline()

    if deadline == None:
        await ctx.send('No deadline current exists.')

        await ctx.message.add_reaction('👎')
        await ctx.message.remove_reaction('⌚', ctx.bot.user)

    now = datetime.utcnow().replace(tzinfo=tz.tzutc())
    end = deadline['end'].replace(tzinfo=tz.tzutc())
    diff = relativedelta(end, now)

    await ctx.send(deadline['message'].format(
        time=end.astimezone(
            tz.gettz(timezone)).strftime('%b %d %Y at %I:%M:%S %p %Z'),
        remain=
        '{days} days, {hours} hours, {minutes} minutes, and {seconds} seconds to go'
        .format(
            days=diff.days,
            hours=diff.hours,
            minutes=diff.minutes,
            seconds=diff.seconds,
        ),
    ))

    await ctx.message.add_reaction('👍')
    await ctx.message.remove_reaction('⌚', ctx.bot.user)
Ejemplo n.º 2
0
async def generate_verification_key(loop):
    for a in range(10):
        key = ''.join(random.choices(string.ascii_uppercase, k=4))
        sbdb = db.SpoilerBotDatabase(loop)
        await sbdb.connect()
        flattened = []
        if await sbdb.get_verification_key(key) == None:
            await sbdb.record_verification_key(key)
            await sbdb.close()
            return key
    sbdb.close()
    raise RuntimeError('Verification key generation failed.')
Ejemplo n.º 3
0
async def resend(ctx, loop, ircbot, channel):
    if channel == None:
        await ctx.message.add_reaction('👎')
        await ctx.send('{author}, you need to specify a channel.'.format(
            author=ctx.author.mention))
        return
    if re.search('^#srl-[a-z0-9]{5}$', channel):
        raceid = channel.partition('-')[-1]
    else:
        await ctx.message.add_reaction('👎')
        await ctx.send(
            '{author}, that doesn\'t look like an SRL race room.'.format(
                author=ctx.author.mention))
        return

    # figure out if this game has already been generated
    sbdb = db.SpoilerBotDatabase(loop)
    await sbdb.connect()
    racedata = await sbdb.get_bracket_race(raceid)
    await sbdb.close()

    if racedata == None:
        await ctx.message.add_reaction('👎')
        await ctx.send(
            '{author}, `$bracketrace` has not yet been ran for this race.'.
            format(author=ctx.author.mention))
        return

    ircbot.send('JOIN', channel=channel)

    hash = racedata['hash']
    title = racedata['title']

    seed = await pyz3r_asyncio.create_seed(
        randomizer='item',
        baseurl=config['alttpr_website']['baseurl'],
        seed_baseurl=config['alttpr_website']['baseurl_seed'],
        hash=hash)

    msg = await generate_bracket_dm(
        seed=seed,
        players=title,
        channel=channel,
    )

    dm = ctx.author.dm_channel
    if dm == None:
        dm = await ctx.author.create_dm()
    await dm.send(msg)

    await ctx.message.add_reaction('👍')
Ejemplo n.º 4
0
async def spoilerseed(channel, author, ircbot, loop):
    if channel == '#speedrunslive':
        return
    # ignore private messages
    if channel == config['srl_irc_nickname']:
        return

    if re.search('^#srl-[a-z0-9]{5}$', channel):
        raceid = channel.partition('-')[-1]
    else:
        return

    sbdb = db.SpoilerBotDatabase(loop)
    await sbdb.connect()
    racedata = await sbdb.get_bracket_race(raceid)
    await sbdb.close()

    if racedata == None:
        ircbot.send(
            'PRIVMSG',
            target=channel,
            message=
            'This race is not yet registered with SpoilerTourneyBot.  Please run $bracketrace command in discord.'
        )
        return

    hash = racedata['hash']

    seed = await pyz3r_asyncio.create_seed(
        randomizer='item',
        baseurl=config['alttpr_website']['baseurl'],
        seed_baseurl=config['alttpr_website']['baseurl_seed'],
        hash=hash)

    ircbot.send('PRIVMSG',
                target=channel,
                message='Seed: {permalink} - {code}'.format(
                    permalink=await seed.url(),
                    code=' | '.join(await seed.code())))
Ejemplo n.º 5
0
async def bracketrace(ctx,
                      loop,
                      ircbot,
                      arg1=None,
                      arg2=None,
                      mode='open',
                      nosrl=False,
                      skirmish=False):
    if nosrl == False:
        if arg1 == None:
            await ctx.message.add_reaction('👎')
            await ctx.send('{author}, you need the SG episode id.'.format(
                author=ctx.author.mention))
            return
        if arg2 == None:
            await ctx.message.add_reaction('👎')
            await ctx.send('{author}, you need the srl room specified.'.format(
                author=ctx.author.mention))
            return
        if re.search('^#srl-[a-z0-9]{5}$', arg2):
            raceid = arg2.partition('-')[-1]
            channel = arg2
        else:
            await ctx.message.add_reaction('👎')
            await ctx.send(
                '{author}, that doesn\'t look like an SRL race room.'.format(
                    author=ctx.author.mention))
            return
        if not await srl.is_race_open(raceid):
            await ctx.message.add_reaction('👎')
            await ctx.send(
                '{author}, that race does not exist or is not in an "Entry Open" state.'
                .format(author=ctx.author.mention))
            return

        # figure out if this game has already been generated
        sbdb = db.SpoilerBotDatabase(loop)
        await sbdb.connect()
        racedata = await sbdb.get_bracket_race(raceid)
        await sbdb.close()

        if not racedata == None:
            await ctx.message.add_reaction('👎')
            await ctx.send(
                '{author}, game data was already generated for that SRL room, try using `$resend #srl-12345` where `#srl-12345` is the SRL channel name to resend seed information and have the bot join the room.'
                .format(author=ctx.author.mention))
            return
    else:
        if arg1 == None:
            await ctx.message.add_reaction('👎')
            await ctx.send(
                '{author}, you the race id.'.format(author=ctx.author.mention))
            return
        raceid = 'nosrl' + ''.join(
            random.choices(string.ascii_letters + string.digits, k=6))
        channel = ''

    if skirmish == False:
        sg_episode_id = arg1
        sge = await sg.find_episode(sg_episode_id)
        participants = await sge.get_participants_discord()
        players = await sge.get_player_names()
        participants.append(ctx.author.name + '#' + ctx.author.discriminator)

        #filter out duplicates
        participants = list(set(participants))

        if participants == False:
            await ctx.message.add_reaction('👎')
            await ctx.send(
                '{author}, that episode doesn\'t appear to exist.'.format(
                    author=ctx.author.mention))
            return

        title = ' vs. '.join(players)

    else:
        title = arg1
        sg_episode_id = 0

    if mode == 'inverted':
        seed = await pyz3r_asyncio.create_seed(
            randomizer='item',  # optional, defaults to item
            baseurl=config['alttpr_website']['baseurl'],
            seed_baseurl=config['alttpr_website']['baseurl_seed'],
            settings={
                "difficulty": "normal",
                "enemizer": False,
                "logic": "NoGlitches",
                "mode": "inverted",
                "tournament": True,
                "variation": "none",
                "weapons": "randomized",
                "lang": "en"
            })
    elif mode == 'nologic':
        seed = await pyz3r_asyncio.create_seed(
            randomizer='item',  # optional, defaults to item
            baseurl=config['alttpr_website']['baseurl'],
            seed_baseurl=config['alttpr_website']['baseurl_seed'],
            settings={
                "difficulty": "normal",
                "enemizer": False,
                "logic": "None",
                "mode": "open",
                "tournament": True,
                "variation": "none",
                "weapons": "randomized",
                "lang": "en"
            })
    elif mode == 'nologickeys':
        seed = await pyz3r_asyncio.create_seed(
            randomizer='item',  # optional, defaults to item
            baseurl=config['alttpr_website']['baseurl'],
            seed_baseurl=config['alttpr_website']['baseurl_seed'],
            settings={
                "difficulty": "normal",
                "enemizer": False,
                "logic": "None",
                "mode": "open",
                "tournament": True,
                "variation": "key-sanity",
                "weapons": "randomized",
                "lang": "en"
            })
    else:
        seed = await pyz3r_asyncio.create_seed(
            randomizer='item',  # optional, defaults to item
            baseurl=config['alttpr_website']['baseurl'],
            seed_baseurl=config['alttpr_website']['baseurl_seed'],
            settings={
                "difficulty": "normal",
                "enemizer": False,
                "logic": "NoGlitches",
                "mode": "open",
                "tournament": True,
                "variation": "none",
                "weapons": "randomized",
                "lang": "en"
            })

    rdb = db.RandomizerDatabase(loop)
    await rdb.connect()
    spoiler_log = await rdb.get_seed_spoiler(seed.hash)
    await rdb.close()

    spoiler_log_url = await helpers.write_json_to_disk(spoiler_log['spoiler'],
                                                       seed)

    modlogchannel = ctx.guild.get_channel(config['log_channel'][ctx.guild.id])
    msg = 'Race {title}:\n\n' \
    'SRL Channel: {srlchannel}\n' \
    'Permalink: {permalink}\n' \
    'Spoiler log: {spoilerlog}'.format(
        title=title,
        srlchannel=channel,
        permalink=await seed.url(),
        spoilerlog=spoiler_log_url
    )
    await modlogchannel.send(msg)

    spdb = db.SpoilerBotDatabase(loop)
    await spdb.connect()
    await spdb.record_bracket_race(
        sg_episode_id=sg_episode_id,
        srl_race_id=raceid,
        hash=seed.hash,
        title=title,
        permalink=await seed.url(),
        spoiler_url=spoiler_log_url,
        initiated_by=ctx.author.name + '#' + ctx.author.discriminator,
    )
    await spdb.close()

    if skirmish == True:
        msg = await generate_skirmish_msg(
            seed=seed,
            title=title,
            channel=channel,
        )
        await ctx.send(msg)
    else:
        msg = await generate_bracket_dm(
            seed=seed,
            title=title,
            channel=channel,
        )
        for user in participants:
            u = ctx.guild.get_member_named(user)
            if u == None:
                await modlogchannel.send(
                    'Unable to find {user} for DM.'.format(user=user, ))
                pass
            else:
                dm = u.dm_channel
                if dm == None:
                    dm = await u.create_dm()
                await dm.send(msg)

    if nosrl == False:
        ircbot.send('JOIN', channel=channel)

    await ctx.message.add_reaction('👍')
Ejemplo n.º 6
0
async def qualifier_cmd(ctx, arg1, logger, loop):
    tz = timezone('US/Eastern')
    logger.info(
        'Qualifier Requested - {servername} - {channelname} - {player} - {seednum}'
        .format(
            servername=ctx.guild.name,
            channelname=ctx.channel.name,
            player=ctx.author,
            seednum=arg1,
        ))
    # if helpers.check_cmd_filter(ctx.guild.id,ctx.channel.name,'qualifier',config):
    #     return

    try:
        seednum = int(arg1)
    except ValueError:
        await ctx.message.add_reaction('👎')
        await ctx.send(
            '{author}, that is not a number.'.format(author=ctx.author.mention)
        )
        return

    spdb = db.SpoilerBotDatabase(loop)
    await spdb.connect()
    qualifier_seed = await spdb.get_qualifier_seed(seednum)
    await spdb.close()

    if qualifier_seed == None:
        await ctx.message.add_reaction('👎')
        await ctx.send('{author}, that seed does not exist.'.format(
            author=ctx.author.mention))
        return

    seed = await pyz3r_asyncio.create_seed(
        randomizer='item',
        baseurl=config['alttpr_website']['baseurl'],
        seed_baseurl=config['alttpr_website']['baseurl_seed'],
        hash=qualifier_seed['hash'])

    spoilerlog = qualifier_seed['spoilerlog']
    verificationkey = await generate_verification_key(loop)

    permalink = await seed.url()
    fscode = ' | '.join(await seed.code())
    timestamp = str(datetime.now(tz).replace(microsecond=0))

    logger.info(
        'Qualifier Generated - {servername} - {channelname} - {player} - {seednum} - {verificationkey}'
        .format(servername=ctx.guild.name,
                channelname=ctx.channel.name,
                player=ctx.author,
                seednum=seednum,
                verificationkey=verificationkey))

    dm = ctx.author.dm_channel
    if dm == None:
        dm = await ctx.author.create_dm()

    await dm.send(
        'This is the verification key that is required to be in the first four characters of the filename of your run:\n`{verificationkey}`\n\n' \
        'Seed number: {seednum}\n' \
        'Timestamp: {timestamp}\n' \
        'Permalink: {permalink}\n' \
        'File select code: [{fscode}]\n' \
        'Spoiler log: {spoilerlog}\n\n' \
        'Submit your run here once completed: <{submiturl}>\n\n' \
        'You have 15 minutes from the receipt of this message to start your run!\n' \
        '**Please DM an admin immediately if this was requested in error**, otherwise it may be counted as a forfeit (slowest time of all runners of the seed plus 30 minutes).\n\n' \
        'Good luck <:mudora:536293302689857567>'.format(
            verificationkey=verificationkey,
            seednum=seednum,
            timestamp=timestamp,
            fscode=fscode,
            permalink=permalink,
            spoilerlog=spoilerlog,
            submiturl=config['qualifier_form_prefill'].format(
                discordtag=urllib.parse.quote_plus(ctx.author.name + '#' + ctx.author.discriminator),
                verificationkey=verificationkey,
                seednum=seednum
            )
        )
    )

    modlogchannel = ctx.guild.get_channel(config['log_channel'][ctx.guild.id])
    msg = 'Qualifier request for {player}:\n\n' \
    'Verification Key: {verificationkey}\n' \
    'Seed Number: {seednum}\n' \
    'Timestamp: {timestamp}'.format(
        player = ctx.author.name + '#' + ctx.author.discriminator,
        verificationkey=verificationkey,
        seednum=seednum,
        timestamp=timestamp,
    )
    await modlogchannel.send(msg)

    logger.info(
        'Qualifier DM Sent - {servername} - {channelname} - {player} - {seednum} - {verificationkey}'
        .format(servername=ctx.guild.name,
                channelname=ctx.channel.name,
                player=ctx.author,
                seednum=seednum,
                verificationkey=verificationkey))

    agcm = gspread_asyncio.AsyncioGspreadClientManager(helpers.get_creds)
    agc = await agcm.authorize()
    wb = await agc.open_by_key(config['gsheet_id'])
    wks = await wb.get_worksheet(0)

    await wks.append_row([
        timestamp,
        str(ctx.author), seednum, verificationkey,
        "=INDEX('Submitted Runs'!E:G,MATCH(INDIRECT(\"R[0]C[-1]\", false),'Submitted Runs'!C:C,0), 1)*3600+INDEX('Submitted Runs'!E:G,MATCH(INDIRECT(\"R[0]C[-1]\", false),'Submitted Runs'!C:C,0), 2)*60+INDEX('Submitted Runs'!E:G,MATCH(INDIRECT(\"R[0]C[-1]\", false),'Submitted Runs'!C:C,0), 3)",
        "=INDEX('Submitted Runs'!H:H,MATCH(INDIRECT(\"R[0]C[-2]\", false),'Submitted Runs'!C:C,0), 1)",
        "=INDEX('Submitted Runs'!I:I,MATCH(INDIRECT(\"R[0]C[-3]\", false),'Submitted Runs'!C:C,0), 1)",
        "=INDEX('Submitted Runs'!J:J,MATCH(INDIRECT(\"R[0]C[-4]\", false),'Submitted Runs'!C:C,0), 1)"
    ],
                         value_input_option='USER_ENTERED')

    logger.info(
        'Qualifier Recorded in Gsheet - {servername} - {channelname} - {player} - {seednum} - {verificationkey}'
        .format(servername=ctx.guild.name,
                channelname=ctx.channel.name,
                player=ctx.author,
                seednum=seednum,
                verificationkey=verificationkey))

    await ctx.message.add_reaction('👍')
Ejemplo n.º 7
0
async def gen_qualifier_seed(ctx, loop, seednum=None):
    try:
        seednum = int(seednum)
    except ValueError:
        await ctx.message.add_reaction('👎')
        await ctx.send(
            '{author}, that is not a number.'.format(author=ctx.author.mention)
        )
        return

    spdb = db.SpoilerBotDatabase(loop)
    await spdb.connect()
    qualifier_seed = await spdb.get_qualifier_seed(seednum)

    if not qualifier_seed == None:
        await ctx.message.add_reaction('👎')
        await ctx.send(
            '{author}, that seed already exists.  It would need to be manually purged from the database first.'
            .format(author=ctx.author.mention))
        await spdb.close()
        return

    seed = await pyz3r_asyncio.create_seed(
        randomizer='item',  # optional, defaults to item
        baseurl=config['alttpr_website']['baseurl'],
        seed_baseurl=config['alttpr_website']['baseurl_seed'],
        settings={
            "difficulty": "normal",
            "enemizer": False,
            "logic": "NoGlitches",
            "mode": "open",
            "tournament": True,
            "variation": "none",
            "weapons": "randomized",
            "lang": "en"
        })

    rdb = db.RandomizerDatabase(loop)
    await rdb.connect()
    spoiler_log = await rdb.get_seed_spoiler(seed.hash)
    await rdb.close()

    spoiler_log_url = await helpers.write_json_to_disk(spoiler_log['spoiler'],
                                                       seed)

    await spdb.insert_qualifier_seed(
        id=seednum,
        hash=seed.hash,
        spoilerlog=spoiler_log_url,
    )

    modlogchannel = ctx.guild.get_channel(config['log_channel'][ctx.guild.id])
    msg = '-----------------------------------------\n' \
    'Qualifier Seed #{seednum}:\n\n' \
    'Permalink: {permalink}\n' \
    'Code: [{code}]\n' \
    'Spoiler log: {spoilerlog}'.format(
        seednum=seednum,
        permalink=await seed.url(),
        spoilerlog=spoiler_log_url,
        code=' | '.join(await seed.code())
    )
    await modlogchannel.send(msg)
    await ctx.send(msg)

    await spdb.close()

    await ctx.message.add_reaction('👍')
Ejemplo n.º 8
0
async def spoilerstart(channel,
                       author,
                       ircbot,
                       discordbot,
                       loop,
                       immediate=False):
    # ignore SRL lobby
    if channel == '#speedrunslive':
        return
    # ignore private messages
    if channel == config['srl_irc_nickname']:
        return

    # extract the raceid from the channel name
    if re.search('^#srl-[a-z0-9]{5}$', channel):
        raceid = channel.partition('-')[-1]
    else:
        return  #we should probably raise an exception instead so we're not hiding an error

    # check to make sure the race is open for entry (not in progress or finished)
    if not await is_race_open(raceid):
        ircbot.send('NOTICE',
                    target=channel,
                    author=author,
                    message='This race is not currently open for entry.')
        return

    # make sure the bot isn't entered into the race already
    # If the bot died and was restarted, a tournament admin might need to force the bot out of the channel
    if not await get_single_player(
            raceid, player=config['srl_irc_nickname'].lower()) == None:
        ircbot.send('PRIVMSG',
                    target=channel,
                    message='Bot is already entered into this race.')
        return

    # retrieve the seed details based on what we stored in the database when running the $bracketrace or $skirmish commands in discord
    sbdb = db.SpoilerBotDatabase(loop)
    await sbdb.connect()
    racedata = await sbdb.get_bracket_race(raceid)
    await sbdb.close()
    if racedata == None:
        ircbot.send(
            'PRIVMSG',
            target=channel,
            message=
            'This race is not yet registered with SpoilerTourneyBot.  Please run $bracketrace command in discord.'
        )
        return

    # give each part of the racedata a friendly variable name to make things easier to read
    sg_episode_id = racedata['sg_episode_id']
    srl_race_id = racedata['srl_race_id']
    hash = racedata['hash']
    title = racedata['title']
    spoiler_url = racedata['spoiler_url']
    initiated_by = racedata['initiated_by']

    # retrieve the seed details from the randomizer website
    seed = await pyz3r_asyncio.create_seed(
        randomizer='item',
        baseurl=config['alttpr_website']['baseurl'],
        seed_baseurl=config['alttpr_website']['baseurl_seed'],
        hash=hash)

    await gatekeeper_immediatestart(ircbot=ircbot,
                                    discordbot=discordbot,
                                    initiated_by_discordtag=initiated_by,
                                    sg_episode_id=sg_episode_id,
                                    channel=channel,
                                    spoilerlogurl=spoiler_url,
                                    title=title,
                                    seed=seed,
                                    raceid=raceid,
                                    loop=loop)