示例#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
示例#2
0
 async def dm_error(self, ctx: commands.Context, error):
     if (isinstance(error, commands.NoPrivateMessage)):
         await ctx.send(BOT_ERROR.DM_ERROR)
     else:
         BOT_ERROR.output_exception(error, self.logger)
         await ctx.send(BOT_ERROR.UNDETERMINED_CONTACT_CODE_OWNER)
     return
示例#3
0
    def __countdown_cmd_change(self, ctx: commands.Context, cd_name: str,
                               cd_time: str):
        result_str = ""
        try:
            pend_test_convert = pendulum.from_format(
                cd_time, self.pend_format)  # check that the format is correct
        except ValueError as error:
            expected = "ERROR: inputted time does not match expected format `month/day/year @ hour:minute AM/PM UTC_offset`\n"
            result_str = expected + " ex. `5/17/20 @ 1:00 PM -06:00`"
            BOT_ERROR.output_debug(result_str, self.logger)
            return result_str

        query_get_timer_by_name = f"SELECT * FROM {self.__get_cd_table_name(ctx.guild.id)} WHERE name=\'{cd_name}\';"
        query_result = self.sqlhelp.execute_read_query(query_get_timer_by_name)
        if (query_result != None):
            if (len(query_result) > 0):
                (query_id, query_name, query_time,
                 query_user_id) = query_result[0]
                if (ctx.author.id == query_user_id):
                    if (self.sqlhelp.execute_update_query(
                            self.__get_cd_table_name(ctx.guild.id),
                            f"time=\'{cd_time}\'", f"id={query_id}")):
                        diff_str = self.__find_pend_diff_str(pend_test_convert)
                        result_str = f"Updated countdown for {cd_name}. Now set for {diff_str}"
                    else:
                        result_str = BOT_ERROR.INVALID_COUNTDOWN_NAME(cd_name)
                else:
                    cd_owner = ctx.guild.get_member(query_user_id)
                    result_str = BOT_ERROR.CANNOT_CHANGE_COUNTDOWN(
                        cd_owner.name)
        else:
            result_str = BOT_ERROR.INVALID_COUNTDOWN_NAME(cd_name)

        return result_str
示例#4
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
示例#5
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
示例#6
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
示例#7
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
示例#8
0
    def run_countdown_command(self, ctx: commands.Context, cd_command: str,
                              cd_name: str, cd_time: str):
        output = self.__find_countdown_hints(cd_command, cd_name, cd_time)
        if (output == ""):  # no hints were needed
            if (not self.sqlhelp.if_table_exists(
                    self.__get_cd_table_name(ctx.guild.id))
                ):  # make sure table exists before executing the CD command
                self.sqlhelp.create_table(
                    self.__get_cd_table_name(ctx.guild.id),
                    "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, time TEXT NOT NULL, user_id INTEGER NOT NULL, UNIQUE(name))"
                )

            if (cd_command == "set"):
                output = self.__countdown_cmd_set(ctx, cd_name, cd_time)
            elif (cd_command == "change"):
                output = self.__countdown_cmd_change(ctx, cd_name, cd_time)
            elif (cd_command == "check"):
                output = self.__countdown_cmd_check(ctx, cd_name)
            elif (cd_command == "remove"):
                output = self.__countdown_cmd_remove(ctx, cd_name)
            elif (cd_command == "list"):
                output = self.__countdown_cmd_list(ctx)
            elif (cd_command == "clean"):
                output = self.__countdown_cmd_clean(ctx)
            else:
                output = BOT_ERROR.INVALID_COUNTDOWN_COMMAND(cd_command)
                output += "\nCountdown options/sub-commands: `set`, `change`, `check` , `remove`, `list`, `clean`."

        return output
示例#9
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
示例#10
0
 async def pin_archive_error(self, error, ctx):
     if isinstance(error, MissingPermissions):
         text = BOT_ERROR.NO_PERMISSION("mod")
         await ctx.send(content=text)
     elif isinstance(error, MissingRequiredArgument):
         await ctx.send(content=BOT_ERROR.MISSING_ARGUMENTS)
     elif isinstance(error, commands.CommandError):
         await ctx.send(content=error)
     else:
         await ctx.send(content=BOT_ERROR.UNDETERMINED_CONTACT_CODE_OWNER)
示例#11
0
 def __countdown_cmd_remove(self, ctx: commands.Context, cd_name: str):
     result_str = ""
     query_get_timer_by_name = f"SELECT * FROM {self.__get_cd_table_name(ctx.guild.id)} WHERE name=\'{cd_name}\';"
     query_result = self.sqlhelp.execute_read_query(query_get_timer_by_name)
     if (query_result != None):
         (query_id, query_name, query_time, query_user_id) = query_result[0]
         if (query_user_id == ctx.author.id):
             if (self.sqlhelp.execute_delete_query(
                     self.__get_cd_table_name(ctx.guild.id),
                     f"id={query_id}")):
                 result_str = f"Countdown timer `{query_name}` removed."
             else:
                 result_str = BOT_ERROR.INVALID_COUNTDOWN_NAME(cd_name)
         else:
             cd_owner = ctx.guild.get_member(query_user_id)
             result_str = BOT_ERROR.CANNOT_CHANGE_COUNTDOWN(cd_owner.name)
     else:
         result_str = BOT_ERROR.INVALID_COUNTDOWN_NAME(cd_name)
     return result_str
