Remove global header when the bot is not connected to the database

This commit is contained in:
Jeremy Zhang 2017-09-11 20:33:20 +00:00
parent 9ef8ef7c90
commit 8a7e3322b9
9 changed files with 3 additions and 110 deletions

View File

@ -5,7 +5,5 @@ config = {
'redis-uri': "redis://", 'redis-uri': "redis://",
'errorreporting-channelid': "",
'logging-location': "/home/titan/Titan/discordbot/titanbot.log", 'logging-location': "/home/titan/Titan/discordbot/titanbot.log",
} }

View File

@ -21,9 +21,6 @@ class Titan(discord.Client):
self.database = DatabaseInterface(self) self.database = DatabaseInterface(self)
self.command = Commands(self, self.database) self.command = Commands(self, self.database)
self.socketio = SocketIOInterface(self, config["redis-uri"]) self.socketio = SocketIOInterface(self, config["redis-uri"])
self.database_connected = False
self.loop.create_task(self.send_webserver_heartbeat())
def _cleanup(self): def _cleanup(self):
try: try:
@ -38,29 +35,6 @@ class Titan(discord.Client):
gathered.exception() gathered.exception()
except: # Can be ignored except: # Can be ignored
pass pass
async def wait_until_dbonline(self):
while not self.database_connected:
await asyncio.sleep(1) # Wait until db is connected
async def send_webserver_heartbeat(self):
await self.wait_until_ready()
await self.wait_until_dbonline()
last_db_conn_status = False
while not self.is_closed:
try:
await self.database.send_webserver_heartbeat()
self.database_connected = True
except:
self.database_connected = False
if last_db_conn_status != self.database_connected and config.get("errorreporting-channelid"):
error_channel = self.get_channel(config["errorreporting-channelid"])
if self.database_connected:
await self.send_message(error_channel, "Titan has obtained connection to the database!")
else:
await self.send_message(error_channel, "Titan has lost connection to the database! Don't panic!! We'll sort this out... hopefully soon.")
last_db_conn_status = self.database_connected
await asyncio.sleep(60)
def run(self): def run(self):
try: try:
@ -87,7 +61,6 @@ class Titan(discord.Client):
try: try:
await self.database.connect(config["database-uri"]) await self.database.connect(config["database-uri"])
self.database_connected = True
except Exception: except Exception:
self.logger.error("Unable to connect to specified database!") self.logger.error("Unable to connect to specified database!")
traceback.print_exc() traceback.print_exc()
@ -117,7 +90,6 @@ class Titan(discord.Client):
print("Skipping indexing server due to no-init flag") print("Skipping indexing server due to no-init flag")
async def on_message(self, message): async def on_message(self, message):
await self.wait_until_dbonline()
await self.database.push_message(message) await self.database.push_message(message)
await self.socketio.on_message(message) await self.socketio.on_message(message)
@ -131,17 +103,14 @@ class Titan(discord.Client):
await getattr(self.command, msg_cmd)(message) #actually run cmd, passing in msg obj await getattr(self.command, msg_cmd)(message) #actually run cmd, passing in msg obj
async def on_message_edit(self, message_before, message_after): async def on_message_edit(self, message_before, message_after):
await self.wait_until_dbonline()
await self.database.update_message(message_after) await self.database.update_message(message_after)
await self.socketio.on_message_update(message_after) await self.socketio.on_message_update(message_after)
async def on_message_delete(self, message): async def on_message_delete(self, message):
await self.wait_until_dbonline()
await self.database.delete_message(message) await self.database.delete_message(message)
await self.socketio.on_message_delete(message) await self.socketio.on_message_delete(message)
async def on_server_join(self, guild): async def on_server_join(self, guild):
await self.wait_until_dbonline()
await self.database.update_guild(guild) await self.database.update_guild(guild)
for channel in guild.channels: for channel in guild.channels:
if not channel.permissions_for(channel.server.me).read_messages: if not channel.permissions_for(channel.server.me).read_messages:
@ -156,75 +125,61 @@ class Titan(discord.Client):
await self.database.update_guild_member(ban, False, True) await self.database.update_guild_member(ban, False, True)
async def on_server_remove(self, guild): async def on_server_remove(self, guild):
await self.wait_until_dbonline()
await self.database.remove_guild(guild) await self.database.remove_guild(guild)
async def on_server_update(self, guildbefore, guildafter): async def on_server_update(self, guildbefore, guildafter):
await self.wait_until_dbonline()
await self.database.update_guild(guildafter) await self.database.update_guild(guildafter)
await self.socketio.on_guild_update(guildafter) await self.socketio.on_guild_update(guildafter)
async def on_server_role_create(self, role): async def on_server_role_create(self, role):
await self.wait_until_dbonline()
if role.name == self.user.name and role.managed: if role.name == self.user.name and role.managed:
await asyncio.sleep(2) await asyncio.sleep(2)
await self.database.update_guild(role.server) await self.database.update_guild(role.server)
await self.socketio.on_guild_role_create(role) await self.socketio.on_guild_role_create(role)
async def on_server_role_delete(self, role): async def on_server_role_delete(self, role):
await self.wait_until_dbonline()
if role.server.me not in role.server.members: if role.server.me not in role.server.members:
return return
await self.database.update_guild(role.server) await self.database.update_guild(role.server)
await self.socketio.on_guild_role_delete(role) await self.socketio.on_guild_role_delete(role)
async def on_server_role_update(self, rolebefore, roleafter): async def on_server_role_update(self, rolebefore, roleafter):
await self.wait_until_dbonline()
await self.database.update_guild(roleafter.server) await self.database.update_guild(roleafter.server)
await self.socketio.on_guild_role_update(roleafter) await self.socketio.on_guild_role_update(roleafter)
async def on_channel_delete(self, channel): async def on_channel_delete(self, channel):
await self.wait_until_dbonline()
await self.database.update_guild(channel.server) await self.database.update_guild(channel.server)
await self.socketio.on_channel_delete(channel) await self.socketio.on_channel_delete(channel)
async def on_channel_create(self, channel): async def on_channel_create(self, channel):
await self.wait_until_dbonline()
await self.database.update_guild(channel.server) await self.database.update_guild(channel.server)
await self.socketio.on_channel_create(channel) await self.socketio.on_channel_create(channel)
async def on_channel_update(self, channelbefore, channelafter): async def on_channel_update(self, channelbefore, channelafter):
await self.wait_until_dbonline()
await self.database.update_guild(channelafter.server) await self.database.update_guild(channelafter.server)
await self.socketio.on_channel_update(channelafter) await self.socketio.on_channel_update(channelafter)
async def on_member_join(self, member): async def on_member_join(self, member):
await self.wait_until_dbonline()
await self.database.update_guild_member(member, active=True, banned=False) await self.database.update_guild_member(member, active=True, banned=False)
await self.socketio.on_guild_member_add(member) await self.socketio.on_guild_member_add(member)
async def on_member_remove(self, member): async def on_member_remove(self, member):
await self.wait_until_dbonline()
await self.database.update_guild_member(member, active=False, banned=False) await self.database.update_guild_member(member, active=False, banned=False)
await self.socketio.on_guild_member_remove(member) await self.socketio.on_guild_member_remove(member)
async def on_member_update(self, memberbefore, memberafter): async def on_member_update(self, memberbefore, memberafter):
await self.wait_until_dbonline()
await self.database.update_guild_member(memberafter) await self.database.update_guild_member(memberafter)
await self.socketio.on_guild_member_update(memberafter) await self.socketio.on_guild_member_update(memberafter)
async def on_member_ban(self, member): async def on_member_ban(self, member):
await self.wait_until_dbonline()
if self.user.id == member.id: if self.user.id == member.id:
return return
await self.database.update_guild_member(member, active=False, banned=True) await self.database.update_guild_member(member, active=False, banned=True)
async def on_member_unban(self, server, user): async def on_member_unban(self, server, user):
await self.wait_until_dbonline()
await self.database.unban_server_user(user, server) await self.database.unban_server_user(user, server)
async def on_server_emojis_update(self, before, after): async def on_server_emojis_update(self, before, after):
await self.wait_until_dbonline()
if len(after) == 0: if len(after) == 0:
await self.database.update_guild(before[0].server) await self.database.update_guild(before[0].server)
await self.socketio.on_guild_emojis_update(before) await self.socketio.on_guild_emojis_update(before)
@ -233,7 +188,6 @@ class Titan(discord.Client):
await self.socketio.on_guild_emojis_update(after) await self.socketio.on_guild_emojis_update(after)
async def on_webhooks_update(self, server): async def on_webhooks_update(self, server):
await self.wait_until_dbonline()
await self.database.update_guild(server) await self.database.update_guild(server)
async def on_socket_raw_receive(self, msg): async def on_socket_raw_receive(self, msg):

