Beispiel #1
0
 async def partnerinfo(self, ctx: commands.Context):
     '''
     Get your partner information via DM (partner name, wishlist, gift preference)
     '''
     currAuthor = ctx.author
     authorIsParticipant = self.SecretSantaHelper.user_is_participant(
         currAuthor.id, self.usr_list)
     if (self.exchange_started and authorIsParticipant):
         (usr_index, user) = self.SecretSantaHelper.get_participant_object(
             currAuthor.id, self.usr_list)
         (partner_index,
          partnerobj) = self.SecretSantaHelper.get_participant_object(
              user.partnerid, self.usr_list)
         msg = "Your partner is " + partnerobj.name + "#" + partnerobj.discriminator + "\n"
         msg = msg + "Their wishlist(s) can be found here: " + partnerobj.wishlisturl + "\n"
         msg = msg + "And their gift preferences can be found here: " + partnerobj.preferences + "\n"
         msg = msg + "If you have trouble accessing your partner's wishlist, please contact an admin to get in touch with your partner. This is a *Secret* Santa, after all!"
         try:
             await currAuthor.send(msg)
             await ctx.send("The information has been sent to your DMs.")
         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)
     elif ((not self.exchange_started) and authorIsParticipant):
         await ctx.send(BOT_ERROR.NOT_STARTED)
     elif (self.exchange_started and (not authorIsParticipant)):
         await ctx.send(BOT_ERROR.EXCHANGE_STARTED_UNJOINED)
     elif ((not self.exchange_started) and (not authorIsParticipant)):
         await ctx.send(BOT_ERROR.UNJOINED)
     else:
         await ctx.send(BOT_ERROR.UNREACHABLE)
     return
Beispiel #2
0
 async def setwishlisturl(self, ctx: commands.Context, *destination: str):
     '''
     [Any number of wishlist URLs or mailing addresses] = set wishlist destinations or mailing address. Surround mailing address with quotation marks and separate EACH wishlist destination with a space (eg. amazonurl/123 "Sesame Street" http://rightstufanime.com/).
     '''
     currAuthor = ctx.author
     if self.SecretSantaHelper.user_is_participant(currAuthor.id,
                                                   self.usr_list):
         if (self.SecretSantaHelper.channel_is_guild(ctx.channel)):
             await ctx.message.delete(
             )  # delete the message before people can see
         (index, user) = self.SecretSantaHelper.get_participant_object(
             currAuthor.id, self.usr_list)
         new_wishlist = "None"
         if (len(destination) == 0):
             pass
         else:
             new_wishlist = " | ".join(destination)
         try:
             # save to config file
             self.config['members'][str(user.usrnum)][
                 SecretSantaConstants.WISHLISTURL] = new_wishlist
             self.config.write()
             # add the input to the value in the user's class instance
             user.wishlisturl = new_wishlist
             try:
                 await currAuthor.send(
                     f"New wishlist URL(s): {new_wishlist}")
                 if (not user.pref_is_set()):
                     userPrompt = f"Great! Now please specify what your preferences for your wishlist might be. Use `{CONFIG.prefix}setprefs [preferences separated by a space]` (e.g. `{CONFIG.prefix}setprefs hippopotamus \"stuffed rabbit\" dog`). Defaults to N/A if not entered."
                     await currAuthor.send(userPrompt)
                 if (user.wishlisturl_is_set() and user.pref_is_set()):
                     signup_complete_msg = f"Congrats, you're now officially enrolled in the Secret Santa! You may change your wishlist URL or preferences with `{CONFIG.prefix}setwishlisturl` or `{CONFIG.prefix}setprefs` any time before the admin begins the Secret Santa."
                     await currAuthor.send(signup_complete_msg)
             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)
         except Exception as e:
             BOT_ERROR.output_exception(e, self.logger)
             try:
                 await currAuthor.send(BOT_ERROR.INVALID_INPUT)
             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)
     else:
         await ctx.send(BOT_ERROR.UNJOINED)
     return
Beispiel #3
0
 async def setprefs(self, ctx: commands.Context, *preferences: str):
     '''
     Set new preferences
     '''
     currAuthor = ctx.author
     if self.SecretSantaHelper.user_is_participant(currAuthor.id,
                                                   self.usr_list):
         if (self.SecretSantaHelper.channel_is_guild(ctx.channel)):
             await ctx.message.delete(
             )  # delete the message before people can see
         (index, user) = self.SecretSantaHelper.get_participant_object(
             currAuthor.id, self.usr_list)
         new_prefs = "None"
         if (len(preferences) == 0):
             pass
         else:
             new_prefs = " | ".join(preferences)
         try:
             #save to config file
             self.config['members'][str(user.usrnum)][
                 SecretSantaConstants.PREFERENCES] = str(new_prefs)
             self.config.write()
             #add the input to the value in the user's class instance
             user.preferences = new_prefs
             try:
                 await currAuthor.send(f"New preferences: {new_prefs}")
                 if (not user.wishlisturl_is_set()):
                     userPrompt = f"Great! Now please specify what your wishlist URL or mailing address. Use `{CONFIG.prefix}setwishlisturl [wishlist urls separated by a space]` (e.g. `{CONFIG.prefix}setwishlisturl amazonurl/123 \"sesame street\"`) to set your wishlist URL."
                     await currAuthor.send(userPrompt)
                 if (user.wishlisturl_is_set() and user.pref_is_set()):
                     signup_complete_msg = f"Congrats, you're now officially enrolled in the Secret Santa! You may change your wishlist URL or preferences with `{CONFIG.prefix}setwishlisturl` or `{CONFIG.prefix}setprefs` any time before the admin begins the Secret Santa."
                     await currAuthor.send(signup_complete_msg)
             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)
         except Exception as e:
             BOT_ERROR.output_exception(e, self.logger)
             try:
                 await currAuthor.send(BOT_ERROR.INVALID_INPUT)
             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)
     else:
         await ctx.send(BOT_ERROR.UNJOINED)
     return
