bbblb 0.0.2__py3-none-any.whl
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.
- bbblb/__init__.py +23 -0
- bbblb/__main__.py +3 -0
- bbblb/api/__init__.py +81 -0
- bbblb/api/bbbapi.py +697 -0
- bbblb/api/bbblbapi.py +265 -0
- bbblb/asgi.py +4 -0
- bbblb/bbblib.py +193 -0
- bbblb/cli/__init__.py +41 -0
- bbblb/cli/maketoken.py +46 -0
- bbblb/cli/run.py +28 -0
- bbblb/model.py +552 -0
- bbblb/poller.py +185 -0
- bbblb/recordings.py +523 -0
- bbblb/settings.py +232 -0
- bbblb/utils.py +57 -0
- bbblb-0.0.2.dist-info/METADATA +100 -0
- bbblb-0.0.2.dist-info/RECORD +20 -0
- bbblb-0.0.2.dist-info/WHEEL +4 -0
- bbblb-0.0.2.dist-info/entry_points.txt +2 -0
- bbblb-0.0.2.dist-info/licenses/LICENSE-AGPL-3.0.md +660 -0
bbblb/__init__.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from .settings import config
|
|
3
|
+
|
|
4
|
+
__version__ = "0.0.2"
|
|
5
|
+
VERSION = __version__.split(".", 2)
|
|
6
|
+
VERSION[-1], _, BUILD = VERSION[-1].partition("-")
|
|
7
|
+
|
|
8
|
+
ROOT_LOGGER = logging.getLogger(__name__)
|
|
9
|
+
ROOT_LOGGER.setLevel(logging.INFO)
|
|
10
|
+
ROOT_LOGGER.propagate = False
|
|
11
|
+
ch = logging.StreamHandler()
|
|
12
|
+
ch.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s %(message)s"))
|
|
13
|
+
ROOT_LOGGER.addHandler(ch)
|
|
14
|
+
|
|
15
|
+
BRANDING = "BBBLB (AGPL-3, https://github.com/defnull/bbblb)"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@config.watch
|
|
19
|
+
def watch_debug_level(name, old, new):
|
|
20
|
+
if name == "DEBUG":
|
|
21
|
+
level = logging.DEBUG if new else logging.INFO
|
|
22
|
+
if level != ROOT_LOGGER.level:
|
|
23
|
+
ROOT_LOGGER.setLevel(logging.DEBUG if new else logging.INFO)
|
bbblb/__main__.py
ADDED
bbblb/api/__init__.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from contextlib import asynccontextmanager
|
|
2
|
+
from functools import partial
|
|
3
|
+
import pathlib
|
|
4
|
+
from starlette.applications import Starlette
|
|
5
|
+
from starlette.routing import Mount
|
|
6
|
+
from starlette.staticfiles import StaticFiles
|
|
7
|
+
from starlette.responses import RedirectResponse
|
|
8
|
+
|
|
9
|
+
from bbblb.api import bbbapi
|
|
10
|
+
from bbblb.api import bbblbapi
|
|
11
|
+
from bbblb import model
|
|
12
|
+
from bbblb import poller
|
|
13
|
+
from bbblb import recordings
|
|
14
|
+
from bbblb import bbblib
|
|
15
|
+
from bbblb.settings import config
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@asynccontextmanager
|
|
19
|
+
async def lifespan(app: Starlette):
|
|
20
|
+
await model.init_engine(config.DB, echo=False)
|
|
21
|
+
poll_worker = poller.Poller()
|
|
22
|
+
importer = recordings.RecordingImporter(
|
|
23
|
+
basedir=pathlib.Path(config.RECORDING_PATH),
|
|
24
|
+
concurrency=config.RECORDING_THREADS,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
async with poll_worker, importer:
|
|
29
|
+
app.state.poll_worker = poll_worker
|
|
30
|
+
app.state.importer = importer
|
|
31
|
+
yield
|
|
32
|
+
finally:
|
|
33
|
+
await bbblib.close_pool()
|
|
34
|
+
await model.dispose_engine()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Playback formats for which we know that they sometimes expect their files
|
|
38
|
+
# in /{format}/* instead of the default /playback/{format}/* path.
|
|
39
|
+
PLAYBACK_FROM_ROOT_FORMATS = ("presentation", "video")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
async def format_redirect_app(format, scope, receive, send):
|
|
43
|
+
assert scope["type"] == "http"
|
|
44
|
+
path = scope["path"].lstrip("/")
|
|
45
|
+
response = RedirectResponse(url=f"/playback/{format}/{path}")
|
|
46
|
+
await response(scope, receive, send)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def make_playback_routes():
|
|
50
|
+
return [
|
|
51
|
+
# Serve /playback/* files in case the reverse proxy in front if BBBLB does not.
|
|
52
|
+
Mount(
|
|
53
|
+
"/playback",
|
|
54
|
+
app=StaticFiles(
|
|
55
|
+
directory=config.RECORDING_PATH / "public",
|
|
56
|
+
check_dir=False,
|
|
57
|
+
follow_symlink=True,
|
|
58
|
+
),
|
|
59
|
+
name="bbb:playback",
|
|
60
|
+
),
|
|
61
|
+
# Redirect misguided playback file requests to the real path. We send
|
|
62
|
+
# redirects instead of real files in case a reverse proxy in front if BBBLB
|
|
63
|
+
# serves /playback/* for us more efficiently.
|
|
64
|
+
*[
|
|
65
|
+
Mount(f"/{format}", app=partial(format_redirect_app, format))
|
|
66
|
+
for format in PLAYBACK_FROM_ROOT_FORMATS
|
|
67
|
+
],
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def make_routes():
|
|
72
|
+
return [
|
|
73
|
+
Mount("/bigbluebutton/api", routes=bbbapi.api_routes),
|
|
74
|
+
Mount("/api", routes=bbblbapi.api_routes),
|
|
75
|
+
*make_playback_routes(),
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def make_app():
|
|
80
|
+
config.populate()
|
|
81
|
+
return Starlette(debug=True, routes=make_routes(), lifespan=lifespan)
|