Skip to content
Snippets Groups Projects
Commit 1fd56d58 authored by David Huss's avatar David Huss :speech_balloon:
Browse files

Add option to create default config on first start

parent 66c5eb04
No related branches found
No related tags found
No related merge requests found
...@@ -24,6 +24,18 @@ FRIENDLY_KEYNAMES = { ...@@ -24,6 +24,18 @@ FRIENDLY_KEYNAMES = {
} }
EXAMPLE_CONFIG = """
[myservername]
securitySalt=YOURSUPERSECRETSECRET
bigbluebutton.web.serverURL=https://bbb.example.com/
; You can add, however, multiple Endpoints:
; [mysecondservername]
; securitySalt=ANOTHERSECRET
; bigbluebutton.web.serverURL=https://bbb.test.com/
"""
def generate_checksum(call_name: str, query_string: str, secret: Secret) -> str: def generate_checksum(call_name: str, query_string: str, secret: Secret) -> str:
""" """
Generate Checksum for the request header (passed as value for `?checksum=`) Generate Checksum for the request header (passed as value for `?checksum=`)
...@@ -35,7 +47,7 @@ def generate_checksum(call_name: str, query_string: str, secret: Secret) -> str: ...@@ -35,7 +47,7 @@ def generate_checksum(call_name: str, query_string: str, secret: Secret) -> str:
return m.hexdigest() return m.hexdigest()
def request_meetings(secret: Secret, bbb_url: Url) -> XmlDictConfig: def request_meetings(secret: Secret, bbb_url: Url, user_config_path: str) -> XmlDictConfig:
""" """
Make a getMeetings-API Call to the bbb instance and return a XmlDictConfig Make a getMeetings-API Call to the bbb instance and return a XmlDictConfig
with the servers response with the servers response
...@@ -43,7 +55,17 @@ def request_meetings(secret: Secret, bbb_url: Url) -> XmlDictConfig: ...@@ -43,7 +55,17 @@ def request_meetings(secret: Secret, bbb_url: Url) -> XmlDictConfig:
call_name = "getMeetings" call_name = "getMeetings"
checksum = generate_checksum(call_name, "", secret) checksum = generate_checksum(call_name, "", secret)
url = "{}/api/{}?checksum={}".format(bbb_url, call_name, checksum) url = "{}/api/{}?checksum={}".format(bbb_url, call_name, checksum)
try:
r = requests.get(url) r = requests.get(url)
except:
click.echo("{} The URL \"{}\" is unreachable.\n Check your network connection, and the URL and Secret of the endpoint.".format(click.style('Error:', fg='red', bold=True), url))
print()
time.sleep(1)
if click.confirm(click.style('Do you want to open the config file at {} with your default editor?'.format(user_config_path), fg="yellow"), abort=True):
click.edit(filename=user_config_path)
exit()
root = ElementTree.XML(r.text) root = ElementTree.XML(r.text)
xmldict = XmlDictConfig(root) xmldict = XmlDictConfig(root)
if "returncode" in xmldict.keys(): if "returncode" in xmldict.keys():
...@@ -56,12 +78,12 @@ def request_meetings(secret: Secret, bbb_url: Url) -> XmlDictConfig: ...@@ -56,12 +78,12 @@ def request_meetings(secret: Secret, bbb_url: Url) -> XmlDictConfig:
return xmldict return xmldict
def get_meetings(secret: Secret, bbb_url: Url) -> Iterable[XmlDictConfig]: def get_meetings(secret: Secret, bbb_url: Url, user_config_path: str) -> Iterable[XmlDictConfig]:
""" """
Request meetings and return a list of them. Sorted by biggest first Request meetings and return a list of them. Sorted by biggest first
""" """
meetings = [] meetings = []
d = request_meetings(secret, bbb_url) d = request_meetings(secret, bbb_url, user_config_path)
if d["meetings"] is None: if d["meetings"] is None:
return [] return []
...@@ -185,13 +207,13 @@ def print_overview(config: Config, leaderboards: bool, participants: bool, prese ...@@ -185,13 +207,13 @@ def print_overview(config: Config, leaderboards: bool, participants: bool, prese
""" """
# Request Meetings from API # Request Meetings from API
meetings = [get_meetings(e.secret, e.url) for e in config.endpoints] meetings = [get_meetings(e.secret, e.url, config.path) for e in config.endpoints]
# Clear screen after request is done, and before printing new data to keep # Clear screen after request is done, and before printing new data to keep
# blinking to a minimum # blinking to a minimum
if watch is not None: if watch is not None:
click.clear() click.clear()
print(watch)
for i, endpoint in enumerate(config.endpoints): for i, endpoint in enumerate(config.endpoints):
meeting = meetings[i] meeting = meetings[i]
...@@ -257,19 +279,36 @@ def init_config() -> Optional[Config]: ...@@ -257,19 +279,36 @@ def init_config() -> Optional[Config]:
elif os.path.isfile(user_config_path): elif os.path.isfile(user_config_path):
return Config().from_config(user_config_path) return Config().from_config(user_config_path)
else: else:
print("ERROR: There was no config file found. Make sure it exists and is readable:") new_config(user_config_path)
def new_config(user_config_path: str):
click.echo("{} There was no config file found. Make sure it exists and is readable at either location:".format(click.style('Error:', fg='red', bold=True), click.style("Error:", fg='red', bold=True)))
print(" [0] {}".format(SERVER_PROPERTIES_FILE)) print(" [0] {}".format(SERVER_PROPERTIES_FILE))
print(" [1] {}".format(user_config_path)) print(" [1] {}".format(user_config_path))
print() print()
print("For now the file just needs to contain three lines:") print("For now the file just needs to contain three lines:")
print("[myservername]") for line in EXAMPLE_CONFIG.splitlines():
print("securitySalt=YOURSUPERSECRETSECRET") click.echo(click.style((line), fg="bright_black"))
print("bigbluebutton.web.serverURL=https://bbb.example.com/")
print() print()
print("(You can define multiple server-blocks however)") if click.confirm(click.style('Do you want to create a config file at {}?'.format(user_config_path), fg="green"), abort=True):
# Create all directories in the path to the config, if they don't exist yet
try:
os.makedirs(user_config_path.rstrip("bbbmon.properties"))
except FileExistsError:
pass
# Write default config
with open(user_config_path, "w") as f:
for line in EXAMPLE_CONFIG.splitlines():
f.write("{}\n".format(line))
# Open with standard editor
click.edit(filename=user_config_path)
exit() exit()
@click.command() @click.command()
@click.option('--endpoint', '-e', multiple=True, help="Filter by one or more endpoints as named in the user configuration (e.g. [servername]). Order is respected.") @click.option('--endpoint', '-e', multiple=True, help="Filter by one or more endpoints as named in the user configuration (e.g. [servername]). Order is respected.")
@click.option('--watch', '-w', help="Run repeatedly with the given interval in seconds", type=click.IntRange(2, 2147483647, clamp=True)) @click.option('--watch', '-w', help="Run repeatedly with the given interval in seconds", type=click.IntRange(2, 2147483647, clamp=True))
......
...@@ -19,6 +19,7 @@ class Config(): ...@@ -19,6 +19,7 @@ class Config():
""" """
def __init__(self): def __init__(self):
self.endpoints = [] self.endpoints = []
self.path = None
def from_server(self, path: str=SERVER_PROPERTIES_FILE) -> 'Config': def from_server(self, path: str=SERVER_PROPERTIES_FILE) -> 'Config':
""" """
...@@ -34,6 +35,7 @@ class Config(): ...@@ -34,6 +35,7 @@ class Config():
bbb_url = "{}/bigbluebutton".format(bbb_url.rstrip('/')) bbb_url = "{}/bigbluebutton".format(bbb_url.rstrip('/'))
endpoint = Endpoint(url=bbb_url, secret=secret) endpoint = Endpoint(url=bbb_url, secret=secret)
self.endpoints.append(endpoint) self.endpoints.append(endpoint)
self.path = path
return self return self
def from_config(self, path: str) -> 'Config': def from_config(self, path: str) -> 'Config':
...@@ -50,6 +52,7 @@ class Config(): ...@@ -50,6 +52,7 @@ class Config():
secret = Secret(config[section]["securitySalt"]).strip() secret = Secret(config[section]["securitySalt"]).strip()
endpoint = Endpoint(url=bbb_url, secret=secret, name=section) endpoint = Endpoint(url=bbb_url, secret=secret, name=section)
self.endpoints.append(endpoint) self.endpoints.append(endpoint)
self.path = path
return self return self
# Fallback for config files without sections # Fallback for config files without sections
except configparser.MissingSectionHeaderError: except configparser.MissingSectionHeaderError:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment