Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
bbb
bbbmon
Commits
7fe39038
Commit
7fe39038
authored
Apr 28, 2020
by
David Huss
💬
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a ton of CLI options, formatting fixes & fancy
parent
012ede87
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
103 additions
and
37 deletions
+103
-37
README.md
README.md
+10
-1
bbbmon/bbbmon.py
bbbmon/bbbmon.py
+75
-35
bbbmon/configuration.py
bbbmon/configuration.py
+17
-0
pyproject.toml
pyproject.toml
+1
-1
No files found.
README.md
View file @
7fe39038
...
...
@@ -57,4 +57,13 @@ bigbluebutton.web.serverURL=https://bbb.example.com/
securitySalt
=
MY_SUPER_SECRET_SECRET
2
bigbluebutton.web.serverURL
=
https://bbb.foo.com/
```
The section names in the square brackets will be used as display names (these support utf-8)
\ No newline at end of file
The section names in the square brackets will be used as display names (these support utf-8)
# Usage
For help run:
```
bash
bbbmon
--help
```
bbbmon/bbbmon.py
View file @
7fe39038
...
...
@@ -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
:
print
(
"{:>5} {:<45} {}"
.
format
(
m
[
key
],
m
[
"meetingName"
],
get_formated_presenter_name
(
m
)))
def
print_duration_leaderboard
(
meetings
:
Iterable
[
XmlDictConfig
]):
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
],
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
))
print
(
" ├─── {:>4} running"
.
format
(
n_running
))
print
(
" └─── {:>4} recording"
.
format
(
n_recording
))
print
()
print
(
"PARTICIPANTS across all {} rooms"
.
format
(
n_running
))
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
show_meetings
:
print_header
(
endpoint
.
name
,
"MEETINGS"
,
fancy
)
print
(
" ├─── {:>4} running"
.
format
(
n_running
))
print
(
" └─── {:>4} recording"
.
format
(
n_recording
))
print
()
print
()
print_leaderboard
(
meetings
,
"participantCount"
)
print
()
print_leaderboard
(
meetings
,
"videoCount"
)
print
()
print_leaderboard
(
meetings
,
"voiceParticipantCount"
)
print
()
print_duration_leaderboard
(
meetings
)
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"
,
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
]:
...
...
@@ -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__"
:
...
...
bbbmon/configuration.py
View file @
7fe39038
...
...
@@ -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
...
...
pyproject.toml
View file @
7fe39038
[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>"
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment