Dnomd343
1 year ago
1 changed files with 101 additions and 122 deletions
@ -1,128 +1,107 @@ |
|||||
#!/usr/bin/env python3 |
#!/usr/bin/env python3 |
||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
import os |
import os |
||||
import sys |
import sys |
||||
|
import yaml |
||||
|
import argparse |
||||
|
from typing import Any |
||||
from syncplay import ep_server |
from syncplay import ep_server |
||||
|
|
||||
|
WorkDir = '/data/' |
||||
def checkOpt(args: list, option: str) -> bool: |
CertDir = '/certs/' |
||||
if option not in args: # option not found |
ConfigFile = 'config.yml' |
||||
return False |
|
||||
args.remove(option) # remove target option |
|
||||
return True |
def debug(msg: str) -> None: |
||||
|
""" Print out debug information. """ |
||||
|
if 'DEBUG' in os.environ and os.environ['DEBUG'] in ['ON', 'TRUE']: |
||||
def fetchOpt(args: list, option: str, default): |
print(f'\033[90m{msg}\033[0m', file=sys.stderr) |
||||
if option not in args: # option not found |
|
||||
return default |
|
||||
index = args.index(option) |
def temp_file(file: str, content: str) -> str: |
||||
if index + 1 == len(args): |
""" Create and save content to temporary files. """ |
||||
print('Error: `%s` missing value' % option, file = sys.stderr) |
file = os.path.join('/tmp/', file) |
||||
sys.exit(1) |
with open(file, 'w') as fp: |
||||
targetVal = args[index + 1] |
fp.write(f'{content}\n') |
||||
del sys.argv[index : index + 2] # remove target option and value |
return file |
||||
return targetVal |
|
||||
|
|
||||
|
def load_args() -> dict[str, Any]: |
||||
isDebug = checkOpt(sys.argv, '--debug') |
""" Loading arguments from the command line. """ |
||||
|
parser = argparse.ArgumentParser(description='Syncplay Docker Bootstrap') |
||||
|
parser.add_argument('-p', '--port', type=int, help='listen port of syncplay server') |
||||
portValue = None # no specify in default |
parser.add_argument('--password', type=str, help='authentication of syncplay server') |
||||
if 'PORT' in os.environ: # `PORT` env variable |
parser.add_argument('--motd', type=str, help='welcome text after the user enters the room') |
||||
portValue = os.environ['PORT'] |
parser.add_argument('--salt', type=str, help='string used to secure passwords') |
||||
portValue = fetchOpt(sys.argv, '--port', portValue) |
parser.add_argument('--random-salt', action='store_true', help='use a randomly generated salt value') |
||||
|
parser.add_argument('--isolate-rooms', action='store_true', help='room isolation enabled') |
||||
|
parser.add_argument('--disable-chat', action='store_true', help='disables the chat feature') |
||||
passwdStr = None # no password in default |
parser.add_argument('--disable-ready', action='store_true', help='disables the readiness indicator feature') |
||||
if 'PASSWD' in os.environ: # `PASSWD` env variable |
parser.add_argument('--enable-stats', action='store_true', help='enable syncplay server statistics') |
||||
passwdStr = os.environ['PASSWD'] |
parser.add_argument('--enable-tls', action='store_true', help='enable tls support of syncplay server') |
||||
passwdStr = fetchOpt(sys.argv, '--password', passwdStr) |
parser.add_argument('--persistent', action='store_true', help='enables room persistence') |
||||
|
parser.add_argument('--max-username', type=int, help='maximum length of usernames') |
||||
|
parser.add_argument('--max-chat-message', type=int, help='maximum length of chat messages') |
||||
saltValue = '' # using empty string in default |
parser.add_argument('--permanent-rooms', type=str, nargs='*', help='permanent rooms of syncplay server') |
||||
if 'SALT' in os.environ: # `SALT` env variable |
args = parser.parse_args() |
||||
saltValue = os.environ['SALT'] |
debug(f'Command line arguments -> {args}') |
||||
if checkOpt(sys.argv, '--random-salt'): |
return {k.replace('_', '-'): v for k, v in vars(args).items()} |
||||
saltValue = None |
|
||||
saltValue = fetchOpt(sys.argv, '--salt', saltValue) |
|
||||
|
def load_config(args: dict[str, Any], file: str) -> dict[str, Any]: |
||||
|
""" Complete uninitialized arguments from configure file. """ |
||||
isolateRoom = False # disable isolate room in default |
if not os.path.exists(file): |
||||
if 'ISOLATE' in os.environ and os.environ['ISOLATE'] in ['ON', 'TRUE']: |
return args |
||||
isolateRoom = True |
config = yaml.safe_load(open(file).read()) |
||||
if checkOpt(sys.argv, '--isolate-room'): |
options = [ |
||||
isolateRoom = True |
'port', 'password', 'motd', 'salt', 'random-salt', |
||||
|
'isolate-rooms', 'disable-chat', 'disable-ready', |
||||
|
'enable-stats', 'enable-tls', 'persistent', |
||||
tlsPath = '/certs' |
'max-username', 'max-chat-message', 'permanent-rooms', |
||||
if 'TLS_PATH' in os.environ: # `TLS_PATH` env variable |
] |
||||
tlsPath = os.environ['TLS_PATH'] |
override = {x: config[x] for x in options if not args[x] and x in config} |
||||
tlsPath = fetchOpt(sys.argv, '--tls', tlsPath) |
debug(f'Configure file override -> {override}') |
||||
|
return args | override |
||||
enableTls = False |
|
||||
if checkOpt(sys.argv, '--enable-tls'): |
|
||||
enableTls = True |
def build_args(opts: dict): |
||||
if 'TLS' in os.environ and os.environ['TLS'] in ['ON', 'TRUE']: |
""" Construct the startup arguments for syncplay server. """ |
||||
enableTls = True |
args = ['--port', opts.get('port', '8999')] |
||||
|
if 'password' in opts: |
||||
|
args += ['--password', opts['password']] |
||||
motdMessage = None # without motd message in default |
if 'motd' in opts: |
||||
if 'MOTD' in os.environ: # `MOTD` env variable |
args += ['--motd-file', temp_file('motd.data', opts['motd'])] |
||||
motdMessage = os.environ['MOTD'] |
|
||||
motdMessage = fetchOpt(sys.argv, '--motd', motdMessage) |
salt = opts.get('salt', None if 'random-salt' in opts else '') |
||||
|
if salt is not None: |
||||
motdFile = fetchOpt(sys.argv, '--motd-file', None) |
args += ['--salt', salt] # using random salt without this option |
||||
if motdFile is not None: |
for opt in ['isolate-rooms', 'disable-chat', 'disable-ready']: |
||||
motdMessage = None # cover motd message |
if opt in opts: |
||||
elif motdMessage is not None: |
args.append(f'--{opt}') |
||||
motdFile = '/app/syncplay/motd' |
|
||||
os.system('mkdir -p /app/syncplay/') |
if 'enable-stats' in opts: |
||||
with open(motdFile, mode = 'w', encoding = 'utf-8') as fileObj: |
args += ['--stats-db-file', os.path.join(WorkDir, 'stats.db')] |
||||
fileObj.write(motdMessage) |
if 'enable-tls' in opts: |
||||
|
args += ['--tls', CertDir] |
||||
|
if 'persistent' in opts: |
||||
if isDebug: # print debug log |
args += ['--rooms-db-file', os.path.join(WorkDir, 'rooms.db')] |
||||
if portValue is not None: |
|
||||
print('Port -> %s' % portValue, file = sys.stderr) |
if 'max-username' in opts: |
||||
|
args += ['--max-username-length', str(opts['max-username'])] |
||||
if saltValue is None: |
if 'max-chat-message' in opts: |
||||
print('Using random salt', file = sys.stderr) |
args += ['--max-chat-message-length', str(opts['max-chat-message'])] |
||||
else: |
if 'permanent-rooms' in opts: |
||||
print('Salt -> `%s`' % saltValue, file = sys.stderr) |
rooms = '\n'.join(opts['permanent-rooms']) |
||||
|
args += ['--permanent-rooms-file', temp_file('rooms.list', rooms)] |
||||
if isolateRoom: |
return args |
||||
print('Isolate room enabled', file = sys.stderr) |
|
||||
|
|
||||
if passwdStr is None: |
if __name__ == '__main__': |
||||
print('Running without password', file = sys.stderr) |
origin_args = load_config(load_args(), os.path.join(WorkDir, ConfigFile)) |
||||
else: |
origin_args = {k: v for k, v in origin_args.items() if v is not None and v is not False} # remove invalid items |
||||
print('Password -> `%s`' % passwdStr, file = sys.stderr) |
debug(f'Parsed arguments -> {origin_args}') |
||||
|
syncplay_args = build_args(origin_args) |
||||
if enableTls: |
debug(f'Syncplay startup arguments -> {syncplay_args}') |
||||
print('TLS enabled -> `%s`' % tlsPath, file = sys.stderr) |
sys.argv = ['syncplay'] + syncplay_args |
||||
|
sys.exit(ep_server.main()) |
||||
if motdFile is not None: |
|
||||
print('MOTD File -> `%s`' % motdFile, file = sys.stderr) |
|
||||
if motdMessage is not None: |
|
||||
print('MOTD message -> `%s`' % motdMessage, file = sys.stderr) |
|
||||
|
|
||||
|
|
||||
if portValue is not None: |
|
||||
sys.argv += ['--port', portValue] |
|
||||
if passwdStr is not None: |
|
||||
sys.argv += ['--password', passwdStr] |
|
||||
if saltValue is not None: |
|
||||
sys.argv += ['--salt', saltValue] |
|
||||
if enableTls: |
|
||||
sys.argv += ['--tls', tlsPath] |
|
||||
if isolateRoom: |
|
||||
sys.argv += ['--isolate-room'] |
|
||||
if motdFile is not None: |
|
||||
sys.argv += ['--motd-file', motdFile] |
|
||||
|
|
||||
|
|
||||
if isDebug: # print debug log |
|
||||
print('Boot args -> %s' % sys.argv, file = sys.stderr) |
|
||||
|
|
||||
|
|
||||
sys.exit(ep_server.main()) |
|
||||
|
Loading…
Reference in new issue