v2_community_bot/v2_community_bot.rs
1//! A bot that OWNS a Concord v2 community. On startup (with `VECTOR_CREATE=1`)
2//! it creates the community, prints a shareable invite link, optionally
3//! Direct-Invites an npub, then greets and echoes in its channels.
4//!
5//! Run:
6//! ```sh
7//! VECTOR_NSEC=nsec1... VECTOR_CREATE=1 cargo run -p vector-sdk --example v2_community_bot
8//! # optionally also: VECTOR_INVITE_NPUB=npub1...
9//! ```
10//!
11//! The community and its invites are on the modern protocol, byte-compatible
12//! with Soapbox/Armada — the exact same discord.js-style API as a v1 bot; the
13//! SDK routes to v2 under the hood.
14
15use vector_sdk::VectorBot;
16
17#[tokio::main]
18async fn main() -> vector_sdk::Result<()> {
19 let nsec = std::env::var("VECTOR_NSEC").expect("set VECTOR_NSEC to your bot's nsec");
20
21 let bot = VectorBot::builder().nsec(nsec).build().await?;
22 println!("v2 community bot online as {}", bot.npub());
23
24 // Create-and-invite is opt-in so a restart doesn't spawn a fresh community
25 // each time (a real bot persists its community id and reuses it).
26 if std::env::var("VECTOR_CREATE").is_ok() {
27 // Creation is one hop through the core facade (the ergonomic surface stays at
28 // the stable published API). A fresh community is created on the modern protocol.
29 let summary = bot.core().create_community_v2("Vector v2 Demo").await?;
30 let id = summary.get("community_id").and_then(|v| v.as_str()).unwrap_or_default().to_string();
31 let community = bot.community(id);
32 println!("created v2 community {}", community.id());
33
34 let url = community.create_invite().await?;
35 println!("shareable invite link: {url}");
36
37 if let Ok(guest) = std::env::var("VECTOR_INVITE_NPUB") {
38 community.invite(&guest).await?;
39 println!("direct-invited {guest}");
40 }
41 }
42
43 // One handler serves DMs and every Community channel — the SDK hides the
44 // transport (and the protocol) difference.
45 bot.on_message(|_bot, msg| async move {
46 if msg.is_mine() {
47 return; // never reply to our own messages (no echo loop)
48 }
49 let _ = msg.channel().typing().await;
50 let _ = msg.reply(&format!("v2 heard: {}", msg.text())).await;
51 })
52 .await?;
53
54 Ok(())
55}