Beispiel #1
0
async def aux_invite_member(ctx, host_member: discord.Member,
                            invited_member: discord.Member):
    guild = ctx.guild
    existing_lab_group = hpf.existing_member_lab_group(host_member)
    if not existing_lab_group:
        await ctx.send(btm.error_not_in_group_for_invite(host_member))
    elif hpf.member_in_teaching_team(invited_member, guild):
        await ctx.send(btm.error_can_not_invite_teaching_team())
    else:
        async with invites_lock:
            group_num = hpf.get_lab_group_number(existing_lab_group.name)
            invite_list = GUILD_CONFIG.group_invites(guild)
            if hpf.existing_member_lab_group(invited_member):
                await ctx.send(
                    btm.error_member_already_in_group(invited_member.name,
                                                      existing_lab_group.name))
            elif invite_list.has_invite(invited_member.id, group_num):
                await ctx.send(btm.error_invite_already_sent(invited_member))
            else:
                # Add invitation
                invite_list.add_invite(invited_member.id, group_num)
                general_text_channel = hpf.get_general_text_channel(guild)
                if general_text_channel:
                    await general_text_channel.send(
                        btm.success_invite_sent_to_group(
                            invited_member, existing_lab_group, group_num))
                group_channel = hpf.get_lab_text_channel(guild, group_num)
                if group_channel:
                    await group_channel.send(
                        btm.success_invite_sent(invited_member))
Beispiel #2
0
async def clean_all_command(ctx, *args):
    async with ctx.channel.typing():
        excluded_groups = hpf.get_excluded_groups(*args)
        groups_to_be_cleaned = [group for group in hpf.all_existing_lab_groups(ctx.guild)
                                if hpf.get_lab_group_number(group.name) not in excluded_groups and is_open_group(ctx.guild, group)]
        for group in sorted(groups_to_be_cleaned, key=lambda c: c.name, reverse=False):
            await aux_clean_group(ctx, group.name)
Beispiel #3
0
async def random_assignment(
        ctx, member: discord.Member,
        available_existing_groups: List[discord.CategoryChannel]):
    if not member.nick:
        await ctx.send(btm.message_member_need_name_error(member))
        return available_existing_groups
    max_group_size = GUILD_CONFIG.max_students_per_group(ctx.guild)
    while len(available_existing_groups) > 0:
        random_lab_group = random.choice(available_existing_groups)
        random_group = hpf.get_lab_group_number(random_lab_group.name)
        if random_group and len(
                hpf.all_students_in_group(ctx.guild,
                                          random_group)) < max_group_size:
            success = await aux_join_group(ctx, member, random_group)
            if success:
                return available_existing_groups
        available_existing_groups.remove(random_lab_group)
    new_group = await aux_create_group(ctx)
    new_group_number = hpf.get_lab_group_number(new_group.name)
    if await aux_join_group(ctx, member, new_group_number):
        ctx.send(btm.message_default_error())
    available_existing_groups.append(new_group)
    return available_existing_groups
Beispiel #4
0
def aux_group_details(ctx,
                      group: discord.CategoryChannel,
                      details: bool = False,
                      none_if_empty: bool = False) -> Optional[str]:
    guild = ctx.guild
    members = hpf.all_students_in_group(guild, group.name)
    if not members and none_if_empty:
        return None
    if details:
        return btm.info_group_details(members,
                                      group,
                                      is_open=is_open_group(guild, group))
    else:
        return btm.message_list_group_members(
            hpf.get_lab_group_number(group.name), members)
async def aux_random_join(ctx, member_mention: discord.Member, *args):
    member = discord.utils.get(ctx.message.mentions, name=member_mention.name)
    excluded_groups = hpf.get_excluded_groups(*args)
    if not member:
        await ctx.send(btm.message_member_not_exists(member_mention.nick))
    elif not excluded_groups:
        await ctx.send("All extra arguments should be integers!")
    else:
        available_lab_groups = []
        for group in hpf.all_existing_lab_groups(ctx.guild):
            group_number = hpf.get_lab_group_number(group.name)
            if group_number and group not in excluded_groups and is_open_group(
                    ctx.guild, group):
                available_lab_groups.append(group)
        await random_assignment(ctx, member, available_lab_groups)
