chatbot1-10 Exercise 3: One Core, Three Platforms ==================================================== ex3.py (save in the project root): import asyncio from bot.channels.discord import DiscordAdapter from bot.channels.slack import SlackAdapter from bot.channels.telegram import TelegramAdapter from bot.core import Bot from bot.providers import FakeProvider class TgAPI: async def send_message(self, chat_id, text, reply_to=None): pass async def send_chat_action(self, chat_id, action="typing"): pass class DcREST: async def create_message(self, channel_id, content, reply_to=None): pass async def trigger_typing(self, channel_id): pass class SlAPI: async def post_message(self, channel, text, thread_ts=None): pass async def main(): bot = Bot(FakeProvider()) # ONE bot core shared by three adapters tg = TelegramAdapter(bot, TgAPI(), username="LibraryBot", bot_id=1) dc = DiscordAdapter(bot, DcREST(), bot_user_id="900") sl = SlackAdapter(bot, SlAPI(), bot_user_id="UBOT") await tg.handle_update({"update_id": 1, "message": {"message_id": 1, "from": {"id": 42, "is_bot": False}, "chat": {"id": 42, "type": "private"}, "date": 1, "text": "/remember I like tea"}}) await dc.handle_message({"id": "m1", "channel_id": "D1", "author": {"id": "42", "bot": False}, "content": "/facts", "mentions": [], "type": 0}) await sl.handle_callback({"type": "event_callback", "event_id": "E1", "event": {"type": "message", "channel_type": "im", "channel": "D2", "user": "U42", "text": "/facts", "ts": "1.1"}}) await tg.handle_update({"update_id": 2, "message": {"message_id": 2, "from": {"id": 42, "is_bot": False}, "chat": {"id": 42, "type": "private"}, "date": 1, "text": "hello from telegram"}}) await dc.handle_message({"id": "m2", "channel_id": "D1", "author": {"id": "42", "bot": False}, "content": "hello from discord", "mentions": [], "type": 0}) await sl.handle_callback({"type": "event_callback", "event_id": "E2", "event": {"type": "message", "channel_type": "im", "channel": "D2", "user": "U42", "text": "hello from slack", "ts": "2.1"}}) print("sessions in the shared store:") for sid in ("telegram:42", "discord:D1", "slack:D2"): print(f" {sid:<12} {len(bot.store.messages(sid))} messages") print("notes stored per user id:") for uid in ("telegram:42", "discord:42", "slack:U42"): print(f" {uid:<12} {[t for _, t in bot.store.facts(uid)]}") asyncio.run(main()) Run with: py ex3.py Output: sessions in the shared store: telegram:42 2 messages discord:D1 2 messages slack:D2 2 messages notes stored per user id: telegram:42 ['I like tea'] discord:42 [] slack:U42 [] Why the other platforms do not see the note: the bot identifies a person by the user id each adapter passes in, and each adapter prefixes it with its platform (telegram:42, discord:42, slack:U42). The same human has no common identifier across the three services, so to the bot they are three unrelated users, and a note belongs to one of them. What linking would require: a way to prove that two accounts are the same person (for example a one-time code that you ask for in one platform and type into the other), storage of the link, and the person's explicit agreement, since it joins data that was collected separately. It also changes the deletion story: /deleteme would have to erase every linked identity. WHY THIS WORKS AS AN ANSWER --------------------------- All three adapters call the same bot.handle(session_id, text, user_id=...). The sessions are separate (telegram:42, discord:D1, slack:D2, two messages each: the question and the answer) and the facts follow the user id: only telegram:42 has the note, and the other two asked for their notes and were told they had none. The stubs only record that something was sent; the point is that the core needed no change to serve a third platform.