Beispiel #1
0
 async def dmpartner(self, ctx: commands.Context, *, message: str):
     '''
     DM your Secret Santa partner anonymously (the person you have) via the bot
     '''
     if (self.SecretSantaHelper.channel_is_guild(ctx.channel)):
         await ctx.message.delete(
         )  # delete the message before people can see
     (curr_idx, curr_user) = self.SecretSantaHelper.get_participant_object(
         ctx.author.id, self.usr_list)
     if ((curr_idx != -1) and self.exchange_started
         ):  # user has joined and the exchange has started
         partner = self.bot.get_user(int(curr_user.partnerid))
         try:
             msg = "You have a message from your secret santa\n"
             msg += f"```{message}```"
             await partner.send(msg)
             BOT_ERROR.output_info(
                 f"{ctx.author.name}#{ctx.author.discriminator} DMd {partner.name}#{partner.discriminator}: {message}",
                 self.logger)
             return
         except Exception as e:
             BOT_ERROR.output_exception(e, self.logger)
             await ctx.author.send(
                 f"Failed to send message to {partner.name}#{partner.discriminator} about their partner. Harass them to turn on server DMs for Secret Santa stuff."
             )
     elif (curr_idx == -1):  # user has not joined
         msg = BOT_ERROR.UNJOINED
         await ctx.author.send(msg)
     elif (not self.exchange_started
           ):  # exchange hasn't started (there are no partners)
         msg = BOT_ERROR.NOT_STARTED
         await ctx.author.send(msg)
     else:
         await ctx.send(BOT_ERROR.UNDETERMINED_CONTACT_CODE_OWNER)
     return
Beispiel #2
0
 async def emote(self, ctx: commands.Context,
                 *emotes: discord.PartialEmoji):
     '''
     Get the URL to emotes without needing to open the link. Custom emotes only.
     '''
     for passed_emote in emotes:
         emote_url = str(passed_emote.url)
         emote_name = passed_emote.name
         emote_id = passed_emote.id
         img_type = "gif" if passed_emote.animated else "png"
         BOT_ERROR.output_info(
             f"Name={emote_name}, ID={emote_id}, IMG_TYPE={img_type}, url={emote_url}",
             self.logger)
         await ctx.send(content=emote_url)
     return
Beispiel #3
0
 async def dmsanta(self, ctx: commands.Context, *, message: str):
     '''
     DM your Secret Santa (the person that has you) via the bot
     '''
     if (self.SecretSantaHelper.channel_is_guild(ctx.channel)):
         await ctx.message.delete(
         )  # delete the message before people can see
     (santa_idx,
      santa_user) = self.SecretSantaHelper.get_participant_object(
          ctx.author.id, self.usr_list, id_is_partner=True)
     if ((santa_idx != -1) and self.exchange_started
         ):  # user has joined and the exchange has started
         santa = self.bot.get_user(int(santa_user.idstr))
         try:
             msg = "You have a message from your secret santa partner\n"
             msg += f"```{message}```"
             await santa.send(msg)
             BOT_ERROR.output_info(
                 f"{ctx.author.name}#{ctx.author.discriminator} DMd {santa.name}#{santa.discriminator}: {message}",
                 self.logger)
             author_msg = "Message sent to your Secret Santa\n"
             author_msg += f"```{message}```"
             await ctx.author.send(author_msg)
             return
         except Exception as e:
             BOT_ERROR.output_exception(e, self.logger)
             await ctx.author.send(
                 f"Failed to send the message to your secret santa. Their DMs may be off. Please ask your Secret Santa admin."
             )
     elif (santa_idx == -1):  # user has not joined
         msg = BOT_ERROR.UNJOINED
         await ctx.author.send(msg)
     elif (not self.exchange_started
           ):  # exchange hasn't started (there are no partners)
         msg = BOT_ERROR.NOT_STARTED
         await ctx.author.send(msg)
     else:
         await ctx.send(BOT_ERROR.UNDETERMINED_CONTACT_CODE_OWNER)
     return
