ryuko-ng/cogs/verification.py

230 lines
9 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)
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"
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(
2020-04-21 06:08:56 +00:00
config.welcome_hashes
)
)
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
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):
snark = random.choice(["bad human", "no u", "no u, rtfm", "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 :)
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)
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
),
)
2019-04-24 07:24:59 +00:00
# Detect if the user uses the wrong hash algorithm
wrong_hash_algos = (
2020-04-21 06:08:56 +00:00
config.welcome_hashes
- {self.hash_choice}
)
2019-04-24 07:24:59 +00:00
for algo in wrong_hash_algos:
for name in itertools.chain(allowed_names, close_names):
if hashlib.new(algo, name.encode("utf-8")).hexdigest() in mcl:
2019-04-24 08:59:04 +00:00
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}."
)
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))