atagen

macltok

public
Star0
Watch0
fa9114fcf75f7bdf1a7cec3b3367d604cf7de472
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git

Blame: examples/headless.rs

96fdf90aacd6atagen2026-09-08 08:24 UTC1
use macltok::{
96fdf90aacd6atagen2026-09-08 08:24 UTC2
    Command, CommandKind, EngineConfig, Event, LifecycleCommand, PasswordLogin, RoomCommand,
96fdf90aacd6atagen2026-09-08 08:24 UTC3
    RoomMembership, Session, StoreConfig, TimelineCommand,
96fdf90aacd6atagen2026-09-08 08:24 UTC4
};
96fdf90aacd6atagen2026-09-08 08:24 UTC5
96fdf90aacd6atagen2026-09-08 08:24 UTC6
#[tokio::main]
96fdf90aacd6atagen2026-09-08 08:24 UTC7
async fn main() -> Result<(), Box<dyn std::error::Error>> {
96fdf90aacd6atagen2026-09-08 08:24 UTC8
    let homeserver = required("MATRIX_HOMESERVER")?;
96fdf90aacd6atagen2026-09-08 08:24 UTC9
    let username = required("MATRIX_USERNAME")?;
96fdf90aacd6atagen2026-09-08 08:24 UTC10
    let password = required("MATRIX_PASSWORD")?;
96fdf90aacd6atagen2026-09-08 08:24 UTC11
    let store_path = required("MATRIX_STORE_PATH")?;
96fdf90aacd6atagen2026-09-08 08:24 UTC12
    let store_passphrase = required("MATRIX_STORE_PASSPHRASE")?;
96fdf90aacd6atagen2026-09-08 08:24 UTC13
    let session = Session::login_password(
96fdf90aacd6atagen2026-09-08 08:24 UTC14
        PasswordLogin {
96fdf90aacd6atagen2026-09-08 08:24 UTC15
            homeserver,
96fdf90aacd6atagen2026-09-08 08:24 UTC16
            username,
96fdf90aacd6atagen2026-09-08 08:24 UTC17
            password,
96fdf90aacd6atagen2026-09-08 08:24 UTC18
            device_display_name: Some("macltok headless example".into()),
fa9114fcf75fatagen2026-09-24 12:51 UTC19
            device_id: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC20
        },
96fdf90aacd6atagen2026-09-08 08:24 UTC21
        StoreConfig::new(store_path, store_passphrase),
96fdf90aacd6atagen2026-09-08 08:24 UTC22
    )
96fdf90aacd6atagen2026-09-08 08:24 UTC23
    .await?;
96fdf90aacd6atagen2026-09-08 08:24 UTC24
    let (engine, handle, mut events) = session.build(EngineConfig::default()).await?;
96fdf90aacd6atagen2026-09-08 08:24 UTC25
    let running = tokio::spawn(engine.run());
96fdf90aacd6atagen2026-09-08 08:24 UTC26
    let mut room_open_id = None;
96fdf90aacd6atagen2026-09-08 08:24 UTC27
    let mut resync_id = None;
96fdf90aacd6atagen2026-09-08 08:24 UTC28
    let mut timeline_items = Vec::new();
96fdf90aacd6atagen2026-09-08 08:24 UTC29
96fdf90aacd6atagen2026-09-08 08:24 UTC30
    loop {
96fdf90aacd6atagen2026-09-08 08:24 UTC31
        tokio::select! {
96fdf90aacd6atagen2026-09-08 08:24 UTC32
            event = events.recv() => {
96fdf90aacd6atagen2026-09-08 08:24 UTC33
                let Some(event) = event else { break; };
96fdf90aacd6atagen2026-09-08 08:24 UTC34
                match event {
96fdf90aacd6atagen2026-09-08 08:24 UTC35
                    Event::RoomsChanged if room_open_id.is_none() => {
96fdf90aacd6atagen2026-09-08 08:24 UTC36
                        if let Some(room) = handle
96fdf90aacd6atagen2026-09-08 08:24 UTC37
                            .rooms()
96fdf90aacd6atagen2026-09-08 08:24 UTC38
                            .await
96fdf90aacd6atagen2026-09-08 08:24 UTC39
                            .into_iter()
96fdf90aacd6atagen2026-09-08 08:24 UTC40
                            .find(|room| room.membership == RoomMembership::Joined)
96fdf90aacd6atagen2026-09-08 08:24 UTC41
                        {
96fdf90aacd6atagen2026-09-08 08:24 UTC42
                            room_open_id = Some(handle
96fdf90aacd6atagen2026-09-08 08:24 UTC43
                                .send(Command::Room(RoomCommand::Open(room.room_id)))
96fdf90aacd6atagen2026-09-08 08:24 UTC44
                                .await?);
96fdf90aacd6atagen2026-09-08 08:24 UTC45
                        }
96fdf90aacd6atagen2026-09-08 08:24 UTC46
                    }
96fdf90aacd6atagen2026-09-08 08:24 UTC47
                    Event::TimelineReset { items, .. } => {
96fdf90aacd6atagen2026-09-08 08:24 UTC48
                        timeline_items = items;
96fdf90aacd6atagen2026-09-08 08:24 UTC49
                        resync_id = None;
96fdf90aacd6atagen2026-09-08 08:24 UTC50
                    }
96fdf90aacd6atagen2026-09-08 08:24 UTC51
                    Event::TimelineChanged { timeline_id, diffs } if resync_id.is_none() => {
96fdf90aacd6atagen2026-09-08 08:24 UTC52
                        for diff in diffs {
96fdf90aacd6atagen2026-09-08 08:24 UTC53
                            if diff.try_apply(&mut timeline_items).is_err() {
96fdf90aacd6atagen2026-09-08 08:24 UTC54
                                resync_id = Some(handle.send(Command::Timeline(
96fdf90aacd6atagen2026-09-08 08:24 UTC55
                                    TimelineCommand::Resync { timeline_id },
96fdf90aacd6atagen2026-09-08 08:24 UTC56
                                )).await?);
96fdf90aacd6atagen2026-09-08 08:24 UTC57
                                break;
96fdf90aacd6atagen2026-09-08 08:24 UTC58
                            }
96fdf90aacd6atagen2026-09-08 08:24 UTC59
                        }
96fdf90aacd6atagen2026-09-08 08:24 UTC60
                        if resync_id.is_none() {
96fdf90aacd6atagen2026-09-08 08:24 UTC61
                            for item in &timeline_items {
96fdf90aacd6atagen2026-09-08 08:24 UTC62
                                if let macltok::TimelineItem::Message(message) = item {
96fdf90aacd6atagen2026-09-08 08:24 UTC63
                                    println!("{}  {}", message.sender_name, message.body);
96fdf90aacd6atagen2026-09-08 08:24 UTC64
                                }
96fdf90aacd6atagen2026-09-08 08:24 UTC65
                            }
96fdf90aacd6atagen2026-09-08 08:24 UTC66
                        }
96fdf90aacd6atagen2026-09-08 08:24 UTC67
                    }
96fdf90aacd6atagen2026-09-08 08:24 UTC68
                    Event::CommandSucceeded { id, command: CommandKind::Room }
96fdf90aacd6atagen2026-09-08 08:24 UTC69
                        if room_open_id == Some(id) => println!("room ready"),
96fdf90aacd6atagen2026-09-08 08:24 UTC70
                    Event::CommandFailed(error) if room_open_id == Some(error.id)
96fdf90aacd6atagen2026-09-08 08:24 UTC71
                        || resync_id == Some(error.id) => return Err(error.message.into()),
96fdf90aacd6atagen2026-09-08 08:24 UTC72
                    Event::CommandFailed(error) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC73
                        eprintln!("{:?}  {}", error.command, error.message);
96fdf90aacd6atagen2026-09-08 08:24 UTC74
                    }
96fdf90aacd6atagen2026-09-08 08:24 UTC75
                    Event::Stopped => break,
96fdf90aacd6atagen2026-09-08 08:24 UTC76
                    _ => {}
96fdf90aacd6atagen2026-09-08 08:24 UTC77
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC78
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC79
            result = tokio::signal::ctrl_c() => {
96fdf90aacd6atagen2026-09-08 08:24 UTC80
                result?;
96fdf90aacd6atagen2026-09-08 08:24 UTC81
                handle
96fdf90aacd6atagen2026-09-08 08:24 UTC82
                    .send(Command::Lifecycle(LifecycleCommand::Shutdown))
96fdf90aacd6atagen2026-09-08 08:24 UTC83
                    .await?;
96fdf90aacd6atagen2026-09-08 08:24 UTC84
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC85
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC86
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC87
    running.await??;
96fdf90aacd6atagen2026-09-08 08:24 UTC88
    Ok(())
96fdf90aacd6atagen2026-09-08 08:24 UTC89
}
96fdf90aacd6atagen2026-09-08 08:24 UTC90
96fdf90aacd6atagen2026-09-08 08:24 UTC91
fn required(name: &str) -> Result<String, Box<dyn std::error::Error>> {
96fdf90aacd6atagen2026-09-08 08:24 UTC92
    std::env::var(name).map_err(|_| format!("{name} is required").into())
96fdf90aacd6atagen2026-09-08 08:24 UTC93
}