示例#12
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
示例#13
0
 def __countdown_cmd_set(self, ctx: commands.Context, cd_name: str,
                         cd_time: str):
     result_str = ""
     try:
         pend_test_convert = pendulum.from_format(
             cd_time, self.pend_format)  # check that the format is correct
         if (self.sqlhelp.insert_records(
                 self.__get_cd_table_name(ctx.guild.id),
                 "(name, time, user_id)",
             [f"('{cd_name}', '{cd_time}', {ctx.author.id})"])):
             diff_str = self.__find_pend_diff_str(pend_test_convert)
             result_str = f"{cd_name} countdown set for {cd_time} ({diff_str})"
         else:
             result_str = BOT_ERROR.COUNTDOWN_NAME_TAKEN
     except ValueError as error:
         expected = "ERROR: inputted time does not match expected format `month/day/year @ hour:minute AM/PM UTC_offset`\n"
         result_str = expected + "ex. `5/17/20 @ 1:00 PM -06:00`"
         BOT_ERROR.output_debug(result_str, self.logger)
     finally:
         return result_str
示例#14
0
 def __countdown_cmd_check(self, ctx: commands.Context, cd_name: str):
     result_str = ""
     query_get_timer_by_name = f"SELECT * FROM {self.__get_cd_table_name(ctx.guild.id)} WHERE name=\'{cd_name}\';"
     query_result = self.sqlhelp.execute_read_query(query_get_timer_by_name)
     if (query_result != None):
         (query_id, query_name, query_time, query_user_id) = query_result[0]
         cd_pend = pendulum.from_format(query_time, self.pend_format)
         diff_str = self.__find_pend_diff_str(cd_pend)
         result_str = f"Time until {cd_name}: {diff_str}"
     else:
         result_str = BOT_ERROR.INVALID_COUNTDOWN_NAME(cd_name)
     return result_str
示例#15
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
示例#16
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
示例#17
0
 async def pause(self, ctx: commands.Context):
     '''
     Pause for people that want to join last-minute (reshuffles and matches upon restart)
     '''
     if (ctx.author.top_role == ctx.guild.roles[-1]):
         self.exchange_started = False
         self.config['programData']['exchange_started'] = False
         self.config.write()
         self.is_paused = True
         await ctx.send(
             "Secret Santa has been paused. New people may now join.")
     else:
         await ctx.send(BOT_ERROR.NO_PERMISSION(ctx.guild.roles[-1]))
     return
示例#18
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
示例#19
0
 async def end(self, ctx: commands.Context):
     '''
     End the Secret Santa
     '''
     if (ctx.author.top_role == ctx.guild.roles[-1]):
         self.exchange_started = False
         self.is_paused = False
         self.config['programData']['exchange_started'] = False
         self.highest_key = 0
         del self.usr_list[:]
         self.config['members'].clear()
         self.config.write()
         await ctx.send("Secret Santa ended")
     else:
         await ctx.send(BOT_ERROR.NO_PERMISSION(ctx.guild.roles[-1]))
     return
示例#20
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
示例#21
0
    async def archive_pins(self, ctx: commands.Context,
                           channel_to_archive: discord.TextChannel,
                           channel_to_message: discord.TextChannel):
        '''
        Archive the pins in one channel to another channel as messages

        ex. `s!archive_pins #general #archive`
        '''

        start_message = f"Attempting to archive pinned messages from {channel_to_archive.mention} to {channel_to_message.mention}"
        await ctx.send(content=start_message)

        pins_to_archive = await channel_to_archive.pins()
        pins_to_archive.reverse()

        for pin in pins_to_archive:
            attachments = pin.attachments
            attachment_str = ""
            for attachment in attachments:
                attachment_str += f"{attachment.url}\n"  # add link to attachments

            pin_author = pin.author.name
            pin_pendulum = pendulum.instance(pin.created_at)
            pin_dt_str = pin_pendulum.format("MMMM DD, YYYY")

            pin_url = pin.jump_url
            pin_content = pin.content
            output_str = f"-**(from `{pin_author}` on {pin_dt_str})** {pin_content}\n"
            output_str += f"Message link: <{pin_url}>\n"
            output_str += f"Attachment links: {attachment_str}"
            if len(output_str) > 2000:
                await ctx.send(content=BOT_ERROR.ARCHIVE_ERROR_LENGTH(pin_url))
            else:
                await channel_to_message.send(content=output_str)

        end_message = f"Pinned message are archived in {channel_to_message.mention}. If the archive messages look good, use **{CONFIG.prefix}unpin_all** to remove the pins in {channel_to_archive.mention}"
        await ctx.send(content=end_message)
示例#22
0
    async def leave(self, ctx: commands.Context):
        '''
        Leave the Secret Santa
        '''
        if (self.exchange_started):
            await ctx.send(BOT_ERROR.EXCHANGE_IN_PROGRESS_LEAVE("a mod"))
            return

        currAuthor = ctx.author
        if (self.SecretSantaHelper.user_is_participant(currAuthor.id,
                                                       self.usr_list)):
            (index, user) = self.SecretSantaHelper.get_participant_object(
                currAuthor.id, self.usr_list)
            self.usr_list.remove(user)
            popped_user = self.config['members'].pop(str(user.usrnum))
            self.config.write()
            if (self.is_paused):
                self.user_left_during_pause = True
            await ctx.send(
                currAuthor.mention +
                f" has left the {str(ctx.guild)} Secret Santa exchange")
        else:
            await ctx.send(BOT_ERROR.UNJOINED)
        return
示例#23
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)
示例#24
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
        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
示例#25
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