use async_trait::async_trait;
use rocketman::{
connection::JetstreamConnection,
handler::{self, Ingestors},
ingestion::LexiconIngestor,
options::JetstreamOptions,
types::event::{Commit, Event},
};
use serde_json::Value;
use std::{sync::Arc, sync::Mutex};
#[tokio::main]
async fn main() {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
.init();
let opts = JetstreamOptions::builder()
.wanted_collections(vec!["app.bsky.feed.post".to_string()])
.build();
let jetstream = JetstreamConnection::new(opts);
let mut ingestors = Ingestors::new();
ingestors.commits.insert(
"app.bsky.feed.post".to_string(),
Box::new(PostIngestor),
);
let cursor: Arc<Mutex<Option<u64>>> = Arc::new(Mutex::new(None));
let msg_rx = jetstream.get_msg_rx();
let reconnect_tx = jetstream.get_reconnect_tx();
let c_cursor = cursor.clone();
tokio::spawn(async move {
while let Ok(message) = msg_rx.recv().await {
if let Err(e) =
handler::handle_message(message, &ingestors, reconnect_tx.clone(), c_cursor.clone())
.await
{
eprintln!("Error processing message: {}", e);
};
}
});
if let Err(e) = jetstream.connect(cursor.clone()).await {
eprintln!("Failed to connect to Jetstream: {}", e);
std::process::exit(1);
}
}
pub struct PostIngestor;
#[async_trait]
impl LexiconIngestor for PostIngestor {
async fn ingest(&self, message: Event<Value>) -> anyhow::Result<()> {
if let Some(Commit {
record: Some(record),
..
}) = message.commit
{
if let Some(Value::String(text)) = record.get("text") {
println!("{text:?}");
}
}
Ok(())
}
}