Coverage for integrations / channels / extensions / __init__.py: 45.7%
92 statements
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-12 04:49 +0000
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-12 04:49 +0000
1"""
2Channel Extensions - Phases 7 & 8
4Additional messaging channel adapters for extended platform support.
5These adapters follow the same patterns as core adapters (Telegram, Discord, Slack)
6but target additional platforms for broader integration capabilities.
8Available Extensions:
10Phase 7:
11- Matrix: End-to-end encrypted messaging via Matrix protocol
12- Teams: Microsoft Teams integration via Bot Framework
13- LINE: LINE Messaging API for LINE platform
14- Mattermost: Open-source Slack alternative with WebSocket and REST API
15- Nextcloud Talk: Nextcloud's communication platform with file sharing
17Phase 8:
18- Twitch: Twitch chat and whispers
19- Zalo: Vietnamese messaging platform OA API
20- Nostr: Decentralized social protocol
21- BlueBubbles: iMessage bridge for cross-platform
22- Voice: Voice calls via Twilio/Vonage
23- RocketChat: Open-source team chat with REST + Realtime API
24- WeChat: WeChat Official Account API
25- Viber: Viber Bot API
26- Messenger: Facebook Messenger via Meta Graph API
27- Instagram: Instagram Direct Messages
28- Twitter: Twitter/X DMs and mentions
29- Email: IMAP/SMTP email integration
31Docker Support:
32 All adapters are designed to work in containerized environments.
33 Configuration can be passed via environment variables.
34"""
36from typing import TYPE_CHECKING
38# Lazy imports to avoid loading dependencies that may not be installed
39__all__ = [
40 # Phase 7 - Matrix
41 "MatrixAdapter", "MatrixConfig", "MatrixRoom", "ThreadInfo", "create_matrix_adapter",
42 # Phase 7 - Teams
43 "TeamsAdapter", "TeamsConfig", "AdaptiveCard", "ConversationRef", "create_teams_adapter",
44 # Phase 7 - LINE
45 "LINEAdapter", "LINEConfig", "FlexBubble", "QuickReplyItem", "create_line_adapter",
46 # Phase 7 - Mattermost
47 "MattermostAdapter", "MattermostConfig", "MattermostChannel", "MattermostUser",
48 "InteractiveMessage", "SlashCommand", "create_mattermost_adapter",
49 # Phase 7 - Nextcloud
50 "NextcloudAdapter", "NextcloudConfig", "NextcloudConversation", "NextcloudParticipant",
51 "NextcloudMessage", "ConversationType", "ParticipantType", "RichObjectParameter", "create_nextcloud_adapter",
52 # Phase 8 - Twitch
53 "TwitchAdapter", "TwitchConfig", "create_twitch_adapter",
54 # Phase 8 - Zalo
55 "ZaloAdapter", "ZaloConfig", "create_zalo_adapter",
56 # Phase 8 - Nostr
57 "NostrAdapter", "NostrConfig", "create_nostr_adapter",
58 # Phase 8 - BlueBubbles
59 "BlueBubblesAdapter", "BlueBubblesConfig", "create_bluebubbles_adapter",
60 # Phase 8 - Voice
61 "VoiceAdapter", "VoiceConfig", "create_voice_adapter",
62 # Phase 8 - RocketChat
63 "RocketChatAdapter", "RocketChatConfig", "create_rocketchat_adapter",
64 # Phase 8 - WeChat
65 "WeChatAdapter", "WeChatConfig", "create_wechat_adapter",
66 # Phase 8 - Viber
67 "ViberAdapter", "ViberConfig", "create_viber_adapter",
68 # Phase 8 - Messenger
69 "MessengerAdapter", "MessengerConfig", "create_messenger_adapter",
70 # Phase 8 - Instagram
71 "InstagramAdapter", "InstagramConfig", "create_instagram_adapter",
72 # Phase 8 - Twitter
73 "TwitterAdapter", "TwitterConfig", "create_twitter_adapter",
74 # Phase 8 - Email
75 "EmailAdapter", "EmailConfig", "create_email_adapter",
76 # Phase 8 - Tlon (Urbit)
77 "TlonAdapter", "TlonConfig", "create_tlon_adapter",
78 # Phase 8 - Open Prose
79 "OpenProseAdapter", "OpenProseConfig", "create_openprose_adapter",
80 # Phase 8 - Telegram User
81 "TelegramUserAdapter", "TelegramUserConfig", "create_telegram_user_adapter",
82 # Phase 8 - Discord User
83 "DiscordUserAdapter", "DiscordUserConfig", "create_discord_user_adapter",
84 # Phase 8 - Zalo User
85 "ZaloUserAdapter", "ZaloUserConfig", "create_zalo_user_adapter",
86 # Discovery helper
87 "get_available_adapters",
88]
91# (channel_name, module_basename, factory_name) — single source of truth
92# for the adapter registry used by both the lazy __getattr__ and the
93# runtime discovery helper `get_available_adapters()`.
94_ADAPTER_REGISTRY = (
95 ("matrix", "matrix_adapter", "create_matrix_adapter"),
96 ("teams", "teams_adapter", "create_teams_adapter"),
97 ("line", "line_adapter", "create_line_adapter"),
98 ("mattermost", "mattermost_adapter", "create_mattermost_adapter"),
99 ("nextcloud", "nextcloud_adapter", "create_nextcloud_adapter"),
100 ("twitch", "twitch_adapter", "create_twitch_adapter"),
101 ("zalo", "zalo_adapter", "create_zalo_adapter"),
102 ("nostr", "nostr_adapter", "create_nostr_adapter"),
103 ("bluebubbles", "bluebubbles_adapter", "create_bluebubbles_adapter"),
104 ("voice", "voice_adapter", "create_voice_adapter"),
105 ("rocketchat", "rocketchat_adapter", "create_rocketchat_adapter"),
106 ("wechat", "wechat_adapter", "create_wechat_adapter"),
107 ("viber", "viber_adapter", "create_viber_adapter"),
108 ("messenger", "messenger_adapter", "create_messenger_adapter"),
109 ("instagram", "instagram_adapter", "create_instagram_adapter"),
110 ("twitter", "twitter_adapter", "create_twitter_adapter"),
111 ("email", "email_adapter", "create_email_adapter"),
112 ("tlon", "tlon_adapter", "create_tlon_adapter"),
113 ("openprose", "openprose_adapter", "create_openprose_adapter"),
114 ("telegram_user", "telegram_user_adapter", "create_telegram_user_adapter"),
115 ("discord_user", "discord_user_adapter", "create_discord_user_adapter"),
116 ("zalo_user", "zalo_user_adapter", "create_zalo_user_adapter"),
117)
120def get_available_adapters() -> dict:
121 """Return a mapping of ``{channel_name: create_adapter_factory}`` for every
122 extension adapter whose backing module imports successfully.
124 Adapters whose dependencies are not installed are silently skipped so that
125 callers (marketing_tools, MCP ``list_channels``, admin API) always see a
126 stable surface. Factories are the ``create_<name>_adapter`` callables
127 declared by each adapter module; callers are expected to invoke them
128 with per-channel config.
129 """
130 import importlib
131 adapters: dict = {}
132 for channel_name, module_basename, factory_name in _ADAPTER_REGISTRY:
133 try:
134 mod = importlib.import_module(f".{module_basename}", __name__)
135 except Exception:
136 # Optional-dep / platform-specific adapters can fail to import.
137 # The discovery surface must stay stable; skip silently.
138 continue
139 factory = getattr(mod, factory_name, None)
140 if callable(factory):
141 adapters[channel_name] = factory
142 return adapters
145def __getattr__(name: str):
146 """Lazy import of adapters to avoid loading unused dependencies."""
148 # Matrix imports
149 if name in ("MatrixAdapter", "MatrixConfig", "MatrixRoom", "ThreadInfo", "create_matrix_adapter"):
150 from .matrix_adapter import (
151 MatrixAdapter,
152 MatrixConfig,
153 MatrixRoom,
154 ThreadInfo,
155 create_matrix_adapter,
156 )
157 return locals()[name]
159 # Teams imports
160 if name in ("TeamsAdapter", "TeamsConfig", "AdaptiveCard", "ConversationRef", "create_teams_adapter"):
161 from .teams_adapter import (
162 TeamsAdapter,
163 TeamsConfig,
164 AdaptiveCard,
165 ConversationRef,
166 create_teams_adapter,
167 )
168 return locals()[name]
170 # LINE imports
171 if name in ("LINEAdapter", "LINEConfig", "FlexBubble", "QuickReplyItem", "create_line_adapter"):
172 from .line_adapter import (
173 LINEAdapter,
174 LINEConfig,
175 FlexBubble,
176 QuickReplyItem,
177 create_line_adapter,
178 )
179 return locals()[name]
181 # Mattermost imports
182 if name in ("MattermostAdapter", "MattermostConfig", "MattermostChannel", "MattermostUser",
183 "InteractiveMessage", "SlashCommand", "create_mattermost_adapter"):
184 from .mattermost_adapter import (
185 MattermostAdapter,
186 MattermostConfig,
187 MattermostChannel,
188 MattermostUser,
189 InteractiveMessage,
190 SlashCommand,
191 create_mattermost_adapter,
192 )
193 return locals()[name]
195 # Nextcloud imports
196 if name in ("NextcloudAdapter", "NextcloudConfig", "NextcloudConversation", "NextcloudParticipant",
197 "NextcloudMessage", "ConversationType", "ParticipantType", "RichObjectParameter",
198 "create_nextcloud_adapter"):
199 from .nextcloud_adapter import (
200 NextcloudAdapter, NextcloudConfig, NextcloudConversation, NextcloudParticipant,
201 NextcloudMessage, ConversationType, ParticipantType, RichObjectParameter, create_nextcloud_adapter,
202 )
203 return locals()[name]
205 # Phase 8 - Twitch
206 if name in ("TwitchAdapter", "TwitchConfig", "create_twitch_adapter"):
207 from .twitch_adapter import TwitchAdapter, TwitchConfig, create_twitch_adapter
208 return locals()[name]
210 # Phase 8 - Zalo
211 if name in ("ZaloAdapter", "ZaloConfig", "create_zalo_adapter"):
212 from .zalo_adapter import ZaloAdapter, ZaloConfig, create_zalo_adapter
213 return locals()[name]
215 # Phase 8 - Nostr
216 if name in ("NostrAdapter", "NostrConfig", "create_nostr_adapter"):
217 from .nostr_adapter import NostrAdapter, NostrConfig, create_nostr_adapter
218 return locals()[name]
220 # Phase 8 - BlueBubbles
221 if name in ("BlueBubblesAdapter", "BlueBubblesConfig", "create_bluebubbles_adapter"):
222 from .bluebubbles_adapter import BlueBubblesAdapter, BlueBubblesConfig, create_bluebubbles_adapter
223 return locals()[name]
225 # Phase 8 - Voice
226 if name in ("VoiceAdapter", "VoiceConfig", "create_voice_adapter"):
227 from .voice_adapter import VoiceAdapter, VoiceConfig, create_voice_adapter
228 return locals()[name]
230 # Phase 8 - RocketChat
231 if name in ("RocketChatAdapter", "RocketChatConfig", "create_rocketchat_adapter"):
232 from .rocketchat_adapter import RocketChatAdapter, RocketChatConfig, create_rocketchat_adapter
233 return locals()[name]
235 # Phase 8 - WeChat
236 if name in ("WeChatAdapter", "WeChatConfig", "create_wechat_adapter"):
237 from .wechat_adapter import WeChatAdapter, WeChatConfig, create_wechat_adapter
238 return locals()[name]
240 # Phase 8 - Viber
241 if name in ("ViberAdapter", "ViberConfig", "create_viber_adapter"):
242 from .viber_adapter import ViberAdapter, ViberConfig, create_viber_adapter
243 return locals()[name]
245 # Phase 8 - Messenger
246 if name in ("MessengerAdapter", "MessengerConfig", "create_messenger_adapter"):
247 from .messenger_adapter import MessengerAdapter, MessengerConfig, create_messenger_adapter
248 return locals()[name]
250 # Phase 8 - Instagram
251 if name in ("InstagramAdapter", "InstagramConfig", "create_instagram_adapter"):
252 from .instagram_adapter import InstagramAdapter, InstagramConfig, create_instagram_adapter
253 return locals()[name]
255 # Phase 8 - Twitter
256 if name in ("TwitterAdapter", "TwitterConfig", "create_twitter_adapter"):
257 from .twitter_adapter import TwitterAdapter, TwitterConfig, create_twitter_adapter
258 return locals()[name]
260 # Phase 8 - Email
261 if name in ("EmailAdapter", "EmailConfig", "create_email_adapter"):
262 from .email_adapter import EmailAdapter, EmailConfig, create_email_adapter
263 return locals()[name]
265 # Phase 8 - Tlon (Urbit)
266 if name in ("TlonAdapter", "TlonConfig", "create_tlon_adapter"):
267 from .tlon_adapter import TlonAdapter, TlonConfig, create_tlon_adapter
268 return locals()[name]
270 # Phase 8 - Open Prose
271 if name in ("OpenProseAdapter", "OpenProseConfig", "create_openprose_adapter"):
272 from .openprose_adapter import OpenProseAdapter, OpenProseConfig, create_openprose_adapter
273 return locals()[name]
275 # Phase 8 - Telegram User
276 if name in ("TelegramUserAdapter", "TelegramUserConfig", "create_telegram_user_adapter"):
277 from .telegram_user_adapter import TelegramUserAdapter, TelegramUserConfig, create_telegram_user_adapter
278 return locals()[name]
280 # Phase 8 - Discord User
281 if name in ("DiscordUserAdapter", "DiscordUserConfig", "create_discord_user_adapter"):
282 from .discord_user_adapter import DiscordUserAdapter, DiscordUserConfig, create_discord_user_adapter
283 return locals()[name]
285 # Phase 8 - Zalo User
286 if name in ("ZaloUserAdapter", "ZaloUserConfig", "create_zalo_user_adapter"):
287 from .zalo_user_adapter import ZaloUserAdapter, ZaloUserConfig, create_zalo_user_adapter
288 return locals()[name]
290 raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
293# Type hints for IDE support
294if TYPE_CHECKING:
295 from .matrix_adapter import (
296 MatrixAdapter,
297 MatrixConfig,
298 MatrixRoom,
299 ThreadInfo,
300 create_matrix_adapter,
301 )
302 from .teams_adapter import (
303 TeamsAdapter,
304 TeamsConfig,
305 AdaptiveCard,
306 ConversationRef,
307 create_teams_adapter,
308 )
309 from .line_adapter import (
310 LINEAdapter,
311 LINEConfig,
312 FlexBubble,
313 QuickReplyItem,
314 create_line_adapter,
315 )
316 from .mattermost_adapter import (
317 MattermostAdapter,
318 MattermostConfig,
319 MattermostChannel,
320 MattermostUser,
321 InteractiveMessage,
322 SlashCommand,
323 create_mattermost_adapter,
324 )
325 from .nextcloud_adapter import (
326 NextcloudAdapter,
327 NextcloudConfig,
328 NextcloudConversation,
329 NextcloudParticipant,
330 NextcloudMessage,
331 ConversationType,
332 ParticipantType,
333 RichObjectParameter,
334 create_nextcloud_adapter,
335 )
336 from .tlon_adapter import TlonAdapter, TlonConfig, create_tlon_adapter
337 from .openprose_adapter import OpenProseAdapter, OpenProseConfig, create_openprose_adapter
338 from .telegram_user_adapter import TelegramUserAdapter, TelegramUserConfig, create_telegram_user_adapter
339 from .discord_user_adapter import DiscordUserAdapter, DiscordUserConfig, create_discord_user_adapter
340 from .zalo_user_adapter import ZaloUserAdapter, ZaloUserConfig, create_zalo_user_adapter