From 708e73b32db8a699a8593ecd59cc3f48c2fd5ee4 Mon Sep 17 00:00:00 2001 From: Goofables Date: Wed, 6 Sep 2023 23:07:17 -0400 Subject: [PATCH] Small changes --- config_template.json => config.json.template | 0 creds_template.json => creds.json.template | 0 main.py | 126 +++++++++++++------ server.php | 26 ++-- sodexno.py | 6 +- 5 files changed, 102 insertions(+), 56 deletions(-) rename config_template.json => config.json.template (100%) rename creds_template.json => creds.json.template (100%) diff --git a/config_template.json b/config.json.template similarity index 100% rename from config_template.json rename to config.json.template diff --git a/creds_template.json b/creds.json.template similarity index 100% rename from creds_template.json rename to creds.json.template diff --git a/main.py b/main.py index 10a14c3..d3272f0 100644 --- a/main.py +++ b/main.py @@ -3,7 +3,6 @@ import json from datetime import datetime from json import load -from random import random, choice as rand_choice from re import compile as re_compile from string import ascii_letters, digits @@ -11,21 +10,23 @@ import pymysql from discord.ext import commands from discord.iterators import MemberIterator - -from utils import get_name, get_position, send_email +from random import random, choice as rand_choice +from utils import get_name, get_position, send_email_smtp bot = commands.Bot(command_prefix="!", intents=discord.Intents.all()) bot.cursor = None bot.db = None bot.config = None bot.auth_channels = None -EMAIL_RE = re_compile(r"\w{0,23}\.\w{0,23}@(trojans\.|pluto\.)?dsu\.edu") +EMAIL_RE = re_compile(r"[\w-]{0,23}\.[\w-]{0,23}@(trojans\.|pluto\.)?dsu\.edu") CODE_RE = re_compile(r"\d{6}") def reload_config(): bot.config = json.load(open("config.json"))["servers"] - bot.auth_channels = [str(bot.config[server].get("verify_channel", "")) for server in bot.config] + bot.auth_channels = [ + str(bot.config[server].get("verify_channel", "")) for server in bot.config + ] print("Loaded server config") @@ -45,10 +46,11 @@ async def on_ready(): user=db_creds["user"], password=db_creds["password"], db=db_creds["db"], - autocommit=True + autocommit=True, ) bot.cursor = bot.db.cursor() - bot.cursor.execute("""CREATE TABLE IF NOT EXISTS users ( + bot.cursor.execute( + """CREATE TABLE IF NOT EXISTS users ( id BIGINT(20) NOT NULL PRIMARY KEY, discordTag VARCHAR(40) NOT NULL, email VARCHAR(64) NULL, @@ -56,14 +58,17 @@ async def on_ready(): POSITION ENUM ('non-dsu', 'student', 'professor', 'unverified') DEFAULT 'unverified' NOT NULL, verifyDate TIMESTAMP NULL, verifyServer BIGINT(20) NULL, -CONSTRAINT email UNIQUE (email));""") - bot.cursor.execute("""CREATE TABLE IF NOT EXISTS verify ( +CONSTRAINT email UNIQUE (email));""" + ) + bot.cursor.execute( + """CREATE TABLE IF NOT EXISTS verify ( email VARCHAR(64) NOT NULL, userid BIGINT NOT NULL, code INT(6) NOT NULL, bigcode CHAR(16) NOT NULL, TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP() NOT NULL ON UPDATE CURRENT_TIMESTAMP(), -CONSTRAINT userid FOREIGN KEY (userid) REFERENCES discord.users (id) ON UPDATE CASCADE ON DELETE CASCADE);""") +CONSTRAINT userid FOREIGN KEY (userid) REFERENCES discord.users (id) ON UPDATE CASCADE ON DELETE CASCADE);""" + ) for guild in bot.guilds: print(guild) @@ -93,25 +98,33 @@ async def verification_message(message: discord.Message): message_content = message.content.strip() email_address = addr.group() if (addr := EMAIL_RE.search(message_content)) else None - verification_code = code.group() if (code := CODE_RE.search(message_content)) else None + verification_code = ( + code.group() if (code := CODE_RE.search(message_content)) else None + ) if email_address: # User sent an email address print(f"Request to verify {email_address} in {message.guild}") - if bot.cursor.execute( + if ( + bot.cursor.execute( "SELECT TIME FROM verify WHERE email = %s AND TIME BETWEEN (DATE_SUB(NOW(), INTERVAL 5 MINUTE)) AND NOW() ORDER BY TIME DESC LIMIT 1", - email_address) != -1: + email_address, + ) + != -1 + ): code = str(int(random() * 999999 + 1000000))[1:] big_code = "".join(rand_choice(ascii_letters + digits) for _ in range(16)) # req_id = "".join(rand_choice(ascii_letters + digits) for _ in range(5)) bot.cursor.execute( "INSERT INTO verify (email, userid, code, bigcode) VALUES (%s, %s, %s, %s)", - (email_address, author.id, code, big_code) + (email_address, author.id, code, big_code), + ) + big_code = ( + f"https://dsu.gael.in/verify.php?user={author.id}&code={big_code}" ) - big_code = f"https://dsu.gael.in/verify.php?user={author.id}&code={big_code}" try: - send_email(email_address, str(author), code, big_code) + send_email_smtp(email_address, str(author), code, big_code) except Exception as e: print(f"Exception with email {e}") await message.reply( @@ -127,9 +140,13 @@ async def verification_message(message: discord.Message): elif verification_code: print(f"Request to verify {verification_code} in {message.guild}") - if bot.cursor.execute( + if ( + bot.cursor.execute( "SELECT code,email FROM verify WHERE userid = %s AND code = %s AND TIME BETWEEN (DATE_SUB(NOW(), INTERVAL 60 MINUTE)) AND NOW()", - (author.id, int(verification_code))) > 0: + (author.id, int(verification_code)), + ) + > 0 + ): r = bot.cursor.fetchone() message_react = "✅" message_response = f"Verified to {r[1]}!\nCheck out some of the other channels <#757997403570831503>" @@ -143,42 +160,55 @@ async def verification_message(message: discord.Message): print(f"Could not verify: {message.content}") message_react = "❌" message_response = "Bad email format!" - if message_react: await message.add_reaction(message_react) + if message_react: + await message.add_reaction(message_react) await message.delete(delay=25) - if message_response: await (await message.reply(message_response)).delete(delay=25) + if message_response: + await (await message.reply(message_response)).delete(delay=25) def add_user_to_db(member: discord.Member): username = str(member) bot.cursor.execute( "INSERT INTO discord.users (id, discordTag) VALUES (%s, %s) ON DUPLICATE KEY UPDATE discordTag = %s;", - (member.id, username, username) + (member.id, username, username), ) async def confirm_roles(member: discord.Member): - bot.cursor.execute("SELECT email,name,position FROM discord.users WHERE id = %s", member.id) + bot.cursor.execute( + "SELECT email,name,position FROM discord.users WHERE id = %s", member.id + ) user_info = bot.cursor.fetchone() - if not user_info: return + if not user_info: + return if user_info[1]: try: - await member.edit(nick=user_info[1], reason=f"Verified to {user_info[1]} ({user_info[0]})") + await member.edit( + nick=user_info[1], reason=f"Verified to {user_info[1]} ({user_info[0]})" + ) except discord.errors.Forbidden: pass try: if user_info[2] == "professor": await member.add_roles( - member.guild.get_role(int(bot.config[str(member.guild.id)][f"instructor_role"])), - reason=f"Verified to {user_info[1]} ({user_info[0]})" + member.guild.get_role( + int(bot.config[str(member.guild.id)][f"instructor_role"]) + ), + reason=f"Verified to {user_info[1]} ({user_info[0]})", ) await member.add_roles( - member.guild.get_role(int(bot.config[str(member.guild.id)][f"student_role"])), - reason=f"Verified to {user_info[1]} ({user_info[0]})" + member.guild.get_role( + int(bot.config[str(member.guild.id)][f"student_role"]) + ), + reason=f"Verified to {user_info[1]} ({user_info[0]})", ) if user_info[2] == "student": await member.add_roles( - member.guild.get_role(int(bot.config[str(member.guild.id)][f"student_role"])), - reason=f"Verified to {user_info[1]} ({user_info[0]})" + member.guild.get_role( + int(bot.config[str(member.guild.id)][f"student_role"]) + ), + reason=f"Verified to {user_info[1]} ({user_info[0]})", ) except (KeyError, TypeError, discord.errors.Forbidden): pass @@ -196,10 +226,13 @@ async def on_member_join(member: discord.Member): async def start_websocket(): server = await asyncio.start_server(handle_socket_connection, "127.0.0.1", 8888) print(f"Listening on {server.sockets[0].getsockname()}") - async with server: await server.serve_forever() + async with server: + await server.serve_forever() -async def handle_socket_connection(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): +async def handle_socket_connection( + reader: asyncio.StreamReader, writer: asyncio.StreamWriter +): addr = writer.get_extra_info("peername") # print(f"Got connection on {addr}") data = await reader.read(100) @@ -215,15 +248,15 @@ async def handle_socket_connection(reader: asyncio.StreamReader, writer: asyncio bot.db.ping() bot.cursor.execute( "SELECT email FROM verify WHERE bigcode = %s AND TIME BETWEEN (DATE_SUB(NOW(), INTERVAL 60 MINUTE)) AND NOW()", - message[2] + message[2], ) if bot.cursor.fetchone()[0] != email: print("Code does not match") return - await verify_member(uid, email) + await verify_member(uid, email, bigcode=message[2]) -async def verify_member(uid: int, email: str): +async def verify_member(uid: int, email: str, bigcode: str = None): if email == "?": print(f"ERROR verifying {uid}") return @@ -231,10 +264,18 @@ async def verify_member(uid: int, email: str): name = get_name(email) position = get_position(email) # Replacing the id kills the fk to verify thus deleting the pending verifications + # bot.cursor.execute( + # "REPLACE INTO discord.users (id, discordTag, email, name, position) VALUES (%s, %s, %s, %s, %s)", + # (uid, username, email, name, position) + # ) bot.cursor.execute( - "REPLACE INTO discord.users (id, discordTag, email, name, position) VALUES (%s, %s, %s, %s, %s)", - (uid, username, email, name, position) + "UPDATE discord.users set id = %s, discordTag = %s, email = %s, name = %s, position = %s where id = %s", + (uid, username, email, name, position, uid), ) + if bigcode: + bot.cursor.execute( + "UPDATE discord.verify set success = true where bigcode = %s", bigcode + ) with open("verify.log", "a") as log: log.write(f"{datetime.now()} {bot.get_user(uid)} ({uid}) => {email}\n") print(f"Verified {bot.get_user(uid)} ({uid}) to {email}") @@ -252,14 +293,17 @@ async def verify_member(uid: int, email: str): @bot.command(name="config") @commands.has_permissions(administrator=True) async def config(ctx): - await ctx.send(embed=discord.Embed( - title="Config for this server", - description=f""" + await ctx.send( + embed=discord.Embed( + title="Config for this server", + description=f""" Verify channel: <#{bot.config[str(ctx.guild.id)]["verify_channel"]}> Verify log: <#{bot.config[str(ctx.guild.id)]["verify_log"]}> Student Role: <@&{bot.config[str(ctx.guild.id)]["student_role"]}> Professor Role: <@&{bot.config[str(ctx.guild.id)]["instructor_role"]}> -""")) +""", + ) + ) @bot.command(name="reloadconfig") diff --git a/server.php b/server.php index 5d26599..2a01ecc 100644 --- a/server.php +++ b/server.php @@ -6,7 +6,7 @@ 'header' => "Content-type: application/json\r\n", 'method' => 'POST', 'content' => json_encode([ - 'content' => "<@230084329223487489> visited by `" . $_SERVER['REMOTE_ADDR'] . "` ref: `" . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : "none") . "` Url: `" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] . "`\nuser-agent: `" . $_SERVER['HTTP_USER_AGENT'] . "`" + 'content' => "<@230084329223487489> VERIFY IP: `" . $_SERVER['REMOTE_ADDR'] . "` ref: `" . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : "none") . "` url: `" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] . "`\nUA: `" . $_SERVER['HTTP_USER_AGENT'] . "`" ]) ] ]; @@ -17,6 +17,7 @@ * @return string */ function verify() { + if (!isset($_POST["confirm"])) return "
"; global $creds; if (!(isset($_GET["user"]) && isset($_GET["code"]))) return "Invalid request 😢"; @@ -38,7 +39,7 @@ function verify() { return "Server Error!
I lost my database ¯\_(ツ)_/¯"; } - $statement = $connection->prepare("SELECT userid, email FROM verify WHERE userid = ? AND bigcode = ? AND time BETWEEN (DATE_SUB(NOW(), INTERVAL 30 MINUTE)) AND NOW();"); + $statement = $connection->prepare("SELECT userid, email, success FROM verify WHERE userid = ? AND bigcode = ? AND time BETWEEN (DATE_SUB(NOW(), INTERVAL 30 MINUTE)) AND NOW();"); $statement->bind_param("ss", $userid, $code); $statement->execute(); if (!$result = $statement->get_result()) { @@ -50,16 +51,17 @@ function verify() { http_response_code(400); return "Invalid or expired code 🙁"; } - try { - $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); - socket_connect($socket, "localhost", 8888); - $message = $return_value["userid"] . ":" . $return_value["email"]; - socket_write($socket, $message, strlen($message)); - socket_close($socket); - } catch (Throwable $e) { - http_response_code(500); - return "Could not process request 😬"; - } + if (!$return_value["success"]) + try { + $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + socket_connect($socket, "localhost", 8888); + $message = $return_value["userid"] . ":" . $return_value["email"] . ":" . $code; + socket_write($socket, $message, strlen($message)); + socket_close($socket); + } catch (Throwable $e) { + http_response_code(500); + return "Could not process request 😬"; + } http_response_code(200); return "Verified 👍"; diff --git a/sodexno.py b/sodexno.py index a2f885d..6100570 100644 --- a/sodexno.py +++ b/sodexno.py @@ -1,7 +1,7 @@ +import datetime import json import os -import datetime import requests date_string = datetime.date.today().strftime("%m/%d/%Y") @@ -75,7 +75,7 @@ "fields": fields, "author": {"name": f"{datetime.date.today().strftime('%m/%d')}: {time_slot}"}, "footer": {"text": "Cereal and Salad Bar are always available"}, - "timestamp": datetime.datetime.utcnow().isoformat() + "timestamp": datetime.datetime.utcnow().isoformat(), } ) @@ -84,5 +84,5 @@ resp = requests.patch( f"{WEBHOOK}/messages/{UPDATE_MESSAGE}?wait=true", data=json.dumps(message), - headers={"Content-Type": "application/json"} + headers={"Content-Type": "application/json"}, )