ryuko-ng/cogs/verification.py

197 lines
8.7 KiB
Python
Raw Normal View History

2018-12-23 16:31:12 +00:00
import discord
from discord.ext import commands
from discord.ext.commands import Cog
2018-12-23 16:31:12 +00:00
import asyncio
import config
import random
from inspect import cleandoc
import hashlib
import itertools
from helpers.checks import check_if_staff
2018-12-23 16:31:12 +00:00
class Verification(Cog):
2019-04-24 03:58:17 +00:00
def __init__(self, bot):
2018-12-23 16:31:12 +00:00
self.bot = bot
self.hash_choice = random.choice(config.welcome_hashes)
2018-12-23 16:31:12 +00:00
# Export reset channel functions
self.bot.do_reset = self.do_reset
self.bot.do_resetalgo = self.do_resetalgo
2018-12-23 16:31:12 +00:00
async def do_reset(self, channel, author, limit: int = 100):
await channel.purge(limit=limit)
await channel.send(config.welcome_header)
2018-12-23 16:31:12 +00:00
rules = ['**{}**. {}'.format(i, cleandoc(r)) for i, r in
enumerate(config.welcome_rules, 1)]
rule_choice = random.randint(2, len(rules))
2019-06-29 18:29:19 +00:00
hash_choice_str = self.hash_choice.upper()
if hash_choice_str == "BLAKE2B":
hash_choice_str += "-512"
elif hash_choice_str == "BLAKE2S":
hash_choice_str += "-256"
2019-04-24 07:24:59 +00:00
rules[rule_choice - 1] += \
'\n' + config.hidden_term_line.format(hash_choice_str)
msg = f"🗑 **Reset**: {author} cleared {limit} messages "\
f" in {channel.mention}"
2018-12-23 16:31:12 +00:00
msg += f"\n💬 __Current challenge location__: under rule {rule_choice}"
2019-02-16 13:55:26 +00:00
log_channel = self.bot.get_channel(config.log_channel)
2018-12-24 00:18:40 +00:00
await log_channel.send(msg)
2019-04-24 07:24:59 +00:00
2018-12-23 16:31:12 +00:00
# find rule that puts us over 2,000 characters, if any
total = 0
messages = []
current_message = ""
for item in rules:
total += len(item) + 2 # \n\n
if total < 2000:
current_message += item + "\n\n"
else:
# we've hit the limit; split!
messages += [current_message]
current_message = "\n\u200B\n" + item + "\n\u200B\n"
total = 0
messages += [current_message]
for item in messages:
await channel.send(item)
2018-12-23 16:31:12 +00:00
await asyncio.sleep(1)
for x in config.welcome_footer:
await channel.send(cleandoc(x))
await asyncio.sleep(1)
2018-12-23 16:31:12 +00:00
async def do_resetalgo(self, channel, author, limit: int = 100):
# randomize hash_choice on reset
self.hash_choice = \
random.choice(tuple(hashlib.algorithms_guaranteed -
self.blacklisted_hashes -
{self.hash_choice}))
msg = f"📘 **Reset Algorithm**: {author} reset "\
f"algorithm in {channel.mention}"
msg += f"\n💬 __Current algorithm__: {self.hash_choice.upper()}"
log_channel = self.bot.get_channel(config.log_channel)
await log_channel.send(msg)
await self.do_reset(channel, author)
@commands.check(check_if_staff)
@commands.command()
async def reset(self, ctx, limit: int = 100, force: bool = False):
"""Wipes messages and pastes the welcome message again. Staff only."""
if ctx.message.channel.id != config.welcome_channel and not force:
await ctx.send(f"This command is limited to"
f" <#{config.welcome_channel}>, unless forced.")
return
await self.do_reset(ctx.channel, ctx.author.mention, limit)
@commands.check(check_if_staff)
@commands.command()
async def resetalgo(self, ctx, limit: int = 100, force: bool = False):
"""Resets the verification algorithm and does what reset does. Staff only."""
if ctx.message.channel.id != config.welcome_channel and not force:
await ctx.send(f"This command is limited to"
f" <#{config.welcome_channel}>, unless forced.")
return
2019-04-25 07:14:12 +00:00
await self.do_resetalgo(ctx.channel, ctx.author.mention, limit)
async def process_message(self, message):
"""Big code that makes me want to shoot myself
Not really a rewrite but more of a port
Git blame tells me that I should blame/credit Robin Lambertz"""
if message.channel.id == config.welcome_channel:
# Assign common stuff into variables to make stuff less of a mess
member = message.author
full_name = str(member)
discrim = str(member.discriminator)
guild = message.guild
chan = message.channel
mcl = message.content.lower()
2019-02-25 09:28:37 +00:00
# Reply to users that insult the bot
2019-02-25 10:09:18 +00:00
oof = ["bad", "broken", "buggy", "bugged",
"stupid", "dumb", "silly", "fuck", "heck", "h*ck"]
2019-02-25 09:28:37 +00:00
if "bot" in mcl and any(insult in mcl for insult in oof):
2019-02-25 09:21:31 +00:00
snark = random.choice(["bad human",
"no u",
2019-02-25 09:28:37 +00:00
"no u, rtfm",
2019-02-25 09:21:31 +00:00
"pebkac"])
2019-02-25 09:17:35 +00:00
return await chan.send(snark)
2019-02-25 09:16:26 +00:00
# Get the role we will give in case of success
success_role = guild.get_role(config.participant_role)
# Get a list of stuff we'll allow and will consider close
allowed_names = [f"@{full_name}", full_name, str(member.id)]
close_names = [f"@{member.name}", member.name, discrim,
f"#{discrim}"]
# Now add the same things but with newlines at the end of them
allowed_names += [(an + '\n') for an in allowed_names]
close_names += [(cn + '\n') for cn in close_names]
allowed_names += [(an + '\r\n') for an in allowed_names]
close_names += [(cn + '\r\n') for cn in close_names]
2019-02-25 09:16:26 +00:00
# [ ͡° ͜ᔦ ͡°] 𝐖𝐞𝐥𝐜𝐨𝐦𝐞 𝐭𝐨 𝐌𝐚𝐜 𝐎𝐒 𝟗.
allowed_names += [(an + '\r') for an in allowed_names]
close_names += [(cn + '\r') for cn in close_names]
# Finally, hash the stuff so that we can access them later :)
2019-04-24 07:24:59 +00:00
hash_allow = [hashlib.new(self.hash_choice,
name.encode('utf-8')).hexdigest()
for name in allowed_names]
# I'm not even going to attempt to break those into lines jfc
2019-04-24 01:32:30 +00:00
if any(allow in mcl for allow in hash_allow):
await member.add_roles(success_role)
2019-04-24 07:24:59 +00:00
return await chan.purge(limit=100, check=lambda m: m.author == message.author or (m.author == self.bot.user and message.author.mention in m.content))
# Detect if the user uses the wrong hash algorithm
wrong_hash_algos = hashlib.algorithms_guaranteed - \
{self.hash_choice} - self.blacklisted_hashes
for algo in wrong_hash_algos:
for name in itertools.chain(allowed_names, close_names):
2019-04-24 08:59:04 +00:00
if hashlib.new(algo, name.encode('utf-8')).hexdigest() in mcl:
log_channel = self.bot.get_channel(config.log_channel)
await log_channel.send(f"User {message.author.mention} tried verification with algo {algo} instead of {self.hash_choice}.")
2019-04-24 07:24:59 +00:00
return await chan.send(f"{message.author.mention} :no_entry: Close, but not quite. Go back and re-read!")
if full_name in message.content or str(member.id) in message.content or member.name in message.content or discrim in message.content:
no_text = ":no_entry: Incorrect. You need to do something *specific* with your name and discriminator instead of just posting it. Please re-read the rules carefully and look up any terms you are not familiar with."
rand_num = random.randint(1, 100)
if rand_num == 42:
no_text = "you're doing it wrong"
elif rand_num == 43:
no_text = "ugh, wrong, read the rules."
2019-04-23 16:12:44 +00:00
elif rand_num == 44:
no_text = "\"The definition of insanity is doing the same thing over and over again, but expecting different results.\"\n-Albert Einstein"
await chan.send(f"{message.author.mention} {no_text}")
2019-04-24 01:32:30 +00:00
@Cog.listener()
async def on_message(self, message):
2019-01-27 23:04:24 +00:00
if message.author.bot:
return
try:
await self.process_message(message)
except discord.errors.Forbidden:
chan = self.bot.get_channel(message.channel)
await chan.send("💢 I don't have permission to do this.")
@Cog.listener()
async def on_message_edit(self, before, after):
2019-02-25 09:16:26 +00:00
if after.author.bot:
2019-01-27 23:04:24 +00:00
return
try:
await self.process_message(after)
except discord.errors.Forbidden:
chan = self.bot.get_channel(after.channel)
await chan.send("💢 I don't have permission to do this.")
2018-12-23 16:31:12 +00:00
def setup(bot):
bot.add_cog(Verification(bot))