use std::io::Write;
use std::process::ExitCode;
use std::time::Duration;
use clap::Parser;
use futures_util::StreamExt;
use nitter_scraper::{NitterQuery, NitterScraper};
use reqwest::Client;
#[derive(Parser)]
struct Args {
instance: String,
#[arg(short, long)]
limit: Option<usize>,
#[arg(long)]
reorder_pinned: bool,
#[arg(long)]
skip_retweets: bool,
#[arg(short, long)]
min_id: Option<u128>,
#[command(subcommand)]
query: NitterQuery,
}
#[tokio::main]
async fn main() -> ExitCode {
let args = Args::parse();
let client = Client::builder()
.timeout(Duration::from_secs(10))
.build()
.unwrap();
let mut nitter_scraper = NitterScraper::builder()
.client(&client)
.instance(args.instance)
.query(args.query)
.reorder_pinned(args.reorder_pinned)
.skip_retweets(args.skip_retweets)
.limit(args.limit)
.min_id(args.min_id)
.build();
let nitter_search = nitter_scraper.search().await;
futures_util::pin_mut!(nitter_search);
while let Some(tweet_result) = nitter_search.next().await {
let tweet = match tweet_result {
Err(e) => {
eprintln!("{}", e);
return e.exit_code();
}
Ok(t) => t,
};
if let Err(e) = writeln!(
std::io::stdout(),
"{}",
serde_json::to_string(&tweet).unwrap()
) {
match e.kind() {
std::io::ErrorKind::BrokenPipe => break,
_ => {
eprintln!("{e}");
return ExitCode::FAILURE;
}
}
}
}
ExitCode::SUCCESS
}