From cb0f1b249e4eecb13263c91acccdd631a5784141 Mon Sep 17 00:00:00 2001 From: Jeremy Zhang Date: Fri, 10 Aug 2018 04:13:56 +0000 Subject: [PATCH] Entirely remove db portion in bot and handle kickban cmds in webapp --- discordbot/config.example.py | 2 + discordbot/titanembeds/bot.py | 5 +- discordbot/titanembeds/commands.py | 49 ++++++++++-- discordbot/titanembeds/database/__init__.py | 76 ------------------- .../database/unauthenticated_bans.py | 15 ---- .../database/unauthenticated_users.py | 11 --- webapp/titanembeds/blueprints/api/api.py | 66 ++++++++++++++++ 7 files changed, 110 insertions(+), 114 deletions(-) delete mode 100644 discordbot/titanembeds/database/__init__.py delete mode 100644 discordbot/titanembeds/database/unauthenticated_bans.py delete mode 100644 discordbot/titanembeds/database/unauthenticated_users.py diff --git a/discordbot/config.example.py b/discordbot/config.example.py index d9cedb1..f29ee46 100644 --- a/discordbot/config.example.py +++ b/discordbot/config.example.py @@ -5,6 +5,8 @@ config = { 'redis-uri': "redis://", + 'titan-web-url': "https://titanembeds.com/", + 'discord-bots-org-token': "DiscordBots.org Post Stats Token", 'bots-discord-pw-token': "bots.discord.pw Post Stats Token", diff --git a/discordbot/titanembeds/bot.py b/discordbot/titanembeds/bot.py index 808f941..463c65e 100644 --- a/discordbot/titanembeds/bot.py +++ b/discordbot/titanembeds/bot.py @@ -1,5 +1,4 @@ from config import config -from titanembeds.database import DatabaseInterface from titanembeds.redisqueue import RedisQueue from titanembeds.commands import Commands from titanembeds.socketio import SocketIOInterface @@ -27,9 +26,8 @@ class Titan(discord.AutoShardedClient): super().__init__(max_messages=20000) self.aiosession = aiohttp.ClientSession(loop=self.loop) self.http.user_agent += ' TitanEmbeds-Bot' - self.database = DatabaseInterface(self) self.redisqueue = RedisQueue(self, config["redis-uri"]) - self.command = Commands(self, self.database) + self.command = Commands(self, config) self.socketio = SocketIOInterface(self, config["redis-uri"]) self.delete_list = deque(maxlen=100) # List of msg ids to prevent duplicate delete @@ -64,7 +62,6 @@ class Titan(discord.AutoShardedClient): self.loop.close() async def start(self): - await self.database.connect(config["database-uri"]) await self.redisqueue.connect() self.loop.create_task(self.redisqueue.subscribe()) await super().start(config["bot-token"]) diff --git a/discordbot/titanembeds/commands.py b/discordbot/titanembeds/commands.py index 8335186..72431d3 100644 --- a/discordbot/titanembeds/commands.py +++ b/discordbot/titanembeds/commands.py @@ -1,13 +1,14 @@ +import aiohttp + class Commands(): - def __init__(self, client, database): + def __init__(self, client, config): self.client = client - self.database = database + self.config = config async def ban(self, message): if not message.author.guild_permissions.ban_members: await message.channel.send(message.author.mention + " I'm sorry, but you do not have permissions to ban guest members.") return - serverid = message.guild.id content = message.content.strip() if len(content.split()) == 2: await message.channel.send(message.author.mention + " Please provide a username-query (or optionally a discriminator) to ban a guest user.\nExample: `ban Titan#0001`") @@ -15,14 +16,30 @@ class Commands(): content = content.split() username = content[2][:content[2].find("#")] if "#" in content[2] else content[2] discriminator = int(content[2][content[2].find("#") + 1:]) if "#" in content[2] else None - reason = await self.database.ban_unauth_user_by_query(message.guild.id, message.author.id, username, discriminator) - await message.channel.send(message.author.mention + " " + reason) + headers = {"Authorization": self.config["bot-token"]} + payload = { + "guild_id": message.guild.id, + "placer_id": message.author.id, + "username": username + } + if discriminator: + payload["discriminator"] = discriminator + url = self.config["titan-web-url"] + "api/bot/ban" + async with aiohttp.ClientSession() as aioclient: + async with aioclient.post(url, json=payload, headers=headers) as resp: + j = await resp.json() + if "error" in j: + await message.channel.send(message.author.mention + " Ban error! " + j["error"]) + return + if "success" in j: + await message.channel.send(message.author.mention + " " + j["success"]) + return + await message.channel.send("Unhandled webservice error in banning guest user!") async def kick(self, message): if not message.author.guild_permissions.kick_members: await message.channel.send(message.author.mention + " I'm sorry, but you do not have permissions to kick guest members.") return - serverid = message.guild.id content = message.content.strip() if len(content.split()) == 2: await message.channel.send(message.author.mention + " Please provide a username-query (or optionally a discriminator) to kick a guest user.\nExample: `kick Titan#0001`") @@ -30,8 +47,24 @@ class Commands(): content = content.split() username = content[2][:content[2].find("#")] if "#" in content[2] else content[2] discriminator = int(content[2][content[2].find("#") + 1:]) if "#" in content[2] else None - reason = await self.database.revoke_unauth_user_by_query(message.guild.id, username, discriminator) - await message.channel.send(message.author.mention + " " + reason) + headers = {"Authorization": self.config["bot-token"]} + payload = { + "guild_id": message.guild.id, + "username": username + } + if discriminator: + payload["discriminator"] = discriminator + url = self.config["titan-web-url"] + "api/bot/revoke" + async with aiohttp.ClientSession() as aioclient: + async with aioclient.post(url, json=payload, headers=headers) as resp: + j = await resp.json() + if "error" in j: + await message.channel.send(message.author.mention + " Kick error! " + j["error"]) + return + if "success" in j: + await message.channel.send(message.author.mention + " " + j["success"]) + return + await message.channel.send("Unhandled webservice error in kicking guest user!") async def invite(self, message): await message.channel.send("You can invite Titan to your server by visiting this link: https://discordapp.com/oauth2/authorize?&client_id=299403260031139840&scope=bot&permissions=641195117") diff --git a/discordbot/titanembeds/database/__init__.py b/discordbot/titanembeds/database/__init__.py deleted file mode 100644 index 7a9c3cf..0000000 --- a/discordbot/titanembeds/database/__init__.py +++ /dev/null @@ -1,76 +0,0 @@ -from gino import Gino -import json -import discord -import datetime - -db = Gino() - -from titanembeds.database.unauthenticated_users import UnauthenticatedUsers -from titanembeds.database.unauthenticated_bans import UnauthenticatedBans - -from titanembeds.utils import get_message_author, get_message_mentions, get_webhooks_list, get_emojis_list, get_roles_list, get_channels_list, list_role_ids, get_attachments_list, get_embeds_list - -class DatabaseInterface(object): - def __init__(self, bot): - self.bot = bot - - async def connect(self, dburi): - await db.set_bind(dburi) - - async def ban_unauth_user_by_query(self, guild_id, placer_id, username, discriminator): - dbuser = None - if discriminator: - dbuser = await UnauthenticatedUsers.query \ - .where(UnauthenticatedUsers.guild_id == int(guild_id)) \ - .where(UnauthenticatedUsers.username.ilike("%" + username + "%")) \ - .where(UnauthenticatedUsers.discriminator == discriminator) \ - .order_by(UnauthenticatedUsers.id.desc()).gino.first() - else: - dbuser = await UnauthenticatedUsers.query \ - .where(UnauthenticatedUsers.guild_id == int(guild_id)) \ - .where(UnauthenticatedUsers.username.ilike("%" + username + "%")) \ - .order_by(UnauthenticatedUsers.id.desc()).gino.first() - if not dbuser: - return "Ban error! Guest user cannot be found." - dbban = await UnauthenticatedBans.query \ - .where(UnauthenticatedBans.guild_id == int(guild_id)) \ - .where(UnauthenticatedBans.last_username == dbuser.username) \ - .where(UnauthenticatedBans.last_discriminator == dbuser.discriminator).gino.first() - if dbban is not None: - if dbban.lifter_id is None: - return "Ban error! Guest user, **{}#{}**, has already been banned.".format(dbban.last_username, dbban.last_discriminator) - await dbban.delete() - dbban = await UnauthenticatedBans.create( - guild_id = int(guild_id), - ip_address = dbuser.ip_address, - last_username = dbuser.username, - last_discriminator = dbuser.discriminator, - timestamp = datetime.datetime.now(), - reason = "", - lifter_id = None, - placer_id = int(placer_id) - ) - return "Guest user, **{}#{}**, has successfully been added to the ban list!".format(dbban.last_username, dbban.last_discriminator) - - async def revoke_unauth_user_by_query(self, guild_id, username, discriminator): - dbuser = None - if discriminator: - dbuser = await UnauthenticatedUsers.query \ - .where(UnauthenticatedUsers.guild_id == int(guild_id)) \ - .where(UnauthenticatedUsers.username.ilike("%" + username + "%")) \ - .where(UnauthenticatedUsers.discriminator == discriminator) \ - .order_by(UnauthenticatedUsers.id.desc()).gino.first() - else: - dbuser = await UnauthenticatedUsers.query \ - .where(UnauthenticatedUsers.guild_id == int(guild_id)) \ - .where(UnauthenticatedUsers.username.ilike("%" + username + "%")) \ - .order_by(UnauthenticatedUsers.id.desc()).gino.first() - if not dbuser: - return "Kick error! Guest user cannot be found." - elif dbuser.revoked: - return "Kick error! Guest user **{}#{}** has already been kicked!".format(dbuser.username, dbuser.discriminator) - await dbuser.update(revoked = True).apply() - return "Successfully kicked **{}#{}**!".format(dbuser.username, dbuser.discriminator) - - async def delete_all_messages_from_channel(self, channel_id): - await Messages.delete.where(Messages.channel_id == int(channel_id)).gino.status() \ No newline at end of file diff --git a/discordbot/titanembeds/database/unauthenticated_bans.py b/discordbot/titanembeds/database/unauthenticated_bans.py deleted file mode 100644 index adfad16..0000000 --- a/discordbot/titanembeds/database/unauthenticated_bans.py +++ /dev/null @@ -1,15 +0,0 @@ -from titanembeds.database import db -import datetime -import time - -class UnauthenticatedBans(db.Model): - __tablename__ = "unauthenticated_bans" - id = db.Column(db.Integer, primary_key=True) # Auto increment id - guild_id = db.Column(db.String(255)) # Guild pretaining to the unauthenticated user - ip_address = db.Column(db.String(255)) # The IP Address of the user - last_username = db.Column(db.String(255)) # The username when they got banned - last_discriminator = db.Column(db.Integer) # The discrim when they got banned - timestamp = db.Column(db.TIMESTAMP) # The timestamp of when the user got banned - reason = db.Column(db.Text()) # The reason of the ban set by the guild moderators - lifter_id = db.Column(db.BigInteger) # Discord Client ID of the user who lifted the ban - placer_id = db.Column(db.BigInteger) # The id of who placed the ban \ No newline at end of file diff --git a/discordbot/titanembeds/database/unauthenticated_users.py b/discordbot/titanembeds/database/unauthenticated_users.py deleted file mode 100644 index 3e8e689..0000000 --- a/discordbot/titanembeds/database/unauthenticated_users.py +++ /dev/null @@ -1,11 +0,0 @@ -from titanembeds.database import db - -class UnauthenticatedUsers(db.Model): - __tablename__ = "unauthenticated_users" - id = db.Column(db.Integer, primary_key=True) # Auto increment id - guild_id = db.Column(db.BigInteger) # Guild pretaining to the unauthenticated user - username = db.Column(db.String(255)) # The username of the user - discriminator = db.Column(db.Integer) # The discriminator to distinguish unauth users with each other - user_key = db.Column(db.Text()) # The secret key used to identify the user holder - ip_address = db.Column(db.String(255)) # The IP Address of the user - revoked = db.Column(db.Boolean()) # If the user's key has been revoked and a new one is required to be generated \ No newline at end of file diff --git a/webapp/titanembeds/blueprints/api/api.py b/webapp/titanembeds/blueprints/api/api.py index 56fe4e5..3219944 100644 --- a/webapp/titanembeds/blueprints/api/api.py +++ b/webapp/titanembeds/blueprints/api/api.py @@ -551,6 +551,72 @@ def webhook_discordbotsorg_vote(): db.session.commit() return ('', 204) +@api.route("/bot/ban", methods=["POST"]) +def bot_ban(): + if request.headers.get("Authorization", "") != config.get("bot-token", ""): + return jsonify(error="Authorization header does not match."), 403 + incoming = request.get_json() + guild_id = incoming.get("guild_id", None) + placer_id = incoming.get("placer_id", None) + username = incoming.get("username", None) + discriminator = incoming.get("discriminator", None) + if not guild_id or not placer_id or not username: + return jsonify(error="Missing required parameters."), 400 + if discriminator: + dbuser = db.session.query(UnauthenticatedUsers) \ + .filter(UnauthenticatedUsers.guild_id == int(guild_id)) \ + .filter(UnauthenticatedUsers.username.ilike("%" + username + "%")) \ + .filter(UnauthenticatedUsers.discriminator == discriminator) \ + .order_by(UnauthenticatedUsers.id.desc()).first() + else: + dbuser = db.session.query(UnauthenticatedUsers) \ + .filter(UnauthenticatedUsers.guild_id == int(guild_id)) \ + .filter(UnauthenticatedUsers.username.ilike("%" + username + "%")) \ + .order_by(UnauthenticatedUsers.id.desc()).first() + if not dbuser: + return jsonify(error="Guest user cannot be found."), 404 + dbban = db.session.query(UnauthenticatedBans) \ + .filter(UnauthenticatedBans.guild_id == int(guild_id)) \ + .filter(UnauthenticatedBans.last_username == dbuser.username) \ + .filter(UnauthenticatedBans.last_discriminator == dbuser.discriminator).first() + if dbban is not None: + if dbban.lifter_id is None: + return jsonify(error="Guest user, **{}#{}**, has already been banned.".format(dbban.last_username, dbban.last_discriminator)), 409 + db.session.delete(dbban) + dbban = UnauthenticatedBans(int(guild_id), dbuser.ip_address, dbuser.username, dbuser.discriminator, "", int(placer_id)) + db.session.add(dbban) + db.session.commit() + return jsonify(success="Guest user, **{}#{}**, has successfully been added to the ban list!".format(dbban.last_username, dbban.last_discriminator)) + +@api.route("/bot/revoke", methods=["POST"]) +def bot_revoke(): + if request.headers.get("Authorization", "") != config.get("bot-token", ""): + return jsonify(error="Authorization header does not match."), 403 + incoming = request.get_json() + guild_id = incoming.get("guild_id", None) + username = incoming.get("username", None) + discriminator = incoming.get("discriminator", None) + if not guild_id or not username: + return jsonify(error="Missing required parameters."), 400 + if discriminator: + dbuser = db.session.query(UnauthenticatedUsers) \ + .filter(UnauthenticatedUsers.guild_id == int(guild_id)) \ + .filter(UnauthenticatedUsers.username.ilike("%" + username + "%")) \ + .filter(UnauthenticatedUsers.discriminator == discriminator) \ + .order_by(UnauthenticatedUsers.id.desc()).first() + else: + dbuser = db.session.query(UnauthenticatedUsers) \ + .filter(UnauthenticatedUsers.guild_id == int(guild_id)) \ + .filter(UnauthenticatedUsers.username.ilike("%" + username + "%")) \ + .order_by(UnauthenticatedUsers.id.desc()).first() + if not dbuser: + return jsonify(error="Guest user cannot be found."), 404 + elif dbuser.revoked: + return jsonify(error="Guest user **{}#{}** has already been kicked!".format(dbuser.username, dbuser.discriminator)), 409 + dbuser.revoked = True + db.session.commit() + return jsonify(success="Successfully kicked **{}#{}**!".format(dbuser.username, dbuser.discriminator)) + @api.route("/af/direct_message", methods=["POST"]) def af_direct_message_post(): cs = request.form.get('cs', None)