Example #1
0
 async def fetch(bot, ctx, allow_started=False, guild_id = None):
     guild = await bot.fetch_guild_from_ctx(ctx, guild_id)
     cc = await guild.fetch_current_challenge()
     BotErr.raise_if(cc is None, 'Create a new challenge first.')
     BotErr.raise_if(cc is not None and not allow_started and await cc.has_started(),
         'Cannot add/delete user/title/pool after a challenge has started.')
     return State(bot, guild, cc)
Example #2
0
 async def rename_pool(self, ctx, old_name, new_name):
     state = await State.fetch(self, ctx, allow_started=True)
     BotErr.raise_if(await state.cc.has_pool(new_name), f'Pool "{new_name}" already exists.')
     pool = await state.fetch_pool(old_name)
     pool.name = new_name
     await pool.update()
     await self.db.commit()
Example #3
0
 async def unban_user(self, ctx, user):
     state = await State.fetch(self, ctx, allow_started=True)
     u = await state.fetch_user(user)
     BotErr.raise_if(not await state.is_user_banned(u),
         f'User {user.mention} is not banned')
     await state.cc.remove_banned_user(u)
     await self.db.commit()
Example #4
0
 async def rename_title(self, ctx, old_name, new_name):
     state = await State.fetch(self, ctx)
     BotErr.raise_if(await state.cc.has_title(new_name), f'Title "{new_name}" already exists.')
     title = await state.fetch_title(old_name)
     title.name = new_name
     await title.update()
     await self.db.commit()
Example #5
0
 async def remove_title(self, ctx, name):
     state = await State.fetch(self, ctx)
     title = await state.fetch_title(name)
     BotErr.raise_if(title.is_used,
                     "Cannot delete title that's already been used.")
     await title.delete()
     await self.db.commit()
Example #6
0
 async def ban_user(self, ctx, user):
     state = await State.fetch(self, ctx, allow_started=True)
     u = await state.fetch_user(user)
     BotErr.raise_if(await state.is_user_banned(u),
         f'User {user.mention} has already been banned')
     await state.cc.add_banned_user(u)
     await self.db.commit()
Example #7
0
    async def start_round(self, ctx, days, pool):
        state = await State.fetch(self, ctx, allow_started=True)
        last_round = await state.cc.fetch_last_round()
        if last_round is not None and not last_round.is_finished:
            raise BotErr(f'Finish round {last_round.num} first.')

        pool = await state.fetch_pool(pool)
        users_participants = await state.cc.fetch_users_participants()
        users = { up[0].id: up[0] for up in users_participants }
        participants = [ up[1] for up in filter(lambda up: not up[1].has_failed(), users_participants) ]
        BotErr.raise_if(len(participants) == 0, 'Not enough participants to start a round.')
        titles = await pool.fetch_unused_titles()
        BotErr.raise_if(len(titles) < len(participants), f'Not enough titles in "{pool}" pool.')

        num = last_round.num + 1 if last_round is not None else 0
        start = datetime.now()
        new_round = await state.cc.add_round(num, start, start + timedelta(days=days))

        rand_titles = [ titles.pop(random.randrange(len(titles))) for _ in range(len(participants)) ]
        for participant, title in zip(participants, rand_titles):
            await new_round.add_roll(participant.id, title.id)
            participant.progress_current = None
            participant.progress_total = None
            title.is_used = True
            await participant.update()
            await title.update()

        await self.db.commit()
        return new_round, { users[p.user_id].name: t.name for p, t in zip(participants, rand_titles) }
Example #8
0
 async def sync_all(self, ctx):
     guild = await Guild.fetch_or_insert(self.db, ctx.message.guild.id)  # todo: move logic?
     challenges = await guild.fetch_challenges()
     BotErr.raise_if(guild.spreadsheet_key is None, 'Spreadsheet key is not set.') # todo: maybe its bad to have single
                                                                                         # spreadsheet_key per guild, maybe
                                                                                         # we need to store it in challange column
     for c in challenges:
         await export(guild.spreadsheet_key, c)
Example #9
0
 async def fetch(bot, ctx, allow_started=False):
     guild = await Guild.fetch_or_insert(bot.db, ctx.message.guild.id)
     cc = await guild.fetch_current_challenge()
     BotErr.raise_if(cc is None, 'Create a new challenge first.')
     BotErr.raise_if(
         cc is not None and not allow_started and await cc.has_started(),
         'Cannot add/delete user/title/pool after a challenge has started.')
     return State(bot, guild, cc)
Example #10
0
 async def add_user(self, ctx, user):
     state = await State.fetch(self, ctx)
     BotErr.raise_if(
         await state.has_participant(user),
         f'User {user.mention} is already participating in this challenge.')
     user = await state.fetch_user(user)
     await state.cc.add_participant(user.id)
     await self.db.commit()
Example #11
0
 async def add_title(self, ctx, pool, user, name, url):
     state = await State.fetch(self, ctx)
     BotErr.raise_if(await state.cc.has_title(name),
                     f'Title "{name}" already exists.')
     participant = await state.fetch_participant(user)
     pool = await state.fetch_pool(pool)
     await pool.add_title(participant.id, name, url)
     await self.db.commit()
Example #12
0
 async def fetch_participant(self, user):
     u = await self.fetch_user(user)
     p = await self.cc.fetch_participant(u.id)
     BotErr.raise_if(
         p is None,
         f'User {user.mention} is not participating in this challenge.')
     BotErr.raise_if(p.has_failed(),
                     f'User {user.mention} has failed this challenge.')
     return p