Beispiel #4
0
 async def restart(self, ctx: commands.Context):
     '''
     Restart the Secret Santa after pause
     '''
     currAuthor = ctx.author
     is_paused = True
     if ((currAuthor.top_role == ctx.guild.roles[-1]) and is_paused):
         # 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)
         list_changed = self.SecretSantaHelper.usr_list_changed_during_pause(
             self.usr_list, self.user_left_during_pause)
         if (list_changed):
             ctx.send(
                 f"User list changed during the pause. Partners must be picked again with `{CONFIG.prefix}start`."
             )
         else:
             self.exchange_started = True
             is_paused = False
             self.config['programData']['exchange_started'] = True
             self.config.write()
             await ctx.send(
                 "No change was made during the pause. Secret Santa resumed with the same partners."
             )
     elif (currAuthor.top_role != ctx.guild.roles[-1]):
         await ctx.send(BOT_ERROR.NO_PERMISSION(ctx.guild.roles[-1]))
     elif (not is_paused):
         await ctx.send(BOT_ERROR.NOT_PAUSED)
     else:
         await ctx.send(BOT_ERROR.UNREACHABLE)
     return
Beispiel #5
0
    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
        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:
                    line_tokens = line.split(" ")
                    line_tokens = [
                        i for i in line_tokens if i
                    ]  # remove empty strings for quality of life (doesn't break with extra spaces)
                    for (idx, token) in enumerate(line_tokens):
                        if token == "for" and idx > 0 and line_tokens[
                                idx - 1] == str(emoji):
                            role_id = line_tokens[idx + 1][3:-1]
                            role = guild.get_role(int(role_id))
                            if payload.event_type == "REACTION_ADD":
                                await user.add_roles(role)
                            else:
                                await user.remove_roles(role)
                            return
Beispiel #6
0
 async def getprefs(self, ctx: commands.Context):
     '''
     Get current preferences
     '''
     currAuthor = ctx.author
     if self.SecretSantaHelper.user_is_participant(ctx.author.id,
                                                   self.usr_list):
         (index, user) = self.SecretSantaHelper.get_participant_object(
             ctx.author.id, self.usr_list)
         try:
             await currAuthor.send(
                 f"Current preference(s): {user.preferences}")
         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)
     else:
         await ctx.send(BOT_ERROR.UNJOINED)
     return
Beispiel #7
0
    async def join(self, ctx: commands.Context):
        '''
        Join Secret Santa if it has not started. Contact the Secret Santa admin if you wish to join.
        '''
        currAuthor = ctx.author
        # check if the exchange has already started
        if self.SecretSantaHelper.user_is_participant(currAuthor.id,
                                                      self.usr_list):
            await ctx.send(BOT_ERROR.ALREADY_JOINED)
        else:
            # initialize instance of Participant for the author
            self.highest_key = self.highest_key + 1
            self.usr_list.append(
                SecretSantaParticipant(currAuthor.name,
                                       currAuthor.discriminator, currAuthor.id,
                                       self.highest_key))
            # write details of the class instance to config and increment total_users
            self.config['members'][str(self.highest_key)] = [
                currAuthor.name, currAuthor.discriminator, currAuthor.id,
                self.highest_key, "", "N/A", ""
            ]
            self.config.write()

            # prompt user about inputting info
            await ctx.send(
                currAuthor.mention +
                f" has been added to the {str(ctx.guild)} Secret Santa exchange!"
                + "\nMore instructions have been DMd to you.")
            try:
                userPrompt = f"Welcome to the __{str(ctx.guild)}__ Secret Santa! To complete your enrollment you'll need to input your wishlist URL and preferences (by DMing this bot) so your Secret Santa can send you something\n"
                await currAuthor.send(userPrompt)
                userPrompt = f".\nFirst we need your wishlist (or the destination for sending gifts). Please use `{CONFIG.prefix}setwishlisturl [wishlist urls separated by a space]` (e.g. `{CONFIG.prefix}setwishlisturl amazonurl/123 \"sesame street\"`) to set your wishlist URL (you may also add your mailing address)."
                await currAuthor.send(userPrompt)
            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)
        return
Beispiel #8
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