Beispiel #4
0
    async def emote(self, ctx: commands.Context, *emotes: str):
        '''
        Get the URL to emotes without needing to open the link.
        '''
        http = urllib3.PoolManager()
        for passed_emote in emotes:
            # Create the base URL of the emote
            emote_parts = passed_emote.split(sep=":")
            (emote_name, emote_id) = (emote_parts[1], (emote_parts[2])[:-1])
            base_url = f"https://cdn.discordapp.com/emojis/{str(emote_id)}"

            # http request to find the appropriate extension
            response = http.urlopen('GET', url=base_url)
            img_type = response.info()['Content-Type']
            img_ext = img_type.split(sep="/")[1]
            http.clear()

            # output
            emote_url = f"{base_url}.{img_ext}"
            BOT_ERROR.output_info(
                f"Name={emote_name}, ID={emote_id}, IMG_TYPE={img_type}, url={emote_url}",
                self.logger)
            await ctx.send(content=emote_url)
        return
Beispiel #5
0
    async def start(self, ctx: commands.Context):
        '''
        Begin the Secret Santa
        '''
        currAuthor = ctx.author
        if (currAuthor.top_role == ctx.guild.roles[-1]):
            # first ensure all users have all info submitted
            all_fields_complete = True
            for user in self.usr_list:
                if (user.wishlisturl_is_set() and user.pref_is_set()):
                    pass
                else:
                    all_fields_complete = False
                    try:
                        await currAuthor.send(
                            BOT_ERROR.HAS_NOT_SUBMITTED(user.name))
                        await ctx.send(
                            "`Partner assignment cancelled: participant info incomplete.`"
                        )
                    except Exception as e:
                        BOT_ERROR.output_exception(e, self.logger)
                        await ctx.send(currAuthor.mention +
                                       BOT_ERROR.DM_FAILED)
                        BOT_ERROR.output_error(
                            currAuthor.mention + BOT_ERROR.DM_FAILED,
                            self.logger)

            # select a random partner for each participant if all information is complete and there are enough people to do it
            if (all_fields_complete and (len(self.usr_list) > 1)):
                BOT_ERROR.output_info("Proposing a partner list", self.logger)
                potential_list = self.SecretSantaHelper.propose_partner_list(
                    self.usr_list)
                while (not self.SecretSantaHelper.partners_are_valid(
                        potential_list)):
                    BOT_ERROR.output_info("Proposing a partner list",
                                          self.logger)
                    potential_list = self.SecretSantaHelper.propose_partner_list(
                        self.usr_list)
                # save to config file
                BOT_ERROR.output_info("Partner assignment successful",
                                      self.logger)
                for user in potential_list:
                    (temp_index, temp_user
                     ) = self.SecretSantaHelper.get_participant_object(
                         int(user.idstr),
                         self.usr_list)  # get the user's object in usr_list
                    (index,
                     partner) = self.SecretSantaHelper.get_participant_object(
                         int(user.partnerid),
                         self.usr_list)  # get their partner
                    temp_user.partnerid = user.partnerid
                    self.config['members'][str(user.usrnum)][
                        SecretSantaConstants.PARTNERID] = user.partnerid
                    self.config.write()
                    # tell participants who their partner is
                    this_user = ctx.guild.get_member(int(user.idstr))
                    message_pt1 = f"{str(partner.name)}#{str(partner.discriminator)} is your Secret Santa partner! Mosey on over to their wishlist URL(s) and pick out a gift! Remember to keep it in the ${CONFIG.min_budget}-{CONFIG.max_budget} range.\n"
                    message_pt2 = f"Their wishlist(s) can be found here: {partner.wishlisturl}\n"
                    message_pt3 = f"And their gift preferences can be found here: {partner.preferences}\n"
                    message_pt4 = f"If you have trouble accessing your partner's wishlist, try `{CONFIG.prefix}dmpartner` or contact an admin to get in touch with them. This is a *secret* santa, after all!"
                    santa_message = message_pt1 + message_pt2 + message_pt3 + message_pt4
                    try:
                        await this_user.send(santa_message)
                    except Exception as e:
                        BOT_ERROR.output_exception(e, self.logger)
                        await currAuthor.send(
                            f"Failed to send message to {this_user.name}#{this_user.discriminator} about their partner. Ask them to turn on server DMs for Secret Santa stuff."
                        )

                # mark the exchange as in-progress
                self.exchange_started = True
                self.is_paused = False
                self.config['programData']['exchange_started'] = True
                self.config.write()
                usr_list = copy.deepcopy(potential_list)
                await ctx.send(
                    "Secret Santa pairs have been picked! Check your PMs and remember not to let your partner know. Have fun!"
                )
            elif not all_fields_complete:
                await ctx.send(currAuthor.mention +
                               BOT_ERROR.SIGNUPS_INCOMPLETE)
            elif not (len(self.usr_list) > 1):
                await ctx.send(BOT_ERROR.NOT_ENOUGH_SIGNUPS)
            else:
                await ctx.send(BOT_ERROR.UNREACHABLE)
        else:
            await ctx.send(BOT_ERROR.NO_PERMISSION(ctx.guild.roles[-1]))
        return
    async def manage_reactions(self, payload: discord.RawReactionActionEvent):
        if (self.role_channel == None):  # if no role channel assigned,
            self.role_channel = self.bot.get_channel(CONFIG.role_channel) if (
                CONFIG.role_channel != -1
            ) else None  # attempt to get role channel
            if (
                    self.role_channel == None
            ):  # if that fails (CONFIG.role_channel == -1 or get_channel fails)
                BOT_ERROR.output_error(BOT_ERROR.REACTION_ROLE_UNASSIGNED,
                                       self.logger)
                return  # end command
            else:
                pass  # reassignment of role_channel worked
        else:
            pass  # role_channel is assigned

        message_id = payload.message_id
        channel_id = payload.channel_id
        emoji = payload.emoji
        emoji_str = str(payload.emoji)
        guild = self.bot.get_guild(payload.guild_id)
        user = guild.get_member(payload.user_id)

        if channel_id == self.role_channel.id:
            message = None
            async for message in self.role_channel.history(limit=200):
                if message.id == message_id:
                    break

            if message != None:
                content = message.content.split("\n")
                for line in content:
                    if ((line[0:2] == "~~") and (line[-1] == "~")
                        ):  # don't pay attention to lines that are crossed out
                        continue
                    line_tokens = [
                        i for i in line.split(" ") if i
                    ]  # remove empty strings for quality of life (doesn't break with extra spaces)
                    test_emote_idx = for_idx = test_role_id_idx = -1
                    try:
                        for_idx = line_tokens.index("for")
                        test_emote_idx, test_role_id_idx = for_idx - 1, for_idx + 1
                    except:
                        for_idx = -1
                    if (for_idx !=
                            -1):  # no 'for' or 'for' is in the wrong place
                        test_emote = line_tokens[test_emote_idx]
                        test_role_id = int(line_tokens[test_role_id_idx][3:-1])
                        BOT_ERROR.output_info(
                            f"Test emote={test_emote.encode('raw_unicode_escape')}, Input emote={emoji_str.encode('raw_unicode_escape')}",
                            self.logger)
                        found_emoji = False
                        if emoji.is_unicode_emoji():
                            found_emoji = (emoji_str == test_emote)
                        else:
                            found_emoji = (emoji_str[1:-1] in test_emote)
                        if found_emoji:
                            role = guild.get_role(test_role_id)
                            BOT_ERROR.output_info(
                                f"Role added/removed=@{role.name}, user={user.name}",
                                self.logger)
                            if payload.event_type == "REACTION_ADD":
                                await user.add_roles(role)
                            else:
                                await user.remove_roles(role)
                            return
Beispiel #7
0
 async def echo(self, ctx: commands.Context, *, content: str):
     '''
     [content] = echos back the [content]
     '''
     BOT_ERROR.output_info(content, self.logger)
     await ctx.send(content)