mirror of
https://codeberg.org/YGGverse/ytd.git
synced 2026-04-08 21:05:30 +00:00
initial commit
This commit is contained in:
parent
bb39b5b504
commit
8dcd80b9fe
6 changed files with 113 additions and 8 deletions
30
Cargo.lock
generated
30
Cargo.lock
generated
|
|
@ -635,6 +635,16 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http_req"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92208b0986f414edaca8ede2c6962c979309346a9e8e19d07d0a7879aae1549e"
|
||||||
|
dependencies = [
|
||||||
|
"native-tls",
|
||||||
|
"unicase",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httparse"
|
name = "httparse"
|
||||||
version = "1.10.1"
|
version = "1.10.1"
|
||||||
|
|
@ -851,6 +861,17 @@ dependencies = [
|
||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "invidious"
|
||||||
|
version = "0.7.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa2cff01a915c4780785828f6bec4ad5f8d03f34307d4183ca210830a8a6d88d"
|
||||||
|
dependencies = [
|
||||||
|
"http_req",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.12.0"
|
version = "2.12.0"
|
||||||
|
|
@ -1980,6 +2001,12 @@ version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
|
@ -2458,12 +2485,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ytd"
|
name = "ytd"
|
||||||
version = "0.3.2"
|
version = "0.4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"invidious",
|
||||||
"log",
|
"log",
|
||||||
"redb",
|
"redb",
|
||||||
"regex",
|
"regex",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ytd"
|
name = "ytd"
|
||||||
version = "0.3.2"
|
version = "0.4.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
@ -14,6 +14,7 @@ anyhow = "1.0.102"
|
||||||
chrono = "0.4.44"
|
chrono = "0.4.44"
|
||||||
clap = { version = "4.6", features = ["derive"] }
|
clap = { version = "4.6", features = ["derive"] }
|
||||||
env_logger = "0.11.10"
|
env_logger = "0.11.10"
|
||||||
|
invidious = "0.7.8"
|
||||||
log = "0.4.29"
|
log = "0.4.29"
|
||||||
redb = "4.0.0"
|
redb = "4.0.0"
|
||||||
regex = "1.12.3"
|
regex = "1.12.3"
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@ sleep = 1
|
||||||
# exec = ""
|
# exec = ""
|
||||||
# stdout_contains = [""]
|
# stdout_contains = [""]
|
||||||
|
|
||||||
|
# Supported values: youtube | invidious
|
||||||
|
|
||||||
|
provider = "youtube"
|
||||||
|
|
||||||
# Channels queue config
|
# Channels queue config
|
||||||
|
|
||||||
[channel.test]
|
[channel.test]
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@ pub struct Command {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
/// Supported values:
|
||||||
|
/// * youtube
|
||||||
|
/// * invidious
|
||||||
|
pub provider: String,
|
||||||
|
/// Channels parsed from the config file
|
||||||
pub channel: HashMap<String, Channel>,
|
pub channel: HashMap<String, Channel>,
|
||||||
/// Persist processed entries between sessions
|
/// Persist processed entries between sessions
|
||||||
pub database: PathBuf,
|
pub database: PathBuf,
|
||||||
|
|
|
||||||
16
src/main.rs
16
src/main.rs
|
|
@ -1,6 +1,7 @@
|
||||||
mod argument;
|
mod argument;
|
||||||
mod config;
|
mod config;
|
||||||
mod database;
|
mod database;
|
||||||
|
mod provider;
|
||||||
|
|
||||||
use argument::Argument;
|
use argument::Argument;
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
|
|
@ -8,8 +9,8 @@ use clap::Parser;
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use database::Database;
|
use database::Database;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
use provider::Provider;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rustypipe::client::RustyPipe;
|
|
||||||
use std::{env::var, process::Command, thread, time::Duration};
|
use std::{env::var, process::Command, thread, time::Duration};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|
@ -34,7 +35,11 @@ async fn main() {
|
||||||
let update = config.update.map(Duration::from_secs);
|
let update = config.update.map(Duration::from_secs);
|
||||||
let sleep = config.sleep.map(Duration::from_secs);
|
let sleep = config.sleep.map(Duration::from_secs);
|
||||||
let mut database = Database::new(&config.database).unwrap();
|
let mut database = Database::new(&config.database).unwrap();
|
||||||
let rp = RustyPipe::new();
|
let client = if "youtube" == config.provider.to_lowercase() {
|
||||||
|
Provider::youtube()
|
||||||
|
} else {
|
||||||
|
Provider::invidious()
|
||||||
|
};
|
||||||
let channel_item_id_regex = Regex::new(r"^[A-z0-9_-]{11}$").unwrap();
|
let channel_item_id_regex = Regex::new(r"^[A-z0-9_-]{11}$").unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -45,11 +50,10 @@ async fn main() {
|
||||||
info!("begin {} channels update...", config.channel.len());
|
info!("begin {} channels update...", config.channel.len());
|
||||||
for (c, channel) in &config.channel {
|
for (c, channel) in &config.channel {
|
||||||
debug!("get `{c}` ({})...", channel.id);
|
debug!("get `{c}` ({})...", channel.id);
|
||||||
match rp.query().channel_videos(&channel.id).await {
|
match client.videos(&channel.id).await {
|
||||||
Ok(result) => {
|
Ok(items) => {
|
||||||
let items = result.content.items;
|
|
||||||
debug!(
|
debug!(
|
||||||
"received {:?} items to handle, limit: {:?}...",
|
"received {} items to handle, limit: {:?}...",
|
||||||
items.len(),
|
items.len(),
|
||||||
channel.items_limit
|
channel.items_limit
|
||||||
);
|
);
|
||||||
|
|
|
||||||
63
src/provider.rs
Normal file
63
src/provider.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
use anyhow::{Result, anyhow};
|
||||||
|
use invidious::{ClientSync, ClientSyncTrait};
|
||||||
|
use rustypipe::client::RustyPipe;
|
||||||
|
|
||||||
|
pub struct Video {
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub is_live: bool,
|
||||||
|
pub is_short: bool,
|
||||||
|
pub is_upcoming: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Provider {
|
||||||
|
Youtube(RustyPipe),
|
||||||
|
Invidious(ClientSync),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Provider {
|
||||||
|
pub fn youtube() -> Self {
|
||||||
|
Self::Youtube(RustyPipe::new())
|
||||||
|
}
|
||||||
|
pub fn invidious() -> Self {
|
||||||
|
Self::Invidious(ClientSync::default())
|
||||||
|
}
|
||||||
|
pub async fn videos(&self, channel_id: &str) -> Result<Vec<Video>> {
|
||||||
|
let mut videos = Vec::new();
|
||||||
|
match self {
|
||||||
|
Provider::Youtube(client) => {
|
||||||
|
for video in client
|
||||||
|
.query()
|
||||||
|
.channel_videos(channel_id)
|
||||||
|
.await?
|
||||||
|
.content
|
||||||
|
.items
|
||||||
|
{
|
||||||
|
videos.push(Video {
|
||||||
|
id: video.id,
|
||||||
|
name: video.name,
|
||||||
|
is_live: video.is_live,
|
||||||
|
is_short: video.is_short,
|
||||||
|
is_upcoming: video.is_upcoming,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Provider::Invidious(client) => {
|
||||||
|
for video in client
|
||||||
|
.channel_videos(channel_id, None)
|
||||||
|
.map_err(|e| anyhow!("{e:?}"))?
|
||||||
|
.videos
|
||||||
|
{
|
||||||
|
videos.push(Video {
|
||||||
|
id: video.id,
|
||||||
|
name: video.title,
|
||||||
|
is_live: video.live,
|
||||||
|
is_short: video.length <= 60,
|
||||||
|
is_upcoming: video.upcoming,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(videos)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue