Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DiscordBot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,4 @@ def code_format(self, text):


client = ModBot()
client.run(discord_token)
client.run(discord_token)
96 changes: 78 additions & 18 deletions DiscordBot/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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."]
Expand All @@ -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."]
Expand All @@ -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 ["<insert rest of reporting flow here>"]
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