Backend APIs¶
Concrete configuration, models, mention helpers, backends, and testing backends for Discord, Slack, Symphony, and Telegram.
Discord¶
Discord backend configuration.
This module provides configuration classes for the Discord backend.
- pydantic model chatom.discord.config.DiscordConfig[source]¶
Bases:
BackendConfigConfiguration for Discord backend.
This configuration is used to connect to Discord using the discord.py library. You need a bot token from the Discord Developer Portal.
- bot_token¶
Discord bot token (can be a file path).
- application_id¶
Discord application ID.
- guild_id¶
Default guild/server ID (optional).
- intents¶
Discord gateway intents to request.
- command_prefix¶
Prefix for bot commands (if using commands extension).
Example
>>> config = DiscordConfig( ... bot_token="your-bot-token", ... application_id="123456789", ... intents=["guilds", "messages", "message_content"], ... ) >>> backend = DiscordBackend(config=config)
- field token: str | SecretStr = SecretStr('')¶
Discord bot token from Developer Portal (can be a file path).
- field application_id: str = ''¶
Discord application ID.
- field guild_id: str = ''¶
Default guild/server ID (optional).
- field intents: list [Optional]¶
Discord gateway intents to request.
- field command_prefix: str = '!'¶
Prefix for bot commands.
- field shard_id: int | None = None¶
Shard ID for sharded bots.
- field shard_count: int | None = None¶
Total number of shards.
- property bot_token_str: str¶
Get the bot token as a plain string.
- Returns:
The bot token string.
- property has_token: bool¶
Check if a bot token is configured.
- Returns:
True if a bot token is set.
Discord-specific User model.
This module provides the Discord-specific User class.
- pydantic model chatom.discord.user.DiscordUser[source]¶
Bases:
UserDiscord-specific user with additional Discord fields.
- discriminator¶
The user’s 4-digit discriminator (legacy).
- global_name¶
The user’s global display name.
- is_system¶
Whether this is a Discord system user.
- accent_color¶
The user’s banner color.
- banner_url¶
URL to the user’s banner image.
- field discriminator: str = '0'¶
The user’s 4-digit discriminator (legacy).
- field global_name: str | None = None¶
The user’s global display name.
- field is_system: bool = False¶
Whether this is a Discord system user.
- field accent_color: int | None = None¶
The user’s banner color.
- field banner_url: str = ''¶
URL to the user’s banner image.
- property full_username: str¶
Get the full username with discriminator (legacy format).
- Returns:
Username#discriminator or just username for new usernames.
- Return type:
str
- classmethod from_discord_user(user: Any) DiscordUser[source]¶
Create a DiscordUser from a discord.py User or Member object.
This factory method converts a discord.py User or Member object into a chatom DiscordUser.
- Parameters:
user – A discord.py User or Member object.
- Returns:
A DiscordUser instance.
Example
>>> # From a discord.py event >>> discord_user = DiscordUser.from_discord_user(event.author)
Discord-specific Channel model.
This module provides the Discord-specific Channel class.
- pydantic model chatom.discord.channel.DiscordChannel[source]¶
Bases:
ChannelDiscord-specific channel with additional Discord fields.
- guild¶
The guild/server this channel belongs to.
- position¶
Sorting position of the channel.
- nsfw¶
Whether the channel is NSFW.
- slowmode_delay¶
Slowmode delay in seconds.
- discord_type¶
Discord-specific channel type.
- bitrate¶
Voice channel bitrate.
- user_limit¶
Voice channel user limit.
- rate_limit_per_user¶
Slowmode rate limit.
- field guild: Organization | None = None¶
The guild/server this channel belongs to.
- field position: int = 0¶
Sorting position of the channel.
- field nsfw: bool = False¶
Whether the channel is NSFW.
- field slowmode_delay: int = 0¶
Slowmode delay in seconds.
- field discord_type: DiscordChannelType = DiscordChannelType.GUILD_TEXT¶
Discord-specific channel type.
- field bitrate: int | None = None¶
Voice channel bitrate.
- field user_limit: int | None = None¶
Voice channel user limit.
- field rate_limit_per_user: int = 0¶
Slowmode rate limit.
- property guild_id: str¶
Get the guild/server ID.
- Returns:
The guild ID, or empty string if not set.
- Return type:
str
- property is_voice: bool¶
Check if this is a voice channel.
- Returns:
True if this is a voice channel.
- Return type:
bool
- property is_text: bool¶
Check if this is a text channel.
- Returns:
True if this is a text channel.
- Return type:
bool
- class chatom.discord.channel.DiscordChannelType(value)[source]¶
Bases:
str,EnumDiscord-specific channel types.
Discord-specific Guild (Organization) model.
This module provides the Discord-specific Guild class which extends Organization.
- pydantic model chatom.discord.guild.DiscordGuild[source]¶
Bases:
OrganizationDiscord-specific guild (server) with additional Discord fields.
A Discord guild is the organization unit in Discord (commonly called a “server”).
The guild’s boost level (0-3).
- nsfw_level¶
The guild’s NSFW content level.
- preferred_locale¶
The guild’s preferred locale.
- approximate_member_count¶
Approximate number of members (may differ from member_count).
- approximate_presence_count¶
Approximate number of online members.
- vanity_url_code¶
The guild’s vanity invite code if set.
- features¶
List of guild features (e.g., “COMMUNITY”, “PARTNERED”).
- field premium_tier: int = 0¶
The guild’s boost level (0-3).
- field nsfw_level: int = 0¶
The guild’s NSFW content level.
- field preferred_locale: str = 'en-US'¶
The guild’s preferred locale.
- field approximate_member_count: int | None = None¶
Approximate number of members.
- field approximate_presence_count: int | None = None¶
Approximate number of online members.
- field vanity_url_code: str | None = None¶
The guild’s vanity invite code if set.
- field features: list [Optional]¶
List of guild features.
- classmethod from_discord_guild(guild: Any) DiscordGuild[source]¶
Create a DiscordGuild from a discord.py Guild object.
- Parameters:
guild – A discord.py Guild object.
- Returns:
DiscordGuild instance.
Discord-specific Message model.
This module provides the Discord-specific Message class.
- pydantic model chatom.discord.message.DiscordMessage[source]¶
Bases:
MessageDiscord-specific message with additional Discord fields.
Based on the Discord API message structure.
Note: Use the inherited channel field for the DiscordChannel object, channel_id is synced from channel.id. Similarly for author/author_id. The mentions field here is a List[str] of user IDs for Discord-specific use, while the base class mention_ids is synced from it.
- discord_type¶
The Discord message type.
- guild¶
The guild/server this message was sent in.
- member¶
Guild member data for the author.
- mention_everyone¶
Whether @everyone was mentioned.
- mention_roles¶
List of mentioned role IDs.
- mention_channels¶
List of mentioned channel IDs.
- nonce¶
Used for message send verification.
- pinned¶
Whether the message is pinned.
- webhook_id¶
Webhook ID if sent by a webhook.
- flags¶
Message flags.
- interaction¶
Interaction data if from an interaction.
- components¶
Message components (buttons, etc.).
- sticker_items¶
Stickers in the message.
- position¶
Position in thread.
- field discord_type: DiscordMessageType = DiscordMessageType.DEFAULT¶
The Discord message type.
- field guild: Organization | None = None¶
The guild/server this message was sent in.
- field member: dict[str, Any] | None = None¶
Guild member data for the author.
- field mention_everyone: bool = False¶
Whether @everyone was mentioned.
- field mention_roles: list[str] [Optional]¶
List of mentioned role IDs.
- field mention_channels: list[str] [Optional]¶
List of mentioned channel IDs.
- field nonce: str | None = None¶
Used for message send verification.
- field pinned: bool = False¶
Whether the message is pinned.
- field webhook_id: str | None = None¶
Webhook ID if sent by a webhook.
- field flags: int = 0¶
Message flags.
- field interaction: dict[str, Any] | None = None¶
Interaction data if from an interaction.
- field components: list[dict[str, Any]] [Optional]¶
Message components (buttons, select menus, etc.).
- field sticker_items: list[dict[str, Any]] [Optional]¶
Stickers in the message.
- field position: int | None = None¶
Position in thread.
- property guild_id: str¶
Get the guild/server ID.
- Returns:
The guild ID, or empty string if not set.
- Return type:
str
- property is_reply: bool¶
Check if this message is a reply.
- property is_ephemeral: bool¶
Check if this is an ephemeral message.
- property is_crossposted: bool¶
Check if this message was crossposted.
- property has_thread: bool¶
Check if this message has a thread.
- property is_voice_message: bool¶
Check if this is a voice message.
- property suppresses_embeds: bool¶
Check if embeds are suppressed.
- property suppresses_notifications: bool¶
Check if notifications are suppressed.
- has_flag(flag: DiscordMessageFlags) bool[source]¶
Check if a specific flag is set.
- Parameters:
flag – The flag to check.
- Returns:
True if the flag is set.
- to_formatted() FormattedMessage[source]¶
Convert this Discord message to a FormattedMessage.
Parses Discord markdown formatting and converts to a FormattedMessage that can be rendered for other backends.
- Returns:
The formatted message representation.
- Return type:
- classmethod from_formatted(formatted: FormattedMessage, backend: str = '', **kwargs: Any) DiscordMessage[source]¶
Create a DiscordMessage from a FormattedMessage.
Renders the FormattedMessage in Discord markdown format.
- Parameters:
formatted – The FormattedMessage to convert.
backend – Target backend (ignored, always uses discord format).
**kwargs – Additional message attributes.
- Returns:
A new DiscordMessage instance.
- Return type:
- classmethod from_api_response(data: dict[str, Any]) DiscordMessage[source]¶
Create a DiscordMessage from a Discord API response.
- Parameters:
data – The API response data.
- Returns:
A DiscordMessage instance.
- class chatom.discord.message.DiscordMessageFlags(value)[source]¶
Bases:
IntEnumDiscord message flags.
Based on Discord API message flags.
- class chatom.discord.message.DiscordMessageType(value)[source]¶
Bases:
IntEnumDiscord message types.
Based on Discord API message types.
Discord-specific Presence model.
This module provides the Discord-specific Presence class.
- class chatom.discord.presence.DiscordActivityType(value)[source]¶
Bases:
str,EnumDiscord-specific activity types.
- pydantic model chatom.discord.presence.DiscordPresence[source]¶
Bases:
PresenceDiscord-specific presence.
- activities¶
List of activities the user is engaged in.
- client_status¶
Status per client (desktop, mobile, web).
- field activities: list [Optional]¶
List of activities the user is engaged in.
- field desktop_status: PresenceStatus = PresenceStatus.OFFLINE¶
Status on desktop client.
- field mobile_status: PresenceStatus = PresenceStatus.OFFLINE¶
Status on mobile client.
- field web_status: PresenceStatus = PresenceStatus.OFFLINE¶
Status on web client.
Discord-specific mention utilities.
This module registers Discord-specific mention formatting.
- chatom.discord.mention.mention_channel(channel: Channel) str[source]¶
- chatom.discord.mention.mention_channel(channel: DiscordChannel) str
- chatom.discord.mention.mention_channel(channel: SlackChannel) str
- chatom.discord.mention.mention_channel(channel: TelegramChannel) str
Generate a mention string for a channel.
This is a single-dispatch function that can be overridden for platform-specific channel types.
- Parameters:
channel – The channel to mention.
- Returns:
The formatted channel mention string.
- Return type:
str
Example
>>> from chatom import Channel, mention_channel >>> channel = Channel(name="general", id="456") >>> mention_channel(channel) '#general'
- chatom.discord.mention.mention_user(user: User) str[source]¶
- chatom.discord.mention.mention_user(user: DiscordUser) str
- chatom.discord.mention.mention_user(user: SlackUser) str
- chatom.discord.mention.mention_user(user: SymphonyUser) str
- chatom.discord.mention.mention_user(user: TelegramUser) str
Generate a mention string for a user.
This is a single-dispatch function that can be overridden for platform-specific user types.
- Parameters:
user – The user to mention.
- Returns:
The formatted mention string.
- Return type:
str
Example
>>> from chatom import User, mention_user >>> user = User(name="John", id="123") >>> mention_user(user) 'John'
Discord backend implementation for chatom.
This module provides the Discord backend using the discord.py library.
- pydantic model chatom.discord.backend.DiscordBackend[source]¶
Bases:
BackendBaseDiscord backend implementation using discord.py.
This provides the backend interface for Discord using the discord.py library. It supports all standard backend operations including messaging, presence, and reactions.
- name¶
The backend identifier (‘discord’).
- display_name¶
Human-readable name.
- format¶
Discord uses its own markdown flavor.
- capabilities¶
Discord-specific capabilities.
- config¶
Discord-specific configuration.
Example
>>> from chatom.discord import DiscordBackend, DiscordConfig >>> config = DiscordConfig(bot_token="your-token") >>> backend = DiscordBackend(config=config) >>> await backend.connect() >>> user = await backend.fetch_user("123456789")
- name: ClassVar[str] = 'discord'¶
- display_name: ClassVar[str] = 'Discord'¶
- mention_pattern: ClassVar[Pattern | None] = re.compile('<@!?(\\d+)>')¶
- user_class¶
alias of
DiscordUser
- channel_class¶
alias of
DiscordChannel
- presence_class¶
alias of
DiscordPresence
- guild_class¶
alias of
DiscordGuild
- field capabilities: BackendCapabilities | None = BackendCapabilities(capabilities=frozenset({<Capability.DELETING: 'deleting'>, <Capability.TYPING_INDICATORS: 'typing_indicators'>, <Capability.PINNING: 'pinning'>, <Capability.USER_MENTIONS: 'user_mentions'>, <Capability.THREADS: 'threads'>, <Capability.ORGANIZATIONS: 'organizations'>, <Capability.VIDEOS: 'videos'>, <Capability.BUTTONS: 'buttons'>, <Capability.EMBEDS: 'embeds'>, <Capability.MARKDOWN: 'markdown'>, <Capability.PLAINTEXT: 'plaintext'>, <Capability.ROLE_MENTIONS: 'role_mentions'>, <Capability.CUSTOM_EMOJI: 'custom_emoji'>, <Capability.CHANNEL_MENTIONS: 'channel_mentions'>, <Capability.CODE_BLOCKS: 'code_blocks'>, <Capability.FILES: 'files'>, <Capability.EVERYONE_MENTION: 'everyone_mention'>, <Capability.IMAGES: 'images'>, <Capability.PRESENCE: 'presence'>, <Capability.FORWARDING: 'forwarding'>, <Capability.REPLIES: 'replies'>, <Capability.AUDIO: 'audio'>, <Capability.SELECT_MENUS: 'select_menus'>, <Capability.EDITING: 'editing'>, <Capability.MESSAGE_SEARCH: 'message_search'>, <Capability.EMOJI_REACTIONS: 'emoji_reactions'>}), max_message_length=2000, max_attachment_size=26214400, max_attachments=10, max_embeds=10, max_reactions=20)¶
- field config: DiscordConfig [Optional]¶
- property bot_user_id: str | None¶
Get the bot’s user ID (cached from connect/get_bot_info).
- property bot_user_name: str | None¶
Get the bot’s username (cached from connect/get_bot_info).
- async connect() None[source]¶
Connect to Discord using the configured bot token.
This creates a Discord client and logs in using the bot token. Note that for full event handling, you may need to run the client with client.start() instead.
- Raises:
RuntimeError – If discord.py is not installed or token is missing.
- async fetch_user(identifier: str | User | None = None, *, id: str | None = None, name: str | None = None, email: str | None = None, handle: str | None = None) User | None[source]¶
Fetch a user from Discord.
Accepts flexible inputs: - User ID as positional arg or id= - User object (returns as-is or refreshes) - name= to search by display name (limited) - handle= to search by username (limited)
Note: Discord API has limited user search capabilities. ID-based lookup is most reliable.
- Parameters:
identifier – A User object or user ID string.
id – User ID.
name – Display name to search for.
email – Email (not supported by Discord).
handle – Username to search for.
- Returns:
The user if found, None otherwise.
- async fetch_channel(identifier: str | Channel | None = None, *, id: str | None = None, name: str | None = None) Channel | None[source]¶
Fetch a channel from Discord.
Accepts flexible inputs: - Channel ID as positional arg or id= - Channel object (returns as-is or refreshes) - name= to search by channel name (requires guild context)
Note: Discord requires channel ID for direct lookup. Name-based search checks cache only.
- Parameters:
identifier – A Channel object or channel ID string.
id – Channel ID.
name – Channel name to search for (cache only).
- Returns:
The channel if found, None otherwise.
- async fetch_messages(channel: str | Channel, limit: int = 100, before: str | Message | datetime | None = None, after: str | Message | datetime | None = None) list[Message][source]¶
Fetch messages from a Discord channel, newest-first.
- Parameters:
channel – The channel to fetch messages from (ID string or Channel object).
limit – Maximum number of messages to return.
before – Upper bound — message id, Message, or datetime.
after – Lower bound — message id, Message, or datetime.
- Returns:
List of messages, ordered newest-to-oldest.
- async search_messages(query: str, channel: str | Channel | None = None, limit: int = 50, **kwargs: Any) list[Message][source]¶
Search for messages matching a query.
Note: Discord’s API doesn’t have a direct message search endpoint for bots. This implementation fetches recent messages and filters locally. For production use with large channels, consider using Discord’s user account search or a database-backed solution.
- Parameters:
query – The search query string (case-insensitive substring match).
channel – Channel to search in (required for Discord).
limit – Maximum number of results.
**kwargs – Additional options: - from_user: Filter by author ID
- Returns:
List of messages containing the query.
- async send_message(channel: str | Channel, content: str, **kwargs: Any) Message[source]¶
Send a message to a Discord channel.
- Parameters:
channel – The channel to send to (ID string or Channel object).
content – The message content. kwargs: Discord thread, reply, embed, file, and text-to-speech options.
- Returns:
The sent message.
- async upload_file(channel: str | Channel, data: bytes, filename: str = 'file', content_type: str = '', title: str = '', content: str = '', **kwargs: Any) Message[source]¶
Upload a file to a Discord channel.
Uses
discord.Fileto send binary data directly.
- async edit_message(message: str | Message, content: str, channel: str | Channel | None = None, **kwargs: Any) Message[source]¶
Edit a Discord message.
- Parameters:
message – The message to edit (ID string or Message object).
content – The new content.
channel – The channel containing the message (required if message is a string).
**kwargs – Additional options.
- Returns:
The edited message.
- async delete_message(message: str | Message, channel: str | Channel | None = None) None[source]¶
Delete a Discord message.
- Parameters:
message – The message to delete (ID string or Message object).
channel – The channel containing the message (required if message is a string).
- async forward_message(message: str | Message, to_channel: str | Channel, *, include_attribution: bool = True, prefix: str | None = None, **kwargs: Any) DiscordMessage[source]¶
Forward a message to another Discord channel.
Discord doesn’t have native forwarding, so this creates a new message with the original content and optional attribution using embeds.
- Parameters:
message – The message to forward (DiscordMessage object or message ID).
to_channel – The destination channel (ID string or Channel object).
include_attribution – If True, include info about original source.
prefix – Optional text to prepend to the forwarded message.
**kwargs – Additional options (embed, reference, etc.).
- Returns:
The forwarded message in the destination channel.
- async set_presence(status: str, status_text: str | None = None, **kwargs: Any) None[source]¶
Set the bot’s presence on Discord.
- Parameters:
status – Presence status (‘online’, ‘idle’, ‘dnd’, ‘invisible’).
status_text – Activity text (game name).
**kwargs – Additional options: - activity_type: Type of activity (‘playing’, ‘streaming’, ‘listening’, ‘watching’, ‘competing’). - url: Streaming URL (for streaming activity).
- async get_presence(user: str | User) Presence | None[source]¶
Get a user’s presence on Discord.
Note: This requires the GUILD_PRESENCES intent and caching. The user must share a guild with the bot.
- Parameters:
user_id – The user ID.
- Returns:
The user’s presence or None if not available.
- async add_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Add a reaction to a message.
- Parameters:
message – The message to react to (ID string or Message object).
emoji – The emoji (unicode or custom format <:name:id>).
channel – The channel containing the message (required if message is a string).
- async remove_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Remove a reaction from a message.
- Parameters:
message – The message to remove reaction from (ID string or Message object).
emoji – The emoji to remove.
channel – The channel containing the message (required if message is a string).
- mention_user(user: User) str[source]¶
Format a user mention for Discord.
- Parameters:
user – The user to mention.
- Returns:
Discord user mention format (<@user_id>).
- mention_channel(channel: Channel) str[source]¶
Format a channel mention for Discord.
- Parameters:
channel – The channel to mention.
- Returns:
Discord channel mention format (<#channel_id>).
- mention_here() str[source]¶
Format an @here mention for Discord.
- Returns:
Discord @here mention format.
- mention_everyone() str[source]¶
Format an @everyone mention for Discord.
- Returns:
Discord @everyone mention format.
- async get_bot_info() User | None[source]¶
Get information about the connected bot user.
- Returns:
The bot’s User object, or None if not available.
- async create_dm(users: list[str | User]) str | None[source]¶
Create a DM channel with a user.
Note: Discord only supports 1:1 DMs from bots, so only the first user in the list is used.
- Parameters:
users – List of users to create a DM with. Only first user is used.
- Returns:
The DM channel ID, or None if creation failed.
- async create_channel(name: str, description: str = '', public: bool = True, guild_id: str | None = None, **kwargs: Any) str | None[source]¶
Create a new guild text channel.
Note: This requires the bot to have MANAGE_CHANNELS permission in the target guild.
- Parameters:
name – The channel name.
description – Optional channel topic/description.
public – If False, creates a private channel (not implemented yet).
guild_id – The guild ID to create the channel in. If not provided, uses config.guild_id.
**kwargs – Additional options: - category_id: Category ID to put the channel under.
- Returns:
The channel ID of the created channel, or None if failed.
- async fetch_channel_by_name(name: str, guild_id: str | None = None) Channel | None[source]¶
Fetch a channel by name from a guild.
This method searches through the guild’s channels to find one matching the given name.
- Parameters:
name – The channel name to search for (case-insensitive).
guild_id – The guild ID to search in. If not provided, uses config.guild_id.
- Returns:
The channel if found, None otherwise.
- async fetch_user_by_name(name: str, guild_id: str | None = None) User | None[source]¶
Fetch a user by username from a guild.
This method searches through the guild’s members to find one matching the given username or display name.
- Parameters:
name – The username or display name to search for (case-insensitive).
guild_id – The guild ID to search in. If not provided, uses config.guild_id.
- Returns:
The user if found, None otherwise.
- async fetch_organization(identifier: str | Organization | None = None, *, id: str | None = None, name: str | None = None) Organization | None[source]¶
Fetch a guild (organization) from Discord.
- Parameters:
identifier – A DiscordGuild object or guild ID string.
id – Guild ID (alternative to positional identifier).
name – Guild name to search for (case-insensitive).
- Returns:
The guild if found, None otherwise.
- async list_organizations() list[Organization][source]¶
List all guilds the bot has access to.
- Returns:
List of guilds.
- async fetch_guild(identifier: str | Organization | None = None, *, id: str | None = None, name: str | None = None) Organization | None[source]¶
Fetch a guild from Discord.
This is an alias for fetch_organization using Discord terminology.
- async list_guilds() list[Organization][source]¶
List all guilds the bot has access to.
This is an alias for list_organizations using Discord terminology.
- async stream_messages(channel: str | Channel | None = None, skip_own: bool = True, skip_history: bool = True) AsyncIterator[DiscordMessage][source]¶
Stream incoming messages in real-time using Discord gateway.
This creates a connection to the Discord gateway and yields messages as they arrive. Requires the bot to be in a guild and have MESSAGE_CONTENT intent enabled.
- Parameters:
channel – Optional channel to filter messages (ID string or Channel object).
skip_own – If True (default), skip messages sent by the bot itself.
skip_history – If True (default), skip messages that existed before the stream started. Only yields new messages.
- Yields:
DiscordMessage – Each message as it arrives.
Mock Discord backend for testing.
This module provides a mock implementation of the Discord backend for use in testing without requiring an actual Discord connection.
- pydantic model chatom.discord.testing.MockDiscordBackend[source]¶
Bases:
DiscordBackendMock Discord backend for testing.
This class provides a mock implementation of the Discord backend that doesn’t require an actual Discord connection. It stores all data in memory and provides methods to set up mock data for tests.
Example
>>> backend = MockDiscordBackend() >>> backend.add_mock_user("123", "TestUser", "testuser") >>> backend.add_mock_channel("456", "general") >>> await backend.connect() >>> user = await backend.fetch_user("123") >>> assert user.name == "TestUser"
- add_mock_user(id: str, name: str, handle: str, *, avatar_url: str = '', discriminator: str = '0', global_name: str | None = None, is_bot: bool = False, is_system: bool = False) DiscordUser[source]¶
Add a mock user for testing.
- Parameters:
id – The user ID.
name – The user’s display name.
handle – The username.
avatar_url – URL to user’s avatar.
discriminator – Legacy discriminator (e.g., “1234”).
global_name – Global display name.
is_bot – Whether the user is a bot.
is_system – Whether it’s a Discord system user.
- Returns:
The created mock user.
- add_mock_channel(id: str, name: str, channel_type: str = 'text', *, topic: str = '', guild_id: str = '', position: int = 0, nsfw: bool = False, discord_type: DiscordChannelType | None = None) DiscordChannel[source]¶
Add a mock channel for testing.
- Parameters:
id – The channel ID.
name – The channel name.
channel_type – The channel type (“text”, “voice”, “dm”, etc.).
topic – The channel topic.
guild_id – The guild/server ID.
position – Channel position.
nsfw – Whether channel is NSFW.
discord_type – The Discord channel type enum (overrides channel_type).
- Returns:
The created mock channel.
- add_mock_message(channel_id: str, user_id: str, content: str, *, message_id: str | None = None, timestamp: datetime | None = None, guild_id: str = '', edited: bool = False) str[source]¶
Add a mock message for testing.
- Parameters:
channel_id – The channel containing the message.
user_id – The author’s user ID.
content – The message content.
message_id – Optional message ID (auto-generated if not provided).
timestamp – Message timestamp (defaults to now).
guild_id – The guild ID.
edited – Whether the message was edited.
- Returns:
The message ID.
- set_mock_presence(user_id: str, status: PresenceStatus = PresenceStatus.ONLINE, *, activities: list[dict[str, Any]] | None = None, desktop_status: PresenceStatus = PresenceStatus.OFFLINE, mobile_status: PresenceStatus = PresenceStatus.OFFLINE, web_status: PresenceStatus = PresenceStatus.OFFLINE) DiscordPresence[source]¶
Set mock presence for a user.
- Parameters:
user_id – The user ID.
status – The presence status.
activities – List of activity data.
desktop_status – Desktop client status.
mobile_status – Mobile client status.
web_status – Web client status.
- Returns:
The created mock presence.
- property sent_messages: list[DiscordMessage]¶
Get all messages sent through this backend.
- Returns:
List of sent messages.
- property edited_messages: list[DiscordMessage]¶
Get all messages edited through this backend.
- Returns:
List of edited messages.
- property deleted_messages: list[dict[str, str]]¶
Get all message IDs deleted through this backend.
- Returns:
List of deleted message IDs.
- get_sent_messages() list[DiscordMessage][source]¶
Get all messages sent through this backend.
- Returns:
List of sent messages (copy).
- get_edited_messages() list[DiscordMessage][source]¶
Get all messages edited through this backend.
- Returns:
List of edited messages.
- get_deleted_messages() list[dict[str, str]][source]¶
Get all messages deleted through this backend.
- Returns:
List of deleted message info (channel_id, message_id).
- get_reactions() list[dict[str, str]][source]¶
Get all reactions added/removed through this backend.
- Returns:
List of reaction info (channel_id, message_id, emoji, action).
- get_presence_updates() list[dict[str, Any]][source]¶
Get all presence updates made through this backend.
- Returns:
List of presence update info.
- async fetch_user(identifier: str | User | None = None, *, id: str | None = None, name: str | None = None, email: str | None = None, handle: str | None = None) User | None[source]¶
Fetch a mock user by ID or other attributes.
- Parameters:
identifier – A User object or user ID string.
id – User ID.
name – Display name to search for.
email – Unused (Discord has no email lookup).
handle – Username to search for.
- Returns:
The mock user if found, None otherwise.
- async fetch_channel(identifier: str | Channel | None = None, *, id: str | None = None, name: str | None = None) Channel | None[source]¶
Fetch a mock channel by ID or name.
- Parameters:
identifier – A Channel object or channel ID string.
id – Channel ID.
name – Channel name to search for.
- Returns:
The mock channel if found, None otherwise.
- async fetch_messages(channel: str | Channel, limit: int = 100, before: str | Message | datetime | None = None, after: str | Message | datetime | None = None) list[Message][source]¶
Fetch mock messages from a channel.
- Parameters:
channel – The channel to fetch from (ID string or Channel object).
limit – Maximum number of messages.
before – Fetch messages before this ID or message.
after – Fetch messages after this ID or message.
- Returns:
List of mock messages.
- async send_message(channel: str | Channel, content: str, **kwargs: Any) Message[source]¶
Send a mock message.
- Parameters:
channel – The channel to send to (ID string or Channel object).
content – The message content.
**kwargs – Additional options.
- Returns:
The mock sent message.
- async edit_message(message: str | Message, content: str, channel: str | Channel | None = None, **kwargs: Any) Message[source]¶
Edit a mock message.
- Parameters:
message – The message to edit (ID string or Message object).
content – The new content.
channel – The channel containing the message (required if message is a string).
**kwargs – Additional options.
- Returns:
The mock edited message.
- async delete_message(message: str | Message, channel: str | Channel | None = None) None[source]¶
Delete a mock message.
- Parameters:
message – The message to delete (ID string or Message object).
channel – The channel containing the message (required if message is a string).
- async forward_message(message: str | Message, to_channel: str | Channel, *, include_attribution: bool = True, prefix: str | None = None, **kwargs: Any) DiscordMessage[source]¶
Forward a mock message to another channel.
- Parameters:
message – The message to forward (DiscordMessage object).
to_channel – The destination channel (ID string or Channel object).
include_attribution – If True, include info about original source.
prefix – Optional text to prepend to the forwarded message.
**kwargs – Additional options.
- Returns:
The forwarded message in the destination channel.
- async set_presence(status: str, status_text: str | None = None, **kwargs: Any) None[source]¶
Set mock presence.
- Parameters:
status – The status string.
status_text – Activity text.
**kwargs – Additional options.
- async get_presence(user: str | User) Presence | None[source]¶
Get mock presence for a user.
- Parameters:
user – The user ID string or User object.
- Returns:
The mock presence if set, None otherwise.
- async add_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Add a mock reaction.
- Parameters:
message – The message to react to (ID string or Message object).
emoji – The emoji to add.
channel – The channel containing the message (required if message is a string).
- async remove_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Remove a mock reaction.
- Parameters:
message – The message to remove reaction from (ID string or Message object).
emoji – The emoji to remove.
channel – The channel containing the message (required if message is a string).
- property created_dms: list[list[str]]¶
Get all DMs created through this backend.
- Returns:
List of user ID lists for each created DM.
Slack¶
Slack backend configuration.
This module provides configuration classes for the Slack backend.
- pydantic model chatom.slack.config.SlackConfig[source]¶
Bases:
BackendConfigConfiguration for Slack backend.
- bot_token¶
Slack Bot User OAuth Token (xoxb-…) or path to file.
- app_token¶
Slack App-Level Token (xapp-…) or path to file.
- signing_secret¶
Slack signing secret for request verification.
- team_id¶
The Slack workspace/team ID.
- default_channel¶
Default channel ID for sending messages.
- socket_mode¶
Whether to use Socket Mode for events.
- ssl¶
Optional SSL context for connections.
Example
>>> config = SlackConfig( ... bot_token="xoxb-your-token", ... app_token="xapp-your-app-token", # For Socket Mode ... signing_secret="your-signing-secret", ... ) >>> backend = SlackBackend(config=config)
- field bot_token: str | SecretStr = SecretStr('')¶
Slack Bot User OAuth Token (xoxb-…) or path to file.
- field app_token: str | SecretStr = SecretStr('')¶
Slack App-Level Token (xapp-…) or path to file.
- field signing_secret: str | SecretStr = SecretStr('')¶
Slack signing secret for request verification.
- field team_id: str = ''¶
The Slack workspace/team ID.
- field default_channel: str = ''¶
Default channel ID for sending messages.
- field socket_mode: bool = False¶
Whether to use Socket Mode for events.
- field ssl: SSLContext | None = None¶
Optional SSL context for connections.
- property bot_token_str: str¶
Get the bot token as a plain string.
- Returns:
The bot token string.
- property app_token_str: str¶
Get the app token as a plain string.
- Returns:
The app token string.
- property signing_secret_str: str¶
Get the signing secret as a plain string.
- Returns:
The signing secret string.
- property has_socket_mode: bool¶
Check if Socket Mode is configured.
Returns True if both socket_mode is enabled and app_token is set.
- Returns:
True if Socket Mode is configured, False otherwise.
Slack-specific User model.
This module provides the Slack-specific User class.
- pydantic model chatom.slack.user.SlackUser[source]¶
Bases:
UserSlack-specific user with additional Slack fields.
- real_name¶
The user’s real name from their profile.
- display_name¶
The user’s display name.
- team_id¶
The ID of the user’s workspace/team.
- is_admin¶
Whether the user is a workspace admin.
- is_owner¶
Whether the user is a workspace owner.
- is_restricted¶
Whether the user is a multi-channel guest.
- is_ultra_restricted¶
Whether the user is a single-channel guest.
- tz¶
The user’s timezone identifier.
- tz_offset¶
The user’s timezone offset in seconds.
- title¶
The user’s job title.
- phone¶
The user’s phone number.
- status_text¶
The user’s current status text.
- status_emoji¶
The user’s current status emoji.
- field real_name: str = ''¶
The user’s real name from their profile.
- field display_name: str = ''¶
The user’s display name.
- field team_id: str = ''¶
The ID of the user’s workspace/team.
- field is_admin: bool = False¶
Whether the user is a workspace admin.
- field is_owner: bool = False¶
Whether the user is a workspace owner.
- field is_restricted: bool = False¶
Whether the user is a multi-channel guest.
- field is_ultra_restricted: bool = False¶
Whether the user is a single-channel guest.
- field tz: str = ''¶
The user’s timezone identifier.
- field tz_offset: int = 0¶
The user’s timezone offset in seconds.
- field title: str = ''¶
The user’s job title.
- field phone: str = ''¶
The user’s phone number.
- field status_text: str = ''¶
The user’s current status text.
- field status_emoji: str = ''¶
The user’s current status emoji.
- property mention_name: str¶
Get the best name to use when mentioning.
- Returns:
The display name, real name, or handle.
- Return type:
str
Slack-specific Channel model.
This module provides the Slack-specific Channel class.
- pydantic model chatom.slack.channel.SlackChannel[source]¶
Bases:
ChannelSlack-specific channel with additional Slack fields.
- is_channel¶
Whether this is a public channel.
- is_group¶
Whether this is a private channel.
- is_im¶
Whether this is a direct message.
- is_mpim¶
Whether this is a multi-party direct message.
- is_private¶
Whether this is a private channel.
Whether this channel is shared with other workspaces.
Whether this channel is shared externally.
Whether this channel is shared org-wide.
- creator¶
User ID of the channel creator.
- purpose¶
Channel purpose text.
- num_members¶
Number of members in the channel.
- unread_count¶
Number of unread messages.
- last_read¶
Timestamp of last read message.
- latest¶
Timestamp of latest message.
- field is_channel: bool = False¶
Whether this is a public channel.
- field is_group: bool = False¶
Whether this is a private channel.
- field is_im: bool = False¶
Whether this is a direct message.
- field is_mpim: bool = False¶
Whether this is a multi-party direct message.
- field is_shared: bool = False¶
Whether this channel is shared with other workspaces.
- field is_ext_shared: bool = False¶
Whether this channel is shared externally.
- field is_org_shared: bool = False¶
Whether this channel is shared org-wide.
- field purpose: str = ''¶
Channel purpose text.
- field num_members: int | None = None¶
Number of members in the channel.
- field unread_count: int = 0¶
Number of unread messages.
- field last_read: str = ''¶
Timestamp of last read message.
- field latest: str = ''¶
Timestamp of latest message.
- property creator_id: str¶
Get the creator’s user ID.
- Returns:
The creator’s ID, or empty string if not set.
- Return type:
str
- property slack_channel_type: ChannelType¶
Determine the channel type from Slack flags.
- Returns:
The generic channel type.
- Return type:
Slack-specific Message model.
This module provides the Slack-specific Message class.
- pydantic model chatom.slack.message.SlackMessage[source]¶
Bases:
MessageSlack-specific message with additional Slack fields.
Based on the Slack API message structure.
Note: Use the inherited channel field for the SlackChannel object, and channel_id for the channel ID string. The sender_id field is deprecated - use author or author_id instead.
- team¶
The team/workspace ID.
- subtype¶
The message subtype.
- blocks¶
Slack Block Kit blocks.
- text¶
The message text (may differ from content due to mentions).
- latest_reply¶
Timestamp of latest reply.
- reply_users¶
List of user IDs who replied.
- is_locked¶
Whether the thread is locked.
- subscribed¶
Whether user is subscribed to thread.
- last_read¶
Timestamp of last read message in thread.
- files¶
List of attached files.
- upload¶
Whether this is a file upload message.
- display_as_bot¶
Whether to display as bot.
- edited¶
Edit information if message was edited.
- field subtype: SlackMessageSubtype | None = None¶
The message subtype.
- field blocks: list[dict[str, Any]] [Optional]¶
Slack Block Kit blocks.
- field reply_count: int = 0¶
Number of replies in thread.
- field latest_reply: str | None = None¶
Timestamp of latest reply.
- field is_locked: bool = False¶
Whether the thread is locked.
- field subscribed: bool = False¶
Whether user is subscribed to thread.
- field last_read: str | None = None¶
Timestamp of last read message in thread.
- field files: list[dict[str, Any]] [Optional]¶
List of attached files.
- field upload: bool = False¶
Whether this is a file upload message.
- field display_as_bot: bool = False¶
Whether to display as bot.
- field edited: dict[str, Any] | None = None¶
Edit information if message was edited.
- property ts: str | None¶
Get the message timestamp (ts).
- property thread_ts: str | None¶
Get the thread timestamp (thread_ts).
Returns the thread’s id if this message is in a thread, None otherwise.
- property team: Organization | None¶
Get the team/workspace ID.
- property sender_id: str | None¶
Get sender ID (deprecated - use author_id instead).
- property bot_id: str | None¶
Get bot ID from author if author is a bot.
For bots, the bot_id is the same as the author’s id.
- property app_id: str | None¶
Get app ID from author if available.
- property is_thread_reply: bool¶
Check if this message is a reply in a thread.
- property is_thread_parent: bool¶
Check if this message started a thread.
- property is_bot_message: bool¶
Check if this message is from a bot.
- property has_blocks: bool¶
Check if this message has Block Kit blocks.
- property has_files: bool¶
Check if this message has attached files.
- mentions_user(user: User) bool[source]¶
Check if this message mentions a specific user.
Slack mentions are in the format <@USER_ID> in the message text.
- Parameters:
user – The User to check for.
- Returns:
True if the user is mentioned, False otherwise.
- property permalink: str | None¶
Get the message permalink if channel_id and ts are available.
- to_formatted() FormattedMessage[source]¶
Convert this Slack message to a FormattedMessage.
Parses Slack mrkdwn formatting and converts to a FormattedMessage that can be rendered for other backends.
- Returns:
The formatted message representation.
- Return type:
- classmethod from_formatted(formatted: FormattedMessage, backend: str = '', **kwargs: Any) SlackMessage[source]¶
Create a SlackMessage from a FormattedMessage.
Renders the FormattedMessage in Slack mrkdwn format.
- Parameters:
formatted – The FormattedMessage to convert.
backend – Target backend (ignored, always uses slack format).
**kwargs – Additional message attributes.
- Returns:
A new SlackMessage instance.
- Return type:
- classmethod from_api_response(data: dict[str, Any]) SlackMessage[source]¶
Create a SlackMessage from a Slack API response.
- Parameters:
data – The API response data.
- Returns:
A SlackMessage instance.
- class chatom.slack.message.SlackMessageSubtype(value)[source]¶
Bases:
str,EnumSlack message subtypes.
Based on Slack API message subtypes.
Slack-specific Presence model.
This module provides the Slack-specific Presence class.
- pydantic model chatom.slack.presence.SlackPresence[source]¶
Bases:
PresenceSlack-specific presence.
- slack_presence¶
Slack-specific presence (active/away).
- auto_away¶
Whether user was automatically marked away.
- manual_away¶
Whether user manually set away.
- connection_count¶
Number of active connections.
- last_activity¶
Timestamp of last activity.
- field slack_presence: SlackPresenceStatus = SlackPresenceStatus.AWAY¶
Slack-specific presence.
- field auto_away: bool = False¶
Whether user was automatically marked away.
- field manual_away: bool = False¶
Whether user manually set away.
- field connection_count: int = 0¶
Number of active connections.
- field last_activity: int | None = None¶
Timestamp of last activity.
- property generic_status: PresenceStatus¶
Convert Slack presence to generic status.
- Returns:
The generic presence status.
- Return type:
- class chatom.slack.presence.SlackPresenceStatus(value)[source]¶
Bases:
str,EnumSlack-specific presence statuses.
- classmethod from_base(status: PresenceStatus) SlackPresenceStatus[source]¶
Convert a base PresenceStatus to SlackPresenceStatus.
- Parameters:
status – The base PresenceStatus to convert.
- Returns:
The corresponding SlackPresenceStatus.
Example
>>> slack_status = SlackPresenceStatus.from_base(PresenceStatus.ONLINE) >>> print(slack_status) # SlackPresenceStatus.ACTIVE
Slack-specific mention utilities.
This module registers Slack-specific mention formatting.
- chatom.slack.mention.mention_channel(channel: Channel) str[source]¶
- chatom.slack.mention.mention_channel(channel: DiscordChannel) str
- chatom.slack.mention.mention_channel(channel: SlackChannel) str
- chatom.slack.mention.mention_channel(channel: TelegramChannel) str
Generate a mention string for a channel.
This is a single-dispatch function that can be overridden for platform-specific channel types.
- Parameters:
channel – The channel to mention.
- Returns:
The formatted channel mention string.
- Return type:
str
Example
>>> from chatom import Channel, mention_channel >>> channel = Channel(name="general", id="456") >>> mention_channel(channel) '#general'
- chatom.slack.mention.mention_user(user: User) str[source]¶
- chatom.slack.mention.mention_user(user: DiscordUser) str
- chatom.slack.mention.mention_user(user: SlackUser) str
- chatom.slack.mention.mention_user(user: SymphonyUser) str
- chatom.slack.mention.mention_user(user: TelegramUser) str
Generate a mention string for a user.
This is a single-dispatch function that can be overridden for platform-specific user types.
- Parameters:
user – The user to mention.
- Returns:
The formatted mention string.
- Return type:
str
Example
>>> from chatom import User, mention_user >>> user = User(name="John", id="123") >>> mention_user(user) 'John'
Slack backend implementation for chatom.
- pydantic model chatom.slack.backend.SlackBackend[source]¶
Bases:
BackendBaseSlack backend implementation.
This provides the backend interface for Slack using the slack_sdk library for API calls.
- name¶
The backend identifier (‘slack’).
- display_name¶
Human-readable name.
- format¶
Slack uses its own mrkdwn format.
- capabilities¶
Slack-specific capabilities.
- config¶
Slack-specific configuration.
Example
>>> config = SlackConfig(bot_token="xoxb-your-token") >>> backend = SlackBackend(config=config) >>> await backend.connect() >>> messages = await backend.fetch_messages("C123456")
- name: ClassVar[str] = 'slack'¶
- display_name: ClassVar[str] = 'Slack'¶
- mention_pattern: ClassVar[Pattern | None] = re.compile('<@(U[A-Z0-9]+)>')¶
- channel_class¶
alias of
SlackChannel
- presence_class¶
alias of
SlackPresence
- field capabilities: BackendCapabilities | None = BackendCapabilities(capabilities=frozenset({<Capability.DELETING: 'deleting'>, <Capability.TYPING_INDICATORS: 'typing_indicators'>, <Capability.PINNING: 'pinning'>, <Capability.RICH_TEXT: 'rich_text'>, <Capability.USER_MENTIONS: 'user_mentions'>, <Capability.FORMS: 'forms'>, <Capability.THREADS: 'threads'>, <Capability.BUTTONS: 'buttons'>, <Capability.EMBEDS: 'embeds'>, <Capability.MARKDOWN: 'markdown'>, <Capability.PLAINTEXT: 'plaintext'>, <Capability.CUSTOM_EMOJI: 'custom_emoji'>, <Capability.CHANNEL_MENTIONS: 'channel_mentions'>, <Capability.CODE_BLOCKS: 'code_blocks'>, <Capability.FILES: 'files'>, <Capability.EVERYONE_MENTION: 'everyone_mention'>, <Capability.IMAGES: 'images'>, <Capability.PRESENCE: 'presence'>, <Capability.FORWARDING: 'forwarding'>, <Capability.TABLES: 'tables'>, <Capability.REPLIES: 'replies'>, <Capability.SELECT_MENUS: 'select_menus'>, <Capability.EDITING: 'editing'>, <Capability.MESSAGE_SEARCH: 'message_search'>, <Capability.EMOJI_REACTIONS: 'emoji_reactions'>}), max_message_length=40000, max_attachment_size=1073741824, max_attachments=10, max_embeds=20, max_reactions=23)¶
- field config: SlackConfig [Optional]¶
- property bot_user_id: str | None¶
Get the bot’s user ID (cached from connect/get_bot_info).
- property bot_user_name: str | None¶
Get the bot’s username (cached from connect/get_bot_info).
- async connect() None[source]¶
Connect to Slack using the configured credentials.
Initializes the Slack WebClient with the bot token from config.
- Raises:
ImportError – If slack_sdk is not installed.
SlackApiError – If authentication fails.
- async fetch_user(identifier: str | User | None = None, *, id: str | None = None, name: str | None = None, email: str | None = None, handle: str | None = None) SlackUser | None[source]¶
Fetch a user from Slack.
Accepts flexible inputs: - User ID as positional arg or id= - SlackUser object (returns as-is or refreshes) - name= to search by display name or real name - email= to search by email address - handle= to search by username
- Parameters:
identifier – A SlackUser object or user ID string.
id – User ID.
name – Display name or real name to search for.
email – Email address to search for.
handle – Username to search for.
- Returns:
The user if found, None otherwise.
- async fetch_channel(identifier: str | Channel | None = None, *, id: str | None = None, name: str | None = None) SlackChannel | None[source]¶
Fetch a channel from Slack.
Accepts flexible inputs: - Channel ID as positional arg or id= - SlackChannel object (returns as-is or refreshes) - name= to search by channel name
- Parameters:
identifier – A SlackChannel object or channel ID string.
id – Channel ID.
name – Channel name to search for.
- Returns:
The channel if found, None otherwise.
- async fetch_messages(channel: str | Channel, limit: int = 100, before: str | Message | datetime | None = None, after: str | Message | datetime | None = None) list[Message][source]¶
Fetch messages from a Slack channel, newest-first.
Uses the conversations.history API with
oldest/latestbounds, paging via cursor to cover the full range up tolimit.- Parameters:
channel – The channel to fetch messages from (ID string or Channel object).
limit – Maximum number of messages to return.
before – Upper bound — Slack ts, Message, or datetime (
latest).after – Lower bound — Slack ts, Message, or datetime (
oldest).
- Returns:
List of messages, ordered newest-to-oldest.
- async search_messages(query: str, channel: str | Channel | None = None, limit: int = 50, **kwargs: Any) list[Message][source]¶
Search for messages matching a query.
Uses the search.messages API. Requires search:read scope.
- Parameters:
query – The search query string. Supports Slack search modifiers like “from:@user”, “in:#channel”, “has:link”, etc.
channel – Optional channel to limit search to (ID string or Channel object).
limit – Maximum number of results (1-100).
**kwargs – Additional options: - sort: “score” or “timestamp” (default: “score”) - sort_dir: “asc” or “desc” (default: “desc”)
- Returns:
List of messages matching the query.
Example
>>> results = await backend.search_messages("important") >>> results = await backend.search_messages("from:@john has:file")
- async send_message(channel: str | Channel, content: str, **kwargs: Any) SlackMessage[source]¶
Send a message to a Slack channel.
Uses the chat.postMessage API.
- Parameters:
channel – The channel to send to (ID string or Channel object).
content – The message content. kwargs: Slack thread, reply, block, attachment, and unfurl options.
- Returns:
The sent message.
- async upload_file(channel: str | Channel, data: bytes, filename: str = 'file', content_type: str = '', title: str = '', content: str = '', **kwargs: Any) Message[source]¶
Upload a file to a Slack channel.
Uses the
files_upload_v2API (Slack SDK >=3.19).
- async download_attachment(attachment: Any, *, message: Message | None = None) bytes[source]¶
Download a Slack attachment’s bytes.
Slack
url_privatelinks require the bot token as a bearer token; this override supplies it. Falls back tofiles.infoto resolve the private URL when the attachment only carries a file ID.
- async edit_message(message: str | Message, content: str, channel: str | Channel | None = None, **kwargs: Any) SlackMessage[source]¶
Edit a Slack message.
Uses the chat.update API.
- Parameters:
message – The message to edit (ts string or SlackMessage object).
content – The new content.
channel – The channel containing the message (required if message is a string).
**kwargs – Additional options.
- Returns:
The edited message.
- async delete_message(message: str | Message, channel: str | Channel | None = None) None[source]¶
Delete a Slack message.
Uses the chat.delete API.
- Parameters:
message – The message to delete (ts string or SlackMessage object).
channel – The channel containing the message (required if message is a string).
- async forward_message(message: Message, to_channel: str | Channel, *, include_attribution: bool = True, prefix: str | None = None, **kwargs: Any) SlackMessage[source]¶
Forward a message to another Slack channel.
Slack doesn’t have native forwarding, so this creates a new message with the original content and optional attribution.
- Parameters:
message – The message to forward (SlackMessage object or message ts).
to_channel – The destination channel (ID string or Channel object).
include_attribution – If True, include info about original source.
prefix – Optional text to prepend to the forwarded message.
**kwargs – Additional options (thread_id, blocks, etc.).
- Returns:
The forwarded message in the destination channel.
- async set_presence(status: str, status_text: str | None = None, **kwargs: Any) None[source]¶
Set user presence on Slack.
Uses the users.setPresence API for presence and users.profile.set for status text.
- Parameters:
status – Presence status (‘auto’ or ‘away’).
status_text – Status text to display.
**kwargs – Additional options (status_emoji, status_expiration, etc.).
- async get_presence(user: str | User) SlackPresence | None[source]¶
Get a user’s presence on Slack.
Uses the users.getPresence API.
- Parameters:
user – The user ID string or User object.
- Returns:
The user’s presence.
- async add_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Add a reaction to a message.
Uses the reactions.add API.
- Parameters:
message – The message to react to (ts string or SlackMessage object).
emoji – The emoji name (without colons).
channel – The channel containing the message (required if message is a string).
- async remove_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Remove a reaction from a message.
Uses the reactions.remove API.
- Parameters:
message – The message to remove reaction from (ts string or SlackMessage object).
emoji – The emoji name to remove.
channel – The channel containing the message (required if message is a string).
- mention_user(user: User) str[source]¶
Format a user mention for Slack.
- Parameters:
user – The user to mention.
- Returns:
Slack user mention format (<@user_id>).
- mention_channel(channel: Channel) str[source]¶
Format a channel mention for Slack.
- Parameters:
channel – The channel to mention.
- Returns:
Slack channel mention format (<#channel_id>).
- mention_here() str[source]¶
Format an @here mention for Slack.
- Returns:
Slack @here mention format (<!here>).
- mention_everyone() str[source]¶
Format an @everyone mention for Slack.
- Returns:
Slack @everyone mention format (<!everyone>).
- mention_channel_all() str[source]¶
Format an @channel mention for Slack.
Notifies all members of the current channel.
- Returns:
Slack @channel mention format (<!channel>).
- async create_dm(users: list[str | User]) str | None[source]¶
Create a DM/IM channel with the specified users.
Uses conversations.open API to create or retrieve a DM channel. For a single user, creates a 1:1 DM. For multiple users, creates a group DM (multi-party DM).
- Parameters:
users – List of users to include in the DM (ID strings or User objects). Can be a single user or a list.
- Returns:
The DM channel ID, or None if creation failed.
- async create_channel(name: str, description: str = '', public: bool = True, **kwargs: Any) str | None[source]¶
Create a new Slack channel.
Uses conversations.create API to create a public or private channel.
- Parameters:
name – The channel name (will be lowercased and spaces replaced).
description – Optional channel description/purpose.
public – Whether the channel is public (default True). Private channels are created with is_private=True.
**kwargs – Additional options: - team_id: Workspace ID for Enterprise Grid.
- Returns:
The channel ID of the created channel, or None if failed.
- async get_bot_info() User | None[source]¶
Get information about the connected bot user.
- Returns:
The bot’s User object.
- async stream_messages(channel: str | Channel | None = None, skip_own: bool = True, skip_history: bool = True) AsyncIterator[SlackMessage][source]¶
Stream incoming messages in real-time using Socket Mode.
This requires an app token (xapp-…) to be configured.
- Parameters:
channel – Optional channel to filter messages (ID string or Channel object).
skip_own – If True (default), skip messages sent by the bot itself.
skip_history – If True (default), skip messages that existed before the stream started. Only yields new messages.
- Yields:
Message – Each message as it arrives.
Mock Slack backend for testing.
This module provides a mock implementation of the Slack backend for use in tests without requiring actual Slack API credentials.
- pydantic model chatom.slack.testing.MockSlackBackend[source]¶
Bases:
SlackBackendMock Slack backend for testing.
This backend simulates Slack API responses without making actual network calls. Useful for unit tests and development.
- mock_users¶
Dictionary of mock users by ID.
- mock_channels¶
Dictionary of mock channels by ID.
- mock_messages¶
Dictionary of messages by channel_id.
- mock_presence¶
Dictionary of presence by user_id.
- sent_messages¶
List of all sent messages (for assertions).
- deleted_messages¶
List of deleted message IDs.
- reactions¶
Dictionary of reactions by (channel_id, message_id).
Example
>>> backend = MockSlackBackend() >>> backend.add_mock_user(SlackUser(id="U123", name="alice")) >>> backend.add_mock_channel(SlackChannel(id="C123", name="general")) >>> await backend.connect() >>> user = await backend.fetch_user("U123") >>> assert user.name == "alice"
- name: ClassVar[str] = 'mock_slack'¶
- display_name: ClassVar[str] = 'Mock Slack'¶
- add_mock_user(id: str, name: str, handle: str | None = None, *, display_name: str | None = None, avatar_url: str = '', is_bot: bool = False) SlackUser[source]¶
Add a mock user to the backend.
- Parameters:
id – The user ID.
name – The user’s display name.
handle – The username/handle.
display_name – Optional display name.
avatar_url – URL to user’s avatar.
is_bot – Whether the user is a bot.
- Returns:
The created mock user.
- add_mock_channel(id: str, name: str, *, topic: str = '', is_private: bool = False, is_archived: bool = False) SlackChannel[source]¶
Add a mock channel to the backend.
- Parameters:
id – The channel ID.
name – The channel name.
topic – The channel topic.
is_private – Whether the channel is private.
is_archived – Whether the channel is archived.
- Returns:
The created mock channel.
- add_mock_message(channel_id: str, user_id: str, content: str, *, message_id: str | None = None, timestamp: datetime | None = None) str[source]¶
Add a mock message to a channel.
- Parameters:
channel_id – The channel ID.
user_id – The sender’s user ID.
content – The message content.
message_id – Optional message ID (auto-generated if not provided).
timestamp – Optional timestamp.
- Returns:
The message ID.
- set_mock_presence(user_id: str, status: PresenceStatus = PresenceStatus.ONLINE, *, status_text: str = '') SlackPresence[source]¶
Set mock presence for a user.
- Parameters:
user_id – The user ID.
status – The presence status.
status_text – Optional status text.
- Returns:
The created presence.
- property sent_messages: list[SlackMessage]¶
Get all messages sent through this backend.
- Returns:
List of sent messages.
- property added_reactions: list[tuple]¶
Get all reactions added through this backend.
- Returns:
List of (channel_id, message_id, emoji) tuples.
- property removed_reactions: list[tuple]¶
Get all reactions removed through this backend.
- Returns:
List of (channel_id, message_id, emoji) tuples.
- property presence_changes: list[dict[str, Any]]¶
Get all presence changes made through this backend.
- Returns:
List of presence changes.
- property created_dms: list[list[str]]¶
Get all DMs created through this backend.
- Returns:
List of user ID lists for each created DM.
- property mock_users: dict[str, SlackUser]¶
Get all mock users.
- Returns:
Dictionary of mock users by ID.
- get_sent_messages() list[SlackMessage][source]¶
Get all messages sent through this backend.
- Returns:
List of sent messages (copy).
- get_deleted_messages() list[tuple][source]¶
Get all deleted message references.
- Returns:
List of (channel_id, message_id) tuples.
- get_reactions(channel_id: str, message_id: str) list[str][source]¶
Get reactions for a message.
- Parameters:
channel_id – The channel ID.
message_id – The message ID.
- Returns:
List of emoji names.
- async fetch_user(identifier: str | User | None = None, *, id: str | None = None, name: str | None = None, email: str | None = None, handle: str | None = None) SlackUser | None[source]¶
Fetch a mock user by ID or other attributes.
- Parameters:
identifier – A User object or user ID string.
id – User ID.
name – Display name to search for.
email – Email address to search for.
handle – Username/handle to search for.
- Returns:
The user if found, None otherwise.
- async fetch_channel(identifier: str | Channel | None = None, *, id: str | None = None, name: str | None = None) SlackChannel | None[source]¶
Fetch a mock channel by ID or name.
- Parameters:
identifier – A Channel object or channel ID string.
id – Channel ID.
name – Channel name to search for.
- Returns:
The channel if found, None otherwise.
- async fetch_messages(channel: str | Channel, limit: int = 100, before: str | Message | datetime | None = None, after: str | Message | datetime | None = None) list[Message][source]¶
Fetch mock messages from a channel.
- Parameters:
channel – The channel to fetch from (ID string or Channel object).
limit – Maximum number of messages.
before – Fetch messages before this timestamp.
after – Fetch messages after this timestamp.
- Returns:
List of messages.
- async send_message(channel: str | Channel, content: str, **kwargs: Any) SlackMessage[source]¶
Send a mock message.
- Parameters:
channel – The channel to send to (ID string or Channel object).
content – The message content.
**kwargs – Additional options.
- Returns:
The sent message.
- async edit_message(message: str | Message, content: str, channel: str | Channel | None = None, **kwargs: Any) SlackMessage[source]¶
Edit a mock message.
- Parameters:
message – The message to edit (ts string or Message object).
content – The new content.
channel – The channel containing the message (required if message is a string).
**kwargs – Additional options.
- Returns:
The edited message.
- async delete_message(message: str | Message, channel: str | Channel | None = None) None[source]¶
Delete a mock message.
- Parameters:
message – The message to delete (ts string or Message object).
channel – The channel containing the message (required if message is a string).
- async forward_message(message: Message, to_channel: str | Channel, *, include_attribution: bool = True, prefix: str | None = None, **kwargs: Any) SlackMessage[source]¶
Forward a mock message to another channel.
- Parameters:
message – The message to forward (SlackMessage object).
to_channel – The destination channel (ID string or Channel object).
include_attribution – If True, include info about original source.
prefix – Optional text to prepend to the forwarded message.
**kwargs – Additional options.
- Returns:
The forwarded message in the destination channel.
- async set_presence(status: str, status_text: str | None = None, **kwargs: Any) None[source]¶
Set mock presence.
- Parameters:
status – Presence status (‘auto’ or ‘away’).
status_text – Status text.
**kwargs – Additional options.
- async get_presence(user: str | User) SlackPresence | None[source]¶
Get mock presence for a user.
- Parameters:
user – The user ID string or User object.
- Returns:
The user’s presence.
- async add_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Add a mock reaction.
- Parameters:
message – The message to react to (ts string or Message object).
emoji – The emoji name.
channel – The channel containing the message (required if message is a string).
- async remove_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Remove a mock reaction.
- Parameters:
message – The message to remove reaction from (ts string or Message object).
emoji – The emoji name.
channel – The channel containing the message (required if message is a string).
Symphony¶
Symphony backend configuration.
This module provides the SymphonyConfig class for configuring the Symphony backend with the Symphony BDK.
- pydantic model chatom.symphony.config.SymphonyConfig[source]¶
Bases:
BackendConfigConfiguration for the Symphony backend.
This class holds all Symphony-specific configuration needed for the Symphony BDK, including pod URL, bot credentials, and optional application settings.
- host¶
The Symphony pod hostname (e.g., “mycompany.symphony.com”).
- port¶
The Symphony pod port (default: 443).
- scheme¶
The URL scheme (default: “https”).
- context¶
Optional context path (default: “”).
- bot_username¶
The bot’s username.
- bot_private_key_path¶
Path to the bot’s RSA private key file.
- bot_private_key_content¶
Direct content of the RSA private key.
- bot_certificate_path¶
Path to the bot’s certificate (for cert auth).
- bot_certificate_content¶
Direct content of the certificate (PEM format). If provided without bot_certificate_path, a temp file is created automatically since Symphony BDK requires a file path.
- bot_certificate_password¶
Password for the certificate.
- app_id¶
Optional extension app ID.
- app_private_key_path¶
Path to the app’s RSA private key.
- agent_host¶
Optional separate agent host (if different from pod).
- agent_port¶
Optional agent port.
- session_auth_host¶
Optional session auth host (if different from pod).
- session_auth_port¶
Optional session auth port.
- key_manager_host¶
Optional key manager host.
- key_manager_port¶
Optional key manager port.
- trust_store_path¶
Path to custom trust store.
- proxy_host¶
Optional proxy host.
- proxy_port¶
Optional proxy port.
- proxy_username¶
Optional proxy username.
- proxy_password¶
Optional proxy password.
Example
>>> # Using RSA key file >>> config = SymphonyConfig( ... host="mycompany.symphony.com", ... bot_username="my-bot", ... bot_private_key_path="/path/to/private-key.pem", ... ) >>> backend = SymphonyBackend(config=config)
>>> # Using certificate content (temp file created automatically) >>> config = SymphonyConfig( ... host="mycompany.symphony.com", ... bot_username="my-bot", ... bot_certificate_content=SecretStr(cert_pem_string), ... )
- field host: str = ''¶
- field port: int = 443¶
- field scheme: str = 'https'¶
- field context: str = ''¶
- field bot_username: str = ''¶
- field bot_private_key_path: str | None = None¶
- field bot_private_key_content: str | SecretStr | None = None¶
- field bot_certificate_path: str | None = None¶
- field bot_certificate_content: str | SecretStr | None = None¶
Direct content of the certificate PEM. If provided without bot_certificate_path, a temp file will be created automatically.
- field bot_certificate_password: str | SecretStr | None = None¶
- field app_id: str | None = None¶
- field app_private_key_path: str | None = None¶
- field pod_host: str | None = None¶
- field pod_port: int | None = None¶
- field agent_host: str | None = None¶
- field agent_port: int | None = None¶
- field session_auth_host: str | None = None¶
- field session_auth_port: int | None = None¶
- field key_manager_host: str | None = None¶
- field key_manager_port: int | None = None¶
- field trust_store_path: str | None = None¶
- field proxy_host: str | None = None¶
- field proxy_port: int | None = None¶
- field proxy_username: str | None = None¶
- field proxy_password: SecretStr | None = None¶
- field timeout: int = 30¶
Request timeout in seconds
- field error_room: str | None = None¶
A room to direct error messages to, if a message fails to be sent.
- field inform_client: bool = False¶
Whether to inform the intended recipient of a failed message.
- field max_attempts: int = 10¶
Max attempts for datafeed and message post requests before raising exception.
- field initial_interval_ms: int = 500¶
Initial interval to wait between attempts, in milliseconds.
- field multiplier: float = 2.0¶
Multiplier between attempt delays for exponential backoff.
- field max_interval_ms: int = 300000¶
Maximum delay between retry attempts, in milliseconds.
- field datafeed_version: str = 'v2'¶
Version of datafeed to use (‘v1’ or ‘v2’).
- field ssl_trust_store_path: str | None = None¶
Path to a custom CA certificate bundle file.
- field ssl_verify: bool = True¶
Whether to verify SSL certificates.
- field message_create_url: str | None = None¶
Custom URL for message creation. Template: https://{host}/agent/v4/stream/{sid}/message/create
- field datafeed_create_url: str | None = None¶
Custom URL for datafeed creation. Template: https://{host}/agent/v5/datafeeds
- field datafeed_delete_url: str | None = None¶
Custom URL for datafeed deletion. Template: https://{host}/agent/v5/datafeeds/{datafeed_id}
- field datafeed_read_url: str | None = None¶
Custom URL for datafeed reading. Template: https://{host}/agent/v5/datafeeds/{datafeed_id}/read
- field room_search_url: str | None = None¶
Custom URL for room search. Template: https://{host}/pod/v3/room/search
- field room_info_url: str | None = None¶
Custom URL for room info. Template: https://{host}/pod/v3/room/{room_id}/info
- field im_create_url: str | None = None¶
Custom URL for IM creation. Template: https://{host}/pod/v1/im/create
- field room_members_url: str | None = None¶
Custom URL for room members. Template: https://{host}/pod/v2/room/{room_id}/membership/list
- field presence_url: str | None = None¶
Custom URL for user presence. Template: https://{host}/pod/v2/user/presence
- field user_detail_url: str | None = None¶
Custom URL for user detail. Template: https://{host}/pod/v2/admin/user/{uid}
- field user_search_url: str | None = None¶
Custom URL for user search. Template: https://{host}/pod/v3/users
- field user_lookup_url: str | None = None¶
Custom URL for user lookup by email/username. Template: https://{host}/pod/v3/users
- property bot_private_key_str: str | None¶
Get the bot private key content as string.
- property bot_certificate_content_str: str | None¶
Get the certificate content as string.
- property bot_certificate_password_str: str | None¶
Get the certificate password as string.
- property proxy_password_str: str | None¶
Get the proxy password as string.
- property has_rsa_auth: bool¶
Check if RSA authentication is configured.
- property has_cert_auth: bool¶
Check if certificate authentication is configured.
- property is_using_temp_cert: bool¶
Check if a temporary certificate file was created.
- cleanup_temp_cert() None[source]¶
Manually cleanup temporary certificate file if created.
This is called automatically on process exit, but can be called manually for explicit cleanup.
- property pod_url: str¶
Build the pod URL.
- class chatom.symphony.config.SymphonyRoomMapper(stream_service=None, backend: SymphonyBackend | None = None)[source]¶
Bases:
objectThread-safe mapper for Symphony room names and IDs.
This class maintains a cache of room name to ID mappings and vice versa, using the stream service to resolve unknown rooms.
- set_backend(backend: SymphonyBackend)[source]¶
Set the chatom backend for room resolution.
- get_room_id(room_name: str) str | None[source]¶
Get the room ID for a given room name.
- Parameters:
room_name – The display name of the room.
- Returns:
The room’s stream ID, or None if not found.
- async get_room_id_async(room_name: str) str | None[source]¶
Get the room ID for a given room name, using async calls if needed.
- Parameters:
room_name – The display name of the room.
- Returns:
The room’s stream ID, or None if not found.
- get_room_name(room_id: str) str | None[source]¶
Get the room name for a given room ID.
- Parameters:
room_id – The room’s stream ID.
- Returns:
The room’s display name, or None if not found.
- async get_room_name_async(room_id: str) str | None[source]¶
Get the room name for a given room ID, using async calls if needed.
- Parameters:
room_id – The room’s stream ID.
- Returns:
The room’s display name, or None if not found.
Symphony-specific User model.
This module provides the Symphony-specific User class.
- pydantic model chatom.symphony.user.SymphonyUser[source]¶
Bases:
UserSymphony-specific user with additional Symphony fields.
- first_name¶
The user’s first name.
- last_name¶
The user’s last name.
- display_name¶
The user’s display name.
- company¶
The user’s company name.
- department¶
The user’s department.
- title¶
The user’s job title.
- location¶
The user’s location.
- work_phone¶
The user’s work phone number.
- mobile_phone¶
The user’s mobile phone number.
- account_type¶
The type of Symphony account.
- roles¶
List of user roles.
- field first_name: str = ''¶
The user’s first name.
- field last_name: str = ''¶
The user’s last name.
- field display_name: str = ''¶
The user’s display name.
- field company: str = ''¶
The user’s company name.
- field department: str = ''¶
The user’s department.
- field title: str = ''¶
The user’s job title.
- field location: str = ''¶
The user’s location.
- field work_phone: str = ''¶
The user’s work phone number.
- field mobile_phone: str = ''¶
The user’s mobile phone number.
- field account_type: str = ''¶
The type of Symphony account.
- field roles: list[str] [Optional]¶
List of user roles.
- property full_name: str¶
Get the user’s full name.
- Returns:
First and last name combined.
- Return type:
str
- property mention_name: str¶
Get the best name to use when mentioning.
- Returns:
The display name or full name.
- Return type:
str
Symphony-specific Channel model.
This module provides the Symphony-specific Channel class. In Symphony, channels are called “streams” or “rooms”.
- pydantic model chatom.symphony.channel.SymphonyChannel[source]¶
Bases:
ChannelSymphony-specific channel (stream) with additional Symphony fields.
- stream_type¶
The type of Symphony stream.
- external¶
Whether the stream includes external users.
- cross_pod¶
Whether the stream is cross-pod.
- active¶
Whether the stream is active.
- read_only¶
Whether the stream is read-only.
- public¶
Whether the stream is public.
- creation_date¶
When the stream was created.
- last_message_date¶
When the last message was sent.
- field stream_type: SymphonyStreamType = SymphonyStreamType.ROOM¶
The type of Symphony stream.
- field external: bool = False¶
Whether the stream includes external users.
- field cross_pod: bool = False¶
Whether the stream is cross-pod.
- field active: bool = True¶
Whether the stream is active.
- field read_only: bool = False¶
Whether the stream is read-only.
- field public: bool = False¶
Whether the stream is public.
- field creation_date: datetime | None = None¶
When the stream was created.
- field last_message_date: datetime | None = None¶
When the last message was sent.
- property generic_channel_type: ChannelType¶
Convert Symphony stream type to generic channel type.
- Returns:
The generic channel type.
- Return type:
- property stream_id: str¶
Alias for id - Symphony uses stream_id terminology.
- Returns:
The stream/channel ID.
- Return type:
str
- chatom.symphony.channel.SymphonyRoom¶
alias of
SymphonyChannel
- class chatom.symphony.channel.SymphonyStreamType(value)[source]¶
Bases:
str,EnumSymphony stream types.
- IM = 'IM'¶
1 chat).
- Type:
Instant message (1
- MIM = 'MIM'¶
Multi-party instant message.
- ROOM = 'ROOM'¶
Chat room.
- POST = 'POST'¶
Wall post.
Symphony-specific Message model.
This module provides the Symphony-specific Message class.
- pydantic model chatom.symphony.message.SymphonyMessage[source]¶
Bases:
MessageSymphony-specific message with additional Symphony fields.
Based on the Symphony REST API message structure.
- message_ml¶
The MessageML content.
- presentation_ml¶
The PresentationML rendered content.
- entity_data¶
Entity data for structured objects.
- data¶
The JSON data associated with the message.
Shared/forwarded message info.
- ingestion_date¶
When the message was ingested.
- diagnostic¶
Diagnostic information.
- sid¶
Session ID.
- original_format¶
The original message format.
- is_chime¶
Whether this is a chime message.
- is_copy_disabled¶
Whether copying is disabled.
- attachments_metadata¶
Metadata about attachments.
- hashtags¶
List of hashtags in the message.
- cashtags¶
List of cashtags in the message.
- mentions¶
List of user mentions in the message.
- field message_ml: str | None = None¶
The MessageML content.
- field presentation_ml: str | None = None¶
The PresentationML rendered content.
- field entity_data: dict[str, Any] [Optional]¶
Entity data for structured objects.
- field data: str | None = None¶
The JSON data associated with the message.
- field shared_message: dict[str, Any] | None = None¶
Shared/forwarded message info.
- field ingestion_date: datetime | None = None¶
When the message was ingested.
- field diagnostic: str | None = None¶
Diagnostic information.
- field sid: str | None = None¶
Session ID.
- field original_format: SymphonyMessageFormat = SymphonyMessageFormat.MESSAGEML¶
The original message format.
- field is_chime: bool = False¶
Whether this is a chime message.
- field is_copy_disabled: bool = False¶
Whether copying is disabled.
- field attachments_metadata: list[dict[str, Any]] [Optional]¶
Metadata about attachments.
- field hashtags: list[str] [Optional]¶
List of hashtags in the message.
- field cashtags: list[str] [Optional]¶
List of cashtags in the message.
Check if this is a shared/forwarded message.
- property message_id: str¶
Get the message ID (same as id).
Returns the message’s id for backward compatibility.
- property stream_id: str¶
Get the stream ID (channel.id).
Returns the channel’s id, or empty string if no channel.
- property has_entity_data: bool¶
Check if this message has entity data.
- property has_hashtags: bool¶
Check if this message contains hashtags.
- property has_cashtags: bool¶
Check if this message contains cashtags.
- property has_mentions: bool¶
Check if this message contains user mentions.
- mentions_user(user: User) bool[source]¶
Check if this message mentions a specific user.
- Parameters:
user – The User to check for.
- Returns:
True if the user is mentioned in this message.
- static extract_mentions_from_data(data: str | None) list[int][source]¶
Extract user IDs from Symphony data field (JSON entity data).
Symphony encodes mentions in the data field as JSON with entity references like {“mention0”: {“type”: “com.symphony.user.mention”, “id”: [{“value”: “123”}]}}.
- Parameters:
data – The JSON data string from the message.
- Returns:
List of user IDs (as integers) mentioned in the message.
- property rendered_content: str¶
Get the rendered content, preferring PresentationML.
- classmethod from_api_response(data: dict[str, Any]) SymphonyMessage[source]¶
Create a SymphonyMessage from an API response.
- Parameters:
data – The API response data.
- Returns:
A SymphonyMessage instance.
- to_formatted() FormattedMessage[source]¶
Convert this Symphony message to a FormattedMessage.
Parses Symphony MessageML/PresentationML formatting and converts to a FormattedMessage that can be rendered for other backends.
- Returns:
The formatted message representation.
- Return type:
- classmethod from_formatted(formatted: FormattedMessage, backend: str = '', **kwargs: Any) SymphonyMessage[source]¶
Create a SymphonyMessage from a FormattedMessage.
Renders the FormattedMessage in Symphony MessageML format.
- Parameters:
formatted – The FormattedMessage to convert.
backend – Target backend (ignored, always uses symphony format).
**kwargs – Additional message attributes.
- Returns:
A new SymphonyMessage instance.
- Return type:
- class chatom.symphony.message.SymphonyMessageFormat(value)[source]¶
Bases:
str,EnumSymphony message format types.
Symphony-specific Presence model.
This module provides the Symphony-specific Presence class.
- pydantic model chatom.symphony.presence.SymphonyPresence[source]¶
Bases:
PresenceSymphony-specific presence.
- symphony_status¶
Symphony-specific status enum.
- category¶
Presence category.
- timestamp¶
When the presence was last updated.
- field symphony_status: SymphonyPresenceStatus = SymphonyPresenceStatus.OFFLINE¶
Symphony-specific status.
- field category: str = ''¶
Presence category.
- field timestamp: int | None = None¶
When the presence was last updated (epoch ms).
- property generic_status: PresenceStatus¶
Convert Symphony status to generic status.
- Returns:
The generic presence status.
- Return type:
- class chatom.symphony.presence.SymphonyPresenceStatus(value)[source]¶
Bases:
str,EnumSymphony-specific presence statuses.
Symphony-specific mention utilities.
This module registers Symphony-specific mention formatting using MessageML.
- chatom.symphony.mention.mention_user(user: User) str[source]¶
- chatom.symphony.mention.mention_user(user: DiscordUser) str
- chatom.symphony.mention.mention_user(user: SlackUser) str
- chatom.symphony.mention.mention_user(user: SymphonyUser) str
- chatom.symphony.mention.mention_user(user: TelegramUser) str
Generate a mention string for a user.
This is a single-dispatch function that can be overridden for platform-specific user types.
- Parameters:
user – The user to mention.
- Returns:
The formatted mention string.
- Return type:
str
Example
>>> from chatom import User, mention_user >>> user = User(name="John", id="123") >>> mention_user(user) 'John'
- chatom.symphony.mention.mention_user_by_email(email: str) str[source]¶
Generate a Symphony mention by email address.
- Parameters:
email – The email address to mention.
- Returns:
The Symphony MessageML mention tag.
- Return type:
str
- chatom.symphony.mention.mention_user_by_uid(uid: str) str[source]¶
Generate a Symphony mention by user ID.
- Parameters:
uid – The user ID to mention.
- Returns:
The Symphony MessageML mention tag.
- Return type:
str
Symphony backend implementation for chatom.
This module provides the Symphony backend using the Symphony BDK (Bot Development Kit).
- pydantic model chatom.symphony.backend.SymphonyBackend[source]¶
Bases:
BackendBaseSymphony backend implementation using Symphony BDK.
This provides the backend interface for Symphony using the official Symphony Bot Development Kit (BDK).
- name¶
The backend identifier (‘symphony’).
- display_name¶
Human-readable name.
- format¶
Symphony uses MessageML format.
- capabilities¶
Symphony-specific capabilities.
- config¶
Symphony-specific configuration.
Example
>>> from chatom.symphony import SymphonyBackend, SymphonyConfig >>> config = SymphonyConfig( ... host="mycompany.symphony.com", ... bot_username="my-bot", ... bot_private_key_path="/path/to/private-key.pem", ... ) >>> backend = SymphonyBackend(config=config) >>> await backend.connect()
- name: ClassVar[str] = 'symphony'¶
- display_name: ClassVar[str] = 'Symphony'¶
- mention_pattern: ClassVar[Pattern | None] = re.compile('<mention\\s+uid="(\\d+)"\\s*/>')¶
- user_class¶
alias of
SymphonyUser
- channel_class¶
alias of
SymphonyChannel
- presence_class¶
alias of
SymphonyPresence
- field capabilities: BackendCapabilities | None = BackendCapabilities(capabilities=frozenset({<Capability.DELETING: 'deleting'>, <Capability.CODE_BLOCKS: 'code_blocks'>, <Capability.FILES: 'files'>, <Capability.IMAGES: 'images'>, <Capability.RICH_TEXT: 'rich_text'>, <Capability.USER_MENTIONS: 'user_mentions'>, <Capability.EDITING: 'editing'>, <Capability.FORWARDING: 'forwarding'>, <Capability.TABLES: 'tables'>, <Capability.HTML: 'html'>, <Capability.PLAINTEXT: 'plaintext'>, <Capability.FORMS: 'forms'>, <Capability.MESSAGE_SEARCH: 'message_search'>, <Capability.EMOJI_REACTIONS: 'emoji_reactions'>}), max_message_length=40000, max_attachment_size=26214400, max_attachments=10, max_embeds=10, max_reactions=20)¶
- field config: SymphonyConfig [Optional]¶
- property bot_user_id: str | None¶
Get the bot’s user ID as a string (cached from connect).
- property bot_user_name: str | None¶
Get the bot’s username (from config or cached from connect).
- normalize_channel_id(channel_id: str) str[source]¶
Canonicalize a Symphony stream id for equality comparison.
Symphony returns stream ids in both standard and URL-safe base64, with or without
=padding, depending on which API produced them (for example the datafeed vs. stream lookups). Decode whichever form was given and re-encode to standard padded base64 so the same stream compares equal regardless of source. Non-base64 values are returned unchanged.- Parameters:
channel_id – The stream id to canonicalize.
- Returns:
The canonical stream id.
- async connect() None[source]¶
Connect to Symphony using the BDK.
This initializes the Symphony BDK and authenticates the bot.
- Raises:
RuntimeError – If symphony-bdk is not installed or connection fails.
- async fetch_user(identifier: str | User | None = None, *, id: str | None = None, name: str | None = None, email: str | None = None, handle: str | None = None) User | None[source]¶
Fetch a user from Symphony.
Accepts flexible inputs: - User ID as positional arg or id= - User object (returns as-is or refreshes) - name= to search by display name - email= to search by email address - handle= to search by username
- Parameters:
identifier – A User object or user ID string.
id – User ID.
name – Display name to search for.
email – Email address to search for.
handle – Username to search for.
- Returns:
The user if found, None otherwise.
- async fetch_channel(identifier: str | Channel | None = None, *, id: str | None = None, name: str | None = None) Channel | None[source]¶
Fetch a channel (stream/room) from Symphony.
Accepts flexible inputs: - Stream ID as positional arg or id= - Channel object (returns as-is or refreshes) - name= to search by room name
- Parameters:
identifier – A Channel object or stream ID string.
id – Stream ID.
name – Room name to search for.
- Returns:
The channel if found, None otherwise.
- async fetch_channel_members(identifier: str | Channel | None = None, *, id: str | None = None, name: str | None = None) list[User][source]¶
Fetch members of a Symphony room.
- Parameters:
identifier – A Channel object or stream ID string.
id – Stream/room ID.
name – Room name (will be resolved via search).
- Returns:
List of users who are members of the room.
- async fetch_messages(channel: str | Channel, limit: int = 100, before: str | Message | datetime | None = None, after: str | Message | datetime | None = None) list[Message][source]¶
Fetch messages from a Symphony stream, newest-first.
Returns up to limit messages ordered newest-to-oldest.
afterandbeforebound the range and accept a millisecond-epoch id string, aMessage(itscreated_atis used), or adatetime. The stream is paged in full over the bounded range (Symphony’s API returns oldest-first from asincetimestamp; we widen/skip to cover everything) before trimming to the most recent limit.- Parameters:
channel – The stream to fetch from (ID string or Channel object).
limit – Maximum number of messages to return.
before – Upper bound — epoch-ms id, Message, or datetime.
after – Lower bound — epoch-ms id, Message, or datetime.
- Returns:
List of messages, ordered newest-to-oldest.
- async search_messages(query: str, channel: str | Channel | None = None, limit: int = 50, **kwargs: Any) list[Message][source]¶
Search for messages matching a query.
Uses Symphony’s message search API.
- Parameters:
query – The search query string.
channel – Optional stream to limit search to (ID string or Channel object).
limit – Maximum number of results.
**kwargs – Additional options: - from_user: Filter by sender user ID - hashtags: List of hashtags to filter by - cashtags: List of cashtags to filter by
- Returns:
List of messages matching the query.
- async send_message(channel: str | Channel, content: str, **kwargs: Any) Message[source]¶
Send a message to a Symphony stream.
- Parameters:
channel – The stream to send to (ID string or Channel object).
content – The message content (MessageML).
kwargs – Symphony template data and attachments; thread and reply options are ignored.
- Returns:
The sent message.
- async upload_file(channel: str | Channel, data: bytes, filename: str = 'file', content_type: str = '', title: str = '', content: str = '', **kwargs: Any) Message[source]¶
Upload a file to a Symphony stream.
Sends the file as an attachment via the Symphony BDK message API. The binary data is written to a temporary file which is passed to the BDK’s attachment parameter.
- async download_attachment(attachment: Any, *, message: Message | None = None) bytes[source]¶
Download a Symphony attachment’s bytes.
Symphony attachments have no public URL; they are fetched with the BDK
get_attachment(stream_id, message_id, attachment_id)call, which returns the content base64-encoded. The required stream and message IDs come from the attachmentmetadata(populated when the message was received) or from the suppliedmessage.
- async edit_message(message: str | Message, content: str, channel: str | Channel | None = None, **kwargs: Any) Message[source]¶
Edit a Symphony message.
Note: Symphony has limited support for message editing via the update_message API.
- Parameters:
message – The message to edit (ID string or Message object).
content – The new content (MessageML).
channel – The stream containing the message (required if message is a string).
**kwargs – Additional options.
- Returns:
The edited message.
- async delete_message(message: str | Message, channel: str | Channel | None = None) None[source]¶
Delete (suppress) a Symphony message.
- Parameters:
message – The message to delete (ID string or Message object).
channel – The stream containing the message (not used for Symphony).
- async forward_message(message: str | Message, to_channel: str | Channel, *, include_attribution: bool = True, prefix: str | None = None, **kwargs: Any) SymphonyMessage[source]¶
Forward a message to another Symphony room/stream.
Symphony doesn’t have native forwarding, so this creates a new message with the original content and optional attribution in MessageML format.
- Parameters:
message – The message to forward (SymphonyMessage object or message ID).
to_channel – The destination stream (ID string or Channel object).
include_attribution – If True, include info about original source.
prefix – Optional text to prepend to the forwarded message.
**kwargs – Additional options (data for entity data, etc.).
- Returns:
The forwarded message in the destination stream.
- async set_presence(status: str, status_text: str | None = None, **kwargs: Any) None[source]¶
Set user presence on Symphony.
- Parameters:
status – Presence status (available, busy, away, etc.).
status_text – Not supported by Symphony.
**kwargs – Additional options: - soft: If True, respect current activity state.
- async get_presence(user: str | User) Presence | None[source]¶
Get a user’s presence on Symphony.
- Parameters:
user – The user ID string or User object.
- Returns:
The user’s presence.
- async add_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Add a reaction to a message.
Note: Symphony doesn’t support reactions in the same way. This raises NotImplementedError.
- Parameters:
message – The message to react to (ID string or Message object).
emoji – The emoji.
channel – The stream containing the message (not used).
- Raises:
NotImplementedError – Symphony doesn’t support emoji reactions.
- async remove_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Remove a reaction from a message.
Note: Symphony doesn’t support reactions.
- Parameters:
message – The message to remove reaction from (ID string or Message object).
emoji – The emoji to remove.
channel – The stream containing the message (not used).
- Raises:
NotImplementedError – Symphony doesn’t support emoji reactions.
- mention_user(user: User) str[source]¶
Format a user mention for Symphony.
- Parameters:
user – The user to mention.
- Returns:
Symphony user mention format (<mention uid=”…”/>).
- mention_channel(channel: Channel) str[source]¶
Format a channel mention for Symphony.
Symphony doesn’t have channel mentions in the same way. Returns the channel name.
- Parameters:
channel – The channel to mention.
- Returns:
The channel name.
- mention_here() str[source]¶
Format an @here mention for Symphony.
Symphony doesn’t have an @here equivalent. Returns an empty string (no-op).
- Returns:
Empty string (Symphony doesn’t support @here).
- mention_everyone() str[source]¶
Format an @everyone mention for Symphony.
Uses Symphony’s mention all users tag.
- Returns:
Symphony MessageML mention all tag.
- mention_channel_all() str[source]¶
Format an @channel mention for Symphony.
Symphony uses the same tag for all broadcast mentions.
- Returns:
Symphony MessageML mention all tag.
- async create_dm(users: list[str | User]) str | None[source]¶
Create a direct message (IM) or multi-party IM.
- Parameters:
users – List of users to include in the DM (ID strings or User objects). The calling bot is implicitly included in the conversation.
- Returns:
The stream ID of the created DM.
- async create_im(users: list[str | User]) str | None[source]¶
Create an instant message (IM) or multi-party IM.
This is an alias for create_dm, using Symphony’s terminology.
- Parameters:
users – List of users to include in the IM (ID strings or User objects).
- Returns:
The stream ID of the created IM.
- async create_channel(name: str, description: str = '', public: bool = False, **kwargs: Any) str | None[source]¶
Create a room (chat room).
- Parameters:
name – The room name.
description – The room description.
public – Whether the room is public.
**kwargs – Additional options: - read_only: Whether the room is read-only.
- Returns:
The stream ID of the created room.
- async create_room(name: str, description: str = '', public: bool = False, **kwargs: Any) str | None[source]¶
Create a room (chat room).
This is an alias for create_channel, using Symphony’s terminology.
- Parameters:
name – The room name.
description – The room description.
public – Whether the room is public.
**kwargs – Additional options: - read_only: Whether the room is read-only.
- Returns:
The stream ID of the created room.
- async get_bot_info() User | None[source]¶
Get information about the connected bot user.
- Returns:
The bot’s User object.
- async stream_messages(channel: str | Channel | None = None, skip_own: bool = True, skip_history: bool = True) AsyncIterator[Message][source]¶
Stream incoming messages in real-time using Symphony datafeed.
This async generator yields Message objects as they arrive.
- Parameters:
channel – Optional stream to filter messages (ID string or Channel object).
skip_own – If True (default), skip messages sent by the bot itself.
skip_history – If True (default), skip messages that existed before the stream started. Only yields new messages.
- Yields:
Message – Each message as it arrives.
Mock Symphony backend for testing.
This module provides a mock implementation of the Symphony backend that doesn’t require actual Symphony servers.
- pydantic model chatom.symphony.testing.MockSymphonyBackend[source]¶
Bases:
BackendBaseMock Symphony backend for testing.
This provides a testing-friendly implementation that simulates Symphony operations without requiring actual servers.
- mock_users¶
Dictionary of mock users by ID.
- mock_streams¶
Dictionary of mock streams (channels) by ID.
- mock_messages¶
Dictionary of messages by stream ID.
- mock_presence¶
Dictionary of presence by user ID.
- sent_messages¶
List of sent messages for verification.
- edited_messages¶
List of edited message IDs.
- deleted_messages¶
List of deleted message IDs.
- presence_changes¶
List of presence changes for verification.
Example
>>> from chatom.symphony import MockSymphonyBackend, SymphonyConfig >>> backend = MockSymphonyBackend() >>> await backend.connect() >>> # Add mock data >>> backend.add_mock_user(123456789, "Test User", "testuser") >>> backend.add_mock_stream("stream123", "Test Room") >>> # Verify operations >>> await backend.send_message("stream123", "<messageML>Hello</messageML>") >>> assert len(backend.sent_messages) == 1
- name: ClassVar[str] = 'symphony'¶
- display_name: ClassVar[str] = 'Symphony (Mock)'¶
- field capabilities: BackendCapabilities | None = BackendCapabilities(capabilities=frozenset({<Capability.DELETING: 'deleting'>, <Capability.CODE_BLOCKS: 'code_blocks'>, <Capability.FILES: 'files'>, <Capability.IMAGES: 'images'>, <Capability.RICH_TEXT: 'rich_text'>, <Capability.USER_MENTIONS: 'user_mentions'>, <Capability.EDITING: 'editing'>, <Capability.FORWARDING: 'forwarding'>, <Capability.TABLES: 'tables'>, <Capability.HTML: 'html'>, <Capability.PLAINTEXT: 'plaintext'>, <Capability.FORMS: 'forms'>, <Capability.MESSAGE_SEARCH: 'message_search'>, <Capability.EMOJI_REACTIONS: 'emoji_reactions'>}), max_message_length=40000, max_attachment_size=26214400, max_attachments=10, max_embeds=10, max_reactions=20)¶
- field config: SymphonyConfig [Optional]¶
- field mock_users: dict[str, dict[str, Any]] [Optional]¶
- field mock_streams: dict[str, dict[str, Any]] [Optional]¶
- field mock_messages: dict[str, list[dict[str, Any]]] [Optional]¶
- field mock_presence: dict[str, SymphonyPresenceStatus] [Optional]¶
- field sent_messages: list[dict[str, Any]] [Optional]¶
- field edited_messages: list[dict[str, Any]] [Optional]¶
- field deleted_messages: list[str] [Optional]¶
- field presence_changes: list[dict[str, Any]] [Optional]¶
- field created_ims: list[list[int]] [Optional]¶
- field created_rooms: list[dict[str, Any]] [Optional]¶
- add_mock_user(user_id: int, display_name: str, username: str, email: str | None = None) None[source]¶
Add a mock user.
- Parameters:
user_id – The user’s Symphony ID.
display_name – The user’s display name.
username – The user’s username.
email – The user’s email address.
- add_mock_stream(stream_id: str, name: str, stream_type: str = 'ROOM') None[source]¶
Add a mock stream (channel).
- Parameters:
stream_id – The stream ID.
name – The stream name.
stream_type – The stream type (ROOM, IM, MIM).
- add_mock_message(stream_id: str, user_id: int, content: str, message_id: str | None = None, timestamp: datetime | None = None) str[source]¶
Add a mock message to a stream.
- Parameters:
stream_id – The stream ID.
user_id – The sender’s user ID.
content – The message content (MessageML).
message_id – Optional message ID. Generated if not provided.
timestamp – Optional timestamp. Uses current time if not provided.
- Returns:
The message ID.
- set_mock_presence(user_id: str, status: SymphonyPresenceStatus) None[source]¶
Set mock presence for a user.
- Parameters:
user_id – The user ID.
status – The presence status.
- async fetch_user(identifier: str | User | None = None, *, id: str | None = None, name: str | None = None, email: str | None = None, handle: str | None = None) User | None[source]¶
Fetch a mock user by ID or other attributes.
- Parameters:
identifier – A User object or user ID string.
id – User ID.
name – Display name to search for.
email – Email address to search for.
handle – Username to search for.
- Returns:
The user if found, None otherwise.
- async fetch_channel(identifier: str | Channel | None = None, *, id: str | None = None, name: str | None = None) Channel | None[source]¶
Fetch a mock channel (stream) by ID or name.
- Parameters:
identifier – A Channel object or stream ID string.
id – Stream ID.
name – Stream name to search for.
- Returns:
The channel if found, None otherwise.
- async fetch_messages(channel: str | Channel, limit: int = 100, before: str | Message | datetime | None = None, after: str | Message | datetime | None = None) list[Message][source]¶
Fetch messages from a mock stream.
- Parameters:
channel – The channel to fetch from (ID string or Channel object).
limit – Maximum number of messages.
before – Fetch messages before this timestamp (ms).
after – Fetch messages after this timestamp (ms).
- Returns:
List of messages.
- async send_message(channel: str | Channel, content: str, **kwargs: Any) Message[source]¶
Send a mock message.
- Parameters:
channel – The channel to send to (stream ID string or Channel object).
content – The message content (MessageML).
**kwargs – Additional options (data, attachments).
- Returns:
The sent message.
- async edit_message(message: str | Message, content: str, channel: str | Channel | None = None, **kwargs: Any) Message[source]¶
Edit a mock message.
- Parameters:
message – The message to edit (ID string or Message object).
content – The new content.
channel – The channel containing the message (required if message is a string).
**kwargs – Additional options.
- Returns:
The edited message.
- async delete_message(message: str | Message, channel: str | Channel | None = None) None[source]¶
Delete (suppress) a mock message.
- Parameters:
message – The message to delete (ID string or Message object).
channel – The channel containing the message (required if message is a string).
- async forward_message(message: str | Message, to_channel: str | Channel, *, include_attribution: bool = True, prefix: str | None = None, **kwargs: Any) SymphonyMessage[source]¶
Forward a mock message to another stream.
- Parameters:
message – The message to forward (SymphonyMessage object).
to_channel – The destination stream (ID string or Channel object).
include_attribution – If True, include info about original source.
prefix – Optional text to prepend to the forwarded message.
**kwargs – Additional options.
- Returns:
The forwarded message in the destination stream.
- async set_presence(status: str, status_text: str | None = None, **kwargs: Any) None[source]¶
Set mock presence.
- Parameters:
status – Presence status.
status_text – Not used in Symphony.
**kwargs – Additional options.
- async get_presence(user: str | User) Presence | None[source]¶
Get mock presence for a user.
- Parameters:
user – The user to get presence for (ID string or User object).
- Returns:
The user’s presence.
- async add_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Add a reaction.
Symphony doesn’t support reactions.
- Raises:
NotImplementedError – Symphony doesn’t support reactions.
- async remove_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Remove a reaction.
Symphony doesn’t support reactions.
- Raises:
NotImplementedError – Symphony doesn’t support reactions.
- mention_user(user: User) str[source]¶
Format a user mention.
- Parameters:
user – The user to mention.
- Returns:
Symphony mention format.
- mention_channel(channel: Channel) str[source]¶
Format a channel mention.
- Parameters:
channel – The channel to mention.
- Returns:
The channel name.
- async create_dm(users: list[str | User]) str | None[source]¶
Create a mock DM/IM.
- Parameters:
users – List of users to include (ID strings or User objects).
- Returns:
The stream ID.
- async create_im(users: list[str | User]) str | None[source]¶
Create a mock IM.
This is an alias for create_dm.
- Parameters:
users – List of users to include (ID strings or User objects).
- Returns:
The stream ID.
- async create_channel(name: str, description: str = '', public: bool = False, **kwargs: Any) str | None[source]¶
Create a mock channel/room.
- Parameters:
name – The room name.
description – The room description.
public – Whether the room is public.
**kwargs – Additional options: - read_only: Whether the room is read-only.
- Returns:
The stream ID.
- async create_room(name: str, description: str = '', public: bool = False, **kwargs: Any) str | None[source]¶
Create a mock room.
This is an alias for create_channel.
- Parameters:
name – The room name.
description – The room description.
public – Whether the room is public.
**kwargs – Additional options.
- Returns:
The stream ID.
Telegram¶
Telegram-specific configuration.
This module provides the Telegram-specific configuration class.
- pydantic model chatom.telegram.config.TelegramConfig[source]¶
Bases:
BackendConfigConfiguration for the Telegram backend.
- bot_token¶
The Telegram Bot API token (from @BotFather).
- api_url¶
Custom Telegram Bot API URL (for local API servers).
- timeout¶
HTTP request timeout in seconds.
- connect_timeout¶
Connection timeout in seconds.
- read_timeout¶
Read timeout in seconds.
- write_timeout¶
Write timeout in seconds.
- pool_timeout¶
Connection pool timeout in seconds.
- field bot_token: SecretStr = SecretStr('')¶
Telegram Bot API token from @BotFather.
- field connect_timeout: float = 5.0¶
Connection timeout in seconds.
- field read_timeout: float = 5.0¶
Read timeout in seconds.
- field write_timeout: float = 5.0¶
Write timeout in seconds.
- field pool_timeout: float = 1.0¶
Connection pool timeout in seconds.
- property bot_token_str: str¶
Get the bot token as a plain string.
- property has_token: bool¶
Check if a bot token is configured.
Telegram-specific User model.
This module provides the Telegram-specific User class.
- pydantic model chatom.telegram.user.TelegramUser[source]¶
Bases:
UserTelegram-specific user with additional Telegram fields.
- first_name¶
User’s first name.
- last_name¶
User’s last name.
- username¶
User’s Telegram username (without @).
- language_code¶
IETF language tag of the user’s language.
Whether the user has Telegram Premium.
Whether the user added the bot to attachment menu.
- field first_name: str = ''¶
User’s first name.
- field last_name: str = ''¶
User’s last name.
- field username: str = ''¶
User’s Telegram username (without @).
- field language_code: str = ''¶
IETF language tag of the user’s language.
- field is_premium: bool = False¶
Whether the user has Telegram Premium.
- field added_to_attachment_menu: bool = False¶
Whether the user added the bot to attachment menu.
- property full_name: str¶
Get the user’s full name.
- classmethod from_telegram_user(user: Any) TelegramUser[source]¶
Create a TelegramUser from a python-telegram-bot User object.
- Parameters:
user – A telegram.User object.
- Returns:
A TelegramUser instance.
Telegram-specific Channel model.
This module provides the Telegram-specific Channel class.
- pydantic model chatom.telegram.channel.TelegramChannel[source]¶
Bases:
ChannelTelegram-specific channel (chat) with additional Telegram fields.
In Telegram, “channels” are called “chats” and can be private (1:1), groups, supergroups, or broadcast channels.
- chat_type¶
Telegram chat type.
- description¶
Chat description/bio.
- invite_link¶
Primary invite link for the chat.
- has_protected_content¶
Whether messages are protected from forwarding.
- is_forum¶
Whether this supergroup has forum topics enabled.
- chat_photo_url¶
URL of the chat’s photo if available.
- field chat_type: TelegramChatType = TelegramChatType.PRIVATE¶
Telegram chat type.
- field description: str = ''¶
Chat description/bio.
- field invite_link: str = ''¶
Primary invite link for the chat.
- field has_protected_content: bool = False¶
Whether messages are protected from forwarding.
- field is_forum: bool = False¶
Whether this supergroup has forum topics enabled.
- field chat_photo_url: str = ''¶
URL of the chat’s photo if available.
- field username: str = ''¶
Public @username of the chat (without @), if set.
- property is_group_chat: bool¶
Check if this is a group or supergroup chat.
- property is_broadcast_channel: bool¶
Check if this is a broadcast channel.
- classmethod from_telegram_chat(chat: Any) TelegramChannel[source]¶
Create a TelegramChannel from a python-telegram-bot Chat object.
- Parameters:
chat – A telegram.Chat object.
- Returns:
A TelegramChannel instance.
- class chatom.telegram.channel.TelegramChatType(value)[source]¶
Bases:
str,EnumTelegram chat types.
Telegram-specific Message model.
This module provides the Telegram-specific Message class.
- pydantic model chatom.telegram.message.TelegramMessage[source]¶
Bases:
MessageTelegram-specific message with additional Telegram fields.
- message_id¶
Telegram’s integer message ID within the chat.
- chat_id¶
The chat ID this message belongs to.
- message_thread_id¶
Thread (topic) ID in a forum supergroup.
- reply_to_message_id¶
ID of the message being replied to.
- forward_origin¶
Information about the original forwarded message.
- entities¶
List of special entities (mentions, URLs, etc.) from the API.
- has_protected_content¶
Whether the message is protected from forwarding.
- field message_id: int = 0¶
Telegram’s integer message ID within the chat.
- field chat_id: str = ''¶
The chat ID this message belongs to.
- field message_thread_id: int | None = None¶
Thread (topic) ID in a forum supergroup.
- field reply_to_message_id: int | None = None¶
ID of the message being replied to.
- field forward_origin: dict[str, Any] | None = None¶
Information about the original forwarded message.
- field entities: list[dict[str, Any]] [Optional]¶
List of message entities from the API.
- field has_protected_content: bool = False¶
Whether the message is protected from forwarding.
- to_formatted() FormattedMessage[source]¶
Convert this Telegram message to a FormattedMessage.
- Returns:
The formatted message representation.
- Return type:
- classmethod from_formatted(formatted: FormattedMessage, backend: str = '', **kwargs: Any) TelegramMessage[source]¶
Create a TelegramMessage from a FormattedMessage.
- Parameters:
formatted – The FormattedMessage to convert.
backend – Target backend (ignored, always uses HTML format).
**kwargs – Additional message attributes.
- Returns:
A new TelegramMessage instance.
- Return type:
- classmethod from_api_response(data: dict[str, Any]) TelegramMessage[source]¶
Create a TelegramMessage from a Telegram API response dict.
- Parameters:
data – The API response data (message dict).
- Returns:
A TelegramMessage instance.
- classmethod from_telegram_message(msg: Any) TelegramMessage[source]¶
Create a TelegramMessage from a python-telegram-bot Message object.
- Parameters:
msg – A telegram.Message object.
- Returns:
A TelegramMessage instance.
Telegram-specific Presence model.
This module provides the Telegram-specific Presence class.
Note: Telegram has very limited presence support. Bots cannot see user online/offline status. Only “last seen” approximations are available for some users, and even that is privacy-controlled.
- pydantic model chatom.telegram.presence.TelegramPresence[source]¶
Bases:
PresenceTelegram-specific presence.
Telegram provides limited presence information. Bots can only see a user’s status if the user has not restricted that in privacy settings.
- last_seen_approximate¶
Approximate last seen description (e.g. “recently”, “within a week”, “within a month”, “long time ago”).
- field last_seen_approximate: str = ''¶
Approximate last seen description.
Telegram-specific mention utilities.
This module registers Telegram-specific mention formatting. Telegram uses HTML-style mentions: <a href=”tg://user?id=123”>Name</a> or @username for public usernames.
- chatom.telegram.mention.mention_channel(channel: Channel) str[source]¶
- chatom.telegram.mention.mention_channel(channel: DiscordChannel) str
- chatom.telegram.mention.mention_channel(channel: SlackChannel) str
- chatom.telegram.mention.mention_channel(channel: TelegramChannel) str
Generate a mention string for a channel.
This is a single-dispatch function that can be overridden for platform-specific channel types.
- Parameters:
channel – The channel to mention.
- Returns:
The formatted channel mention string.
- Return type:
str
Example
>>> from chatom import Channel, mention_channel >>> channel = Channel(name="general", id="456") >>> mention_channel(channel) '#general'
- chatom.telegram.mention.mention_user(user: User) str[source]¶
- chatom.telegram.mention.mention_user(user: DiscordUser) str
- chatom.telegram.mention.mention_user(user: SlackUser) str
- chatom.telegram.mention.mention_user(user: SymphonyUser) str
- chatom.telegram.mention.mention_user(user: TelegramUser) str
Generate a mention string for a user.
This is a single-dispatch function that can be overridden for platform-specific user types.
- Parameters:
user – The user to mention.
- Returns:
The formatted mention string.
- Return type:
str
Example
>>> from chatom import User, mention_user >>> user = User(name="John", id="123") >>> mention_user(user) 'John'
Telegram backend implementation for chatom.
- pydantic model chatom.telegram.backend.TelegramBackend[source]¶
Bases:
BackendBaseTelegram backend implementation using python-telegram-bot.
Uses the Telegram Bot API via python-telegram-bot library for all API interactions. Supports sending/receiving messages, reactions, file uploads, and real-time message streaming via polling.
- name¶
The backend identifier (‘telegram’).
- display_name¶
Human-readable name.
- format¶
Telegram uses the Bot API HTML subset for rich text.
- capabilities¶
Telegram-specific capabilities.
- config¶
Telegram-specific configuration.
Example
>>> config = TelegramConfig(bot_token="123456:ABC-DEF...") >>> backend = TelegramBackend(config=config) >>> await backend.connect() >>> msg = await backend.send_message("-100123456789", "Hello!")
- name: ClassVar[str] = 'telegram'¶
- display_name: ClassVar[str] = 'Telegram'¶
- user_class¶
alias of
TelegramUser
- channel_class¶
alias of
TelegramChannel
- presence_class¶
alias of
TelegramPresence
- field capabilities: BackendCapabilities | None = BackendCapabilities(capabilities=frozenset({<Capability.VIDEOS: 'videos'>, <Capability.AUDIO: 'audio'>, <Capability.CODE_BLOCKS: 'code_blocks'>, <Capability.FILES: 'files'>, <Capability.IMAGES: 'images'>, <Capability.USER_MENTIONS: 'user_mentions'>, <Capability.MARKDOWN: 'markdown'>, <Capability.PLAINTEXT: 'plaintext'>, <Capability.HTML: 'html'>, <Capability.REPLIES: 'replies'>, <Capability.EMOJI_REACTIONS: 'emoji_reactions'>}), max_message_length=4000, max_attachment_size=26214400, max_attachments=10, max_embeds=10, max_reactions=20)¶
- field config: TelegramConfig [Optional]¶
- property bot_user_id: str | None¶
Get the bot’s user ID.
- property bot_user_name: str | None¶
Get the bot’s username.
- async connect() None[source]¶
Connect to Telegram by initializing the Bot and verifying credentials.
- Raises:
ImportError – If python-telegram-bot is not installed.
RuntimeError – If the token is missing or invalid.
- async fetch_user(identifier: str | User | None = None, *, id: str | None = None, name: str | None = None, email: str | None = None, handle: str | None = None) User | None[source]¶
Fetch a user from Telegram.
Note: Telegram Bot API does not support arbitrary user lookup. Users can only be fetched if the bot has interacted with them via getChatMember in a known chat. ID-based lookup checks the cache first. name/handle lookup is cache-only.
- Parameters:
identifier – A TelegramUser object or user ID string.
id – User ID.
name – Display name to search for (cache only).
email – Email (not supported by Telegram).
handle – Username to search for (cache only).
- Returns:
The user if found, None otherwise.
- async fetch_channel(identifier: str | Channel | None = None, *, id: str | None = None, name: str | None = None) Channel | None[source]¶
Fetch a channel (chat) from Telegram.
Uses the getChat API to fetch chat information by ID. Name-based lookup checks cache only.
- Parameters:
identifier – A TelegramChannel object or chat ID string.
id – Chat ID.
name – Chat name to search for (cache only).
- Returns:
The channel if found, None otherwise.
- async fetch_messages(channel: str | Channel, limit: int = 100, before: str | Message | datetime | None = None, after: str | Message | datetime | None = None) list[Message][source]¶
Fetch messages from a Telegram chat.
Note: The Telegram Bot API does not support fetching message history. Bots can only receive messages in real-time via updates/webhooks. This method returns an empty list as message history is not available.
- Parameters:
channel – The channel to fetch messages from.
limit – Maximum number of messages.
before – Fetch messages before this message.
after – Fetch messages after this message.
- Returns:
Empty list (Telegram Bot API limitation).
- async send_message(channel: str | Channel, content: str, **kwargs: Any) TelegramMessage[source]¶
Send a message to a Telegram chat.
Uses the sendMessage API. Supports HTML parse mode by default.
- Parameters:
channel – The chat to send to (ID string or Channel object).
content – The message content (HTML formatted). kwargs: Telegram thread, reply, parse mode, notification, and content-protection options.
- Returns:
The sent message.
- async upload_file(channel: str | Channel, data: bytes, filename: str = 'file', content_type: str = '', title: str = '', content: str = '', **kwargs: Any) Message[source]¶
Upload a file to a Telegram chat.
Uses
send_photofor image MIME types andsend_documentfor everything else.
- async download_attachment(attachment: Any, *, message: Message | None = None) bytes[source]¶
Download an attachment’s bytes from Telegram.
Telegram media is referenced by
file_id(stored as the attachmentid), which is resolved to a temporary download viagetFile.
- async edit_message(message: str | Message, content: str, channel: str | Channel | None = None, **kwargs: Any) TelegramMessage[source]¶
Edit a Telegram message.
Uses the editMessageText API.
- Parameters:
message – The message to edit (ID string or TelegramMessage).
content – The new content.
channel – The chat containing the message (required if message is str).
**kwargs – Additional options.
- Returns:
The edited message.
- async delete_message(message: str | Message, channel: str | Channel | None = None) None[source]¶
Delete a Telegram message.
Uses the deleteMessage API.
- Parameters:
message – The message to delete (ID string or TelegramMessage).
channel – The chat containing the message (required if message is str).
- async forward_message(message: str | Message, to_channel: str | Channel, *, include_attribution: bool = True, prefix: str | None = None, **kwargs: Any) TelegramMessage[source]¶
Forward a message to another Telegram chat.
Telegram has native forward support via the forwardMessage API. If include_attribution is False and source info is available, uses native forwarding. Otherwise sends a new message with attribution.
- Parameters:
message – The message to forward (TelegramMessage object).
to_channel – The destination chat.
include_attribution – If True, include info about original source.
prefix – Optional text to prepend.
**kwargs – Additional options.
- Returns:
The forwarded message.
- async add_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Add a reaction to a message.
Uses the setMessageReaction API (Telegram Bot API 7.0+).
- Parameters:
message – The message to react to.
emoji – The emoji to react with (Unicode emoji).
channel – The chat containing the message.
- async remove_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Remove a reaction from a message.
Telegram’s API sets the full reaction list, so removing means setting an empty list.
- Parameters:
message – The message to remove reaction from.
emoji – The emoji to remove (unused - clears all bot reactions).
channel – The chat containing the message.
- mention_user(user: User) str[source]¶
Format a user mention for Telegram.
- Parameters:
user – The user to mention.
- Returns:
Telegram user mention string.
- mention_channel(channel: Channel) str[source]¶
Format a channel mention for Telegram.
- Parameters:
channel – The channel to mention.
- Returns:
Telegram channel mention string.
- async get_bot_info() User | None[source]¶
Get information about the connected bot.
- Returns:
The bot’s User object.
- async set_presence(status: str, status_text: str | None = None, **kwargs: Any) None[source]¶
Set bot presence.
Note: Telegram bots don’t have traditional presence/status. This is a no-op for API compatibility.
- Parameters:
status – Status string (ignored).
status_text – Status text (ignored).
- async get_presence(user: str | User) Presence | None[source]¶
Get a user’s presence.
Note: Telegram bots have very limited access to user presence. Returns None as presence is not reliably available.
- Parameters:
user – The user to check.
- Returns:
None (Telegram limitation).
- async create_dm(users: list[str | User]) str | None[source]¶
Create a DM with a user.
In Telegram, DMs are just private chats identified by the user’s ID. The bot must have been contacted by the user first.
- Parameters:
users – List of users (only first is used for 1:1 DM).
- Returns:
The chat ID (same as user ID for private chats).
- async discover_chats(timeout: float = 5.0) list[TelegramChannel][source]¶
Discover chats by consuming recent getUpdates.
Useful for finding chat IDs / usernames when you know the bot has received messages in specific groups or channels.
- Parameters:
timeout – Seconds to wait for updates (default 5).
- Returns:
List of unique TelegramChannel objects found.
- async stream_messages(channel: str | Channel | None = None, skip_own: bool = True, skip_history: bool = True) AsyncIterator[TelegramMessage][source]¶
Stream incoming messages in real-time using polling.
Uses Telegram’s getUpdates long-polling to receive messages.
- Parameters:
channel – Optional chat to filter messages by.
skip_own – If True, skip messages sent by the bot itself.
skip_history – If True, skip old messages.
- Yields:
TelegramMessage – Each message as it arrives.
Mock Telegram backend for testing.
This module provides a mock implementation of the Telegram backend for use in testing without requiring an actual Telegram connection.
- pydantic model chatom.telegram.testing.MockTelegramBackend[source]¶
Bases:
TelegramBackendMock Telegram backend for testing.
Stores all data in memory and provides methods to set up mock data for tests.
Example
>>> backend = MockTelegramBackend() >>> backend.add_mock_user("123", "Alice", "alice") >>> backend.add_mock_channel("-100456", "general") >>> await backend.connect() >>> user = await backend.fetch_user("123") >>> assert user.name == "Alice"
- add_mock_user(id: str, name: str, handle: str = '', *, first_name: str = '', last_name: str = '', username: str = '', is_bot: bool = False, is_premium: bool = False, language_code: str = '') TelegramUser[source]¶
Add a mock user for testing.
- Parameters:
id – The user ID.
name – The user’s display name.
handle – The username (without @).
first_name – First name.
last_name – Last name.
username – Telegram username (defaults to handle).
is_bot – Whether the user is a bot.
is_premium – Whether the user has Telegram Premium.
language_code – User’s language code.
- Returns:
The created mock user.
- add_mock_channel(id: str, name: str, channel_type: str = 'supergroup', *, topic: str = '', description: str = '', chat_type: TelegramChatType | None = None, is_forum: bool = False) TelegramChannel[source]¶
Add a mock channel for testing.
- Parameters:
id – The chat ID.
name – The chat name/title.
channel_type – Chat type string (“private”, “group”, “supergroup”, “channel”).
topic – The chat topic.
description – The chat description.
chat_type – TelegramChatType enum (overrides channel_type).
is_forum – Whether the chat is a forum supergroup.
- Returns:
The created mock channel.
- add_mock_message(channel_id: str, user_id: str, content: str, *, message_id: str | None = None, timestamp: datetime | None = None, edited: bool = False) str[source]¶
Add a mock message for testing.
- Parameters:
channel_id – The chat containing the message.
user_id – The author’s user ID.
content – The message content.
message_id – Optional message ID (auto-generated if not provided).
timestamp – Message timestamp.
edited – Whether the message was edited.
- Returns:
The message ID.
- set_mock_presence(user_id: str, status: PresenceStatus = PresenceStatus.ONLINE, *, last_seen_approximate: str = '') TelegramPresence[source]¶
Set mock presence for a user.
- Parameters:
user_id – The user ID.
status – The presence status.
last_seen_approximate – Approximate last seen description.
- Returns:
The created mock presence.
- property sent_messages: list[TelegramMessage]¶
Get all messages sent through this backend.
- property edited_messages: list[TelegramMessage]¶
Get all messages edited through this backend.
- property deleted_messages: list[dict[str, str]]¶
Get all message IDs deleted through this backend.
- get_sent_messages() list[TelegramMessage][source]¶
Get all messages sent through this backend (copy).
- get_edited_messages() list[TelegramMessage][source]¶
Get all messages edited through this backend (copy).
- get_deleted_messages() list[dict[str, str]][source]¶
Get all messages deleted through this backend (copy).
- get_reactions() list[dict[str, str]][source]¶
Get all reactions added/removed through this backend (copy).
- property created_dms: list[list[str]]¶
Get all DMs created through this backend.
- async fetch_user(identifier: str | User | None = None, *, id: str | None = None, name: str | None = None, email: str | None = None, handle: str | None = None) User | None[source]¶
Fetch a mock user.
- async fetch_channel(identifier: str | Channel | None = None, *, id: str | None = None, name: str | None = None) Channel | None[source]¶
Fetch a mock channel.
- async fetch_messages(channel: str | Channel, limit: int = 100, before: str | Message | datetime | None = None, after: str | Message | datetime | None = None) list[Message][source]¶
Fetch mock messages from a channel.
- async send_message(channel: str | Channel, content: str, **kwargs: Any) TelegramMessage[source]¶
Send a mock message.
- async edit_message(message: str | Message, content: str, channel: str | Channel | None = None, **kwargs: Any) TelegramMessage[source]¶
Edit a mock message.
- async delete_message(message: str | Message, channel: str | Channel | None = None) None[source]¶
Delete a mock message.
- async forward_message(message: str | Message, to_channel: str | Channel, *, include_attribution: bool = True, prefix: str | None = None, **kwargs: Any) TelegramMessage[source]¶
Forward a mock message.
- async set_presence(status: str, status_text: str | None = None, **kwargs: Any) None[source]¶
Set mock presence.
- async add_reaction(message: str | Message, emoji: str, channel: str | Channel | None = None) None[source]¶
Add a mock reaction.