diff --git a/src/main.rs b/src/main.rs index d81dad1..c0403de 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,8 +15,16 @@ struct Args { #[derive(Subcommand)] enum Commands { - /// Scrapes the lofi girl website file server for mp3 files. - Scrape, + /// Scrapes the lofi girl website file server for files. + Scrape { + /// The file extention to search for, defaults to mp3. + #[clap(long, short, default_value = "mp3")] + extention: String, + + /// Whether to include the full HTTP URL or just the distinguishing part. + #[clap(long, short)] + include_full: bool, + }, /// Starts the player. Play, } @@ -26,7 +34,10 @@ async fn main() -> eyre::Result<()> { let cli = Args::parse(); match cli.command { - Commands::Scrape => scrape::scrape().await, + Commands::Scrape { + extention, + include_full, + } => scrape::scrape(extention, include_full).await, Commands::Play => play::play().await, } } diff --git a/src/player.rs b/src/player.rs index ef65bdb..7d6d3ac 100644 --- a/src/player.rs +++ b/src/player.rs @@ -2,7 +2,7 @@ use std::{collections::VecDeque, sync::Arc}; use arc_swap::ArcSwapOption; use reqwest::Client; -use rodio::{Decoder, OutputStream, OutputStreamHandle, Sink}; +use rodio::{OutputStream, OutputStreamHandle, Sink}; use tokio::{ select, sync::{ diff --git a/src/scrape.rs b/src/scrape.rs index 3e47492..bd7ab8d 100644 --- a/src/scrape.rs +++ b/src/scrape.rs @@ -3,12 +3,13 @@ use std::sync::LazyLock; use futures::{stream::FuturesUnordered, StreamExt}; use scraper::{Html, Selector}; +const BASE_URL: &'static str = "https://lofigirl.com/wp-content/uploads/"; + static SELECTOR: LazyLock = LazyLock::new(|| Selector::parse("html > body > pre > a").unwrap()); async fn parse(path: &str) -> eyre::Result> { - let response = - reqwest::get(format!("https://lofigirl.com/wp-content/uploads/{}", path)).await?; + let response = reqwest::get(format!("{}{}", BASE_URL, path)).await?; let document = response.text().await?; let html = Html::parse_document(&document); @@ -23,7 +24,9 @@ async fn parse(path: &str) -> eyre::Result> { /// /// It's a bit hacky, and basically works by checking all of the years, then months, and then all of the files. /// This is done as a way to avoid recursion, since async rust really hates recursive functions. -async fn scan() -> eyre::Result> { +async fn scan(extention: &str, include_full: bool) -> eyre::Result> { + let extention = &format!(".{}", extention); + let items = parse("").await?; let years: Vec = items @@ -48,8 +51,12 @@ async fn scan() -> eyre::Result> { let items = items .into_iter() .filter_map(|x| { - if x.ends_with(".mp3") { - Some(format!("{path}{x}")) + if x.ends_with(extention) { + if include_full { + Some(format!("{BASE_URL}{path}{x}")) + } else { + Some(format!("{path}{x}")) + } } else { None } @@ -69,8 +76,8 @@ async fn scan() -> eyre::Result> { eyre::Result::Ok(files) } -pub async fn scrape() -> eyre::Result<()> { - let files = scan().await?; +pub async fn scrape(extention: String, include_full: bool) -> eyre::Result<()> { + let files = scan(&extention, include_full).await?; for file in files { println!("{}", file); } diff --git a/src/tracks.rs b/src/tracks.rs index 59751f9..769ff8c 100644 --- a/src/tracks.rs +++ b/src/tracks.rs @@ -38,12 +38,15 @@ impl TrackInfo { } } +/// The main track struct, which includes the actual decoded file +/// as well as some basic information about it. pub struct Track { pub info: TrackInfo, pub data: Data, } impl Track { + /// Fetches, downloads, and decodes a random track from the tracklist. pub async fn random(client: &Client) -> eyre::Result { let name = random().await?; let data = download(&name, client).await?;