diff --git a/DiscordBot/bot.py b/DiscordBot/bot.py index ec5dddb6..641c3cf2 100644 --- a/DiscordBot/bot.py +++ b/DiscordBot/bot.py @@ -128,4 +128,4 @@ def code_format(self, text): client = ModBot() -client.run(discord_token) \ No newline at end of file +client.run(discord_token) diff --git a/DiscordBot/report.py b/DiscordBot/report.py index d2bba994..25ed8c29 100644 --- a/DiscordBot/report.py +++ b/DiscordBot/report.py @@ -8,6 +8,20 @@ class State(Enum): MESSAGE_IDENTIFIED = auto() REPORT_COMPLETE = auto() +class Reason(Enum): + SPAM = auto() + HARASSMENT = auto() + DOXING = auto() + REPORT_OTHER = auto() + OTHER = auto() + UNKNOWN = auto() + +class DoxingSubReason(Enum): + SENSITIVE_INFO = auto() + THREATENING_LEAK = auto() + EXPOSING_INFO = auto() + UNKNOWN = auto() + class Report: START_KEYWORD = "report" CANCEL_KEYWORD = "cancel" @@ -17,14 +31,14 @@ def __init__(self, client): self.state = State.REPORT_START self.client = client self.message = None - - async def handle_message(self, message): - ''' - This function makes up the meat of the user-side reporting flow. It defines how we transition between states and what - prompts to offer at each of those states. You're welcome to change anything you want; this skeleton is just here to - get you started and give you a model for working with Discord. - ''' + self.reason = Reason.UNKNOWN + self.doxing_subreason = DoxingSubReason.UNKNOWN + self.imminent_danger = None + self.askToBlock = False + self.isBlocked = None + self.userID = None + async def handle_message(self, message): if message.content == self.CANCEL_KEYWORD: self.state = State.REPORT_COMPLETE return ["Report cancelled."] @@ -38,7 +52,6 @@ async def handle_message(self, message): return [reply] if self.state == State.AWAITING_MESSAGE: - # Parse out the three ID strings from the message link m = re.search('/(\d+)/(\d+)/(\d+)', message.content) if not m: return ["I'm sorry, I couldn't read that link. Please try again or say `cancel` to cancel."] @@ -52,21 +65,68 @@ async def handle_message(self, message): message = await channel.fetch_message(int(m.group(3))) except discord.errors.NotFound: return ["It seems this message was deleted or never existed. Please try again or say `cancel` to cancel."] - - # Here we've found the message - it's up to you to decide what to do next! self.state = State.MESSAGE_IDENTIFIED + self.userID = message.author.id return ["I found this message:", "```" + message.author.name + ": " + message.content + "```", \ - "This is all I know how to do right now - it's up to you to build out the rest of my reporting flow!"] + "What is your reason for reporting? You can say `spam`, `harassment`, `doxing`, `reporting on behalf of someone else`, or `other`."] if self.state == State.MESSAGE_IDENTIFIED: - return [""] + if self.reason == Reason.UNKNOWN: + if message.content.lower() == "spam": + self.reason = Reason.SPAM + elif message.content.lower() == "harassment": + self.reason = Reason.HARASSMENT + elif message.content.lower() == "doxing": + self.reason = Reason.DOXING + elif message.content.lower() == "reporting on behalf of someone else": + self.reason = Reason.REPORT_OTHER + elif message.content.lower() == "other": + self.reason = Reason.OTHER + else: + return ["Please specify the reason for your report."] - return [] - - def report_complete(self): - return self.state == State.REPORT_COMPLETE - + if self.reason == Reason.SPAM or self.reason == Reason.HARASSMENT or self.reason == Reason.REPORT_OTHER or self.reason == Reason.OTHER: + self.state = State.REPORT_COMPLETE + self.askToBlock = True + return ["Thank you for the report. Our moderation team will take appropriate action. Would you like to block the user? You can say `yes` or `no`."] + elif self.state == State.MESSAGE_IDENTIFIED and self.reason == Reason.DOXING and self.doxing_subreason == DoxingSubReason.UNKNOWN: + if message.content.lower() == "sensitive information about me": + self.doxing_subreason = DoxingSubReason.SENSITIVE_INFO + elif message.content.lower() == "threatening to leak my information": + self.doxing_subreason = DoxingSubReason.THREATENING_LEAK + elif message.content.lower() == "exposing my information": + self.doxing_subreason = DoxingSubReason.EXPOSING_INFO + if self.doxing_subreason == DoxingSubReason.UNKNOWN: + return ["Please specify. You can say `sensitive information about me`, `threatening to leak my information`, or `exposing my information`."] + elif self.doxing_subreason != DoxingSubReason.UNKNOWN: + if self.imminent_danger == None: + return ["Does the information present an imminent physical danger to you? You can say `yes` or `no`."] + else: + self.state = State.REPORT_COMPLETE + self.askToBlock = True + if self.imminent_danger: + return ["Your report has been received. Our moderation team will investigate the situation and resolve the situation as soon as possible. In the meantime, would you like to block the user? You can say `yes` or `no`."] + else: + return ["Thank you for the report. Our moderation team will take appropriate action. Would you like to block the user? You can say `yes` or `no`."] - + if self.state == State.MESSAGE_IDENTIFIED and self.reason == Reason.DOXING and self.doxing_subreason != DoxingSubReason.UNKNOWN and self.imminent_danger == None: + if message.content.lower() == "yes": + self.imminent_danger = True + elif message.content.lower() == "no": + self.imminent_danger = False + self.askToBlock = True + return ["We will remind the user of our doxing policy. Your report has been received. Our moderation team will take appropriate action. Would you like to block the user? You can say `yes` or `no`."] + + if self.askToBlock == True: + if message.content.lower() == "yes": + self.isBlocked = True + self.askToBlock = False + return["User blocked. Thank you for your report."] + elif message.content.lower() == "no": + self.isBlocked = False + self.askToBlock = False + return["User not blocked. Thank you for your report."] + def report_complete(self): + return self.state == State.REPORT_COMPLETE