View File

@ -7,7 +7,6 @@ from sqlalchemy.ext.declarative import declarative_base
import json import json
import discord import discord
import time
Base = declarative_base() Base = declarative_base()
@ -16,7 +15,6 @@ from titanembeds.database.messages import Messages
from titanembeds.database.guild_members import GuildMembers from titanembeds.database.guild_members import GuildMembers
from titanembeds.database.unauthenticated_users import UnauthenticatedUsers from titanembeds.database.unauthenticated_users import UnauthenticatedUsers
from titanembeds.database.unauthenticated_bans import UnauthenticatedBans from titanembeds.database.unauthenticated_bans import UnauthenticatedBans
from titanembeds.database.keyvalue_properties import KeyValueProperties
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 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
@ -289,15 +287,3 @@ class DatabaseInterface(object):
dbuser.revoked = True dbuser.revoked = True
session.commit() session.commit()
return "Successfully kicked **{}#{}**!".format(dbuser.username, dbuser.discriminator) return "Successfully kicked **{}#{}**!".format(dbuser.username, dbuser.discriminator)
async def send_webserver_heartbeat(self):
async with threadpool():
with self.get_session() as session:
key = "bot_heartbeat"
q = session.query(KeyValueProperties).filter(KeyValueProperties.key == key)
if q.count() == 0:
session.add(KeyValueProperties(key=key, value=time.time()))
else:
firstobj = q.first()
firstobj.value = time.time()
session.commit()

