2021-09-11 16:18:35 +00:00
from sanic import Sanic
2021-09-16 22:40:05 +00:00
from sanic . exceptions import NotFound , ServerError , abort
2021-08-17 22:54:24 +00:00
from sanic . response import html , file , redirect
2021-04-18 01:03:44 +00:00
from sanic . response import json as resp_json
from sanic_cors import CORS
2021-04-18 02:52:34 +00:00
from syncer import sync
2021-04-18 20:32:31 +00:00
import asyncio
2021-04-18 01:03:44 +00:00
from jinja2 import Environment , FileSystemLoader
2021-09-01 21:25:44 +00:00
from jinja2 . utils import select_autoescape
2021-04-18 01:03:44 +00:00
from urllib . parse import unquote
2021-04-17 20:28:57 +00:00
from setproctitle import setproctitle
from typing import Any , Optional , List
from multiprocessing . queues import Queue
from queue import Empty
from time import sleep
import json
2021-04-18 01:03:44 +00:00
import os
2021-04-17 20:28:57 +00:00
2021-09-11 15:49:08 +00:00
from helpers . os_environment import (
isBundelled ,
resolve_external_file_path ,
resolve_local_file_path ,
)
2021-04-17 20:28:57 +00:00
from helpers . logging_manager import LoggingManager
from helpers . device_manager import DeviceManager
from helpers . state_manager import StateManager
2021-04-18 01:03:44 +00:00
from helpers . the_terminator import Terminator
2021-09-01 21:25:44 +00:00
from helpers . normalisation import get_normalised_filename_if_available
from helpers . myradio_api import MyRadioAPI
2021-09-11 22:44:15 +00:00
from helpers . alert_manager import AlertManager
2021-04-17 20:28:57 +00:00
2021-09-11 15:49:08 +00:00
env = Environment (
loader = FileSystemLoader ( " %s /ui-templates/ " % os . path . dirname ( __file__ ) ) ,
autoescape = select_autoescape ( ) ,
)
2021-08-17 22:54:24 +00:00
2021-09-08 23:34:54 +00:00
LOG_FILEPATH = resolve_external_file_path ( " logs " )
LOG_FILENAME = LOG_FILEPATH + " /WebServer.log "
2021-08-17 22:54:24 +00:00
# From Sanic's default, but set to log to file.
2021-09-08 23:34:54 +00:00
os . makedirs ( LOG_FILEPATH , exist_ok = True )
2021-08-17 22:54:24 +00:00
LOGGING_CONFIG = dict (
version = 1 ,
disable_existing_loggers = False ,
loggers = {
" sanic.root " : { " level " : " INFO " , " handlers " : [ " file " ] } ,
" sanic.error " : {
" level " : " INFO " ,
" handlers " : [ " error_file " ] ,
" propagate " : True ,
" qualname " : " sanic.error " ,
} ,
" sanic.access " : {
" level " : " INFO " ,
" handlers " : [ " access_file " ] ,
" propagate " : True ,
" qualname " : " sanic.access " ,
} ,
} ,
handlers = {
" file " : {
" class " : " logging.FileHandler " ,
" formatter " : " generic " ,
2021-09-11 15:49:08 +00:00
" filename " : LOG_FILENAME ,
2021-08-17 22:54:24 +00:00
} ,
" error_file " : {
" class " : " logging.FileHandler " ,
" formatter " : " generic " ,
2021-09-11 15:49:08 +00:00
" filename " : LOG_FILENAME ,
2021-08-17 22:54:24 +00:00
} ,
" access_file " : {
" class " : " logging.FileHandler " ,
" formatter " : " access " ,
2021-09-11 15:49:08 +00:00
" filename " : LOG_FILENAME ,
2021-08-17 22:54:24 +00:00
} ,
} ,
formatters = {
" generic " : {
" format " : " %(asctime)s | [ %(process)d ] [ %(levelname)s ] %(message)s " ,
" class " : " logging.Formatter " ,
} ,
" access " : {
" format " : " %(asctime)s | ( %(name)s )[ %(levelname)s ][ %(host)s ]: "
+ " %(request)s %(message)s %(status)d %(byte)d " ,
" class " : " logging.Formatter " ,
} ,
} ,
)
app = Sanic ( " BAPSicle Web Server " , log_config = LOGGING_CONFIG )
2021-04-18 01:03:44 +00:00
def render_template ( file , data , status = 200 ) :
template = env . get_template ( file )
html_content = template . render ( data = data )
return html ( html_content , status = status )
2021-04-17 20:28:57 +00:00
logger : LoggingManager
server_state : StateManager
2021-04-18 02:14:14 +00:00
api : MyRadioAPI
2021-09-11 22:44:15 +00:00
alerts : AlertManager
2021-04-17 20:28:57 +00:00
player_to_q : List [ Queue ] = [ ]
player_from_q : List [ Queue ] = [ ]
# General UI Endpoints
2021-04-18 01:03:44 +00:00
@app.exception ( NotFound )
def page_not_found ( request , e : Any ) :
2021-09-16 22:40:05 +00:00
data = { " ui_page " : " 404 " , " ui_title " : " 404 " , " code " : 404 , " title " : " Page Not Found " , " message " : " Looks like you fell off the tip of the iceberg. " }
return render_template ( " error.html " , data = data , status = 404 )
2021-04-17 20:28:57 +00:00
2021-09-16 22:40:05 +00:00
@app.exception ( Exception , ServerError )
def server_error ( request , e : Exception ) :
data = { " ui_page " : " 500 " , " ui_title " : " 500 " , " code " : 500 , " title " : " Something went very wrong! " , " message " : " Looks like the server fell over. Try viewing the WebServer logs for more details. " }
return render_template ( " error.html " , data = data , status = 500 )
2021-04-17 20:28:57 +00:00
@app.route ( " / " )
2021-04-18 01:03:44 +00:00
def ui_index ( request ) :
2021-04-27 20:48:17 +00:00
config = server_state . get ( )
2021-04-17 20:28:57 +00:00
data = {
" ui_page " : " index " ,
" ui_title " : " " ,
2021-09-11 22:44:15 +00:00
" alert_count " : alerts . alert_count_current ,
2021-04-27 20:48:17 +00:00
" server_version " : config [ " server_version " ] ,
" server_build " : config [ " server_build " ] ,
" server_name " : config [ " server_name " ] ,
" server_beta " : config [ " server_beta " ] ,
2021-09-11 15:49:08 +00:00
" server_branch " : config [ " server_branch " ] ,
2021-04-17 20:28:57 +00:00
}
return render_template ( " index.html " , data = data )
@app.route ( " /status " )
2021-04-18 01:03:44 +00:00
def ui_status ( request ) :
2021-04-17 20:28:57 +00:00
channel_states = [ ]
2021-04-18 19:27:54 +00:00
for i in range ( server_state . get ( ) [ " num_channels " ] ) :
2021-04-17 20:28:57 +00:00
channel_states . append ( status ( i ) )
2021-09-11 16:18:35 +00:00
data = { " channels " : channel_states ,
" ui_page " : " status " , " ui_title " : " Status " }
2021-04-17 20:28:57 +00:00
return render_template ( " status.html " , data = data )
2021-09-11 22:44:15 +00:00
@app.route ( " /alerts " )
def ui_alerts ( request ) :
channel_states = [ ]
for i in range ( server_state . get ( ) [ " num_channels " ] ) :
channel_states . append ( status ( i ) )
data = {
" alerts_current " : alerts . alerts_current ,
" alerts_count_current " : alerts . alert_count_current ,
" ui_page " : " alerts " ,
" ui_title " : " Alerts "
}
return render_template ( " alerts.html " , data = data )
2021-04-17 20:28:57 +00:00
@app.route ( " /config/player " )
2021-04-18 01:03:44 +00:00
def ui_config_player ( request ) :
2021-04-17 20:28:57 +00:00
channel_states = [ ]
2021-04-18 19:27:54 +00:00
for i in range ( server_state . get ( ) [ " num_channels " ] ) :
2021-04-17 20:28:57 +00:00
channel_states . append ( status ( i ) )
outputs = DeviceManager . getAudioOutputs ( )
data = {
" channels " : channel_states ,
" outputs " : outputs ,
" ui_page " : " config " ,
" ui_title " : " Player Config " ,
}
return render_template ( " config_player.html " , data = data )
@app.route ( " /config/server " )
2021-04-18 01:03:44 +00:00
def ui_config_server ( request ) :
2021-04-17 20:28:57 +00:00
data = {
" ui_page " : " server " ,
" ui_title " : " Server Config " ,
2021-04-18 19:27:54 +00:00
" state " : server_state . get ( ) ,
2021-04-17 20:28:57 +00:00
" ser_ports " : DeviceManager . getSerialPorts ( ) ,
2021-09-11 15:49:08 +00:00
" tracklist_modes " : [ " off " , " on " , " delayed " , " fader-live " ] ,
2021-04-17 20:28:57 +00:00
}
return render_template ( " config_server.html " , data = data )
@app.route ( " /config/server/update " , methods = [ " POST " ] )
2021-04-18 01:03:44 +00:00
def ui_config_server_update ( request ) :
2021-04-22 22:14:55 +00:00
# TODO Validation!
2021-04-18 20:18:20 +00:00
server_state . update ( " server_name " , request . form . get ( " name " ) )
server_state . update ( " host " , request . form . get ( " host " ) )
server_state . update ( " port " , int ( request . form . get ( " port " ) ) )
server_state . update ( " num_channels " , int ( request . form . get ( " channels " ) ) )
server_state . update ( " ws_port " , int ( request . form . get ( " ws_port " ) ) )
2021-09-01 21:26:40 +00:00
serial_port = request . form . get ( " serial_port " )
2021-09-11 16:18:35 +00:00
server_state . update ( " serial_port " , None if serial_port ==
" None " else serial_port )
2021-04-17 20:28:57 +00:00
# Because we're not showing the api key once it's set.
2021-04-18 20:18:20 +00:00
if " myradio_api_key " in request . form and request . form . get ( " myradio_api_key " ) != " " :
2021-09-11 16:18:35 +00:00
server_state . update ( " myradio_api_key " ,
request . form . get ( " myradio_api_key " ) )
2021-04-17 20:28:57 +00:00
2021-09-11 16:18:35 +00:00
server_state . update ( " myradio_base_url " ,
request . form . get ( " myradio_base_url " ) )
2021-04-18 20:18:20 +00:00
server_state . update ( " myradio_api_url " , request . form . get ( " myradio_api_url " ) )
2021-09-11 15:49:08 +00:00
server_state . update (
2021-09-11 16:18:35 +00:00
" myradio_api_tracklist_source " , request . form . get (
" myradio_api_tracklist_source " )
2021-09-11 15:49:08 +00:00
)
2021-04-22 22:14:55 +00:00
server_state . update ( " tracklist_mode " , request . form . get ( " tracklist_mode " ) )
2021-04-18 20:18:20 +00:00
return redirect ( " /restart " )
2021-04-17 20:28:57 +00:00
@app.route ( " /logs " )
2021-04-18 01:03:44 +00:00
def ui_logs_list ( request ) :
2021-05-25 22:10:39 +00:00
files = os . listdir ( resolve_external_file_path ( " /logs " ) )
log_files = [ ]
2021-09-11 16:18:35 +00:00
for file_name in files :
if file_name . endswith ( " .log " ) :
log_files . append ( file_name . rstrip ( " .log " ) )
2021-05-25 22:10:39 +00:00
log_files . sort ( )
2021-09-11 15:49:08 +00:00
data = { " ui_page " : " logs " , " ui_title " : " Logs " , " logs " : log_files }
2021-04-17 20:28:57 +00:00
return render_template ( " loglist.html " , data = data )
@app.route ( " /logs/<path:path> " )
2021-04-18 01:03:44 +00:00
def ui_logs_render ( request , path ) :
2021-05-15 22:51:12 +00:00
page = request . args . get ( " page " )
if not page :
return redirect ( f " /logs/ { path } ?page=1 " )
page = int ( page )
assert page > = 1
2021-09-16 22:40:05 +00:00
try :
log_file = open ( resolve_external_file_path ( " /logs/ {} .log " ) . format ( path ) )
except FileNotFoundError :
abort ( 404 )
return
2021-04-17 20:28:57 +00:00
data = {
2021-09-11 15:49:08 +00:00
" logs " : log_file . read ( ) . splitlines ( ) [
2021-09-11 16:18:35 +00:00
- 300 * page : ( - 300 * ( page - 1 ) if page > 1 else None )
2021-09-11 15:49:08 +00:00
] [ : : - 1 ] ,
2021-04-17 20:28:57 +00:00
" ui_page " : " logs " ,
" ui_title " : " Logs - {} " . format ( path ) ,
2021-09-11 15:49:08 +00:00
" page " : page ,
2021-04-17 20:28:57 +00:00
}
log_file . close ( )
return render_template ( " log.html " , data = data )
# Player Audio Control Endpoints
# Just useful for messing arround without presenter / websockets.
2021-04-18 01:03:44 +00:00
@app.route ( " /player/<channel:int>/<command> " )
def player_simple ( request , channel : int , command : str ) :
2021-04-17 20:28:57 +00:00
simple_endpoints = [ " play " , " pause " , " unpause " , " stop " , " unload " , " clear " ]
if command in simple_endpoints :
player_to_q [ channel ] . put ( " UI: " + command . upper ( ) )
2021-04-18 01:03:44 +00:00
return redirect ( " /status " )
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
abort ( 404 )
2021-04-17 20:28:57 +00:00
2021-04-18 02:14:14 +00:00
@app.route ( " /player/<channel:int>/seek/<pos:number> " )
2021-04-18 01:03:44 +00:00
def player_seek ( request , channel : int , pos : float ) :
2021-04-17 20:28:57 +00:00
player_to_q [ channel ] . put ( " UI:SEEK: " + str ( pos ) )
2021-04-18 01:03:44 +00:00
return redirect ( " /status " )
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
@app.route ( " /player/<channel:int>/load/<channel_weight:int> " )
def player_load ( request , channel : int , channel_weight : int ) :
2021-04-17 20:28:57 +00:00
player_to_q [ channel ] . put ( " UI:LOAD: " + str ( channel_weight ) )
2021-04-18 01:03:44 +00:00
return redirect ( " /status " )
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
@app.route ( " /player/<channel:int>/remove/<channel_weight:int> " )
def player_remove ( request , channel : int , channel_weight : int ) :
2021-04-17 20:28:57 +00:00
player_to_q [ channel ] . put ( " UI:REMOVE: " + str ( channel_weight ) )
2021-04-18 01:03:44 +00:00
return redirect ( " /status " )
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
@app.route ( " /player/<channel:int>/output/<name:string> " )
def player_output ( request , channel : int , name : Optional [ str ] ) :
player_to_q [ channel ] . put ( " UI:OUTPUT: " + unquote ( str ( name ) ) )
return redirect ( " /config/player " )
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
@app.route ( " /player/<channel:int>/autoadvance/<state:int> " )
def player_autoadvance ( request , channel : int , state : int ) :
2021-04-17 20:28:57 +00:00
player_to_q [ channel ] . put ( " UI:AUTOADVANCE: " + str ( state ) )
2021-04-18 01:03:44 +00:00
return redirect ( " /status " )
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
@app.route ( " /player/<channel:int>/repeat/<state:string> " )
def player_repeat ( request , channel : int , state : str ) :
2021-04-17 20:28:57 +00:00
player_to_q [ channel ] . put ( " UI:REPEAT: " + state . upper ( ) )
2021-04-18 01:03:44 +00:00
return redirect ( " /status " )
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
@app.route ( " /player/<channel:int>/playonload/<state:int> " )
def player_playonload ( request , channel : int , state : int ) :
2021-04-17 20:28:57 +00:00
player_to_q [ channel ] . put ( " UI:PLAYONLOAD: " + str ( state ) )
2021-04-18 01:03:44 +00:00
return redirect ( " /status " )
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
@app.route ( " /player/<channel:int>/status " )
def player_status_json ( request , channel : int ) :
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
return resp_json ( status ( channel ) )
2021-04-17 20:28:57 +00:00
@app.route ( " /player/all/stop " )
2021-04-18 01:03:44 +00:00
def player_all_stop ( request ) :
2021-04-17 20:28:57 +00:00
for channel in player_to_q :
channel . put ( " UI:STOP " )
2021-04-18 01:03:44 +00:00
return redirect ( " /status " )
2021-04-17 20:28:57 +00:00
# Show Plan Functions
2021-09-11 15:49:08 +00:00
2021-04-18 20:18:20 +00:00
@app.route ( " /plan/load/<timeslotid:int> " )
2021-04-18 01:03:44 +00:00
def plan_load ( request , timeslotid : int ) :
2021-04-17 20:28:57 +00:00
for channel in player_to_q :
2021-09-03 21:25:13 +00:00
channel . put ( " UI:GETPLAN: " + str ( timeslotid ) )
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
return redirect ( " /status " )
2021-04-17 20:28:57 +00:00
@app.route ( " /plan/clear " )
2021-04-18 01:03:44 +00:00
def plan_clear ( request ) :
2021-04-17 20:28:57 +00:00
for channel in player_to_q :
channel . put ( " UI:CLEAR " )
2021-04-18 01:03:44 +00:00
return redirect ( " /status " )
2021-04-17 20:28:57 +00:00
# API Proxy Endpoints
2021-09-11 15:49:08 +00:00
2021-04-17 20:28:57 +00:00
@app.route ( " /plan/list " )
2021-04-18 02:14:14 +00:00
async def api_list_showplans ( request ) :
2021-04-17 20:28:57 +00:00
2021-04-18 02:14:14 +00:00
return resp_json ( await api . get_showplans ( ) )
2021-04-17 20:28:57 +00:00
2021-04-18 02:14:14 +00:00
@app.route ( " /library/search/track " )
async def api_search_library ( request ) :
2021-04-17 20:28:57 +00:00
2021-09-11 15:49:08 +00:00
return resp_json (
await api . get_track_search (
request . args . get ( " title " ) , request . args . get ( " artist " )
)
)
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
@app.route ( " /library/playlists/<type:string> " )
2021-04-18 02:14:14 +00:00
async def api_get_playlists ( request , type : str ) :
2021-04-17 20:28:57 +00:00
if type not in [ " music " , " aux " ] :
abort ( 401 )
2021-04-18 02:14:14 +00:00
if type == " music " :
return resp_json ( await api . get_playlist_music ( ) )
else :
return resp_json ( await api . get_playlist_aux ( ) )
2021-04-17 20:28:57 +00:00
2021-04-18 01:03:44 +00:00
@app.route ( " /library/playlist/<type:string>/<library_id:string> " )
2021-04-18 02:14:14 +00:00
async def api_get_playlist ( request , type : str , library_id : str ) :
2021-04-17 20:28:57 +00:00
if type not in [ " music " , " aux " ] :
abort ( 401 )
2021-04-18 02:14:14 +00:00
if type == " music " :
return resp_json ( await api . get_playlist_music_items ( library_id ) )
else :
return resp_json ( await api . get_playlist_aux_items ( library_id ) )
2021-04-17 20:28:57 +00:00
# JSON Outputs
@app.route ( " /status-json " )
2021-04-18 01:03:44 +00:00
def json_status ( request ) :
2021-04-17 20:28:57 +00:00
channel_states = [ ]
2021-04-18 19:27:54 +00:00
for i in range ( server_state . get ( ) [ " num_channels " ] ) :
2021-04-17 20:28:57 +00:00
channel_states . append ( status ( i ) )
2021-04-18 19:27:54 +00:00
return resp_json ( { " server " : server_state . get ( ) , " channels " : channel_states } )
2021-04-17 20:28:57 +00:00
# Get audio for UI to generate waveforms.
2021-04-18 01:03:44 +00:00
@app.route ( " /audiofile/<type:string>/<id:int> " )
async def audio_file ( request , type : str , id : int ) :
2021-04-17 20:28:57 +00:00
if type not in [ " managed " , " track " ] :
abort ( 404 )
2021-09-11 16:18:35 +00:00
filename = resolve_external_file_path (
" music-tmp/ {} - {} .mp3 " . format ( type , id ) )
2021-08-16 22:43:09 +00:00
# Swap with a normalised version if it's ready, else returns original.
filename = get_normalised_filename_if_available ( filename )
# Send file or 404
return await file ( filename )
2021-04-17 20:28:57 +00:00
# Static Files
2021-09-11 15:49:08 +00:00
app . static (
" /favicon.ico " , resolve_local_file_path ( " ui-static/favicon.ico " ) , name = " ui-favicon "
)
2021-04-18 02:52:34 +00:00
app . static ( " /static " , resolve_local_file_path ( " ui-static " ) , name = " ui-static " )
2021-08-16 22:43:09 +00:00
dist_directory = resolve_local_file_path ( " presenter-build " )
2021-09-11 15:49:08 +00:00
app . static ( " /presenter " , dist_directory )
app . static (
" /presenter/ " ,
resolve_local_file_path ( " presenter-build/index.html " ) ,
strict_slashes = True ,
name = " presenter-index " ,
)
2021-04-17 20:28:57 +00:00
# Helper Functions
2021-09-11 15:49:08 +00:00
2021-04-17 20:28:57 +00:00
def status ( channel : int ) :
while not player_from_q [ channel ] . empty ( ) :
2021-09-11 16:18:35 +00:00
# Just waste any previous status responses.
player_from_q [ channel ] . get ( )
2021-04-17 20:28:57 +00:00
player_to_q [ channel ] . put ( " UI:STATUS " )
retries = 0
while retries < 40 :
try :
response = player_from_q [ channel ] . get_nowait ( )
if response . startswith ( " UI:STATUS: " ) :
response = response . split ( " : " , 2 ) [ 2 ]
# TODO: Handle OKAY / FAIL
2021-09-11 16:18:35 +00:00
response = response [ response . index ( " : " ) + 1 : ]
2021-04-17 20:28:57 +00:00
try :
response = json . loads ( response )
except Exception as e :
raise e
return response
except Empty :
pass
retries + = 1
sleep ( 0.02 )
2021-09-11 15:49:08 +00:00
2021-04-17 20:28:57 +00:00
# WebServer Start / Stop Functions
@app.route ( " /quit " )
2021-04-18 01:03:44 +00:00
def quit ( request ) :
2021-04-18 19:27:54 +00:00
server_state . update ( " running_state " , " quitting " )
2021-04-18 21:23:25 +00:00
data = {
" ui_page " : " message " ,
" ui_title " : " Quitting BAPSicle " ,
" title " : " See you later! " ,
" ui_menu " : False ,
2021-09-11 15:49:08 +00:00
" message " : " BAPSicle is going back into winter hibernation, see you again soon! " ,
2021-04-18 21:23:25 +00:00
}
return render_template ( " message.html " , data )
2021-04-18 19:27:54 +00:00
@app.route ( " /restart " )
def restart ( request ) :
server_state . update ( " running_state " , " restarting " )
2021-04-18 21:23:25 +00:00
data = {
" ui_page " : " message " ,
" ui_title " : " Restarting BAPSicle " ,
" title " : " Please Wait... " ,
" ui_menu " : False ,
" message " : " Just putting BAPSicle back in the freezer for a moment! " ,
" redirect_to " : " / " ,
2021-09-11 15:49:08 +00:00
" redirect_wait_ms " : 10000 ,
2021-04-18 21:23:25 +00:00
}
return render_template ( " message.html " , data )
2021-04-17 20:28:57 +00:00
# Don't use reloader, it causes Nested Processes!
2021-04-18 02:14:14 +00:00
def WebServer ( player_to : List [ Queue ] , player_from : List [ Queue ] , state : StateManager ) :
2021-04-17 20:28:57 +00:00
2021-09-11 22:44:15 +00:00
global player_to_q , player_from_q , server_state , api , app , alerts
2021-04-17 20:28:57 +00:00
player_to_q = player_to
player_from_q = player_from
server_state = state
2021-04-18 02:14:14 +00:00
logger = LoggingManager ( " WebServer " )
api = MyRadioAPI ( logger , state )
2021-09-11 22:44:15 +00:00
alerts = AlertManager ( )
2021-04-18 02:14:14 +00:00
2021-04-18 01:03:44 +00:00
process_title = " Web Server "
2021-04-17 20:28:57 +00:00
setproctitle ( process_title )
CORS ( app , supports_credentials = True ) # Allow ALL CORS!!!
2021-04-18 01:03:44 +00:00
terminate = Terminator ( )
while not terminate . terminate :
try :
2021-09-11 15:49:08 +00:00
sync (
app . run (
host = server_state . get ( ) [ " host " ] ,
port = server_state . get ( ) [ " port " ] ,
debug = ( not isBundelled ( ) ) ,
auto_reload = False ,
access_log = ( not isBundelled ( ) ) ,
)
)
2021-04-18 01:03:44 +00:00
except Exception :
break
2021-04-18 20:32:31 +00:00
loop = asyncio . get_event_loop ( )
if loop :
loop . close ( )
if app :
app . stop ( )
del app