Example #13
0
    async def remove_title(self, ctx, name, is_admin=False):
        state = await State.fetch(self, ctx, allow_started=is_admin)
        title = await state.fetch_title(name)

        participant = await state.fetch_participant(ctx.message.author)
        BotErr.raise_if(participant.id != title.participant_id and not is_admin, "Can't remove other's title") 
        BotErr.raise_if(title.is_used, "Cannot delete title that's already been used.")
        await title.delete()
        await self.db.commit()
Example #14
0
 async def fetch_last_round(self, allow_past_deadline=False):
     lr = await self.cc.fetch_last_round()
     BotErr.raise_if(lr is None, 'Create a new round first.')
     BotErr.raise_if(
         lr is not None and
         (lr.is_finished
          or not allow_past_deadline and datetime.now() > lr.finish_time),
         'Round has ended.')
     return lr
Example #15
0
 async def _set_title(self, roll, new_title):
     BotErr.raise_if(new_title.is_used, f'Title "{new_title.name}" is already used.')
     old_title = await roll.fetch_title()
     old_title.is_used = False
     roll.title_id = new_title.id
     new_title.is_used = True
     await old_title.update()
     await roll.update()
     await new_title.update()
Example #16
0
 async def start_challenge(self, ctx, name):
     guild = await Guild.fetch_or_insert(self.db, ctx.message.guild.id)
     if guild.current_challenge_id is not None:
         raise BotErr(f'Finish "{(await guild.fetch_current_challenge()).name}" challenge first.')
     BotErr.raise_if(await guild.has_challenge(name), f'Challenge "{name}" already exists.')
     challenge = await guild.add_challenge(name, datetime.now())
     await challenge.add_pool('main')
     guild.current_challenge_id = challenge.id
     await guild.update()
     await self.db.commit()
Example #17
0
 async def reroll(self, ctx, user, pool):
     state = await State.fetch(self, ctx, allow_started=True)
     last_round = await state.fetch_last_round()
     participant = await state.fetch_participant(user)
     roll = await last_round.fetch_roll(participant.id)
     pool = await state.fetch_pool(pool)
     titles = await pool.fetch_unused_titles()
     BotErr.raise_if(len(titles) == 0, f'Not enough titles in "{pool}" pool.')
     new_title = random.choice(titles)
     await self._set_title(roll, new_title)
     await self.db.commit()
     return new_title
Example #18
0
    async def fetch_guild_from_ctx(self, ctx, guild_id):
        guild = ctx.message.guild
        if guild:
            guild = await Guild.fetch_or_insert(self.db, guild.id)
        else: # we're in dms, so we try to deduce the guild from db
            author = ctx.message.author
            user = await User.fetch_or_insert(self.db, author.id, author.name)
            active_guilds = await user.fetch_active_guilds()

            if guild_id == None and len(active_guilds) > 1:
                raise GuildAmbiguity(active_guilds)
            BotErr.raise_if(len(active_guilds) == 0, 'No active guilds')

            guild = active_guilds[0]
            if guild_id:
                guild = [ g for g in active_guilds if g.id == guild_id ][0]
        return guild
Example #19
0
    async def add_title(self, ctx, params, is_admin=False):
        # ? maybe move it into a class
        state = await State.fetch(self, ctx, guild_id = params['guild_id'], allow_started=is_admin)
        name = params['title_name']
        user = params['user']
        pool = params['pool']
        url = params['url']

        if 'is_hidden' in params:
            is_hidden = params['is_hidden']
        else:
            is_hidden = False
        
        score = params['score']
        duration = params['duration']
        num_of_episodes = params['num_of_episodes']
        difficulty = params['difficulty']

        BotErr.raise_if(await state.cc.has_title(name), f'Title "{name}" already exists.')
        participant = await state.fetch_participant(user)
        pool = await state.fetch_pool(pool)
        await pool.add_title(participant.id, name, url, score, num_of_episodes, duration, difficulty, is_hidden)
        await self.db.commit()
Example #20
0
    async def add_user(self, ctx, user):
        state = await State.fetch(self, ctx)
        u = await state.fetch_user(user)

        BotErr.raise_if(await state.is_user_banned(u),
            f'User {user.mention} is banned in this challenge')
        BotErr.raise_if(await state.cc.has_started(),
            f'The challenge has already started.')
        BotErr.raise_if(await state.has_participant(user),
            f'User {user.mention} is already participating in this challenge.')

        await state.cc.add_participant(u.id)
        await self.db.commit()
Example #21
0
 async def fetch_title(self, name):
     t = await self.cc.fetch_title(name)
     BotErr.raise_if(t is None, f'Title "{name}" does not exist.')
     return t
Example #22
0
 async def add_pool(self, ctx, name):
     state = await State.fetch(self, ctx)
     BotErr.raise_if(await state.cc.has_pool(name), f'Pool "{name}" already exists.')
     await state.cc.add_pool(name)
     await self.db.commit()
Example #23
0
 async def sync(self, ctx, guild_id=None):
     state = await State.fetch(self, ctx, allow_started=True, guild_id=guild_id)
     BotErr.raise_if(state.guild.spreadsheet_key is None, 'Spreadsheet key is not set.')
     await export(state.guild.spreadsheet_key, state.cc)
Example #24
0
 async def fetch_pool(self, name):
     p = await self.cc.fetch_pool(name)
     BotErr.raise_if(p is None, f'Pool "{name}" does not exist.')
     return p