View File

@ -1,17 +0,0 @@
from titanembeds.database import db, Base
import datetime
class KeyValueProperties(Base):
__tablename__ = "keyvalue_properties"
id = db.Column(db.Integer, primary_key=True) # Auto incremented id
key = db.Column(db.String(255), nullable=False) # Property Key
value = db.Column(db.Text()) # Property value
expiration = db.Column(db.TIMESTAMP) # Suggested Expiration for value (None = no expire) in secs
def __init__(self, key, value, expiration=None):
self.key = key
self.value = value
if expiration:
self.expiration = datetime.now() + timedelta(seconds = expiration)
else:
self.expiration = None

View File

@ -2,7 +2,7 @@ from config import config
from .database import db from .database import db
from flask import Flask, render_template, request, session, url_for, redirect, jsonify from flask import Flask, render_template, request, session, url_for, redirect, jsonify
from flask_sslify import SSLify from flask_sslify import SSLify
from titanembeds.utils import rate_limiter, discord_api, bot_alive, socketio from titanembeds.utils import rate_limiter, discord_api, socketio
from .blueprints import api, user, admin, embed, gateway from .blueprints import api, user, admin, embed, gateway
import os import os
from titanembeds.database import get_administrators_list from titanembeds.database import get_administrators_list
@ -53,5 +53,4 @@ def before_request():
@app.context_processor @app.context_processor
def context_processor(): def context_processor():
bot_status = bot_alive() return {"devs": get_administrators_list()}
return {"bot_status": bot_status, "devs": get_administrators_list()}

View File

@ -24,7 +24,6 @@
{% endif %} {% endif %}
</head> </head>
<body> <body>
{% include 'nobot_header.html.j2' %}
<div class="navbar-fixed"> <div class="navbar-fixed">
<nav> <nav>
<div class="nav-wrapper"> <div class="nav-wrapper">
@ -78,7 +77,6 @@
<div id="loginmodal" class="modal"> <div id="loginmodal" class="modal">
<div class="modal-content"> <div class="modal-content">
{% include 'nobot_header.html.j2' %}
<h4>{{ login_greeting }}</h4> <h4>{{ login_greeting }}</h4>
<div id="loginmodal-maincontent" class="row valign-wrap"> <div id="loginmodal-maincontent" class="row valign-wrap">
<div id="modal_guildinfobox" class="col m3 s12 center-align"> <div id="modal_guildinfobox" class="col m3 s12 center-align">

View File

@ -1,10 +0,0 @@
{% if not bot_status["status"] %}
<div style="border: solid 3px red; background-color: yellow; color: black;">
<p>
<strong>NOTICE!</strong>
The bot is <strong>currently not online</strong> or has <strong>lost the connection</strong> to the webserver.
If you see this header, please <a href="https://discord.io/titan" target="_blank" style="background-color: orange; color: blue;">notify us</a> as soon as possible for us to fix this issue.
Down since approximately <code>{{ bot_status["formatted_utc"] }}</code> UTC (<code>{{ bot_status["epoch_seconds"] }} epoch seconds</code>).
</p>
</div>
{% endif %}

View File

@ -23,7 +23,6 @@
{% include 'google_analytics.html.j2' %} {% include 'google_analytics.html.j2' %}
</head> </head>
<body> <body>
{% include 'nobot_header.html.j2' %}
<main> <main>
{% if session['unauthenticated'] is defined and not session['unauthenticated'] %} {% if session['unauthenticated'] is defined and not session['unauthenticated'] %}
<ul id="menu_dropdown" class="dropdown-content"> <ul id="menu_dropdown" class="dropdown-content">

View File

@ -1,4 +1,4 @@
from titanembeds.database import db, Guilds, KeyValueProperties, get_keyvalproperty from titanembeds.database import db, Guilds
from flask import request, session from flask import request, session
from flask_limiter import Limiter from flask_limiter import Limiter
from flask_socketio import SocketIO from flask_socketio import SocketIO
@ -74,20 +74,6 @@ def guild_accepts_visitors(guild_id):
def guild_query_unauth_users_bool(guild_id): def guild_query_unauth_users_bool(guild_id):
dbGuild = db.session.query(Guilds).filter(Guilds.guild_id==guild_id).first() dbGuild = db.session.query(Guilds).filter(Guilds.guild_id==guild_id).first()
return dbGuild.unauth_users return dbGuild.unauth_users
def bot_alive():
results = {"status": False, "formatted_utc": "Never", "epoch_seconds": None}
epoch = get_keyvalproperty("bot_heartbeat")
if not epoch:
return results
epoch = float(epoch)
utc = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(epoch))
results["formatted_utc"] = utc
results["epoch_seconds"] = epoch
now = time.time()
if now - epoch < 60 * 5:
results["status"] = True
return results
rate_limiter = Limiter(key_func=get_client_ipaddr) # Default limit by ip address rate_limiter = Limiter(key_func=get_client_ipaddr) # Default limit by ip address
socketio = SocketIO() socketio = SocketIO()