Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.
ParamDescription
querySearch string. None returns all topics.
limitTopics per page (max 100).
offset_dateDate of last topic in previous page (for pagination).
offset_idtop_msg_id of last topic in previous page.
offset_topicTopic 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. Pass None to use the default blue.
  • icon_emoji_id - Custom emoji document ID (from a premium sticker set) to use as the topic icon. Pass None to 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
}
}