Telegram allows commenting on a channel post or on a generic supergroup message, thanks to message threads.
Schema:
messageReplyHeader#a6d57763 flags:# reply_to_msg_id:int reply_to_peer_id:flags.0?Peer reply_to_top_id:flags.1?int = MessageReplyHeader;
messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector<Peer> channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;
message#85d6cbe2 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
---functions---
messages.search#a0fda762 flags:# peer:InputPeer q:string from_id:flags.0?InputPeer top_msg_id:flags.1?int filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
Threads are usually automatically created when replying to any message in a group.
For example, all replies to a message with ID 420
are associated to thread with ID 420
, unique to this group; this thread ID is contained in the reply_to_top_id
field of reply_to
messageReplyHeader, along with an eventual reply_to_msg_id
, for replies to messages within a thread.
Replies to messages in a thread are part of the same thread, and do not spawn new threads.
When receiving a message from a group that is also the top of a thread (the message with ID 420
), the replies
optional field will contain a messageReplies constructor, containing the message ID and PTS of the latest reply in the thread, and the message ID of the latest read thread reply, along with the total number of replies in the thread.
Replies to a thread can also be manually fetched using messages.search, providing to top_msg_id
the thread ID.
messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector<Peer> channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;
The same messageReplies constructor seen above will also be contained in channel posts, this time containing information about the comment section of a specific channel post.
The comment section of a channel post is simply the message thread of the automatically forwarded channel message in the linked discussion supergroup; the ID of the linked discussion supergroup will be contained in the messageReplies.channel_id
field.
For channel posts, the recent_repliers
field will also contain information about the last few comment posters for a specific thread, to show a small list of commenter profile pictures in client previews.
messageFwdHeader#5f777dce flags:# imported:flags.7?true from_id:flags.0?Peer from_name:flags.5?string date:int channel_post:flags.2?int post_author:flags.3?string saved_from_peer:flags.4?Peer saved_from_msg_id:flags.4?int psa_type:flags.6?string = MessageFwdHeader;
messageReplyHeader#a6d57763 flags:# reply_to_msg_id:int reply_to_peer_id:flags.0?Peer reply_to_top_id:flags.1?int = MessageReplyHeader;
message#85d6cbe2 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update;
---functions---
contacts.blockFromReplies#29a8962c flags:# delete_message:flags.0?true delete_history:flags.1?true report_spam:flags.2?true msg_id:int = Updates;
contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
Since a user can comment in channel posts without joining the actual discussion supergroup, there must be a way for them to receive notifications about replies in comment sections.
For this reason, a special @replies
username is provided.
Its ID for main and testing endpoints can be seen in the tdlib sources.
When someone replies to one of our messages in the comment section of a channel post, and the user is not subscribed to the discussion group, the client will receive two updates:
id
set to the ID of the replyfrom_id
set to the peer that replied to uspeer_id
set to the peer of the discussion groupreply_to.reply_to_msg_id
set to the ID of our messagereply_to.reply_to_top_id
set to the thread ID. id
set to the common ID sequence for usersfrom_id
set to the peer of @replies
peer_id
set to our own peerfwd_from.saved_from_msg_id
set to the ID of the replyfwd_from.from_id
set to the the peer that replied to usreply_to.reply_to_peer_id
set to the peer of the discussion groupreply_to.reply_to_msg_id
set to the ID of our messagereply_to.reply_to_top_id
set to the thread IDClients should display messages coming from @replies
as a read-only supergroup, with each reply displayed as a separate message from the author of the reply, with a "View in chat" button like for channel comments.