bbbctl 0.4.3__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bbbctl
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: BigBlueButton API command-line client
|
|
5
5
|
Author-email: Marcel Hellkamp <marc@gsites.de>
|
|
6
|
-
Requires-Python: >=3.
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-Expression: MIT
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -92,7 +92,7 @@ for meeting in client.getMeetings():
|
|
|
92
92
|
|
|
93
93
|
# License
|
|
94
94
|
|
|
95
|
-
Copyright (c) 2020-
|
|
95
|
+
Copyright (c) 2020-2026, Marcel Hellkamp.
|
|
96
96
|
|
|
97
97
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
98
98
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -78,7 +78,7 @@ for meeting in client.getMeetings():
|
|
|
78
78
|
|
|
79
79
|
# License
|
|
80
80
|
|
|
81
|
-
Copyright (c) 2020-
|
|
81
|
+
Copyright (c) 2020-2026, Marcel Hellkamp.
|
|
82
82
|
|
|
83
83
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
84
84
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -6,10 +6,10 @@ build-backend = "flit_core.buildapi"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "bbbctl"
|
|
9
|
-
version = "0.
|
|
9
|
+
version = "0.5.0"
|
|
10
10
|
description = "BigBlueButton API command-line client"
|
|
11
11
|
readme = "README.md"
|
|
12
|
-
requires-python = ">=3.
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
13
|
license = "MIT"
|
|
14
14
|
authors = [
|
|
15
15
|
{ name = "Marcel Hellkamp", email = "marc@gsites.de" },
|
|
@@ -319,8 +319,8 @@ CREATE_LOCKS = {
|
|
|
319
319
|
"cam": "lockSettingsDisableCam",
|
|
320
320
|
"mic": "lockSettingsDisableMic",
|
|
321
321
|
"chat": "lockSettingsDisablePublicChat",
|
|
322
|
-
"pm": "
|
|
323
|
-
"notes": "
|
|
322
|
+
"pm": "lockSettingsDisablePrivateChat",
|
|
323
|
+
"notes": "lockSettingsDisableNotes",
|
|
324
324
|
"userlist": "lockSettingsHideUserList",
|
|
325
325
|
"cursor": "lockSettingsHideViewersCursor",
|
|
326
326
|
}
|
|
@@ -367,7 +367,7 @@ class BBBApiClient:
|
|
|
367
367
|
with urllib.request.urlopen(url, context=self.ssl) as f:
|
|
368
368
|
xml = f.read().decode("utf8")
|
|
369
369
|
if self.debug >= 2:
|
|
370
|
-
for line in xml:
|
|
370
|
+
for line in xml.splitlines():
|
|
371
371
|
print(f"<<< {line}", file=sys.stderr)
|
|
372
372
|
root = ET.fromstring(xml)
|
|
373
373
|
if (status := root.find("./returncode")) is None or status.text != "SUCCESS":
|
|
@@ -412,8 +412,20 @@ class BBBApiClient:
|
|
|
412
412
|
|
|
413
413
|
def build_parser():
|
|
414
414
|
|
|
415
|
-
def
|
|
416
|
-
|
|
415
|
+
def csv_choice(choices):
|
|
416
|
+
choices = set(choices)
|
|
417
|
+
|
|
418
|
+
def parse(value):
|
|
419
|
+
items = [item.strip() for item in value.split(",") if item.strip()]
|
|
420
|
+
unknown = [item for item in items if item not in choices]
|
|
421
|
+
if unknown:
|
|
422
|
+
raise argparse.ArgumentTypeError(
|
|
423
|
+
"invalid choice: %s (choose from %s)"
|
|
424
|
+
% (", ".join(unknown), ", ".join(sorted(choices)))
|
|
425
|
+
)
|
|
426
|
+
return items
|
|
427
|
+
|
|
428
|
+
return parse
|
|
417
429
|
|
|
418
430
|
def kv_type(value):
|
|
419
431
|
k, _, v = value.partition("=")
|
|
@@ -422,7 +434,7 @@ def build_parser():
|
|
|
422
434
|
return (k, v)
|
|
423
435
|
|
|
424
436
|
parser = argparse.ArgumentParser()
|
|
425
|
-
main_sub = parser.add_subparsers(title="Commands")
|
|
437
|
+
main_sub = parser.add_subparsers(title="Commands", required=True)
|
|
426
438
|
|
|
427
439
|
parser.add_argument(
|
|
428
440
|
"--server",
|
|
@@ -456,7 +468,7 @@ def build_parser():
|
|
|
456
468
|
"record",
|
|
457
469
|
help="List, show, publish, unpublish or delete recordings",
|
|
458
470
|
)
|
|
459
|
-
rec_sub = rec.add_subparsers(title="Manage recordings")
|
|
471
|
+
rec_sub = rec.add_subparsers(title="Manage recordings", required=True)
|
|
460
472
|
|
|
461
473
|
cmd = rec_sub.add_parser("list", help="List all recordings")
|
|
462
474
|
cmd.add_argument("--meeting", help="Filter by external meetingID")
|
|
@@ -481,7 +493,7 @@ def build_parser():
|
|
|
481
493
|
meet = main_sub.add_parser(
|
|
482
494
|
"meeting", help="List, inspect, create, join or end meetings"
|
|
483
495
|
)
|
|
484
|
-
meet_sub = meet.add_subparsers()
|
|
496
|
+
meet_sub = meet.add_subparsers(required=True)
|
|
485
497
|
|
|
486
498
|
cmd = meet_sub.add_parser("list", help="List meetings")
|
|
487
499
|
cmd.add_argument("--sort", help="Sort by a specific key")
|
|
@@ -513,8 +525,7 @@ def build_parser():
|
|
|
513
525
|
cmd.add_argument(
|
|
514
526
|
"--lock",
|
|
515
527
|
help="Shortcuts for --lockSettingsDisable... parameters.",
|
|
516
|
-
|
|
517
|
-
type=csv_type,
|
|
528
|
+
type=csv_choice(CREATE_LOCKS.keys()),
|
|
518
529
|
)
|
|
519
530
|
|
|
520
531
|
cmd.add_argument(
|
|
@@ -528,15 +539,13 @@ def build_parser():
|
|
|
528
539
|
cmd.add_argument(
|
|
529
540
|
"--disabledFeatures",
|
|
530
541
|
help="Disable features for this meeting. Set multiple values as comma-separated list.",
|
|
531
|
-
|
|
532
|
-
type=csv_type,
|
|
542
|
+
type=csv_choice(CREATE_FEATURES),
|
|
533
543
|
)
|
|
534
544
|
|
|
535
545
|
cmd.add_argument(
|
|
536
546
|
"--disabledFeaturesExclude",
|
|
537
547
|
help="Remove featres from the --disabledFeatures list. Set multiple values as comma-separated list.",
|
|
538
|
-
|
|
539
|
-
type=csv_type,
|
|
548
|
+
type=csv_choice(CREATE_FEATURES),
|
|
540
549
|
)
|
|
541
550
|
|
|
542
551
|
for name, (type_, help) in CREATE_PARAMS.items():
|
|
@@ -635,8 +644,6 @@ def find_bbb_property(name):
|
|
|
635
644
|
def main():
|
|
636
645
|
parser = build_parser()
|
|
637
646
|
args = parser.parse_args()
|
|
638
|
-
if not hasattr(args, "cmd"):
|
|
639
|
-
parser.parse_args(sys.argv[1:] + ["-h"])
|
|
640
647
|
|
|
641
648
|
server = (
|
|
642
649
|
args.server
|
|
@@ -799,8 +806,8 @@ def cmd_meet_create(api, args):
|
|
|
799
806
|
params = {"meetingID": args.id, "name": args.name}
|
|
800
807
|
|
|
801
808
|
# Process --lock first so it can be overridden by explicit --no-lockSettingsBlaBla
|
|
802
|
-
for k, v in CREATE_LOCKS:
|
|
803
|
-
if k in args.lock:
|
|
809
|
+
for k, v in CREATE_LOCKS.items():
|
|
810
|
+
if k in (args.lock or []):
|
|
804
811
|
params[v] = "true"
|
|
805
812
|
|
|
806
813
|
# Apply all CREATE_PARAMS
|
|
@@ -814,25 +821,29 @@ def cmd_meet_create(api, args):
|
|
|
814
821
|
params[name] = str(value)
|
|
815
822
|
|
|
816
823
|
# Apply --meta key=value
|
|
817
|
-
for k, v in args.meta:
|
|
824
|
+
for k, v in args.meta or []:
|
|
818
825
|
if v:
|
|
819
826
|
params[f"meta_{k}"] = str(v)
|
|
820
827
|
|
|
821
828
|
# Apply --disable feature,feature
|
|
822
829
|
disabled = set()
|
|
823
830
|
enabled = set()
|
|
824
|
-
for feature in args.
|
|
831
|
+
for feature in args.disabledFeatures or []:
|
|
825
832
|
if feature in CREATE_FEATURES:
|
|
826
833
|
disabled.add(feature)
|
|
827
|
-
for feature in args.
|
|
834
|
+
for feature in args.disabledFeaturesExclude or []:
|
|
828
835
|
if feature in CREATE_FEATURES:
|
|
829
836
|
enabled.add(feature)
|
|
830
|
-
disabled.
|
|
837
|
+
disabled.discard(feature)
|
|
831
838
|
if disabled:
|
|
832
839
|
params["disabledFeatures"] = ",".join(sorted(disabled))
|
|
833
|
-
if
|
|
840
|
+
if enabled:
|
|
834
841
|
params["disabledFeaturesExclude"] = ",".join(sorted(enabled))
|
|
835
842
|
|
|
843
|
+
# Apply raw key=value parameters last so they can override shortcuts.
|
|
844
|
+
for k, v in args.params:
|
|
845
|
+
params[k] = str(v)
|
|
846
|
+
|
|
836
847
|
created = api.createMeeting(**params)
|
|
837
848
|
|
|
838
849
|
if args.join:
|
|
@@ -897,7 +908,10 @@ def cmd_meet_nuke(api, args):
|
|
|
897
908
|
pass
|
|
898
909
|
else:
|
|
899
910
|
continue
|
|
900
|
-
api.end(
|
|
911
|
+
api.end(
|
|
912
|
+
meetingID=meeting.find("meetingID").text,
|
|
913
|
+
password=meeting.find("moderatorPW").text,
|
|
914
|
+
)
|
|
901
915
|
|
|
902
916
|
|
|
903
917
|
def cmd_sign(api, args):
|
|
File without changes
|