use std::collections::HashSet;
use std::env;
use std::time::Duration;
use chan::{Client, Post};
#[chan::tokio::main]
async fn main() -> chan::Result<()> {
let mut args = env::args().skip(1);
let board = args.next().unwrap_or_else(|| "po".to_string());
let thread_no: u64 = args
.next()
.and_then(|s| s.parse().ok())
.expect("usage: poll_thread <board> <thread_no>");
let client = Client::new();
let mut seen: HashSet<u64> = HashSet::new();
let mut since: Option<String> = None;
loop {
match client
.get_full_thread_if_modified(&board, thread_no, since.as_deref())
.await
{
Ok(None) => {
eprintln!("304 Not Modified");
}
Ok(Some(cond)) => {
since = cond.last_modified;
for post in &cond.value.posts {
if seen.insert(post.no) {
print_post(&board, post);
}
}
if cond.value.op().archived || cond.value.op().closed {
eprintln!("Thread archived or closed. Exiting.");
return Ok(());
}
}
Err(chan::Error::NotFound(_)) => {
eprintln!("Thread 404'd. Exiting.");
return Ok(());
}
Err(e) => return Err(e),
}
tokio::time::sleep(Duration::from_secs(30)).await;
}
}
fn print_post(board: &str, p: &Post) {
let who = match (&p.trip, &p.id) {
(Some(t), Some(id)) => format!("{} {} ({})", p.name, t, id),
(Some(t), None) => format!("{} {}", p.name, t),
(None, Some(id)) => format!("{} ({})", p.name, id),
(None, None) => p.name.clone(),
};
println!("--- >>{} {} [{}] ---", p.no, who, p.now);
if let Some(sub) = &p.sub {
println!("Subject: {}", sub);
}
if let Some(att) = &p.attachment {
println!("File: {} ({} bytes)", att.url(board), att.size);
}
if let Some(com) = &p.com {
println!("{}", com);
}
println!();
}