2022-02-22 12:57:48 +09:00
|
|
|
import os
|
2022-02-13 13:00:10 +09:00
|
|
|
import secrets
|
|
|
|
import toml
|
|
|
|
from collections import OrderedDict
|
|
|
|
|
|
|
|
from quart import Quart
|
|
|
|
from werkzeug.security import generate_password_hash
|
|
|
|
|
2022-02-20 13:23:32 +09:00
|
|
|
from anonstream.utils.captcha import create_captcha_factory, create_captcha_signer
|
|
|
|
from anonstream.utils.colour import color_to_colour
|
|
|
|
from anonstream.utils.user import generate_token
|
2022-02-13 13:00:10 +09:00
|
|
|
|
2022-02-20 13:42:24 +09:00
|
|
|
def create_app(config_file):
|
|
|
|
with open(config_file) as fp:
|
2022-02-13 13:00:10 +09:00
|
|
|
config = toml.load(fp)
|
|
|
|
|
|
|
|
auth_password = secrets.token_urlsafe(6)
|
|
|
|
auth_pwhash = generate_password_hash(auth_password)
|
2022-02-15 19:11:53 +09:00
|
|
|
print('Broadcaster username:', config['auth']['username'])
|
2022-02-13 13:00:10 +09:00
|
|
|
print('Broadcaster password:', auth_password)
|
|
|
|
|
|
|
|
app = Quart('anonstream')
|
2022-02-23 08:03:14 +09:00
|
|
|
app.jinja_options.update({
|
|
|
|
'trim_blocks': True,
|
|
|
|
'lstrip_blocks': True,
|
|
|
|
})
|
2022-02-16 18:55:30 +09:00
|
|
|
app.config.update({
|
|
|
|
'SECRET_KEY': config['secret_key'].encode(),
|
|
|
|
'AUTH_USERNAME': config['auth']['username'],
|
|
|
|
'AUTH_PWHASH': auth_pwhash,
|
|
|
|
'AUTH_TOKEN': generate_token(),
|
2022-02-22 12:57:48 +09:00
|
|
|
'SEGMENT_DIRECTORY': os.path.realpath(config['segments']['directory']),
|
|
|
|
'SEGMENT_PLAYLIST': os.path.join(os.path.realpath(config['segments']['directory']), config['segments']['playlist']),
|
|
|
|
'SEGMENT_PLAYLIST_CACHE_LIFETIME': config['segments']['playlist_cache_lifetime'],
|
|
|
|
'SEGMENT_PLAYLIST_STALE_THRESHOLD': config['segments']['playlist_stale_threshold'],
|
|
|
|
'SEGMENT_SEARCH_COOLDOWN': config['segments']['search_cooldown'],
|
|
|
|
'SEGMENT_SEARCH_TIMEOUT': config['segments']['search_timeout'],
|
|
|
|
'SEGMENT_STREAM_INITIAL_BUFFER': config['segments']['stream_initial_buffer'],
|
2022-02-22 19:43:09 +09:00
|
|
|
'STREAM_TITLE': config['title']['file'],
|
|
|
|
'STREAM_TITLE_CACHE_LIFETIME': config['title']['file_cache_lifetime'],
|
2022-02-16 18:55:30 +09:00
|
|
|
'DEFAULT_HOST_NAME': config['names']['broadcaster'],
|
|
|
|
'DEFAULT_ANON_NAME': config['names']['anonymous'],
|
2022-02-20 13:23:32 +09:00
|
|
|
'MAX_STATES': config['memory']['states'],
|
|
|
|
'MAX_CAPTCHAS': config['memory']['captchas'],
|
2022-02-17 21:51:09 +09:00
|
|
|
'MAX_CHAT_MESSAGES': config['memory']['chat_messages'],
|
|
|
|
'MAX_CHAT_SCROLLBACK': config['memory']['chat_scrollback'],
|
2022-02-20 16:20:43 +09:00
|
|
|
'TASK_PERIOD_ROTATE_USERS': config['tasks']['rotate_users'],
|
|
|
|
'TASK_PERIOD_ROTATE_CAPTCHAS': config['tasks']['rotate_captchas'],
|
|
|
|
'TASK_PERIOD_BROADCAST_USERS_UPDATE': config['tasks']['broadcast_users_update'],
|
2022-02-23 07:51:29 +09:00
|
|
|
'TASK_PERIOD_BROADCAST_STREAM_INFO_UPDATE': config['tasks']['broadcast_stream_info_update'],
|
2022-02-19 09:35:42 +09:00
|
|
|
'THRESHOLD_USER_NOTWATCHING': config['thresholds']['user_notwatching'],
|
|
|
|
'THRESHOLD_USER_TENTATIVE': config['thresholds']['user_tentative'],
|
2022-02-18 21:24:19 +09:00
|
|
|
'THRESHOLD_USER_ABSENT': config['thresholds']['user_absent'],
|
|
|
|
'THRESHOLD_NOJS_CHAT_TIMEOUT': config['thresholds']['nojs_chat_timeout'],
|
2022-02-17 21:51:09 +09:00
|
|
|
'CHAT_COMMENT_MAX_LENGTH': config['chat']['max_name_length'],
|
|
|
|
'CHAT_NAME_MAX_LENGTH': config['chat']['max_name_length'],
|
|
|
|
'CHAT_NAME_MIN_CONTRAST': config['chat']['min_name_contrast'],
|
|
|
|
'CHAT_BACKGROUND_COLOUR': color_to_colour(config['chat']['background_color']),
|
2022-02-21 07:07:32 +09:00
|
|
|
'FLOOD_DURATION': config['flood']['duration'],
|
|
|
|
'FLOOD_THRESHOLD': config['flood']['threshold'],
|
2022-02-20 13:23:32 +09:00
|
|
|
'CAPTCHA_LIFETIME': config['captcha']['lifetime'],
|
|
|
|
'CAPTCHA_FONTS': config['captcha']['fonts'],
|
|
|
|
'CAPTCHA_ALPHABET': config['captcha']['alphabet'],
|
|
|
|
'CAPTCHA_LENGTH': config['captcha']['length'],
|
|
|
|
'CAPTCHA_BACKGROUND_COLOUR': color_to_colour(config['captcha']['background_color']),
|
|
|
|
'CAPTCHA_FOREGROUND_COLOUR': color_to_colour(config['captcha']['foreground_color']),
|
2022-02-16 18:55:30 +09:00
|
|
|
})
|
|
|
|
|
2022-02-20 13:23:32 +09:00
|
|
|
assert app.config['MAX_STATES'] >= 0
|
2022-02-18 21:24:19 +09:00
|
|
|
assert app.config['MAX_CHAT_SCROLLBACK'] >= 0
|
2022-02-19 09:35:42 +09:00
|
|
|
assert (
|
|
|
|
app.config['MAX_CHAT_MESSAGES'] >= app.config['MAX_CHAT_SCROLLBACK']
|
|
|
|
)
|
|
|
|
assert (
|
|
|
|
app.config['THRESHOLD_USER_ABSENT']
|
|
|
|
>= app.config['THRESHOLD_USER_TENTATIVE']
|
|
|
|
>= app.config['THRESHOLD_USER_NOTWATCHING']
|
|
|
|
)
|
2022-02-16 18:55:30 +09:00
|
|
|
|
2022-02-18 10:32:34 +09:00
|
|
|
app.messages_by_id = OrderedDict()
|
|
|
|
app.messages = app.messages_by_id.values()
|
2022-02-20 16:20:43 +09:00
|
|
|
|
|
|
|
app.users_by_token = {}
|
2022-02-18 10:32:34 +09:00
|
|
|
app.users = app.users_by_token.values()
|
2022-02-20 16:20:43 +09:00
|
|
|
|
|
|
|
app.captchas = OrderedDict()
|
2022-02-20 13:23:32 +09:00
|
|
|
app.captcha_factory = create_captcha_factory(app.config['CAPTCHA_FONTS'])
|
|
|
|
app.captcha_signer = create_captcha_signer(app.config['SECRET_KEY'])
|
2022-02-20 16:20:43 +09:00
|
|
|
|
2022-02-23 07:51:29 +09:00
|
|
|
# State for tasks
|
2022-02-20 16:20:43 +09:00
|
|
|
app.users_update_buffer = set()
|
2022-02-23 07:51:29 +09:00
|
|
|
app.stream_uptime = None
|
|
|
|
app.stream_title = None
|
2022-02-13 13:00:10 +09:00
|
|
|
|
2022-02-23 07:51:29 +09:00
|
|
|
# Background tasks' asyncio.sleep tasks, cancelled on shutdown
|
2022-02-20 10:06:13 +09:00
|
|
|
app.background_sleep = set()
|
|
|
|
|
|
|
|
@app.after_serving
|
2022-02-19 12:14:37 +09:00
|
|
|
async def shutdown():
|
2022-02-20 10:06:13 +09:00
|
|
|
# make all background tasks finish
|
|
|
|
for task in app.background_sleep:
|
|
|
|
task.cancel()
|
2022-02-19 12:14:37 +09:00
|
|
|
|
|
|
|
@app.before_serving
|
|
|
|
async def startup():
|
2022-02-13 13:00:10 +09:00
|
|
|
import anonstream.routes
|
2022-02-19 12:14:37 +09:00
|
|
|
import anonstream.tasks
|
2022-02-13 13:00:10 +09:00
|
|
|
|
|
|
|
return app
|