bbbctl 0.1.0__tar.gz → 0.3.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.
- {bbbctl-0.1.0/src/bbbctl.egg-info → bbbctl-0.3.0}/PKG-INFO +1 -1
- {bbbctl-0.1.0 → bbbctl-0.3.0}/setup.cfg +1 -1
- {bbbctl-0.1.0 → bbbctl-0.3.0/src/bbbctl.egg-info}/PKG-INFO +1 -1
- {bbbctl-0.1.0 → bbbctl-0.3.0}/src/bbbctl.py +50 -20
- {bbbctl-0.1.0 → bbbctl-0.3.0}/LICENSE +0 -0
- {bbbctl-0.1.0 → bbbctl-0.3.0}/README.md +0 -0
- {bbbctl-0.1.0 → bbbctl-0.3.0}/pyproject.toml +0 -0
- {bbbctl-0.1.0 → bbbctl-0.3.0}/src/bbbctl.egg-info/SOURCES.txt +0 -0
- {bbbctl-0.1.0 → bbbctl-0.3.0}/src/bbbctl.egg-info/dependency_links.txt +0 -0
- {bbbctl-0.1.0 → bbbctl-0.3.0}/src/bbbctl.egg-info/entry_points.txt +0 -0
- {bbbctl-0.1.0 → bbbctl-0.3.0}/src/bbbctl.egg-info/top_level.txt +0 -0
|
@@ -6,10 +6,9 @@ import urllib.parse
|
|
|
6
6
|
import hashlib
|
|
7
7
|
import sys, os
|
|
8
8
|
import xml.etree.ElementTree as ET
|
|
9
|
-
from xml.dom import minidom
|
|
10
9
|
import json
|
|
11
10
|
import datetime
|
|
12
|
-
import
|
|
11
|
+
import ssl
|
|
13
12
|
|
|
14
13
|
__all__ = ["BBBApiClient", "ApiError"]
|
|
15
14
|
|
|
@@ -23,9 +22,10 @@ class ApiError(RuntimeError):
|
|
|
23
22
|
|
|
24
23
|
|
|
25
24
|
class BBBApiClient:
|
|
26
|
-
def __init__(self, api, secret):
|
|
25
|
+
def __init__(self, api, secret, ssl_context=None):
|
|
27
26
|
self.api = api.rstrip("/")
|
|
28
27
|
self.secret = secret
|
|
28
|
+
self.ssl = ssl_context or ssl.create_default_context()
|
|
29
29
|
|
|
30
30
|
def makeurl(self, command, **query):
|
|
31
31
|
query = urllib.parse.urlencode(query)
|
|
@@ -39,7 +39,7 @@ class BBBApiClient:
|
|
|
39
39
|
|
|
40
40
|
def call(self, command, **query):
|
|
41
41
|
url = self.makeurl(command, **query)
|
|
42
|
-
with urllib.request.urlopen(url) as f:
|
|
42
|
+
with urllib.request.urlopen(url, context=self.ssl) as f:
|
|
43
43
|
xml = f.read().decode("utf8")
|
|
44
44
|
root = ET.fromstring(xml)
|
|
45
45
|
if root.find("./returncode").text != "SUCCESS":
|
|
@@ -84,6 +84,10 @@ def build_parser():
|
|
|
84
84
|
"--secret",
|
|
85
85
|
help="API secretd (default: BBBCTL_SECRET or local config)",
|
|
86
86
|
)
|
|
87
|
+
parser.add_argument(
|
|
88
|
+
"--insecure",
|
|
89
|
+
help="Skip TLS verification and accept self-signed or invalid SSL certificates as if they were valid",
|
|
90
|
+
)
|
|
87
91
|
|
|
88
92
|
parser.add_argument(
|
|
89
93
|
"--format",
|
|
@@ -125,7 +129,7 @@ def build_parser():
|
|
|
125
129
|
|
|
126
130
|
cmd = meet_sub.add_parser("list", help="List meetings")
|
|
127
131
|
cmd.add_argument("--sort", help="Sort by a specific key")
|
|
128
|
-
cmd.add_argument("--no-user", action="store_true", help="Do not show
|
|
132
|
+
cmd.add_argument("--no-user", action="store_true", help="Do not show participants")
|
|
129
133
|
cmd.set_defaults(cmd=cmd_meet_list)
|
|
130
134
|
|
|
131
135
|
cmd = meet_sub.add_parser("info", help="Show meeting details")
|
|
@@ -135,10 +139,10 @@ def build_parser():
|
|
|
135
139
|
cmd = meet_sub.add_parser("create", help="Create meeting")
|
|
136
140
|
cmd.add_argument("id", help="Meeting ID")
|
|
137
141
|
cmd.add_argument("name", help="Meeting name")
|
|
138
|
-
cmd.add_argument("--record", help="Allow
|
|
142
|
+
cmd.add_argument("--record", help="Allow recording?", action="store_true")
|
|
139
143
|
cmd.add_argument(
|
|
140
144
|
"--mod",
|
|
141
|
-
help="Directly create and print a join link for this username. Can be repeated.",
|
|
145
|
+
help="Directly create and print a moderator join link for this username. Can be repeated.",
|
|
142
146
|
action="append",
|
|
143
147
|
)
|
|
144
148
|
cmd.set_defaults(cmd=cmd_meet_create)
|
|
@@ -161,7 +165,8 @@ def build_parser():
|
|
|
161
165
|
cmd.set_defaults(cmd=cmd_meet_end)
|
|
162
166
|
|
|
163
167
|
cmd = meet_sub.add_parser("nuke", help="End ALL meeting")
|
|
164
|
-
cmd.add_argument("--doit", help="
|
|
168
|
+
cmd.add_argument("--doit", help="Disable dry-run mode and actually end meetings?", action="store_true")
|
|
169
|
+
cmd.add_argument("--ask", help="Ask for every meeting?", action="store_true")
|
|
165
170
|
cmd.set_defaults(cmd=cmd_meet_nuke)
|
|
166
171
|
|
|
167
172
|
return parser
|
|
@@ -176,6 +181,7 @@ config_paths = [
|
|
|
176
181
|
"/etc/bigbluebutton/bbb-web.properties",
|
|
177
182
|
"/usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties",
|
|
178
183
|
"/var/lib/tomcat7/webapps/bigbluebutton/WEB-INF/classes/bigbluebutton.properties",
|
|
184
|
+
"./bbbctl.conf",
|
|
179
185
|
]
|
|
180
186
|
|
|
181
187
|
|
|
@@ -213,12 +219,17 @@ def main():
|
|
|
213
219
|
)
|
|
214
220
|
|
|
215
221
|
server = server.rstrip("/")
|
|
216
|
-
if
|
|
222
|
+
if "://" not in server:
|
|
217
223
|
server = "https://" + server
|
|
218
224
|
if not server.endswith("/bigbluebutton/api"):
|
|
219
225
|
server += "/bigbluebutton/api"
|
|
220
226
|
|
|
221
|
-
|
|
227
|
+
ctx = ssl.create_default_context()
|
|
228
|
+
if args.insecure:
|
|
229
|
+
ctx.check_hostname = False
|
|
230
|
+
ctx.verify_mode = ssl.CERT_NONE
|
|
231
|
+
|
|
232
|
+
client = BBBApiClient(server, secret, ssl_context=ctx)
|
|
222
233
|
|
|
223
234
|
try:
|
|
224
235
|
args.cmd(client, args)
|
|
@@ -249,7 +260,7 @@ def format_human(e, indent=""):
|
|
|
249
260
|
result = indent + e.tag + ":"
|
|
250
261
|
if e.tag.lower() in ("starttime", "endtime"):
|
|
251
262
|
value = "%s (%s)" % (
|
|
252
|
-
datetime.datetime.
|
|
263
|
+
datetime.datetime.fromtimestamp(float(value) / 1000, datetime.timezone.utc),
|
|
253
264
|
value,
|
|
254
265
|
)
|
|
255
266
|
if value:
|
|
@@ -278,7 +289,19 @@ def format_json(e, *a, **ka):
|
|
|
278
289
|
|
|
279
290
|
|
|
280
291
|
_should_be_list = ["attendees"]
|
|
281
|
-
_should_be_number = [
|
|
292
|
+
_should_be_number = [
|
|
293
|
+
"createTime",
|
|
294
|
+
"duration",
|
|
295
|
+
"startTime",
|
|
296
|
+
"endTime",
|
|
297
|
+
"participantCount",
|
|
298
|
+
"listenerCount",
|
|
299
|
+
"voiceParticipantCount",
|
|
300
|
+
"videoCount",
|
|
301
|
+
"maxUsers",
|
|
302
|
+
"moderatorCount",
|
|
303
|
+
]
|
|
304
|
+
|
|
282
305
|
|
|
283
306
|
def _unpack_xml(e):
|
|
284
307
|
if e.tag in _should_be_list:
|
|
@@ -290,8 +313,8 @@ def _unpack_xml(e):
|
|
|
290
313
|
return int(value)
|
|
291
314
|
if not value:
|
|
292
315
|
return None
|
|
293
|
-
if value in (
|
|
294
|
-
return value ==
|
|
316
|
+
if value in ("true", "false"):
|
|
317
|
+
return value == "true"
|
|
295
318
|
return value
|
|
296
319
|
|
|
297
320
|
|
|
@@ -351,7 +374,8 @@ def cmd_meet_create(api, args):
|
|
|
351
374
|
link = api.getJoinLink(
|
|
352
375
|
meetingID=args.id,
|
|
353
376
|
fullName=name,
|
|
354
|
-
|
|
377
|
+
createTime=created.find("createTime").text,
|
|
378
|
+
role="MODERATOR",
|
|
355
379
|
)
|
|
356
380
|
print(name + ":", link)
|
|
357
381
|
|
|
@@ -365,6 +389,7 @@ def cmd_meet_join(api, args):
|
|
|
365
389
|
|
|
366
390
|
if args.open:
|
|
367
391
|
import webbrowser
|
|
392
|
+
|
|
368
393
|
webbrowser.open_new_tab(link)
|
|
369
394
|
else:
|
|
370
395
|
print(link)
|
|
@@ -378,11 +403,6 @@ def cmd_meet_end(api, args):
|
|
|
378
403
|
def cmd_meet_nuke(api, args):
|
|
379
404
|
meetings = list(api.getMeetings())
|
|
380
405
|
for meeting in meetings:
|
|
381
|
-
if args.doit:
|
|
382
|
-
api.end(
|
|
383
|
-
meetingID=meeting.find("meetingID").text,
|
|
384
|
-
password=meeting.find("moderatorPW").text,
|
|
385
|
-
)
|
|
386
406
|
print(
|
|
387
407
|
"{dryrun}id={id} user={users} name={name!r}".format(
|
|
388
408
|
dryrun="" if args.doit else "(dry run) ",
|
|
@@ -391,6 +411,16 @@ def cmd_meet_nuke(api, args):
|
|
|
391
411
|
name=meeting.find("meetingName").text,
|
|
392
412
|
)
|
|
393
413
|
)
|
|
414
|
+
if args.doit:
|
|
415
|
+
if args.ask:
|
|
416
|
+
answer = input("End this meeting? [Yna] ").strip().lower()
|
|
417
|
+
if answer == "a":
|
|
418
|
+
args.ask = False
|
|
419
|
+
elif answer in ("", "y"):
|
|
420
|
+
pass
|
|
421
|
+
else:
|
|
422
|
+
continue
|
|
423
|
+
api.end(meetingID=meeting.find("meetingID").text)
|
|
394
424
|
|
|
395
425
|
|
|
396
426
|
if __name__ == "__main__":
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|