feat(aria2): 重构 download 函数并添加新功能
- 重构 download 函数,返回通知接收器以支持进度更新 - 新增 search 模块,实现关键词搜索功能 - 更新 single模块,增加音频格式判断- 引入日志模块,优化调试输出 - 新增特殊字符替换函数,用于文件名处理
This commit is contained in:
38
src/main.rs
38
src/main.rs
@@ -1,4 +1,8 @@
|
|||||||
|
use crate::aria2::download;
|
||||||
|
use crate::single::{multiple, replace_special_char};
|
||||||
use log::Level::Debug;
|
use log::Level::Debug;
|
||||||
|
use std::fs;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
mod aria2;
|
mod aria2;
|
||||||
mod search;
|
mod search;
|
||||||
@@ -8,6 +12,38 @@ pub mod utils;
|
|||||||
type ErrorString = String;
|
type ErrorString = String;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() -> Result<(), ErrorString> {
|
||||||
simple_logger::init_with_level(Debug).unwrap();
|
simple_logger::init_with_level(Debug).unwrap();
|
||||||
|
|
||||||
|
let multiple = multiple(7308249639).await?;
|
||||||
|
let mut handles = vec![];
|
||||||
|
for song in multiple {
|
||||||
|
let handle: tokio::task::JoinHandle<Result<_, ErrorString>> = tokio::spawn(async move {
|
||||||
|
let single = single::single(song).await?;
|
||||||
|
download(
|
||||||
|
single.download_url.clone(),
|
||||||
|
format!("{}/{}", single.id, format!("{}.{}", single.name, single.format))
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
download(
|
||||||
|
single.pic_url.clone(),
|
||||||
|
format!("{}/{}", single.id, format!("{}.jpg", single.id))
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let json = serde_json::to_string_pretty(&single)
|
||||||
|
.map_err(|e| ErrorString::from(e.to_string()))?;
|
||||||
|
fs::write(format!("E:\\163\\{}\\{}.json", single.id, single.id), json)
|
||||||
|
.map_err(|e| ErrorString::from(e.to_string()))?;
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
handles.push(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
for handle in handles {
|
||||||
|
tokio::join!(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
tokio::time::sleep(Duration::from_secs(5000000000)).await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
use crate::utils::create_reqwest_client;
|
|
||||||
use crate::ErrorString;
|
use crate::ErrorString;
|
||||||
|
use crate::utils::create_reqwest_client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
use crate::utils::create_reqwest_client;
|
|
||||||
use crate::ErrorString;
|
use crate::ErrorString;
|
||||||
|
use crate::utils::create_reqwest_client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct SingleSongsInfo {
|
pub struct SingleSongsInfo {
|
||||||
pub id: i64,
|
pub id: i64,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@@ -12,6 +12,7 @@ pub struct SingleSongsInfo {
|
|||||||
pub pic_url: String,
|
pub pic_url: String,
|
||||||
pub download_url: String,
|
pub download_url: String,
|
||||||
pub format: String,
|
pub format: String,
|
||||||
|
pub lyric: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@@ -21,6 +22,7 @@ struct DetailJson {
|
|||||||
al_name: String,
|
al_name: String,
|
||||||
pic: String,
|
pic: String,
|
||||||
url: String,
|
url: String,
|
||||||
|
lyric: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn single(id: i64) -> Result<SingleSongsInfo, ErrorString> {
|
pub async fn single(id: i64) -> Result<SingleSongsInfo, ErrorString> {
|
||||||
@@ -55,6 +57,7 @@ pub async fn single(id: i64) -> Result<SingleSongsInfo, ErrorString> {
|
|||||||
} else {
|
} else {
|
||||||
String::from("mp3")
|
String::from("mp3")
|
||||||
},
|
},
|
||||||
|
lyric: info_result.lyric,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,3 +72,44 @@ pub fn replace_special_char(s: String) -> String {
|
|||||||
.replace(r#"|"#, "-")
|
.replace(r#"|"#, "-")
|
||||||
.replace(r#"""#, "-")
|
.replace(r#"""#, "-")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct PlayList {
|
||||||
|
playlist: PlayListDetail,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct PlayListDetail {
|
||||||
|
tracks: Vec<PlayListDetailTrack>,
|
||||||
|
}
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct PlayListDetailTrack {
|
||||||
|
id: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn multiple(id: i64) -> Result<Vec<i64>, ErrorString> {
|
||||||
|
let client = create_reqwest_client().await?;
|
||||||
|
|
||||||
|
let info_handle: JoinHandle<Result<PlayList, ErrorString>> = tokio::spawn(async move {
|
||||||
|
let info_request_url = format!("https://163.genshinmc.eu.org/playlist/detail?id={id}");
|
||||||
|
client
|
||||||
|
.get(info_request_url)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("无法获取歌曲信息: {e}"))?
|
||||||
|
.json::<PlayList>()
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("无法解析歌曲信息: {e}"))
|
||||||
|
});
|
||||||
|
|
||||||
|
let info_result = info_handle
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("歌曲信息获取失败: {e}"))??;
|
||||||
|
|
||||||
|
Ok(info_result
|
||||||
|
.playlist
|
||||||
|
.tracks
|
||||||
|
.iter()
|
||||||
|
.map(|track| track.id)
|
||||||
|
.collect::<Vec<i64>>())
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user