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

Add a ton of CLI options, formatting fixes & fancy

parent 012ede87
......@@ -58,3 +58,12 @@ securitySalt=MY_SUPER_SECRET_SECRET2
bigbluebutton.web.serverURL=https://bbb.foo.com/
```
The section names in the square brackets will be used as display names (these support utf-8)
# Usage
For help run:
```bash
bbbmon --help
```
......@@ -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:
"""
Get the formated name of the presenter for a given meeting
"""
presenter = get_presenter(meeting)
if presenter is not None:
return "{:<30} ({})".format(presenter["fullName"], presenter["userID"])
return "{:<30}".format(presenter["fullName"])
else:
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.
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)
for m in sorted_by:
if presenter:
if presenter_id:
print("{:>5} {:<45} {}".format(m[key], m["meetingName"], get_formated_presenter_name_id(m)))
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]):
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.
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)
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
out an overview of the current bbb-usage
......@@ -162,12 +188,14 @@ def print_overview(config: Config):
# Print divider if there is more than one endpoint
if i > 0:
print()
print("="*80)
print("="*click.get_terminal_size()[0])
print()
# If there are no meetings, skip to next endpoint
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
n_running = len(meetings)
......@@ -178,25 +206,29 @@ def print_overview(config: Config):
n_video = sum([int(m["videoCount"]) for m in meetings])
n_moderator = sum([int(m["moderatorCount"]) for m in meetings])
print("MEETINGS on [{}]:".format(endpoint.name))
if show_meetings:
print_header(endpoint.name, "MEETINGS", fancy)
print(" ├─── {:>4} running".format(n_running))
print(" └─── {:>4} recording".format(n_recording))
print()
print("PARTICIPANTS across all {} rooms".format(n_running))
if participants:
print_header(endpoint.name, "PARTICIPANTS across all {} rooms".format(n_running), fancy)
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))
if leaderboards:
print()
print_leaderboard(meetings, "participantCount")
print_leaderboard(meetings, "participantCount", endpoint.name, presenter, presenter_id, fancy)
print()
print_leaderboard(meetings, "videoCount")
print_leaderboard(meetings, "videoCount", endpoint.name, presenter, presenter_id, fancy)
print()
print_leaderboard(meetings, "voiceParticipantCount")
print_leaderboard(meetings, "voiceParticipantCount", endpoint.name, presenter, presenter_id, fancy)
print()
print_duration_leaderboard(meetings)
print_duration_leaderboard(meetings, endpoint.name, presenter, presenter_id, fancy)
def init_config() -> Optional[Config]:
......@@ -227,10 +259,18 @@ def init_config() -> Optional[Config]:
exit()
def main():
Config = init_config()
print_overview(Config)
@click.command()
@click.option('--endpoint', '-e', multiple=True, help="Filter by one or more endpoints as named in the user configuration. Order is respected.")
@click.option('--leaderboards/--no-leaderboards', default=True, show_default=True, help="Hide or show the meeting leaderboards")
@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__":
......
......@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
import configparser
from typing import NewType, Optional, Tuple, Iterable, List
import click
# Default path
SERVER_PROPERTIES_FILE = "/usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties"
......@@ -55,6 +56,22 @@ class Config():
self = self.from_server(path)
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):
"""
The length of a Config is represented by the number of endpoints
......
[tool.poetry]
name = "bbbmon"
version = "0.1.8"
version = "0.1.9"
description = "A small CLI utility to monitor bbb usage"
authors = ["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