diff --git a/src/command.rs b/src/command.rs new file mode 100644 index 0000000..67e2c58 --- /dev/null +++ b/src/command.rs @@ -0,0 +1,80 @@ +use std::path::Path; +use std::sync::Arc; + +use entity::*; +use futures_util::{pin_mut, StreamExt}; +use migration::OnConflict; +use sea_orm::entity::prelude::*; +use sea_orm::ActiveValue::Set; + +use crate::bilibili::{BiliClient, FavoriteList}; +use crate::Result; + +pub async fn handle_favorite( + bili_client: Arc, + fid: i32, + connection: Arc, +) -> Result<()> { + let favorite_list = FavoriteList::new(bili_client.clone(), fid.to_string()); + let info = favorite_list.get_info().await?; + let favorite_obj = favorite::Entity::insert(favorite::ActiveModel { + f_id: Set(fid), + name: Set(info.title), + path: Set("/home/amtoaer/Documents/code/rust/bili-sync/video".to_string()), + enabled: Set(true), + ..Default::default() + }) + .on_conflict( + OnConflict::column(favorite::Column::FId) + .update_column(favorite::Column::Name) + .update_column(favorite::Column::Path) + .update_column(favorite::Column::Enabled) + .to_owned(), + ) + .exec_with_returning(connection.as_ref()) + .await?; + println!( + "Hi there! I'm going to scan this favorite: {:?}", + favorite_obj + ); + let video_stream = favorite_list.into_video_stream(); + pin_mut!(video_stream); + while let Some(v) = video_stream.next().await { + let not_exists = video::Entity::find() + .filter( + video::Column::Bvid + .eq(&v.bvid) + .and(video::Column::FavoriteId.eq(fid)), + ) + .count(connection.as_ref()) + .await + .is_ok_and(|x| x == 0); + if !not_exists { + break; + } + let _video_obj = video::Entity::insert(video::ActiveModel { + favorite_id: Set(fid), + bvid: Set(v.bvid), + path: Set(Path::new(favorite_obj.path.as_str()) + .join(&v.title) + .to_str() + .unwrap() + .to_string()), + name: Set(v.title), + category: Set(v.vtype.to_string()), + intro: Set(v.intro), + cover: Set(v.cover), + ctime: Set(v.ctime.to_string()), + pubtime: Set(v.pubtime.to_string()), + favtime: Set(v.fav_time.to_string()), + downloaded: Set(false), + valid: Set(true), + tags: Set("[]".to_string()), + single_page: Set(false), + ..Default::default() + }) + .exec_with_returning(connection.as_ref()) + .await?; + } + Ok(()) +} diff --git a/src/database.rs b/src/database.rs new file mode 100644 index 0000000..86ca3d4 --- /dev/null +++ b/src/database.rs @@ -0,0 +1,7 @@ +use sea_orm::{ConnectOptions, Database, DatabaseConnection}; + +use crate::Result; +pub async fn database_connection() -> Result { + let opt = ConnectOptions::new("sqlite://./data.sqlite?mode=rwc"); + Ok(Database::connect(opt).await?) +} diff --git a/src/lib.rs b/src/lib.rs index 9d8bf31..09d32cc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,8 @@ use std::error; pub mod bilibili; +pub mod command; +pub mod database; pub mod downloader; type Result = std::result::Result>; diff --git a/src/main.rs b/src/main.rs index b029cc7..9aa8ffd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,69 +1,17 @@ -use std::path::Path; -use std::rc::Rc; +use std::sync::Arc; -use bili_sync::bilibili::{ - AudioQuality, BestStream, BiliClient, FavoriteList, FilterOption, Video, VideoCodecs, - VideoQuality, -}; -use bili_sync::downloader::Downloader; -use futures_util::{pin_mut, StreamExt}; +use bili_sync::bilibili::BiliClient; +use bili_sync::command::handle_favorite; +use bili_sync::database::database_connection; #[tokio::main] -async fn main() { - let bili_client = Rc::new(BiliClient::new(None)); - let favorite_list = FavoriteList::new(bili_client.clone(), "52642258".to_string()); - dbg!(favorite_list.get_info().await.unwrap()); - - let video_stream = favorite_list.into_video_stream(); - // from doc: https://docs.rs/async-stream/latest/async_stream/ - pin_mut!(video_stream); - - let third_video_info = dbg!(video_stream.skip(2).next().await.unwrap()); - let third_video = Video::new(bili_client.clone(), third_video_info.bvid); - dbg!(third_video.get_tags().await.unwrap()); - - let pages = dbg!(third_video.get_pages().await.unwrap()); - let best_stream = dbg!(third_video - .get_page_analyzer(&pages[0]) - .await - .unwrap() - .best_stream(&FilterOption { - video_max_quality: VideoQuality::QualityDolby, - video_min_quality: VideoQuality::Quality360p, - audio_max_quality: AudioQuality::QualityDolby, - audio_min_quality: AudioQuality::Quality64k, - codecs: Rc::new(vec![VideoCodecs::HEV, VideoCodecs::AVC]), - no_dolby_video: false, - no_dolby_audio: false, - no_hdr: false, - no_hires: false, - })) - .unwrap(); - - let downloader = Downloader::default(); - let base = Path::new("./"); - let output_path = base.join(format!("{}.mp4", third_video_info.title)); - - match best_stream { - BestStream::Mixed(stream) => { - let url = dbg!(stream.url()); - downloader.fetch(url, &output_path).await.unwrap(); - } - BestStream::VideoAudio { video, audio } => { - let url = dbg!(video.url()); - let Some(audio) = audio else { - downloader.fetch(url, &output_path).await.unwrap(); - return; - }; - let video_path = base.join(format!("{}_video_tmp", third_video_info.title)); - downloader.fetch(url, &video_path).await.unwrap(); - let url = dbg!(audio.url()); - let audio_path = base.join(format!("{}_audio_tmp", third_video_info.title)); - downloader.fetch(url, &audio_path).await.unwrap(); - downloader - .merge(&video_path, &audio_path, &output_path) - .await - .unwrap(); +async fn main() -> ! { + let connection = Arc::new(database_connection().await.unwrap()); + let bili_client = Arc::new(BiliClient::new(None)); + loop { + for fid in [52642258] { + let _ = handle_favorite(bili_client.clone(), fid, connection.clone()).await; } + tokio::time::sleep(std::time::Duration::from_secs(60)).await; } }