Forum Topics
Telegram supergroups can be converted to forums - they gain named topics that act as separate message threads inside one chat. Each topic has its own message history, read state, and optional icon.
Enable forum mode on a supergroup with toggle_forum.
Enable / disable forum mode
async
client.toggle_forum(peer: impl Into<PeerRef>, enabled: bool) → Result<(), InvocationError>
Turn forum mode on or off for a supergroup. Requires channel admin rights. Once enabled the chat gains a General topic (topic ID 1) automatically.
#![allow(unused)]
fn main() {
client.toggle_forum(peer.clone(), true).await?; // enable
client.toggle_forum(peer.clone(), false).await?; // disable
}
List topics
async
client.get_forum_topics(peer: impl Into<PeerRef>, query: Option<String>, limit: i32, offset_date: i32, offset_id: i32, offset_topic: i32) → Result<Vec<tl::enums::ForumTopic>, InvocationError>
Paginate through forum topics. Use
query to search by topic title. Start with all offsets at 0.
| Param | Description |
|---|---|
query | Search string. None returns all topics. |
limit | Topics per page (max 100). |
offset_date | Date of last topic in previous page (for pagination). |
offset_id | top_msg_id of last topic in previous page. |
offset_topic | Topic ID of last topic in previous page. |
#![allow(unused)]
fn main() {
// First page
let topics = client
.get_forum_topics(peer.clone(), None, 100, 0, 0, 0)
.await?;
for topic in &topics {
if let tl::enums::ForumTopic::Topic(t) = topic {
println!("[{}] {} - {} unread", t.id, t.title, t.unread_count);
}
}
}
async
client.get_forum_topics_by_id(peer: impl Into<PeerRef>, topic_ids: Vec<i32>) → Result<Vec<tl::enums::ForumTopic>, InvocationError>
Fetch specific topics by their IDs in one request.
#![allow(unused)]
fn main() {
let topics = client.get_forum_topics_by_id(peer.clone(), vec![1, 42, 99]).await?;
}
Create & edit topics
async
client.create_forum_topic(peer: impl Into<PeerRef>, title: impl Into<String>, icon_color: Option<i32>, icon_emoji_id: Option<i64>) → Result<(), InvocationError>
Create a new topic in a forum supergroup.
icon_color- RGB color int for the topic icon. Telegram supports six presets:0x6FB9F0,0xFFD67E,0xCB86DB,0x8EEE98,0xFF93B2,0xFB6F5F. PassNoneto use the default blue.icon_emoji_id- Custom emoji document ID (from a premium sticker set) to use as the topic icon. PassNoneto use a plain color circle.
#![allow(unused)]
fn main() {
// Simple topic
client.create_forum_topic(peer.clone(), "📢 Announcements", None, None).await?;
// Colored topic
client.create_forum_topic(
peer.clone(),
"🛠 Dev",
Some(0x6FB9F0),
None,
).await?;
}
async
client.edit_forum_topic(peer: impl Into<PeerRef>, topic_id: i32, title: Option<String>, icon_emoji_id: Option<i64>, closed: Option<bool>, hidden: Option<bool>) → Result<(), InvocationError>
Update topic properties. Pass
None for any field to leave it unchanged.
closed-Some(true)to prevent new messages;Some(false)to reopen.hidden- Only valid for topic ID 1 (General). Hides it from the topic list.
#![allow(unused)]
fn main() {
// Rename a topic
client.edit_forum_topic(peer.clone(), 42, Some("New Name".into()), None, None, None).await?;
// Close a topic
client.edit_forum_topic(peer.clone(), 42, None, None, Some(true), None).await?;
// Hide the General topic
client.edit_forum_topic(peer.clone(), 1, None, None, None, Some(true)).await?;
}
Delete topic history
async
client.delete_forum_topic_history(peer: impl Into<PeerRef>, top_msg_id: i32) → Result<(), InvocationError>
Delete all messages inside a forum topic.
top_msg_id is the topic's root message ID (returned as ForumTopic::Topic.id). This is destructive and irreversible. The method automatically pages through the deletion until all messages are removed.
#![allow(unused)]
fn main() {
// Wipe the "Dev" topic (top_msg_id = 42)
client.delete_forum_topic_history(peer.clone(), 42).await?;
}
Sending messages to a topic
To send a message inside a specific topic, set reply_to on the InputMessage to the topic’s top_msg_id:
#![allow(unused)]
fn main() {
use ferogram::InputMessage;
// Send into topic #42
client.send_message(
peer.clone(),
InputMessage::text("Hello topic!").reply_to(Some(42)),
).await?;
}
ForumTopic fields reference
#![allow(unused)]
fn main() {
if let tl::enums::ForumTopic::Topic(t) = topic {
t.id // i32: topic ID / top_msg_id
t.title // String: display name
t.icon_color // i32: RGB color
t.icon_emoji_id // Option<i64>: custom emoji ID
t.top_message // i32: most recent message ID
t.unread_count // i32: unread messages
t.unread_mentions_count // i32
t.closed // bool: no new messages allowed
t.pinned // bool: pinned in topic list
t.short // bool: General topic placeholder
}
}