async def on_member_unban(server, user): msgProcessStart = analytics.getEventTime() if common.isDiscordMainServer(server) is not True: return await discord.bot.send_message( discord.mod_channel(), "{0} **Unbanned User:** {1.mention} (Name:`{1.name}#{1.discriminator}` ID:`{1.id}`)" .format(common.bernardUTCTimeNow(), user)) #check if the user was retroactively rebanned, if they were remove from said list. database.cursor.execute('SELECT * FROM bans_retroactive WHERE id=%s', (user.id, )) retdb = database.cursor.fetchone() if retdb is not None: database.cursor.execute('DELETE FROM bans_retroactive WHERE id=%s', (user.id, )) database.connection.commit() await discord.bot.send_message( discord.mod_channel(), "{0} **Retroactive Unban:** {1.mention} (Name:`{1.name}#{1.discriminator}` ID:`{1.id}`)" .format(common.bernardUTCTimeNow(), user)) journal.update_journal_event(module=__name__, event="RETROACTIVE_UNBAN", userid=user.id, contents=retdb['reason']) #capture the event in the internal log journal.update_journal_event( module=__name__, event="ON_MEMBER_UNBAN", userid=user.id, contents="{0.name}#{0.discriminator}".format(user)) analytics.onMemberProcessTime(msgProcessStart, analytics.getEventTime())
async def on_message_edit(before, after): msgProcessStart = analytics.getEventTime() if common.isDiscordMainServer(before.server) is not True: return if before.content != after.content: if len(before.content) + len(after.content) < 1800: msg = "{0} **Caught Edited Message!**" \ "{1.author.mention} (Name:`{1.author}` ID:`{1.author.id}`) in {1.channel.mention} \n" \ " Original: \"`{1.content}`\" \n\n" \ " Edited: \"`{2.content}`\" \n".format(common.bernardUTCTimeNow(), before, after) msg_sent = await discord.bot.send_message( discord.messages_channel(), msg) else: msgs = [ "{0} **Caught Edited Message! (WARNING: may be truncated)** {1.author.mention} (Name:`{1.author}` ID:`{1.author.id}`) in {1.channel.mention}" .format(common.bernardUTCTimeNow(), before), " Original:```{0}```".format(before.content[:1980]), " Edited:```{0}```".format(after.content[:1980]) ] for msg in msgs: msg_sent = await discord.bot.send_message( discord.messages_channel(), msg) journal_msg = "https://discordapp.com/channels/{0.channel.server.id}/{0.channel.id}/{0.id}".format( msg_sent) journal.update_journal_event(module=__name__, event="ON_MESSAGE_EDIT", userid=before.author.id, eventid=before.id, contents=journal_msg) analytics.onMessageProcessTime(msgProcessStart, analytics.getEventTime())
async def on_member_remove(user): global ignore_depart msgProcessStart = analytics.getEventTime() if common.isDiscordMainServer(user.server) is not True: return #if the user was banned or removed for another reason dont issue the depart statement if user.id in ignore_depart: ignore_depart.remove(user.id) return await discord.bot.send_message( discord.mod_channel(), "{0} **Departing User:** {1.mention} (Name:`{1.name}#{1.discriminator}` ID:`{1.id}`)" .format(common.bernardUTCTimeNow(), user)) #remove any invites from this user await invites.on_member_leave_invite_cleanup(user) #remove any cached subscriber information subscriber.on_member_remove_purgedb(user) #capture the event in the internal log journal.update_journal_event( module=__name__, event="ON_MEMBER_REMOVE", userid=user.id, contents="{0.name}#{0.discriminator}".format(user)) analytics.onMemberProcessTime(msgProcessStart, analytics.getEventTime())
async def on_member_ban(member): msgProcessStart = analytics.getEventTime() if common.isDiscordMainServer(member.server) is not True: return ignore_depart.append(member.id) await discord.bot.send_message( discord.mod_channel(), "{0} **Banned User:** {1.mention} (Name:`{1.name}#{1.discriminator}` ID:`{1.id}`)" .format(common.bernardUTCTimeNow(), member)) #remove any invites from this user await invites.on_member_leave_invite_cleanup(member) #remove any cached subscriber information subscriber.on_member_remove_purgedb(member) #capture the event in the internal log journal.update_journal_event( module=__name__, event="ON_MEMBER_BANNED", userid=member.id, contents="{0.name}#{0.discriminator}".format(member)) analytics.onMemberProcessTime(msgProcessStart, analytics.getEventTime())
async def attachments(msg): if config.cfg['auditing']['attachments']['enable'] == 0: return if common.isDiscordAdministrator(msg.author): return if msg.attachments is False: return for attachment in msg.attachments: exploded = attachment['filename'].split(".")[1:] for ext in exploded: ext = ext.replace(".", "").replace("-", "") if ext in config.cfg['auditing']['attachments']['restricted']: await discord.bot.delete_message(msg) await discord.bot.send_message( msg.channel, "{0}, <:pepoG:352533294862172160> that file format is not allowed to be uploaded here. Filename: `{1}`" .format(msg.author.mention, attachment['filename'])) journal.update_journal_event(module=__name__, event="AUDIT_DELETE_ATTACHMENT", userid=msg.author.id, eventid=msg.id, contents=attachment['filename']) logger.warn("deleting uploaded file: {0}".format( attachment['filename']))
async def scheduler_unban_member(work): now = int(time.time()) logger.info( "UNBAN_MEMBER JOB ID {0[id]} BANNED BY {0[id_invoker]} BAN HAS EXPIRED, UNBANNING {0[id_targeted]}" .format(work)) #call the unban unban_status_discord = await common.unban_id(str(work['id_targeted'])) if unban_status_discord: logger.info( "UNBAN_MEMBER JOB ID {0[id]} USER ID {0[id_targeted]} BAN SUCCESSFULLY REMOVED FROM DISCORD." .format(work)) #update the modlog channel await discord.bot.send_message( discord.mod_channel(), "{0} **Scheduled Unban:** ID:`{1[id_targeted]}`)".format( common.bernardUTCTimeNow(), work)) #set a user journal record the unban has happened journal.update_journal_event( module=__name__, event="ON_MEMBER_UNBAN_SCHEDULED", userid=work['id_targeted'], contents="SCHEDULER JOBID: {0[id]}".format(work)) else: logger.warn( "UNBAN_MEMBER JOB ID {0[id]} USER ID {0[id_targeted]} BAN WAS NOT REMOVED FROM DISCORD, USER ALREADY UNBANNED?" .format(work)) await scheduler_mark_work_done(work)
async def cleanup(ctx, target=None, history=100): start = analytics.getEventTime() if common.isDiscordRegulator(ctx.message.author) != True: return #make user input something usable first, conform outlandish commands to be sane if target is None and history is None: await discord.bot.say("Syntax: `!cleanup @mention <1-1000>` where # is last x chat messages to check per channel. Defaults to 100.") return elif target is None: await discord.bot.say("Error: You must target a user by `@mention` or raw ID.") return elif history > 1000: await discord.bot.say("Warning: This command only supports up to the last 1000 channel messages. Limiting your request to 1000.") history = 1000 else: pass #get the raw mention or just pass the ID depending on what the use supplied. member only needed for protection target_id = discord.get_targeted_id(ctx) target_member = discord.default_server.get_member(target_id) # Only use the Member lookup for Reg/Admin protection #if xiphirx = soy if target_id == discord.bot.user.id: await discord.bot.say("⚠️{0.message.author.mention} you are not allowed to cleanup after the bot!".format(ctx)) return #dont allow this to be called on regulators/administrators if target_member is not None: if common.isDiscordRegulator(target_member): logger.warn("cleanup() called and is exiting: ID:{0.message.author.id} attempted to call cleanup on ID:{1} but was denied by: IS_REGULATOR_PROTECTED".format(ctx, target_id)) await discord.bot.say("⚠️{0.message.author.mention} you are not allowed to call that on other admins/regulators!".format(ctx)) return #while this runs lets not flood the mod channel with messages deleted.IGNORE_IDS.append(target_id) await discord.bot.say("{0.message.author.mention} starting now ID:`{1}` and will @ you when task completed.".format(ctx, target_id)) logger.info("cleanup() {0.message.author.name} started deletion on ID:{1}. Checking all channels last {2} messages.".format(ctx, target_id, history)) for channel in ctx.message.server.channels: if channel.type == discord.discord.ChannelType.text: logger.info("cleanup() {0.message.author.name} started deletion on channel ID: {0.message.channel.id} for user ID:{1}".format(ctx, target_id)) await delete_messages_from_channel(ctx, channel, target_id, history) #no need to keep the id around deleted.IGNORE_IDS.remove(target_id) #create both a journal entry for the user targeted journal.update_journal_event(module=__name__, event="MESSAGE_CLEANUP_MODERATOR", userid=target_id, contents="Invoked by: {0.author.name} in channel {0.channel}".format(ctx.message)) journal.update_journal_regulator(invoker=ctx.message.author.id, target=target_id, eventdata=history, action="MESSAGE_CLEANUP_MODERATOR", messageid=ctx.message.id) secs_taken = int(analytics.getEventTime() - start) await discord.bot.say("{0.message.author.mention} cleanup on ID `{1}` completed! Took ~{2} seconds".format(ctx, target_id, secs_taken))
async def warn(ctx, target, *, reason): if common.isDiscordRegulator(ctx.message.author) != True: return # convert the target into a usable ID target_id = discord.get_targeted_id(ctx) target_member = await discord.get_user_info(target_id) if target_member is None: await discord.bot.say( "{} тЪая╕П I was not able to lookup that user ID.".format( ctx.message.author.mention)) return # warn reason has to have at least a word in it if len(reason) < 4: await discord.bot.say( "тЪая╕П Warning reason must be longer than 4 characters. `!warn @username reason goes here`" ) return # warn reason has to be a reasonable length if len(reason) > 200: await discord.bot.say( "тЪая╕П Reason too long - please limit to 200 characters or less.") return if allow_regulation(ctx, target_id): # return what is happening in the same channel to alert the user await discord.bot.say( "тЬФя╕П {} is warning {} with the reason of `{}`.".format( ctx.message.author.mention, target_member.mention, reason)) # update the internal bot log journal.update_journal_regulator(invoker=ctx.message.author.id, target=target_id, eventdata=reason, action="WARN_MEMBER", messageid=ctx.message.id) # update the internal user log journal.update_journal_event(module=__name__, event="ON_MEMBER_WARN", userid=target_id, contents="{0.name}#{0.discriminator} " "warned by {1.name}#{1.discriminator} " "with reason '{2}'".format( target_member, ctx.message.author, reason)) else: await discord.bot.say( "ЁЯЫС {} unable to moderate user. Either you failed to tag the user properly or the member is protected from regulators." .format(ctx.message.author.mention))
async def discord_invites(msg): #enable the module or not if config.cfg['auditing']['invites']['enable'] == 0: return #ignore admins we dont even care what they do if common.isDiscordAdministrator(msg.author): return #use regex to find discord.gg links in all shapes and sizes, stop if we dont find any matched_discord = re.findall('discord.*gg\/([^\s]+)', msg.content.lower()) if len(matched_discord) == 0: return #if the config is using the @everyone role if config.cfg['auditing']['invites']['lowest_role_blocked'] == "everyone": if msg.author.top_role.is_everyone == True: await discord.bot.delete_message(msg) await discord.bot.send_message( msg.channel, "тЪая╕П {0} Members without a role are unable to post Discord invites." .format(msg.author.mention)) logger.warn( "deleted invite {0} under reason: 'everyone role'".format( matched_discord[0])) journal.update_journal_event(module=__name__, event="AUDIT_DELETE_INVITE", userid=msg.author.id, eventid=msg.id, contents=matched_discord[0]) elif msg.author.top_role.id == config.cfg['auditing']['invites'][ 'lowest_role_blocked']: await discord.bot.delete_message(msg) await discord.bot.send_message( msg.channel, "тЪая╕П {0} Your role does not meet the minimum requirements to post Discord invites." .format(msg.author.mention)) logger.warn( "deleted invite {0} under reason: 'underpowered role'".format( matched_discord[0])) journal.update_journal_event(module=__name__, event="AUDIT_DELETE_INVITE", userid=msg.author.id, eventid=msg.id, contents=matched_discord[0]) else: logger.warn("allowing discord user to post invite link: {0}".format( matched_discord[0]))
async def on_member_update(before, after): msgProcessStart = analytics.getEventTime() if common.isDiscordMainServer(before.server) is not True: return #handle nickname changes if before.nick != after.nick: if before.nick is None: await discord.bot.send_message( discord.mod_channel(), "{0} **Server Nickname Added:** {1.mention} was `{1.name}` is now `{2.nick}` (ID:`{1.id}`)" .format(common.bernardUTCTimeNow(), before, after)) journal.update_journal_event( module=__name__, event="ON_MEMBER_NICKNAME_ADD", userid=after.id, contents="{0.name} -> {1.nick}".format(before, after)) elif after.nick is None: await discord.bot.send_message( discord.mod_channel(), "{0} **Server Nickname Removed:** {1.mention} was `{1.nick}` is now `{2.name}` (ID:`{1.id}`)" .format(common.bernardUTCTimeNow(), before, after)) journal.update_journal_event( module=__name__, event="ON_MEMBER_NICKNAME_REMOVE", userid=after.id, contents="{0.nick} -> {1.name}".format(before, after)) else: await discord.bot.send_message( discord.mod_channel(), "{0} **Server Nickname Changed:** {1.mention} was `{1.nick}` is now `{2.nick}` (ID:`{1.id}`)" .format(common.bernardUTCTimeNow(), before, after)) journal.update_journal_event( module=__name__, event="ON_MEMBER_NICKNAME_CHANGE", userid=after.id, contents="{0.nick} -> {1.nick}".format(before, after)) #handle username changes if before.name != after.name: await discord.bot.send_message( discord.mod_channel(), "{0} **Discord Username Changed:** {1.mention} was `{1.name}` is now `{2.name}` (ID:`{1.id}`)" .format(common.bernardUTCTimeNow(), before, after)) journal.update_journal_event(module=__name__, event="ON_USERNAME_CHANGE", userid=after.id, contents="{0.name} -> {1.name}".format( before, after)) analytics.onMemberProcessTime(msgProcessStart, analytics.getEventTime())
async def on_message_delete(message): msgProcessStart = analytics.getEventTime() if common.isDiscordMainServer(message.server) is not True: return if message.author.id in IGNORE_IDS: logger.info( "on_message_delete() ignoring deleted message user id is in IGNORE_IDS variable" ) return if message.attachments and message.content == "": msg = "{0.author.mention} (Name:`{0.author}` ID:`{0.author.id}`) in {0.channel.mention} \n Deleted Attachment: `{0.attachments[0][filename]}` \n URL: <{0.attachments[0][url]}>".format( message) journal_msg = "Attachment: {0.attachments[0][filename]} Size: {0.attachments[0][size]}".format( message) elif message.attachments and message.content != "": msg = "{0.author.mention} (Name:`{0.author}` ID:`{0.author.id}`) in {0.channel.mention} \n Message: \"`{0.content}`\" \n\n Deleted Attachment: `{0.attachments[0][filename]}` \n URL: <{0.attachments[0][url]}>".format( message) journal_msg = "Text: {0.content} Attachment: {0.attachments[0][filename]} Size: {0.attachments[0][size]}".format( message) else: msg = "{0.author.mention} (Name:`{0.author}` ID:`{0.author.id}`) in {0.channel.mention} \n Message: \"`{0.content}`\" \n\n".format( message) journal_msg = "Text: {0.content}".format(message) await discord.bot.send_message( discord.messages_channel(), "{0} **Caught Deleted Message!** {1}".format( common.bernardUTCTimeNow(), msg)) journal.update_journal_event(module=__name__, event="ON_MESSAGE_DELETE", userid=message.author.id, eventid=message.id, contents=journal_msg) analytics.onMessageProcessTime(msgProcessStart, analytics.getEventTime())
async def on_member_join(user): msgProcessStart = analytics.getEventTime() if common.isDiscordMainServer(user.server) is not True: return #the user got here somehow, get the discord.Invite object we *think* they came from invite = await invites.on_member_join_attempt_invite_source(user) #if the user is retroactively banned, handle it and issue the ban database.cursor.execute('SELECT * FROM bans_retroactive WHERE id=%s', (user.id, )) retdb = database.cursor.fetchone() print(user.id, retdb) if retdb is not None: ignore_depart.append(user.id) await common.ban_verbose( user, "RETROACTIVE_BAN_VIA_BOT_DB - '{}'".format(retdb['reason'])) await discord.bot.send_message( discord.mod_channel(), "{0} **Retroactive Ban:** {1.mention} (Name:`{1.name}#{1.discriminator}` ID:`{1.id}` REASON: `{2}`)" .format(common.bernardUTCTimeNow(), user, retdb['reason'])) journal.update_journal_event(module=__name__, event="RETROACTIVE_BAN", userid=user.id, contents=retdb['reason']) return ##send the message to the admin defined channel await discord.bot.send_message( discord.mod_channel(), "{0} **New User:** {1.mention} (Name:`{1.name}#{1.discriminator}` ID:`{1.id}`) **Account Age:** {2} **From:** `{3}`" .format(common.bernardUTCTimeNow(), user, common.bernardAccountAgeToFriendly(user), invite)) #handle kicking / banning of "new" accounts if config.cfg['auditing']['account_age_min']['enable']: logger.info( "on_member_join() Account age minimum is enabled: Minimum account age required {} minutes." .format( config.cfg['auditing']['account_age_min']['min_age_required'])) account_age_minutes = int((datetime.datetime.utcnow().timestamp() - user.created_at.timestamp()) / 60) #if the users account is too new lets apply logic to kick or ban if account_age_minutes <= config.cfg['auditing']['account_age_min'][ 'min_age_required']: journal.update_journal_event( module=__name__, event="ON_MEMBER_JOIN_ACCOUNT_TOONEW", userid=user.id, contents="{0.name}#{0.discriminator} - {1} mins old".format( user, account_age_minutes)) #await discord.bot.send_message(user, config.cfg['auditing']['account_age_min']['enforcement_dm']) await asyncio.sleep(3) if config.cfg['auditing']['account_age_min'][ 'enforcement'] == "ban": logger.warn( "on_member_join() BANNING ID {0.id} for being too new. Account age was {1} minutes, config is {2} minute age.." .format( user, account_age_minutes, config.cfg['auditing'] ['account_age_min']['min_age_required'])) await common.ban_verbose( user, "BOT_BAN_VIA_ACCOUNT_TOONEW - {} min old".format( account_age_minutes)) else: logger.warn( "on_member_join() KICKING ID {0.id} for being too new. Account age was {1} minutes, config is {2} minute age." .format( user, account_age_minutes, config.cfg['auditing'] ['account_age_min']['min_age_required'])) await discord.bot.kick(user) #do a subscriber check and assign any roles on joining check_sub = subscriber.subscriber_update(user) await check_sub.update_subscriber() #capture the event in the internal log journal.update_journal_event( module=__name__, event="ON_MEMBER_JOIN", userid=user.id, contents="{0.name}#{0.discriminator}".format(user)) analytics.onMemberProcessTime(msgProcessStart, analytics.getEventTime())
async def blacklisted_domains(msg): if config.cfg['auditing']['blacklisted_domains']['enable'] == 0: return if common.isDiscordAdministrator(msg.author): return #matched regex into URLs list full_urls = re.findall( 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', msg.content) if len(full_urls) == 0: return for url in full_urls: #extract the url into only what we care about https://github.com/john-kurkowski/tldextract tldext = tldextract.extract(url) domain = "{0.domain}.{0.suffix}".format(tldext) #lookup the tld in the db database.cursor.execute( 'SELECT * FROM auditing_blacklisted_domains WHERE domain=%s', (domain.lower(), )) dbres = database.cursor.fetchone() #if we dont find the domain just move along if dbres == None: continue #up the hit counter in the DB database.cursor.execute( 'UPDATE auditing_blacklisted_domains SET hits=%s WHERE domain=%s', (dbres['hits'] + 1, domain)) database.connection.commit() #if we found a domain lets act on it | methods audit / delete / kick / ban if dbres['action'] == "audit": logger.info( "Domain audit of user {0.author} blacklisted_domains() domain {1[domain]} found" .format(msg, dbres)) elif dbres['action'] == "delete": logger.warn( "blacklisted_domains() message delete from domain {0[domain]} for user {1.author} ({1.author.id})" .format(dbres, msg)) await discord.bot.delete_message(msg) await discord.bot.send_message( msg.channel, "тЪая╕П {0.author.mention} that domain `{1[domain]}` is prohibited here." .format(msg, dbres)) journal.update_journal_event(module=__name__, event="AUDIT_DOMAIN_DELETE", userid=msg.author.id, eventid=msg.id, contents=dbres['domain']) return elif dbres['action'] == "kick": logger.warn( "blacklisted_domains() user kick from domain {0[domain]} for user {1.author} ({1.author.id})" .format(dbres, msg)) await discord.bot.delete_message(msg) await discord.bot.send_message( msg.channel, "ЁЯЫС {0.author.mention} that domain `{1[domain]}` is prohibited here with the policy to kick poster. Kicking..." .format(msg, dbres)) await discord.bot.kick(msg.author) journal.update_journal_event(module=__name__, event="AUDIT_DOMAIN_KICK", userid=msg.author.id, eventid=msg.id, contents=dbres['domain']) return elif dbres['action'] == "ban": logger.warn( "blacklisted_domains() user ban from domain {0[domain]} for user {1.author} ({1.author.id})" .format(dbres, msg)) await discord.bot.delete_message(msg) await discord.bot.send_message( msg.channel, "ЁЯЫС {0.author.mention} that domain `{1[domain]}` is prohibited here with the policy to **BAN** poster. Banning..." .format(msg, dbres)) await common.ban_verbose( msg.author, "BOT_AUTOBAN_FOR_BLACKLISTED_DOMAIN - 'Domain:{0[domain]} URL:{1}'" .format(dbres, url)) journal.update_journal_event(module=__name__, event="AUDIT_DOMAIN_BAN", userid=msg.author.id, eventid=msg.id, contents=dbres['domain']) return else: logger.error( "Unknown action attempted in blacklisted_domains() while handling a blacklisted domain {0[domain]} method {0[action]}" .format(dbres))
async def update_subscriber(self): #ask for the data from the provider (destinygg) self.provider_data = await common.getJSON( config.cfg['subscriber']['provider']['endpoint'] + "/?privatekey=" + config.cfg['subscriber']['provider']['privatekey'] + "&discordid=" + self.user.id) if self.provider_data == None: self.result = "{0.mention} could not look you up with provider. Check your profile on destiny.gg".format( self.user) return #get the discord role self.get_provider_to_discord_role() if self.feature == "pleb": self.result = "{0.mention} provider returned no active subscription.".format( self.user) return #find when the subs expire, and pad it by the configured grace period self.expires = time.mktime( time.strptime(self.provider_data['subscription']['end'], config.cfg['subscriber']['provider']['timestamp'])) self.expires_day = int( time.strftime('%j', time.gmtime(self.expires)) ) + config.cfg['subscriber']['settings']['grace_days'] #check the db to see if this is an update or an insert database.cursor.execute('SELECT * FROM subscribers WHERE userid=%s', (self.user.id, )) existing = database.cursor.fetchone() if existing is None: database.cursor.execute( 'INSERT INTO subscribers' '(userid, roleid, tier, last_updated, expires_epoch, expires_day)' 'VALUES (%s,%s,%s,%s,%s,%s) ', (self.user.id, self.roleid, self.feature, time.time(), self.expires, self.expires_day)) logger.info( "Adding new subscriber {0} with {1} expires day {2} ".format( self.user.name, self.feature, self.expires_day)) journal.update_journal_event(module=__name__, event="SUBCRIBER_NEW", userid=self.user.id, contents=self.expires_day) self.role = discord.discord.Role( id=self.roleid, server=config.cfg['discord']['server']) await discord.bot.add_roles(self.user, self.role) self.result = "{0.mention} Subscrption added! {1} with {2} days until revocation.".format( self.user, self.feature, self.expires_day - self.today) database.connection.commit() return else: logger.info("Updating existing subscriber {0}".format( self.user.name)) #if the new role doesnt match the old one, remove the old role first then add the new one, otherwise same just update DB if existing['tier'] != self.feature: logger.info("{0} old role {1} new role {2}".format( self.user.name, existing['tier'], self.feature)) #remove the old role self.oldrole = discord.discord.Role( id=existing['roleid'], server=config.cfg['discord']['server']) await discord.bot.remove_roles(self.user, self.oldrole) #turns out if you send them right away theres a race condition and the removed role comes back lol await asyncio.sleep(3) #add the new role self.newrole = discord.discord.Role( id=self.roleid, server=config.cfg['discord']['server']) await discord.bot.add_roles(self.user, self.newrole) self.result = "{0.mention} Subscrption updated! was {1}, is now {2} with {3} days until revocation.".format( self.user, existing['roleid'], self.feature, self.expires_day - self.today) #update the db self.result = "{0.mention} Nothing has changed. {1} with {2} days until revocation.".format( self.user, self.feature, self.expires_day - self.today) database.cursor.execute( 'UPDATE subscribers SET roleid=%s, tier=%s, last_updated=%s, expires_epoch=%s, expires_day=%s WHERE userid=%s', (self.roleid, self.feature, time.time(), self.expires, self.expires_day, self.user.id)) database.connection.commit()
async def slur_filter(message): # get the score of the message contents regex_result = regex_scoring_msg(message.content) # if the message scored 0, we can ignore if regex_result['score'] == 0: return # if we got this far, we need to lookup their account age account_min_old = int((datetime.datetime.utcnow().timestamp() - message.author.created_at.timestamp()) / 60) account_age_score = account_age_scoring(account_min_old) # and the amount of time in the discord account_member_score = account_join_time(message.author.id) # and how many times they have recently been AUTomodded account_previous_score = previous_automod_scoring(message.author.id) multiplier = account_age_score + account_member_score if multiplier is not 0: final_score = (regex_result['score'] * multiplier) + account_previous_score else: final_score = regex_result['score'] + account_previous_score if final_score == 0: return # fail safe if the score is 0 # if we made it here, time to push some punishments await discord.bot.delete_message(message ) # delete the message from Discord journal.update_journal_event( module=__name__, event="ON_MESSAGE_DELETE_AUTOMOD", userid=message.author.id, eventid=message.id, contents=message.content) # update the users journal # decide how hard to punish the user, and punish them punishment = get_punishment_tier(final_score) # Get a censored string of what the user said to get automodded clean_gamerwords = [] for gamerword in regex_result['words']: clean_gamerwords.append(censor_word(gamerword)) clean_modded_words = ','.join(clean_gamerwords) # alert the user to what they have done await discord.bot.send_message( message.channel, "{0.author.mention} is being automoderated with enforcement **{1}**: `({2})`" .format(message, punishment, clean_modded_words)) await asyncio.sleep(2) # sleep for 2 seconds until the ban is fired if punishment == "BAN_PERMA": punishment_journal_type = "BAN_MEMBER" ban = await common.ban_verbose( message.author, "AUTOMOD BAN_PERMA SCORE:{}".format(final_score)) if ban is False: await discord.bot.send_message( message.channel, "❓ Something's f****d! Unable to issue ban to Discord API. Bother <@{}>" .format(config.cfg['bernard']['owner'])) elif punishment == "BAN_24H" or punishment == "BAN_1H": punishment_journal_type = "BAN_MEMBER" ban = await common.ban_verbose( message.author, "AUTOMOD {0} SCORE:{1}".format(punishment, final_score)) if ban is False: await discord.bot.send_message( message.channel, "❓ Something's f****d! Unable to issue ban to Discord API. Bother <@{}>" .format(config.cfg['bernard']['owner'])) else: if punishment == "BAN_24H": time_to_fire = time.time() + 86400 else: time_to_fire = time.time() + 3600 # don't forget to set the unban event scheduler.set_future_task(invoker=discord.bot.user.id, target=message.author.id, channel=message.channel.id, timestamp=time_to_fire, event="UNBAN_MEMBER", msg="Automod SCORE:{0} WORDS:{1}".format( final_score, clean_modded_words)) elif punishment == "KICK": punishment_journal_type = "KICK_MEMBER" await discord.bot.kick(message.author) elif punishment == "WARN_HARD": punishment_journal_type = "WARN_MEMBER" await discord.bot.send_message( message.channel, "{0.author.mention} Please review the rules! Your message is not allowed and has been removed. A rapsheet warning has been issued." .format(message, punishment, final_score)) else: punishment_journal_type = None await discord.bot.send_message( message.channel, "{0.author.mention} Please review the rules! Your message is not allowed and has been removed. Next time I may not be as nice. (unoffical warning)" .format(message, punishment, final_score)) # update the regulator log if punishment_journal_type is not None: journal.update_journal_regulator( invoker=discord.bot.user.id, target=message.author.id, eventdata="Automod POLICY:{0} SCORE:{1} WORDS:{2}".format( punishment, final_score, clean_modded_words), action=punishment_journal_type, messageid=message.id) # log the action to the database database.cursor.execute( 'INSERT INTO automod_gamerwords' '(score_final, score_regex, score_prev_infractions, multiply_age_member, multiply_age_account, action, time, id_targeted, message)' 'VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)', (final_score, regex_result['score'], account_previous_score, account_member_score, account_age_score, punishment, time.time(), message.author.id, message.content)) database.connection.commit()