async def aux_go_for_help_from_command(ctx, member: discord.Member) -> bool: await aux_leave_group(ctx, member, show_not_in_group_error=False) # Get next group guild = member.guild async with help_queue_lock: group, message_id = GUILD_CONFIG.help_queue(guild).next() if not group: return False # If group found general_text_channel = hpf.get_general_text_channel(guild) try: message = await general_text_channel.fetch_message(message_id) await message.add_reaction(get_unicode_emoji_from_alias('thumbsup')) except discord.NotFound: pass if general_text_channel: await general_text_channel.send( btm.info_on_the_way_to(member, hpf.get_lab_group_name(group))) # Go for help group_text_channel = hpf.get_lab_text_channel(guild, group) if group_text_channel: await group_text_channel.send( btm.message_help_on_the_way(member, show_mention=True)) await aux_join_group(ctx, member, group, group_message=False) return True
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))
async def leave_group(guild: discord.Guild, member: discord.Member, existing_lab_role: discord.Role, existing_lab_group: discord.CategoryChannel, group_message: bool = True, general_message: bool = True): # Disconnect from the group voice channel if connected to it voice_channel = hpf.existing_member_lab_voice_channel(member) if voice_channel and member.voice and member.voice.channel == voice_channel: general_voice_channel = hpf.get_general_voice_channel(guild) # if no general_voice_channel, it will move user out of the current voice channel await member.move_to(general_voice_channel if hpf. member_in_teaching_team(member, guild) else None) # Message to group text channel text_channel = hpf.existing_member_lab_text_channel(member) if group_message and text_channel: await text_channel.send( btm.message_member_left_group(hpf.get_nick(member), existing_lab_group.name)) # Remove group role await member.remove_roles(existing_lab_role) print(f'Role "{existing_lab_role}" removed to {member}') # Message to general channel general_text_channel = hpf.get_general_text_channel(guild) if general_message and general_text_channel and not hpf.member_in_teaching_team( member, guild): await general_text_channel.send( btm.message_member_left_group(hpf.get_nick(member), existing_lab_group.name))
async def join_group(guild: discord.Guild, member: discord.Member, new_role: discord.Role, new_lab_group: discord.CategoryChannel, group_message: bool = True, general_message: bool = True): await member.add_roles(new_role) print(f'Role "{new_role}" assigned to {member}') # Move to voice channel if connected voice_channel = hpf.get_lab_voice_channel(guild, new_lab_group.name) if voice_channel and member.voice and member.voice.channel: await member.move_to(voice_channel) # Message to group text channel text_channel = hpf.get_lab_text_channel(guild, new_lab_group.name) if group_message and text_channel: await text_channel.send( btm.message_mention_member_when_join_group(member, new_lab_group.name)) # Message to general channel general_text_channel = hpf.get_general_text_channel(guild) if general_message and general_text_channel and not hpf.member_in_teaching_team( member, guild): await general_text_channel.send( btm.message_member_joined_group(hpf.get_nick(member), new_lab_group.name))
async def aux_leave_group(ctx, member: discord.Member, group_message: bool = True, general_message: bool = True, show_open_message: bool = True, show_not_in_group_error: bool = True): guild = ctx.guild existing_lab_role = hpf.existing_member_lab_role(member) if existing_lab_role: existing_lab_group = hpf.existing_member_lab_group(member) await leave_group(guild, member, existing_lab_role, existing_lab_group, group_message=group_message, general_message=general_message) # If group get empty, open it if len(hpf.all_students_in_group(guild, existing_lab_group.name)) < 1 \ and is_closed_group(guild, existing_lab_group) \ and not hpf.member_in_teaching_team(member, guild): await open_group(guild, existing_lab_group) if show_open_message: general_text_channel = hpf.get_general_text_channel(guild) await general_text_channel.send( btm.success_group_open(existing_lab_group)) elif show_not_in_group_error: await ctx.send(btm.message_member_not_in_any_group(member))
async def aux_delete_group(ctx, group: Union[int, str], show_bot_message: bool = True): async with create_delete_lock: guild = ctx.guild category = hpf.get_lab_group(guild, group) role = hpf.get_lab_role(guild, group) success = False if category: channels = category.channels for group_member in (role.members if role else []): await aux_leave_group(ctx, group_member, show_not_in_group_error=False) for channel in channels: print(f'Deleting channel: {channel.name}') await channel.delete() print(f'Deleting category: {category.name}') await category.delete() await aux_remove_group(guild, category) success = True elif show_bot_message: await ctx.send(btm.message_group_not_exists_error(category.name)) if role: print(f'Deleting role: {role.name}') await role.delete() if success and show_bot_message: general_text_channel = hpf.get_general_text_channel(guild) if general_text_channel: await general_text_channel.send( btm.message_group_deleted(category.name))
async def save_all_task(): await bot.wait_until_ready() guild = bot.get_guild(int(TEST_GUILD_ID)) general_text_channel = hpf.get_general_text_channel(guild) sleep_time = timedelta(hours=12, minutes=0, seconds=0) while True: await GUILD_CONFIG.save_all() now = datetime.now() await general_text_channel.send( f"Last config snapshot at {now.strftime('%H:%M:%S %Z on %d %b %Y')}" ) await asyncio.sleep(sleep_time.seconds)
async def aux_broadcast(ctx, message: str): guild = ctx.guild general_text_channel = hpf.get_general_text_channel(guild) if general_text_channel: await general_text_channel.send( btm.broadcast_message_from(ctx.author, message)) for group in hpf.all_existing_lab_groups(guild): text_channel = hpf.get_lab_text_channel(guild, group.name) if GUILD_CONFIG.broadcast_to_empty_groups(guild) or len( hpf.all_students_in_group(guild, group.name)) > 0: await text_channel.send( btm.broadcast_message_from(ctx.author, message))
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())
async def aux_close_group(ctx, group: Optional[discord.CategoryChannel]): guild = ctx.guild member_group = hpf.existing_member_lab_group(ctx.author) is_in_teaching_team = hpf.member_in_teaching_team(ctx.author, guild) if not member_group and not is_in_teaching_team: await ctx.send(btm.message_member_not_in_any_group(ctx.author)) elif group and (not (is_in_teaching_team or group == member_group)): await ctx.send( btm.error_member_not_part_of_group( ctx.author, group if group else member_group)) else: group_to_be_closed = group if group else member_group await close_group(guild, group_to_be_closed) general_text_channel = hpf.get_general_text_channel(guild) if general_text_channel: await general_text_channel.send( btm.success_group_closed(group_to_be_closed)) print("OPEN_GROUPS", GUILD_CONFIG.open_groups(guild)) print("CLOSED_GROUPS", GUILD_CONFIG.closed_groups(guild))
async def aux_create_group(ctx) -> Optional[discord.CategoryChannel]: async with create_delete_lock: # Get existing lab groups guild = ctx.guild existing_lab_groups = hpf.all_existing_lab_groups(guild) # Get new group number (assumes a previous lab group could have been deleted) next_num = 1 for idx, category in enumerate( sorted(existing_lab_groups, key=lambda c: c.name), 2): pattern = re.compile(f"Group[\s]+{next_num}") if re.search(pattern, category.name) is None: break next_num = idx # Create new names new_category_name = hpf.get_lab_group_name(next_num) new_role_name = hpf.get_role_name(next_num) text_channel_name = hpf.get_text_channel_name(next_num) voice_channel_name = hpf.get_voice_channel_name(next_num) # Check if category or channels already exist existing_category = discord.utils.get(guild.categories, name=new_category_name) existing_text_channel = discord.utils.get(guild.channels, name=text_channel_name) existing_voice_channel = discord.utils.get(guild.channels, name=voice_channel_name) if not (existing_category or existing_text_channel or existing_voice_channel): try: # Create new role new_role = await create_new_role(guild, new_role_name, mentionable=True) # Set lab group permissions default = discord.Permissions() allow_text_voice_stream = discord.Permissions( PMask.VIEW | PMask.PARTIAL_TEXT | PMask.PARTIAL_VOICE | PMask.STREAM) can_not_view_channel = discord.Permissions(PMask.VIEW) overwrites = { role: discord.PermissionOverwrite.from_pair( default, can_not_view_channel) for role in hpf.all_existing_lab_roles(guild) } student_role = discord.utils.get(guild.roles, name=STUDENT_ROLE_NAME) if student_role: overwrites[ student_role] = discord.PermissionOverwrite.from_pair( default, can_not_view_channel) overwrites[new_role] = discord.PermissionOverwrite.from_pair( allow_text_voice_stream, default) # Create new lab group print(f'Creating a new category: {new_category_name}') new_category = await guild.create_category_channel( new_category_name, overwrites=overwrites) # Deny access to the lab groups created before await update_previous_lab_groups_permission( new_role, new_category, deny_mask=PMask.VIEW) # Create new text and voice channels print( f'Creating a new channels: ({text_channel_name}) and ({voice_channel_name})' ) text_channel = await new_category.create_text_channel( text_channel_name) await new_category.create_voice_channel(voice_channel_name) # Success message general_text_channel = hpf.get_general_text_channel(guild) if general_text_channel: await general_text_channel.send( btm.message_group_created(new_category_name, next_num)) await text_channel.send( btm.message_welcome_group(new_category_name)) await open_group(guild, new_category) return new_category except Exception as e: print(e) await ctx.send(btm.message_unexpected_error("create-group")) await aux_delete_group(ctx, next_num, show_bot_message=False) raise e