Message Models¶
Classes for representing messages and message-related events.
Overview¶
Message models represent the core communication data in fbchat-muqit. Messages can contain text, mentions, attachments, reactions, and can be replies to other messages.
from fbchat_muqit import Client, Message, MessageType
async with Client(cookies_file_path="cookies.json") as client:
# Fetch messages
messages = await client.fetch_thread_messages(
thread_id="123456789",
message_limit=10
)
for message in messages:
print(f"{message.sender_id}: {message.text}")
if message.attachments:
print(f" Has {len(message.attachments)} attachments")
Message Classes¶
Message¶
- class fbchat_muqit.Message¶
Bases:
StructRepresents a facebook messenger message
- attachments: List[ImageAttachment | VideoAttachment | GifAttachment | StickerAttachment | FileAttachment | AudioAttachment | PostAttachment | SharedAttachment | ReelAttachment | ProfileAttachment | ExternalAttachment | None] | None¶
List of attachments data that were sent such as Image, Video, Shared Facebook Post/ youtube videos etc.
- can_unsend: bool¶
Wether the the message can be unsent by client
- id: str¶
Id of the message
- message_type: MessageType¶
Type of message (Video, Image, Text, e.g.)
- reaction: List[MessageReaction] | None¶
Id of the reactors
- replied_to_message_id: str | None¶
- sender_id: str¶
The message sender’s User id
- text: str¶
The text of the message
- thread_folder: ThreadFolder¶
The Thread location INBOX, ARCHIVE etc.
- thread_id: str¶
The thread message was sent to.
- thread_participants: tuple[int] | None¶
Users in the thread message was sent.
- thread_type: ThreadType¶
Type of the thread thread message was sent (User, Group, Page e.g.)
- timestamp: int¶
The timestamp message was sent.
- unsent: bool¶
wether the message is unsent for everyone
Message Types¶
- class fbchat_muqit.MessageType¶
Bases:
EnumTypes of messages that can be received.
- ADMIN_TEXT = 'admin_text'¶
- AUDIO = 'audio'¶
- EMOJI = 'emoji'¶
- EXTERNAL_URL = 'external_url'¶
- FACEBOOK_GAME = 'game'¶
- FACEBOOK_POST = 'post'¶
- FACEBOOK_PRODUCT = 'product'¶
- FACEBOOK_PROFILE = 'profile'¶
- FACEBOOK_REEL = 'reel'¶
- FACEBOOK_STORY = 'story'¶
- FILE = 'file'¶
- GIF = 'animated_image'¶
- IMAGE = 'image'¶
- LOCATION = 'location'¶
- MESSAGE_PINNED = 'message_pinned'¶
- MESSAGE_REACTION = 'message_reaction'¶
- MESSAGE_REPLY = 'message_reply'¶
- MESSAGE_UNSENT = 'message_unsent'¶
- POLL_CREATED = 'poll_created'¶
- POLL_VOTED = 'poll_voted'¶
- STICKER = 'sticker'¶
- TEXT = 'text'¶
- VIDEO = 'video'¶
Emoji Size¶
Mentions¶
Mention¶
Mentions¶
Message Events¶
Message Reaction¶
- class fbchat_muqit.MessageReaction¶
Bases:
StructRepresents A Reaction Message
- id: str¶
The message Id
- reacted_message_sender: int¶
The Author of the message User reactor to.
- reaction: str | None¶
The Reaction Emoji
- reactor: int¶
The User who reacted to the Message
- thread_id: Value¶
The Thread Id of the message.
- timestamp: int | None¶
The timestamp of the Stamp
Message Remove¶
Message Unsend¶
Reaction Enum¶
Usage Examples¶
Sending Messages with Mentions¶
from fbchat_muqit import Client, Mention
async with Client(cookies_file_path="cookies.json") as client:
# Method 1: Manual mention with offset and length
text = "Hey @John, check this out!"
mention = Mention(
user_id="100001234567890",
offset=4, # Position where "@John" starts
length=5 # Length of "@John"
)
await client.send_message(
text=text,
thread_id="123456789",
mentions=[mention]
)
# Method 2: Using Mentions.from_text (automatically finds positions)
from fbchat_muqit import Mentions
text = "Hello Alice and Bob!"
mentions = Mentions.from_text(
text=text,
users=[
("100001111111111", "Alice"),
("100002222222222", "Bob")
]
)
await client.send_message(
text=text,
thread_id="123456789",
mentions=mentions.users
)
Working with Message Types¶
from fbchat_muqit import Message, MessageType
from fbchat_muqit import ImageAttachment, VideoAttachment, StickerAttachment
async def handle_message(message: Message):
"""Handle different types of messages."""
# Check message type
if message.message_type == MessageType.TEXT:
print(f"📝 Text: {message.text}")
elif message.message_type == MessageType.IMAGE:
print(f"📷 Image message")
for attachment in message.attachments:
if isinstance(attachment, ImageAttachment):
print(f" URL: {attachment.preview.url}")
elif message.message_type == MessageType.VIDEO:
print(f"🎥 Video message")
for attachment in message.attachments:
if isinstance(attachment, VideoAttachment):
print(f" Duration: {attachment.playable_duration}ms")
elif message.message_type == MessageType.STICKER:
print(f"😊 Sticker message")
for attachment in message.attachments:
if isinstance(attachment, StickerAttachment):
print(f" Label: {attachment.label}")
elif message.message_type == MessageType.EMOJI:
print(f"😀 Emoji: {message.text}")
# Check for mentions
if message.mentions:
mentioned_users = [m.user_id for m in message.mentions]
print(f"👥 Mentions: {mentioned_users}")
# Check for reactions
if message.reaction:
print(f"❤️ Reactions: {len(message.reaction)}")
# Check if it's a reply
if message.replied_to_message_id:
print(f"↩️ Reply to: {message.replied_to_message_id}")
Handling Message Reactions¶
from fbchat_muqit import Client, EventType
from fbchat_muqit import MessageReaction, Reaction
client = Client(cookies_file_path="cookies.json")
@client.event(EventType.MESSAGE_REACTION)
async def on_reaction(event: MessageReaction):
"""Handle message reactions."""
message_id = event.id
thread_id = event.thread_id.threadFbId
reactor_id = event.reactor
reaction = event.reaction
if event.reaction_type == Reaction.ADDED:
print(f"➕ User {reactor_id} reacted {reaction} to message {message_id}")
# Fetch user info
users = await client.fetch_user_info(str(reactor_id))
if str(reactor_id) in users:
user_name = users[str(reactor_id)].name
print(f" Reactor: {user_name}")
# Auto-react back
await client.react(
reaction="❤️",
message_id=message_id,
thread_id=thread_id
)
elif event.reaction_type == Reaction.REMOVED:
print(f"➖ User {reactor_id} removed {reaction} from message {message_id}")
Handling Message Unsend¶
from fbchat_muqit import MessageUnsend
@client.event(EventType.MESSAGE_UNSENT)
async def on_message_unsent(event: MessageUnsend):
"""Handle when someone unsends a message."""
message_id = event.id
sender_id = event.sender_id
thread_id = event.thread_id.threadFbId
print(f"🗑️ Message {message_id} was unsent by {sender_id}")
# Fetch sender info
users = await client.fetch_user_info(str(sender_id))
if str(sender_id) in users:
sender_name = users[str(sender_id)].name
print(f" Sender: {sender_name}")
# Log for moderation purposes
await log_unsent_message(message_id, sender_id, thread_id)
Building a Message Logger¶
from fbchat_muqit import Client, EventType, Message
from datetime import datetime
import json
class MessageLogger:
"""Log all messages to a file."""
def __init__(self, client: Client, log_file: str = "messages.json"):
self.client = client
self.log_file = log_file
self.messages = []
# Register event handler
self.client.event(EventType.MESSAGE)(self.on_message)
async def on_message(self, message: Message):
"""Log incoming messages."""
log_entry = {
'message_id': message.id,
'thread_id': message.thread_id,
'sender_id': message.sender_id,
'text': message.text,
'timestamp': message.timestamp,
'message_type': message.message_type.value,
'has_attachments': bool(message.attachments),
'attachment_count': len(message.attachments) if message.attachments else 0,
'has_mentions': bool(message.mentions),
'mention_count': len(message.mentions) if message.mentions else 0,
'reaction_count': len(message.reaction) if message.reaction else 0,
'is_reply': bool(message.replied_to_message_id),
'logged_at': datetime.now().isoformat()
}
# Fetch sender name
users = await self.client.fetch_user_info(message.sender_id)
if message.sender_id in users:
log_entry['sender_name'] = users[message.sender_id].name
self.messages.append(log_entry)
# Print summary
sender = log_entry.get('sender_name', message.sender_id)
print(f"📝 [{sender}]: {message.text[:50]}")
# Save periodically
if len(self.messages) % 10 == 0:
await self.save_logs()
async def save_logs(self):
"""Save logs to file."""
with open(self.log_file, 'w') as f:
json.dump(self.messages, f, indent=2)
print(f"💾 Saved {len(self.messages)} messages to {self.log_file}")
# Usage
async with Client(cookies_file_path="cookies.json") as client:
logger = MessageLogger(client)
await client.listen()
Advanced: Auto-Reply Bot¶
from fbchat_muqit import Client, EventType, Message
import re
class AutoReplyBot:
"""Auto-reply bot with keyword detection."""
def __init__(self, client: Client):
self.client = client
self.keywords = {
r'\b(hello|hi|hey)\b': "Hello! How can I help you?",
r'\b(help|support)\b': "For support, please visit our help center.",
r'\b(thanks|thank you)\b': "You're welcome! 😊",
r'\b(bye|goodbye)\b': "Goodbye! Have a great day!"
}
self.client.event(EventType.MESSAGE)(self.on_message)
async def on_message(self, message: Message):
"""Auto-reply to messages with keywords."""
# Skip own messages
if message.sender_id == self.client.uid:
return
text = message.text.lower()
# Check for keywords
for pattern, reply in self.keywords.items():
if re.search(pattern, text, re.IGNORECASE):
# Send auto-reply
await self.client.send_message(
text=reply,
thread_id=message.thread_id
)
print(f"🤖 Auto-replied to {message.sender_id}")
break
# Usage
async with Client(cookies_file_path="cookies.json") as client:
bot = AutoReplyBot(client)
await client.listen()
Working with Message Chains¶
from fbchat_muqit import Message
async def get_conversation_thread(
client: Client,
message: Message,
max_depth: int = 10
) -> list[Message]:
"""Get the full conversation thread for a message."""
thread = [message]
current = message
depth = 0
# Follow reply chain backwards
while current.replied_to_message_id and depth < max_depth:
replied_msg = await client.fetch_message_info(
current.replied_to_message_id,
current.thread_id
)
if replied_msg:
thread.insert(0, replied_msg)
current = replied_msg
depth += 1
else:
break
return thread
# Usage
message = await client.fetch_message_info(msg_id, thread_id)
conversation = await get_conversation_thread(client, message)
print("Conversation thread:")
for i, msg in enumerate(conversation, 1):
print(f"{i}. {msg.sender_id}: {msg.text}")
See Also¶
Attachment Models - Attachment models
Thread Models - Thread models
Timestamp Events - Timestamp events
Client - Client methods for sending messages
/guides/sending-messages - Guide on sending messages