async def aux_raise_hand(ctx):
    member = ctx.author
    existing_lab_group = hpf.existing_member_lab_group(member)
    general_text_channel = hpf.get_general_text_channel(ctx.guild)
    if not existing_lab_group:
        await ctx.channel.send(btm.message_member_not_in_group_for_help())
    elif ctx.channel != hpf.existing_member_lab_text_channel(member):
        await ctx.channel.send(
            btm.error_stay_in_your_seat(ctx.author, existing_lab_group))
    elif general_text_channel:
        group_num = hpf.get_lab_group_number(existing_lab_group.name)
        # Check if group already asked for help
        async with help_queue_lock:
            help_queue = GUILD_CONFIG.help_queue(ctx.guild)
            queue_size = help_queue.size()
            if group_num in help_queue:
                await ctx.channel.send(
                    btm.info_help_queue_size(queue_size -
                                             1) if queue_size > 1 else ":eyes:"
                )
                return
        # Get help
        online_team = hpf.all_teaching_team_members(ctx.author.guild)
        available_team = [
            member for member in online_team
            if not hpf.existing_member_lab_group(member)
        ]
        help_message = None
        if available_team:
            await ctx.channel.send(btm.message_asking_for_help())
            help_message = await general_text_channel.send(
                btm.message_call_for_help(existing_lab_group.name,
                                          available_team))
        elif online_team:
            await ctx.channel.send(btm.message_no_one_available_error())
            help_message = await general_text_channel.send(
                btm.message_call_for_help(existing_lab_group.name,
                                          online_team))
        else:
            await ctx.channel.send(btm.message_no_one_online_error())
        if help_message:
            async with help_queue_lock:
                if queue_size > 0:
                    await ctx.channel.send(btm.info_help_queue_size(queue_size)
                                           )
                help_queue.add(group=group_num, message_id=help_message.id)
    else:
        await ctx.channel.send(btm.message_can_not_get_help_error())
Beispiel #7
0
async def map_size_of_members_to_group(
        guild: discord.Guild) -> Dict[int, List[discord.CategoryChannel]]:
    print('Getting num of members per group')
    size_to_group = {}
    print('Created dictionary')
    for group in hpf.all_existing_lab_groups(guild):
        print('Processing group ' + group.name)
        group_num = hpf.get_lab_group_number(group.name)
        if is_open_group(guild, group):
            size = len(hpf.all_students_in_group(guild, group_num))
            print('The group is open and it has ' + str(size) + " members")
            groups = size_to_group.get(size)
            if groups is None:
                groups = []
                size_to_group[size] = groups
            groups.append(group)
    print('Done. The dictionary: ' + str(size_to_group))
    return size_to_group
Beispiel #8
0
async def aux_random_join_all(ctx, *args):
    # Get excluded groups
    excluded_groups = hpf.get_excluded_groups(*args)
    #if not excluded_groups:
    #    await ctx.send("All extra arguments should be integers for excluded groups.")
    #    return
    # Get available groups
    available_lab_groups = []
    for group in hpf.all_existing_lab_groups(ctx.guild):
        group_number = hpf.get_lab_group_number(group.name)
        if group_number and group not in excluded_groups and is_open_group(
                ctx.guild, group):
            available_lab_groups.append(group)
    no_group_members = hpf.all_students_with_no_group(ctx.guild)
    # Assign groups
    for member in no_group_members:
        # if member.status == discord.Status.online:
        available_lab_groups = await random_assignment(ctx, member,
                                                       available_lab_groups)
Beispiel #9
0
async def on_reaction_add(reaction: discord.Reaction, user: Union[discord.Member, discord.User]):
    message = reaction.message
    emoji = reaction.emoji
    guild = message.guild
    # bot reacted for marking the message as attended
    if bot.user == user:
        return
    elif message.author == bot.user and re.search(r"calling for help", message.content):
        success = False
        if len(message.reactions) <= 1 and hpf.member_in_teaching_team(user, guild):
            success = await rhh.go_for_help_from_message(user, message, group=hpf.get_lab_group_number(message.content))
        if not success:
            await message.remove_reaction(reaction, user)
    elif message.author == bot.user and len(message.reactions) <= 1:
        if same_emoji(emoji, 'slight_smile'):
            await message.add_reaction(get_unicode_emoji_from_alias('thumbsup'))
            await message.channel.send(emoji)
    else:
        print(emoji, get_unicode_from_emoji(emoji))
