synology_apm_repo.sdk.units.saas.teams_chat module

TeamsChatProvider: M365 Teams channels + 1:1/group chats.

render_channel_html renders each channel/chat as one self-contained HTML page — the unit’s only exported form. The raw message DB is still reachable via RawObjectProvider (the CLI’s --verbose / TUI’s diagnostic mode), listed like any other unrecognized SaaS object.

Channel’s own tree wraps a flat, one-level listing of every channel (_TeamsEntityFlatTree) in tree_strategy.CategorizedGroupTree for its Standard/Private/Shared split (keyed off the real channel_info_table.channel_type column) – the same TreeStrategy machinery Site/Calendar use for their own synthetic category level. Chat has no such concept and uses the bare, unwrapped flat tree directly. root()/children() delegate to whichever of the two self._tree is uniformly, via that shared protocol, the same shape SaasWorkloadProvider uses for every other SaaS workload – this class still isn’t built on that class itself, since its own discovery mechanism (below) doesn’t fit the config-driven tables/object_names model that class assumes. unit() needs no such delegation: everything it reads (object_id, degraded) already lives on the Node children() built.

Unlike every other SaaS provider here, Teams and Chat locate their service-level DBs via one shared discovery mechanism: the index entry points at an INDEX object rather than naming one service DB directly, since the number of channels/chats is only known at backup time. Chat’s own rendering path is implemented generically from the docs’ description of that shared mechanism (FORMAT-SPEC.md: teams-chat-containers) rather than from an observed instance.

Every leaf this provider builds carries kind=UnitKind.TEAMS_CHAT_MESSAGE directly, and every container (root and each channel category alike) declares the same value as its own attrs["leaf_kind"] — the browser resolves both its column set and its content-preview renderer straight off UnitKind, with no provider-specific attrs marker needed.

class synology_apm_repo.sdk.units.saas.teams_chat.TeamsChatProvider(repo, version)

Bases: object

UnitProvider for one Teams or Chat (M365 only) workload version. Raises UnsupportedDataFormatError from create if no channel/chat index is found, so callers can degrade to RawObjectProvider like every other application-layer provider. Build one with create, never the constructor directly — locating the index and reading the container DB are I/O and can’t run synchronously.

async classmethod create(repo, version, saas_streams, *, shared=None)

saas_streams is borrowed, not owned — the version’s saas_obj is opened via the caller’s shared SaasStreamCache rather than a private SaasStream this provider would otherwise need to close itself.

shared is accepted only for calling-convention uniformity with units/dispatch.py’s _ProviderFactory — TEAMS/ USER_CHAT never offer more than this one candidate, so it is always None in practice and unused here: Teams/Chat’s channel/chat index discovery resolves its own INDEX object (see _resolve_message_index) rather than the saas_obj/object-name-index resolution SharedSaasContext carries.

async close()

Release every sqlite connection this provider owns: _db. Tolerates _db never having been assigned (create() failing before it resolved an index), so it’s safe to call from create()’s own failure path. The version’s own stream is borrowed from the caller’s SaasStreamCache, not owned here, so there’s nothing of its own to release.

root()

Pure construction — no I/O, so this stays synchronous (see UnitProvider).

async children(node, offset=0, limit=None)
async unit(node)