Skip to content
Snippets Groups Projects

WIP: Resolve "Support recordings"

Open Nik | Klampfradler requested to merge 6-support-recordings into master
1 file
+ 231
0
Compare changes
  • Side-by-side
  • Inline
+ 231
0
"""Data structures for manageing meeting """
import logging
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, Dict, Optional
from ._caching import cache
from .util import camel_to_snake, snake_to_camel, to_field_type
if TYPE_CHECKING: # pragma: no cover
from .meeting import Meeting
logger = logging.getLogger(__name__)
@dataclass
class PreviewImage:
"""One preview image of a processed recording format.
This object holds the information about one image and and is linked to
exactly one recording format.
"""
format: "PlaybackFormat" # noqa: F821
alt: str = ""
height: int = field(default=0, compare=False)
width: int = field(default=0, compare=False)
url: Optional[str] = None
def __post_init__(self):
"""Self-register in linked format."""
self.format.preview_images.append(self)
def _update_from_response(self, res: Dict[str, Any]) -> None:
pass
# FIXME Find out how to get to attributes and text nodes
def to_dict(self, *args: str, **kwargs: str) -> Dict[str, Any]:
"""Return relevant data of this image as a dictionary.
The dictionary can be used to build an XML document compatible
with BigBlueButton API clients.
If names of attributes are passed as positional arguments, only
these attributes are returned in the dictionary.
If attribute names are passed as names of keyword arguments,
they are renamed to the string passed as value in the dictionary.
"""
pass
#FIXME FInd out how to build a dict for attributes and text nodes
@dataclass
class PlaybackFormat:
"""One format of a processed recording.
This object holds the information about one format and and is linked to
exactly one recording.
"""
recording: "Recording" # noqa: F821
type_: Optional[str] = None
url: Optional[str] = None
processing_time: int = field(default=0, compare=False)
length: int = field(default=0, compare=False)
preview_images: List[PreviewImage] = field(default_factory=list, compare=False)
def __post_init__(self):
"""Self-register in linked recording."""
self.recording.formats.append(self)
def _update_from_response(self, res: Dict[str, Any]) -> None:
for name, value in res.items():
if name == "preview":
if not value or not value["images"] or not value["images"]["image"]:
self.preview_images.clear()
else:
if not isinstance(value["images"]["image"], list):
value["images"]["image"] = [value["images"]["image"]]
for image_dict in value["images"]["image"]:
image = PreviewImage(self)
image._update_from_response(image_dict)
else:
snake_name = camel_to_snake(name)
if hasattr(self, snake_name):
setattr(self, snake_name, to_field_type(self, snake_name, value))
def to_dict(self, *args: str, **kwargs: str) -> Dict[str, Any]:
"""Return relevant data of this format as a dictionary.
The dictionary can be used to build an XML document compatible
with BigBlueButton API clients.
If names of attributes are passed as positional arguments, only
these attributes are returned in the dictionary.
If attribute names are passed as names of keyword arguments,
they are renamed to the string passed as value in the dictionary.
"""
res: Dict[str, Any] = {}
for name, value in self.__dict__.items():
if args and name not in args and name not in kwargs:
continue
if name == "preview":
res["preview"] = {
"images": {
"image": [
image.to_dict() for image in self.preview_images
]
}
}
elif value is not None:
if name in kwargs:
camel_name = kwargs[name]
else:
camel_name = snake_to_camel(name)
if isinstance(value, bool):
str_value = "true" if value else "false"
else:
str_value = str(value)
res[camel_name] = str_value
return res
@dataclass
class Recording:
"""One recording that was made during a meeting.
This object holds the information about one recording and is linked to
exactly one meeting.
"""
meeting: "Meeting" # noqa: F821
record_id: Optional[str] = None
meta: Dict[str, str] = field(default_factory=dict)
published: Optional[bool] = field(default=None, compare=False)
state: Optional[str] = field(default=None, compare=False)
start_time: int = field(default=0, compare=False)
end_time: int = field(default=0, compare=False)
participants: int = field(default=0, compare=False)
formats: List[PlaybackFormat] = field(default_factory=list, init=False, compare=False)
def __post_init__(self):
"""Self-register in linked meeting."""
self.meeting.recordings.append(self)
def _update_from_response(self, res: Dict[str, Any]) -> None:
for name, value in res.items():
if name == "playback":
if not value or not value["format"]:
self.formats.clear()
else:
if not isinstance(value["format"], list):
value["format"] = [value["format"]]
for format_dict in value["format"]:
format = PlaybackFormat(self)
format._update_from_response(format_dict)
elif name == "metadata":
if value:
self.meta = dict(value)
else:
self.meta.clear()
else:
snake_name = camel_to_snake(name)
if hasattr(self, snake_name):
setattr(self, snake_name, to_field_type(self, snake_name, value))
def to_dict(self, *args: str, **kwargs: str) -> Dict[str, Any]:
"""Return relevant data of this recording as a dictionary.
The dictionary can be used to build an XML document compatible
with BigBlueButton API clients.
If names of attributes are passed as positional arguments, only
these attributes are returned in the dictionary.
If attribute names are passed as names of keyword arguments,
they are renamed to the string passed as value in the dictionary.
"""
res: Dict[str, Any] = {}
for name, value in self.__dict__.items():
if args and name not in args and name not in kwargs:
continue
if name == "meeting":
# Recordings carry a lot of duplicated data in their response
res["meetingID"] = self.meeting.meeting_id
res["name"] = self.meeting.name
res["internalMeetingID"] = self.meeting.internal_meeting_id
res["isBreakout"] = self.meeting.is_breakout
elif name == "formats":
res["playback"] = {
"format": [
format.to_dict() for format in self.formats.values()
]
}
elif value is not None:
if name in kwargs:
camel_name = kwargs[name]
else:
camel_name = snake_to_camel(name)
if isinstance(value, bool):
str_value = "true" if value else "false"
else:
str_value = str(value)
res[camel_name] = str_value
return res
Loading