Beispiel #10
0
async def aux_assign_all(ctx):
    print('Assigning students to open groups automatically')
    # Get number of members per group
    size_to_group = await map_size_of_members_to_group(ctx.guild)
    largest_size = max(size_to_group)
    max_group_size = GUILD_CONFIG.max_students_per_group(ctx.guild)

    no_group_students = hpf.all_students_with_no_group(ctx.guild)
    print(str(len(no_group_students)) + ' students are without a group')
    online_no_group_students = hpf.select_online_members(
        ctx.guild, no_group_students)
    # online_no_group_students = no_group_students   # ... for debugging late at night
    print(
        str(len(online_no_group_students)) +
        ' students are online without a group')

    online_no_group_students_with_nick = []
    for student in online_no_group_students:
        if not student.nick:
            await ctx.send(btm.message_member_need_name_error(student))
        else:
            online_no_group_students_with_nick.append(student)

    print(
        str(len(online_no_group_students_with_nick)) +
        ' students are online without a group but have a nick')

    if not online_no_group_students_with_nick:
        await ctx.send(
            "There are no online students with a nickname and without a group to assign."
        )
        return

    await ctx.send('Assigning ' +
                   str(len(online_no_group_students_with_nick)) +
                   ' online students with a nickname and without a group.')

    print('Shuffling students')
    random.shuffle(online_no_group_students_with_nick)

    for i in range(1, max_group_size):
        added_member = []
        groups = size_to_group.get(i)
        print('Processing existing groups of size ' + str(i))
        if not groups is None:
            for group in groups:
                group_num = hpf.get_lab_group_number(group.name)
                print('Processing group ' + group.name + ' num ' +
                      str(group_num))
                if online_no_group_students_with_nick:
                    member = online_no_group_students_with_nick.pop(0)
                    print('Assigning student ' + member.nick)
                    success = await aux_join_group(ctx, member, group_num)
                    if success:
                        added_member.append(group)
                    else:
                        ctx.send('Unknown error adding ' + member.nick)
                else:
                    return
                # else skip member for now
            print('Updating group sizes')
            next_group = size_to_group.get(i + 1)
            if next_group is None:
                next_group = []
                size_to_group[i + 1] = next_group
            for group in added_member:
                groups.remove(group)
                if i < max_group_size:
                    next_group.append(group)

    print('Processing empty groups')
    empty_groups = size_to_group.get(0)
    print(str(len(empty_groups)) + ' empty groups exist')
    while online_no_group_students_with_nick:
        print('Moving to next empty group')
        if empty_groups is None or not empty_groups:
            empty_group = await aux_create_group(ctx)
            print('Created new empty group')
        else:
            empty_group = empty_groups.pop(0)
            print('Reusing existing empty group')
        empty_group_num = hpf.get_lab_group_number(empty_group.name)
        print('Empty group number is ' + str(empty_group_num))
        for i in range(max_group_size):
            if not online_no_group_students_with_nick:
                break
            print('Adding member ' + str(i + 1) + ' to group ' +
                  str(empty_group_num))
            member = online_no_group_students_with_nick.pop(0)
            print('Left to assign ' +
                  str(len(online_no_group_students_with_nick)))
            await aux_join_group(ctx, member, empty_group_num)
            # avoid having a group with 1 if possible
            if (len(online_no_group_students_with_nick) == 2
                    and max_group_size - (i + 1) < 2):
                print('Skipping to ensure at least 2 members in each group')
                break

    print('Finished assignment')
Beispiel #11
0
async def aux_join_group(ctx,
                         member: discord.Member,
                         group: Union[int, str],
                         group_message: bool = True,
                         general_message: bool = True) -> bool:
    guild = ctx.guild
    new_role = hpf.get_lab_role(guild, group)
    new_lab_group = hpf.get_lab_group(guild, group)
    existing_lab_group = hpf.existing_member_lab_group(member)
    max_group_size = GUILD_CONFIG.max_students_per_group(guild)
    if GUILD_CONFIG.require_nickname(guild) and not member.nick:
        await ctx.send(btm.message_member_need_name_error(member))
    elif existing_lab_group:
        await ctx.send(
            btm.error_member_already_in_group(hpf.get_nick(member),
                                              existing_lab_group.name))
    elif not new_role:
        await ctx.send(btm.message_lab_group_not_exists(new_lab_group.name))
    elif not hpf.member_in_teaching_team(member, guild) and len(
            hpf.all_students_in_group(guild, group)) >= max_group_size:
        await ctx.send(
            btm.message_max_members_in_group_error(new_lab_group.name,
                                                   max_group_size))
    else:
        if not hpf.member_in_teaching_team(member, guild):
            group_num = hpf.get_lab_group_number(new_lab_group.name)
            async with invites_lock:
                invite_list = GUILD_CONFIG.group_invites(guild)
                invited = invite_list.has_invite(member.id, group_num)
                if is_closed_group(guild, new_lab_group) and not invited:
                    text_channel = hpf.get_lab_text_channel(guild, group)
                    if text_channel:
                        await text_channel.send(
                            btm.error_someone_try_to_enter(member))
                    await ctx.send(btm.error_lab_group_is_closed(new_lab_group)
                                   )
                    return False
                if invited:
                    invite_list.remove_invite(member.id, group_num)
                await join_group(guild,
                                 member,
                                 new_role,
                                 new_lab_group,
                                 group_message=group_message,
                                 general_message=general_message)
        else:
            await join_group(guild,
                             member,
                             new_role,
                             new_lab_group,
                             group_message=group_message,
                             general_message=general_message)
        # Remove other invitations
        async with invites_lock:
            invite_list = GUILD_CONFIG.group_invites(guild)
            old_invites = invite_list.retrieve_invites(member.id)
            for group_invite in old_invites:
                text_channel = hpf.get_lab_text_channel(guild, group_invite)
                await text_channel.send(
                    btm.info_member_accepted_another_invite(member))
        return True
    return False