Commit 7fe39038 authored by David Huss's avatar David Huss 💬
Browse files

Add a ton of CLI options, formatting fixes & fancy

parent 012ede87
...@@ -57,4 +57,13 @@ bigbluebutton.web.serverURL=https://bbb.example.com/ ...@@ -57,4 +57,13 @@ bigbluebutton.web.serverURL=https://bbb.example.com/
securitySalt=MY_SUPER_SECRET_SECRET2 securitySalt=MY_SUPER_SECRET_SECRET2
bigbluebutton.web.serverURL=https://bbb.foo.com/ bigbluebutton.web.serverURL=https://bbb.foo.com/
``` ```
The section names in the square brackets will be used as display names (these support utf-8) The section names in the square brackets will be used as display names (these support utf-8)
\ No newline at end of file
# Usage
For help run:
```bash
bbbmon --help
```
...@@ -117,41 +117,67 @@ def format_duration(meeting: XmlDictConfig) -> str: ...@@ -117,41 +117,67 @@ def format_duration(meeting: XmlDictConfig) -> str:
def get_formated_presenter_name_id(meeting: XmlDictConfig) -> str:
"""
Get the formated name of the presenter for a given meeting (with id)
"""
presenter = get_presenter(meeting)
if presenter is not None:
return "{:<30} ({})".format(presenter["fullName"], presenter["userID"])
else:
return "no Presenter"
def get_formated_presenter_name(meeting: XmlDictConfig) -> str: def get_formated_presenter_name(meeting: XmlDictConfig) -> str:
""" """
Get the formated name of the presenter for a given meeting Get the formated name of the presenter for a given meeting
""" """
presenter = get_presenter(meeting) presenter = get_presenter(meeting)
if presenter is not None: if presenter is not None:
return "{:<30} ({})".format(presenter["fullName"], presenter["userID"]) return "{:<30}".format(presenter["fullName"])
else: else:
return "no Presenter" return "no Presenter"
def print_leaderboard(meetings: Iterable[XmlDictConfig], key: str): def print_leaderboard(meetings: Iterable[XmlDictConfig], key: str, endpoint_name: str, presenter: bool, presenter_id: bool, fancy: bool):
""" """
Print a leaderboard of all meetings sorted by a given key (e.g. Print a leaderboard of all meetings sorted by a given key (e.g.
participantCount) participantCount)
""" """
print("LEADERBOARD ({})".format(FRIENDLY_KEYNAMES[key])) print_header(endpoint_name, "LEADERBOARD ({})".format(FRIENDLY_KEYNAMES[key]), fancy)
sorted_by = sorted([m for m in meetings], key=lambda x:int(x[key]), reverse=True) sorted_by = sorted([m for m in meetings], key=lambda x:int(x[key]), reverse=True)
for m in sorted_by: for m in sorted_by:
print("{:>5} {:<45} {}".format(m[key], m["meetingName"], get_formated_presenter_name(m))) if presenter:
if presenter_id:
print("{:>5} {:<45} {}".format(m[key], m["meetingName"], get_formated_presenter_name_id(m)))
def print_duration_leaderboard(meetings: Iterable[XmlDictConfig]): else:
print("{:>5} {:<45} {}".format(m[key], m["meetingName"], get_formated_presenter_name(m)))
else:
print("{:>5} {}".format(m[key], m["meetingName"]))
def print_duration_leaderboard(meetings: Iterable[XmlDictConfig], endpoint_name: str, presenter: bool, presenter_id: bool, fancy: bool):
""" """
Print a leaderboard of all meetings sorted by a given key (e.g. Print a leaderboard of all meetings sorted by a given key (e.g.
participantCount) participantCount)
""" """
print("LEADERBOARD (Duration)") print_header(endpoint_name, "LEADERBOARD (Duration)", fancy)
by_duration = sorted([m for m in meetings], key=lambda x:int(get_duration(x).total_seconds()), reverse=True) by_duration = sorted([m for m in meetings], key=lambda x:int(get_duration(x).total_seconds()), reverse=True)
for m in by_duration: for m in by_duration:
print("{:>12} {:<45} {}".format(format_duration(m), m["meetingName"], get_formated_presenter_name(m))) if presenter:
if presenter_id:
print("{:>12} {:<38} {}".format(format_duration(m), m["meetingName"], get_formated_presenter_name_id(m)))
else:
print("{:>12} {:<38} {}".format(format_duration(m), m["meetingName"], get_formated_presenter_name(m)))
else:
print("{:>12} {}".format(format_duration(m), m["meetingName"]))
def print_header(endpoint_name: str, text: str, fancy=True):
if fancy:
click.echo(click.style(" [{}] {} ".format(endpoint_name, text), fg='black', bg='white', bold=True))
else:
print("[{}] {}".format(endpoint_name, text))
def print_overview(config: Config): def print_overview(config: Config, leaderboards: bool, participants: bool, presenter: bool, presenter_id: bool, show_meetings: bool, fancy: bool):
""" """
For each endpoint in the configuration get the active meetings and print For each endpoint in the configuration get the active meetings and print
out an overview of the current bbb-usage out an overview of the current bbb-usage
...@@ -162,12 +188,14 @@ def print_overview(config: Config): ...@@ -162,12 +188,14 @@ def print_overview(config: Config):
# Print divider if there is more than one endpoint # Print divider if there is more than one endpoint
if i > 0: if i > 0:
print() print()
print("="*80) print("="*click.get_terminal_size()[0])
print() print()
# If there are no meetings, skip to next endpoint # If there are no meetings, skip to next endpoint
if len(meetings) == 0: if len(meetings) == 0:
print("MEETINGS on [{}]: None".format(endpoint.name)) if show_meetings:
print_header(endpoint.name, "MEETINGS", fancy)
print(" └─── Currently no active meetings.")
continue continue
n_running = len(meetings) n_running = len(meetings)
...@@ -178,25 +206,29 @@ def print_overview(config: Config): ...@@ -178,25 +206,29 @@ def print_overview(config: Config):
n_video = sum([int(m["videoCount"]) for m in meetings]) n_video = sum([int(m["videoCount"]) for m in meetings])
n_moderator = sum([int(m["moderatorCount"]) for m in meetings]) n_moderator = sum([int(m["moderatorCount"]) for m in meetings])
print("MEETINGS on [{}]:".format(endpoint.name)) if show_meetings:
print(" ├─── {:>4} running".format(n_running)) print_header(endpoint.name, "MEETINGS", fancy)
print(" └─── {:>4} recording".format(n_recording)) print(" ├─── {:>4} running".format(n_running))
print() print(" └─── {:>4} recording".format(n_recording))
print("PARTICIPANTS across all {} rooms".format(n_running)) print()
print(" └─┬─ {:>4} total".format(n_participants))
print(" ├─ {:>4} listening only".format(n_listeners))
print(" ├─ {:>4} mic on".format(n_voice))
print(" ├─ {:>4} video on".format(n_video))
print(" └─ {:>4} moderators".format(n_moderator))
print() if participants:
print_leaderboard(meetings, "participantCount") print_header(endpoint.name, "PARTICIPANTS across all {} rooms".format(n_running), fancy)
print() print(" └─┬─ {:>4} total".format(n_participants))
print_leaderboard(meetings, "videoCount") print(" ├─ {:>4} listening only".format(n_listeners))
print() print(" ├─ {:>4} mic on".format(n_voice))
print_leaderboard(meetings, "voiceParticipantCount") print(" ├─ {:>4} video on".format(n_video))
print() print(" └─ {:>4} moderators".format(n_moderator))
print_duration_leaderboard(meetings)
if leaderboards:
print()
print_leaderboard(meetings, "participantCount", endpoint.name, presenter, presenter_id, fancy)
print()
print_leaderboard(meetings, "videoCount", endpoint.name, presenter, presenter_id, fancy)
print()
print_leaderboard(meetings, "voiceParticipantCount", endpoint.name, presenter, presenter_id, fancy)
print()
print_duration_leaderboard(meetings, endpoint.name, presenter, presenter_id, fancy)
def init_config() -> Optional[Config]: def init_config() -> Optional[Config]:
...@@ -227,10 +259,18 @@ def init_config() -> Optional[Config]: ...@@ -227,10 +259,18 @@ def init_config() -> Optional[Config]:
exit() exit()
@click.command()
def main(): @click.option('--endpoint', '-e', multiple=True, help="Filter by one or more endpoints as named in the user configuration. Order is respected.")
Config = init_config() @click.option('--leaderboards/--no-leaderboards', default=True, show_default=True, help="Hide or show the meeting leaderboards")
print_overview(Config) @click.option('--participants/--no-participants', default=True, show_default=True, help="Hide or show the participants")
@click.option('--meetings/--no-meetings', default=True, show_default=True, help="Hide or show the meetings")
@click.option('--presenter/--no-presenter', default=True, show_default=True, help="Hide or show the presenters")
@click.option('--presenter-id/--no-presenter-id', default=True, show_default=True, help="Hide or show the presenter IDs")
@click.option('--fancy/--no-fancy', default=True, show_default=True, help="Use fancy headers")
def main(leaderboards, participants, presenter, presenter_id, meetings, endpoint, fancy):
config = init_config()
config.filter_endpoints(endpoint)
print_overview(config, leaderboards, participants, presenter, presenter_id, meetings, fancy)
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import configparser import configparser
from typing import NewType, Optional, Tuple, Iterable, List from typing import NewType, Optional, Tuple, Iterable, List
import click
# Default path # Default path
SERVER_PROPERTIES_FILE = "/usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties" SERVER_PROPERTIES_FILE = "/usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties"
...@@ -55,6 +56,22 @@ class Config(): ...@@ -55,6 +56,22 @@ class Config():
self = self.from_server(path) self = self.from_server(path)
return self return self
def filter_endpoints(self, endpoint_options: List[str]) -> 'Config':
if len(endpoint_options) == 0:
return self
else:
existing_names = [e.name for e in self.endpoints]
filtered_endpoints = []
for endpoint_option in endpoint_options:
if not endpoint_option in existing_names:
click.echo("{} there is no endpoint called \"{}\" in the configuration. It will be ignored.\n".format(click.style('Error:', fg='red', bold=True), click.style(endpoint_option, fg='red', bold=True)))
else:
filtered_endpoints.append([e for e in self.endpoints if e.name == endpoint_option][0])
self.endpoints = filtered_endpoints
return self
def __len__(self): def __len__(self):
""" """
The length of a Config is represented by the number of endpoints The length of a Config is represented by the number of endpoints
......
[tool.poetry] [tool.poetry]
name = "bbbmon" name = "bbbmon"
version = "0.1.8" version = "0.1.9"
description = "A small CLI utility to monitor bbb usage" description = "A small CLI utility to monitor bbb usage"
authors = ["David Huss <david.huss@hfbk-hamburg.de>"] authors = ["David Huss <david.huss@hfbk-hamburg.de>"]
maintainers = ["David Huss <david.huss@hfbk-hamburg.de>"] maintainers = ["David Huss <david.huss@hfbk-hamburg.de>"]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment