diff --git a/discordbot/titanembeds/bot.py b/discordbot/titanembeds/bot.py index 6b04d20..706a5ce 100644 --- a/discordbot/titanembeds/bot.py +++ b/discordbot/titanembeds/bot.py @@ -98,7 +98,10 @@ class Titan(discord.Client): await self.database.update_guild(server) if server.large: await self.request_offline_members(server) - server_bans = await self.get_bans(server) + if server.me.server_permissions.ban_members: + server_bans = await self.get_bans(server) + else: + server_bans = [] for member in server.members: banned = member.id in [u.id for u in server_bans] await self.database.update_guild_member( @@ -113,17 +116,6 @@ class Titan(discord.Client): print("Skipping indexing server due to no-init flag") async def on_message(self, message): - crashChar = 'ौौौौ' - if crashChar in message.content: - try: - await bot.delete_message(message) - await bot.send_message(message.channel, - "**I've delete a message posted by {} because it contained characters which crashes discord. I've also banned him.**".format( - message.author.name + "#" + message.author.discriminator + "(ID: " + message.author.id + ")")) - await message.server.ban(message.author, "Causing discord to crash because of weird characters.") - except: - pass - return await self.wait_until_dbonline() await self.database.push_message(message) await self.socketio.on_message(message) @@ -149,21 +141,18 @@ class Titan(discord.Client): async def on_server_join(self, guild): await self.wait_until_dbonline() - await asyncio.sleep(1) - if not guild.me.server_permissions.administrator: - await asyncio.sleep(1) - await self.leave_server(guild) - return - await self.database.update_guild(guild) for channel in guild.channels: + if not channel.permissions_for(channel.server.me).read_messages: + continue async for message in self.logs_from(channel, limit=50, reverse=True): await self.database.push_message(message) for member in guild.members: await self.database.update_guild_member(member, True, False) - banned = await self.get_bans(guild) - for ban in banned: - await self.database.update_guild_member(ban, False, True) + if guild.me.server_permissions.ban_members: + banned = await self.get_bans(guild) + for ban in banned: + await self.database.update_guild_member(ban, False, True) async def on_server_remove(self, guild): await self.wait_until_dbonline() diff --git a/discordbot/titanembeds/database/__init__.py b/discordbot/titanembeds/database/__init__.py index 621731a..398700c 100644 --- a/discordbot/titanembeds/database/__init__.py +++ b/discordbot/titanembeds/database/__init__.py @@ -98,7 +98,10 @@ class DatabaseInterface(object): session.commit() async def update_guild(self, guild): - server_webhooks = await self.bot.get_server_webhooks(guild) + if guild.me.server_permissions.manage_webhooks: + server_webhooks = await self.bot.get_server_webhooks(guild) + else: + server_webhooks = [] async with threadpool(): with self.get_session() as session: gui = session.query(Guilds).filter(Guilds.guild_id == guild.id).first() diff --git a/webapp/titanembeds/blueprints/api/api.py b/webapp/titanembeds/blueprints/api/api.py index 7da9254..9d773e3 100644 --- a/webapp/titanembeds/blueprints/api/api.py +++ b/webapp/titanembeds/blueprints/api/api.py @@ -340,13 +340,16 @@ def change_unauthenticated_username(): def process_query_guild(guild_id, visitor=False): widget = discord_api.get_widget(guild_id) channels = get_guild_channels(guild_id, visitor) - discordmembers = get_online_discord_users(guild_id, widget) + if widget.get("success", True): + discordmembers = get_online_discord_users(guild_id, widget) + else: + discordmembers = [{"id": 0, "color": "FFD6D6", "status": "dnd", "username": "Discord Server Widget is Currently Disabled"}] embedmembers = get_online_embed_users(guild_id) emojis = get_guild_emojis(guild_id) if visitor: for channel in channels: channel["write"] = False - return jsonify(channels=channels, discordmembers=discordmembers, embedmembers=embedmembers, emojis=emojis, instant_invite=widget.get("instant_invite")) + return jsonify(channels=channels, discordmembers=discordmembers, embedmembers=embedmembers, emojis=emojis, instant_invite=widget.get("instant_invite", None)) @api.route("/query_guild", methods=["GET"]) @valid_session_required(api=True) diff --git a/webapp/titanembeds/discordrest.py b/webapp/titanembeds/discordrest.py index c3490af..c89d54f 100644 --- a/webapp/titanembeds/discordrest.py +++ b/webapp/titanembeds/discordrest.py @@ -135,6 +135,8 @@ class DiscordREST: def get_widget(self, guild_id): _endpoint = _DISCORD_API_BASE + "/servers/{guild_id}/widget.json".format(guild_id=guild_id) embed = self.get_guild_embed(guild_id) + if not embed.get("success", True): + return {"success": False} if not embed['content']['enabled']: self.modify_guild_embed(guild_id, enabled=True, channel_id=guild_id) widget = requests.get(_endpoint).json() diff --git a/webapp/titanembeds/oauth.py b/webapp/titanembeds/oauth.py index e160549..e0bfab9 100644 --- a/webapp/titanembeds/oauth.py +++ b/webapp/titanembeds/oauth.py @@ -96,5 +96,5 @@ def generate_guild_icon_url(id, hash): return guild_icon_url + str(id) + "/" + str(hash) + ".jpg" def generate_bot_invite_url(guild_id): - url = "https://discordapp.com/oauth2/authorize?&client_id={}&scope=bot&permissions={}&guild_id={}".format(config['client-id'], '536083583', guild_id) + url = "https://discordapp.com/oauth2/authorize?&client_id={}&scope=bot&permissions={}&guild_id={}".format(config['client-id'], '537349164', guild_id) return url diff --git a/webapp/titanembeds/templates/add_bot.html.j2 b/webapp/titanembeds/templates/add_bot.html.j2 index 4a6b77a..a51b16b 100644 --- a/webapp/titanembeds/templates/add_bot.html.j2 +++ b/webapp/titanembeds/templates/add_bot.html.j2 @@ -3,8 +3,8 @@ {% block content %}

Would you like to invite Titan to your server?

-

Please keep in mind that Titan currently requires Administrator permissions to function.
-This is strictly enforced for the bot to send messages to all the channels, read role permissions, access banned users list, etc.

+

Please keep in mind that Titan works best with Administrator permissions to function.
+However this is not required. For those who do not want to give Titan Administrator, we've handpicked the permissions to give Titan for the best experience.

@@ -32,8 +32,7 @@ This is strictly enforced for the bot to send messages to all the channels, read

Step 2

Oops!
-

There seems to be a problem processing the invite.
- Please make sure that the bot is given Administrator permission in the server.

+

There seems to be a problem processing the invite.


You may try adding the bot to the server again, or report the bug on our Discord server.

diff --git a/webapp/titanembeds/userbookkeeping.py b/webapp/titanembeds/userbookkeeping.py index 13954af..2588d1c 100644 --- a/webapp/titanembeds/userbookkeeping.py +++ b/webapp/titanembeds/userbookkeeping.py @@ -1,6 +1,7 @@ from titanembeds.database import db, Guilds, UnauthenticatedUsers, UnauthenticatedBans, AuthenticatedUsers, GuildMembers, get_guild_member from titanembeds.utils import guild_accepts_visitors, guild_query_unauth_users_bool, get_client_ipaddr from titanembeds.oauth import check_user_can_administrate_guild, user_has_permission +from config import config from flask import session from sqlalchemy import and_ import json @@ -107,6 +108,9 @@ def get_guild_channels(guild_id, force_everyone=False): member_roles = get_member_roles(guild_id, session['user_id']) if guild_id not in member_roles: member_roles.append(guild_id) + bot_member_roles = get_member_roles(guild_id, config["client-id"]) + if guild_id not in bot_member_roles: + bot_member_roles.append(guild_id) dbguild = db.session.query(Guilds).filter(Guilds.guild_id == guild_id).first() guild_channels = json.loads(dbguild.channels) guild_roles = json.loads(dbguild.roles) @@ -114,70 +118,99 @@ def get_guild_channels(guild_id, force_everyone=False): result_channels = [] for channel in guild_channels: if channel['type'] == "text": - result = {"channel": channel, "read": False, "write": False, "mention_everyone": False} - if guild_owner == session.get("user_id"): - result["read"] = True - result["write"] = True - result["mention_everyone"] = True - result_channels.append(result) - continue - channel_perm = 0 - - # @everyone - for role in guild_roles: - if role["id"] == guild_id: - channel_perm |= role["permissions"] - continue - - # User Guild Roles - for m_role in member_roles: - for g_role in guild_roles: - if g_role["id"] == m_role: - channel_perm |= g_role["permissions"] - continue - - # If has server administrator permission - if user_has_permission(channel_perm, 3): - result["read"] = True - result["write"] = True - result["mention_everyone"] = True - result_channels.append(result) - continue - - denies = 0 - allows = 0 - - # channel specific - for overwrite in channel["permission_overwrites"]: - if overwrite["type"] == "role" and overwrite["id"] in member_roles: - denies |= overwrite["deny"] - allows |= overwrite["allow"] - - channel_perm = (channel_perm & ~denies) | allows - - # member specific - for overwrite in channel["permission_overwrites"]: - if overwrite["type"] == "member" and overwrite["id"] == session.get("user_id"): - channel_perm = (channel_perm & ~overwrite['deny']) | overwrite['allow'] - break - - result["read"] = user_has_permission(channel_perm, 10) - result["write"] = user_has_permission(channel_perm, 11) - result["mention_everyone"] = user_has_permission(channel_perm, 17) - - # If default channel, you can read - if channel["id"] == guild_id: - result["read"] = True - - # If you cant read channel, you cant write in it - if not user_has_permission(channel_perm, 10): + result = get_channel_permission(channel, guild_id, guild_owner, guild_roles, member_roles, session.get("user_id"), force_everyone) + bot_result = get_channel_permission(channel, guild_id, guild_owner, guild_roles, bot_member_roles, config["client-id"], False) + if not bot_result["read"]: result["read"] = False + if not bot_result["write"]: result["write"] = False + if not bot_result["mention_everyone"]: result["mention_everyone"] = False - result_channels.append(result) return sorted(result_channels, key=lambda k: k['channel']['position']) +def get_channel_permission(channel, guild_id, guild_owner, guild_roles, member_roles, user_id=None, force_everyone=False): + result = {"channel": channel, "read": False, "write": False, "mention_everyone": False} + if not user_id: + user_id = session.get("user_id") + if guild_owner == user_id: + result["read"] = True + result["write"] = True + result["mention_everyone"] = True + return result + channel_perm = 0 + + # @everyone + for role in guild_roles: + if role["id"] == guild_id: + channel_perm |= role["permissions"] + continue + + # User Guild Roles + for m_role in member_roles: + for g_role in guild_roles: + if g_role["id"] == m_role: + channel_perm |= g_role["permissions"] + continue + + # If has server administrator permission + if user_has_permission(channel_perm, 3): + result["read"] = True + result["write"] = True + result["mention_everyone"] = True + return result + + denies = 0 + allows = 0 + + # channel specific + for overwrite in channel["permission_overwrites"]: + if overwrite["type"] == "role" and overwrite["id"] in member_roles: + denies |= overwrite["deny"] + allows |= overwrite["allow"] + + channel_perm = (channel_perm & ~denies) | allows + + # member specific + for overwrite in channel["permission_overwrites"]: + if overwrite["type"] == "member" and overwrite["id"] == session.get("user_id"): + channel_perm = (channel_perm & ~overwrite['deny']) | overwrite['allow'] + break + + result["read"] = user_has_permission(channel_perm, 10) + result["write"] = user_has_permission(channel_perm, 11) + result["mention_everyone"] = user_has_permission(channel_perm, 17) + + # If default channel, you can read + if channel["id"] == guild_id: + result["read"] = True + + # If you cant read channel, you cant write in it + if not user_has_permission(channel_perm, 10): + result["read"] = False + result["write"] = False + result["mention_everyone"] = False + return result + +def bot_can_create_webhooks(guild): + perm = 0 + guild_roles = json.loads(guild.roles) + # @everyone + for role in guild_roles: + if role["id"] == guild.guild_id: + perm |= role["permissions"] + continue + member_roles = get_member_roles(guild.guild_id, config["client-id"]) + # User Guild Roles + for m_role in member_roles: + for g_role in guild_roles: + if g_role["id"] == m_role: + perm |= g_role["permissions"] + continue + return user_has_permission(perm, 29) + def guild_webhooks_enabled(guild_id): dbguild = db.session.query(Guilds).filter(Guilds.guild_id == guild_id).first() - return dbguild.webhook_messages \ No newline at end of file + if not dbguild.webhook_messages: + return False + return bot_can_create_webhooks(dbguild) \ No newline at end of file