mirror of
https://github.com/amtoaer/bili-sync.git
synced 2026-07-09 22:43:55 +08:00
refactor: 重构 nfo,增强拓展性和可读性,方便后续变更 (#345)
This commit is contained in:
@@ -1,213 +1,241 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bili_sync_entity::*;
|
use bili_sync_entity::*;
|
||||||
|
use chrono::NaiveDateTime;
|
||||||
use quick_xml::Error;
|
use quick_xml::Error;
|
||||||
use quick_xml::events::{BytesCData, BytesText};
|
use quick_xml::events::{BytesCData, BytesText};
|
||||||
use quick_xml::writer::Writer;
|
use quick_xml::writer::Writer;
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::{AsyncWriteExt, BufWriter};
|
||||||
|
|
||||||
use crate::config::NFOTimeType;
|
use crate::config::{CONFIG, NFOTimeType};
|
||||||
|
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
pub enum NFO<'a> {
|
||||||
pub enum NFOMode {
|
Movie(Movie<'a>),
|
||||||
MOVIE,
|
TVShow(TVShow<'a>),
|
||||||
TVSHOW,
|
Upper(Upper),
|
||||||
EPOSODE,
|
Episode(Episode<'a>),
|
||||||
UPPER,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ModelWrapper<'a> {
|
pub struct Movie<'a> {
|
||||||
Video(&'a video::Model),
|
pub name: &'a str,
|
||||||
Page(&'a page::Model),
|
pub intro: &'a str,
|
||||||
|
pub bvid: &'a str,
|
||||||
|
pub upper_id: i64,
|
||||||
|
pub upper_name: &'a str,
|
||||||
|
pub aired: NaiveDateTime,
|
||||||
|
pub tags: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NFOSerializer<'a>(pub ModelWrapper<'a>, pub NFOMode);
|
pub struct TVShow<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub intro: &'a str,
|
||||||
|
pub bvid: &'a str,
|
||||||
|
pub upper_id: i64,
|
||||||
|
pub upper_name: &'a str,
|
||||||
|
pub aired: NaiveDateTime,
|
||||||
|
pub tags: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
/// serde xml 似乎不太好用,先这么裸着写
|
pub struct Upper {
|
||||||
/// (真是又臭又长啊
|
pub upper_id: String,
|
||||||
impl NFOSerializer<'_> {
|
pub pubtime: NaiveDateTime,
|
||||||
pub async fn generate_nfo(self, nfo_time_type: &NFOTimeType) -> Result<String> {
|
}
|
||||||
|
|
||||||
|
pub struct Episode<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub pid: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NFO<'_> {
|
||||||
|
pub async fn generate_nfo(self) -> Result<String> {
|
||||||
let mut buffer = r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
let mut buffer = r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
"#
|
"#
|
||||||
.as_bytes()
|
.as_bytes()
|
||||||
.to_vec();
|
.to_vec();
|
||||||
let mut tokio_buffer = tokio::io::BufWriter::new(&mut buffer);
|
let mut tokio_buffer = BufWriter::new(&mut buffer);
|
||||||
let mut writer = Writer::new_with_indent(&mut tokio_buffer, b' ', 4);
|
let writer = Writer::new_with_indent(&mut tokio_buffer, b' ', 4);
|
||||||
match self {
|
match self {
|
||||||
NFOSerializer(ModelWrapper::Video(v), NFOMode::MOVIE) => {
|
NFO::Movie(movie) => {
|
||||||
let nfo_time = match nfo_time_type {
|
Self::write_movie_nfo(writer, movie).await?;
|
||||||
NFOTimeType::FavTime => v.favtime,
|
|
||||||
NFOTimeType::PubTime => v.pubtime,
|
|
||||||
};
|
|
||||||
writer
|
|
||||||
.create_element("movie")
|
|
||||||
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
|
||||||
writer
|
|
||||||
.create_element("plot")
|
|
||||||
.write_cdata_content_async(BytesCData::new(Self::format_plot(v)))
|
|
||||||
.await?;
|
|
||||||
writer.create_element("outline").write_empty_async().await?;
|
|
||||||
writer
|
|
||||||
.create_element("title")
|
|
||||||
.write_text_content_async(BytesText::new(&v.name))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("actor")
|
|
||||||
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
|
||||||
writer
|
|
||||||
.create_element("name")
|
|
||||||
.write_text_content_async(BytesText::new(&v.upper_id.to_string()))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("role")
|
|
||||||
.write_text_content_async(BytesText::new(&v.upper_name))
|
|
||||||
.await?;
|
|
||||||
Ok(writer)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("year")
|
|
||||||
.write_text_content_async(BytesText::new(&nfo_time.format("%Y").to_string()))
|
|
||||||
.await?;
|
|
||||||
if let Some(tags) = &v.tags {
|
|
||||||
let tags: Vec<String> = serde_json::from_value(tags.clone()).unwrap_or_default();
|
|
||||||
for tag in tags {
|
|
||||||
writer
|
|
||||||
.create_element("genre")
|
|
||||||
.write_text_content_async(BytesText::new(&tag))
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writer
|
|
||||||
.create_element("uniqueid")
|
|
||||||
.with_attribute(("type", "bilibili"))
|
|
||||||
.write_text_content_async(BytesText::new(&v.bvid))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("aired")
|
|
||||||
.write_text_content_async(BytesText::new(&nfo_time.format("%Y-%m-%d").to_string()))
|
|
||||||
.await?;
|
|
||||||
Ok(writer)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
NFOSerializer(ModelWrapper::Video(v), NFOMode::TVSHOW) => {
|
NFO::TVShow(tvshow) => {
|
||||||
let nfo_time = match nfo_time_type {
|
Self::write_tvshow_nfo(writer, tvshow).await?;
|
||||||
NFOTimeType::FavTime => v.favtime,
|
|
||||||
NFOTimeType::PubTime => v.pubtime,
|
|
||||||
};
|
|
||||||
writer
|
|
||||||
.create_element("tvshow")
|
|
||||||
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
|
||||||
writer
|
|
||||||
.create_element("plot")
|
|
||||||
.write_cdata_content_async(BytesCData::new(Self::format_plot(v)))
|
|
||||||
.await?;
|
|
||||||
writer.create_element("outline").write_empty_async().await?;
|
|
||||||
writer
|
|
||||||
.create_element("title")
|
|
||||||
.write_text_content_async(BytesText::new(&v.name))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("actor")
|
|
||||||
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
|
||||||
writer
|
|
||||||
.create_element("name")
|
|
||||||
.write_text_content_async(BytesText::new(&v.upper_id.to_string()))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("role")
|
|
||||||
.write_text_content_async(BytesText::new(&v.upper_name))
|
|
||||||
.await?;
|
|
||||||
Ok(writer)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("year")
|
|
||||||
.write_text_content_async(BytesText::new(&nfo_time.format("%Y").to_string()))
|
|
||||||
.await?;
|
|
||||||
if let Some(tags) = &v.tags {
|
|
||||||
let tags: Vec<String> = serde_json::from_value(tags.clone()).unwrap_or_default();
|
|
||||||
for tag in tags {
|
|
||||||
writer
|
|
||||||
.create_element("genre")
|
|
||||||
.write_text_content_async(BytesText::new(&tag))
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writer
|
|
||||||
.create_element("uniqueid")
|
|
||||||
.with_attribute(("type", "bilibili"))
|
|
||||||
.write_text_content_async(BytesText::new(&v.bvid))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("aired")
|
|
||||||
.write_text_content_async(BytesText::new(&nfo_time.format("%Y-%m-%d").to_string()))
|
|
||||||
.await?;
|
|
||||||
Ok(writer)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
NFOSerializer(ModelWrapper::Video(v), NFOMode::UPPER) => {
|
NFO::Upper(upper) => {
|
||||||
writer
|
Self::write_upper_nfo(writer, upper).await?;
|
||||||
.create_element("person")
|
|
||||||
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
|
||||||
writer.create_element("plot").write_empty_async().await?;
|
|
||||||
writer.create_element("outline").write_empty_async().await?;
|
|
||||||
writer
|
|
||||||
.create_element("lockdata")
|
|
||||||
.write_text_content_async(BytesText::new("false"))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("dateadded")
|
|
||||||
.write_text_content_async(BytesText::new(
|
|
||||||
&v.pubtime.format("%Y-%m-%d %H:%M:%S").to_string(),
|
|
||||||
))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("title")
|
|
||||||
.write_text_content_async(BytesText::new(&v.upper_id.to_string()))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("sorttitle")
|
|
||||||
.write_text_content_async(BytesText::new(&v.upper_id.to_string()))
|
|
||||||
.await?;
|
|
||||||
Ok(writer)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
NFOSerializer(ModelWrapper::Page(p), NFOMode::EPOSODE) => {
|
NFO::Episode(episode) => {
|
||||||
writer
|
Self::write_episode_nfo(writer, episode).await?;
|
||||||
.create_element("episodedetails")
|
|
||||||
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
|
||||||
writer.create_element("plot").write_empty_async().await?;
|
|
||||||
writer.create_element("outline").write_empty_async().await?;
|
|
||||||
writer
|
|
||||||
.create_element("title")
|
|
||||||
.write_text_content_async(BytesText::new(&p.name))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("season")
|
|
||||||
.write_text_content_async(BytesText::new("1"))
|
|
||||||
.await?;
|
|
||||||
writer
|
|
||||||
.create_element("episode")
|
|
||||||
.write_text_content_async(BytesText::new(&p.pid.to_string()))
|
|
||||||
.await?;
|
|
||||||
Ok(writer)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
tokio_buffer.flush().await?;
|
tokio_buffer.flush().await?;
|
||||||
Ok(String::from_utf8(buffer)?)
|
Ok(String::from_utf8(buffer)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn write_movie_nfo(mut writer: Writer<&mut BufWriter<&mut Vec<u8>>>, movie: Movie<'_>) -> Result<()> {
|
||||||
|
writer
|
||||||
|
.create_element("movie")
|
||||||
|
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
||||||
|
writer
|
||||||
|
.create_element("plot")
|
||||||
|
.write_cdata_content_async(BytesCData::new(Self::format_plot(movie.bvid, movie.intro)))
|
||||||
|
.await?;
|
||||||
|
writer.create_element("outline").write_empty_async().await?;
|
||||||
|
writer
|
||||||
|
.create_element("title")
|
||||||
|
.write_text_content_async(BytesText::new(movie.name))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("actor")
|
||||||
|
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
||||||
|
writer
|
||||||
|
.create_element("name")
|
||||||
|
.write_text_content_async(BytesText::new(&movie.upper_id.to_string()))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("role")
|
||||||
|
.write_text_content_async(BytesText::new(movie.upper_name))
|
||||||
|
.await?;
|
||||||
|
Ok(writer)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("year")
|
||||||
|
.write_text_content_async(BytesText::new(&movie.aired.format("%Y").to_string()))
|
||||||
|
.await?;
|
||||||
|
if let Some(tags) = movie.tags {
|
||||||
|
for tag in tags {
|
||||||
|
writer
|
||||||
|
.create_element("genre")
|
||||||
|
.write_text_content_async(BytesText::new(&tag))
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer
|
||||||
|
.create_element("uniqueid")
|
||||||
|
.with_attribute(("type", "bilibili"))
|
||||||
|
.write_text_content_async(BytesText::new(movie.bvid))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("aired")
|
||||||
|
.write_text_content_async(BytesText::new(&movie.aired.format("%Y-%m-%d").to_string()))
|
||||||
|
.await?;
|
||||||
|
Ok(writer)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write_tvshow_nfo(mut writer: Writer<&mut BufWriter<&mut Vec<u8>>>, tvshow: TVShow<'_>) -> Result<()> {
|
||||||
|
writer
|
||||||
|
.create_element("tvshow")
|
||||||
|
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
||||||
|
writer
|
||||||
|
.create_element("plot")
|
||||||
|
.write_cdata_content_async(BytesCData::new(Self::format_plot(tvshow.bvid, tvshow.intro)))
|
||||||
|
.await?;
|
||||||
|
writer.create_element("outline").write_empty_async().await?;
|
||||||
|
writer
|
||||||
|
.create_element("title")
|
||||||
|
.write_text_content_async(BytesText::new(tvshow.name))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("actor")
|
||||||
|
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
||||||
|
writer
|
||||||
|
.create_element("name")
|
||||||
|
.write_text_content_async(BytesText::new(&tvshow.upper_id.to_string()))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("role")
|
||||||
|
.write_text_content_async(BytesText::new(tvshow.upper_name))
|
||||||
|
.await?;
|
||||||
|
Ok(writer)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("year")
|
||||||
|
.write_text_content_async(BytesText::new(&tvshow.aired.format("%Y").to_string()))
|
||||||
|
.await?;
|
||||||
|
if let Some(tags) = tvshow.tags {
|
||||||
|
for tag in tags {
|
||||||
|
writer
|
||||||
|
.create_element("genre")
|
||||||
|
.write_text_content_async(BytesText::new(&tag))
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer
|
||||||
|
.create_element("uniqueid")
|
||||||
|
.with_attribute(("type", "bilibili"))
|
||||||
|
.write_text_content_async(BytesText::new(tvshow.bvid))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("aired")
|
||||||
|
.write_text_content_async(BytesText::new(&tvshow.aired.format("%Y-%m-%d").to_string()))
|
||||||
|
.await?;
|
||||||
|
Ok(writer)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write_upper_nfo(mut writer: Writer<&mut BufWriter<&mut Vec<u8>>>, upper: Upper) -> Result<()> {
|
||||||
|
writer
|
||||||
|
.create_element("person")
|
||||||
|
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
||||||
|
writer.create_element("plot").write_empty_async().await?;
|
||||||
|
writer.create_element("outline").write_empty_async().await?;
|
||||||
|
writer
|
||||||
|
.create_element("lockdata")
|
||||||
|
.write_text_content_async(BytesText::new("false"))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("dateadded")
|
||||||
|
.write_text_content_async(BytesText::new(&upper.pubtime.format("%Y-%m-%d %H:%M:%S").to_string()))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("title")
|
||||||
|
.write_text_content_async(BytesText::new(&upper.upper_id))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("sorttitle")
|
||||||
|
.write_text_content_async(BytesText::new(&upper.upper_id))
|
||||||
|
.await?;
|
||||||
|
Ok(writer)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write_episode_nfo(mut writer: Writer<&mut BufWriter<&mut Vec<u8>>>, episode: Episode<'_>) -> Result<()> {
|
||||||
|
writer
|
||||||
|
.create_element("episodedetails")
|
||||||
|
.write_inner_content_async::<_, _, Error>(|writer| async move {
|
||||||
|
writer.create_element("plot").write_empty_async().await?;
|
||||||
|
writer.create_element("outline").write_empty_async().await?;
|
||||||
|
writer
|
||||||
|
.create_element("title")
|
||||||
|
.write_text_content_async(BytesText::new(episode.name))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("season")
|
||||||
|
.write_text_content_async(BytesText::new("1"))
|
||||||
|
.await?;
|
||||||
|
writer
|
||||||
|
.create_element("episode")
|
||||||
|
.write_text_content_async(BytesText::new(&episode.pid))
|
||||||
|
.await?;
|
||||||
|
Ok(writer)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn format_plot(model: &video::Model) -> String {
|
fn format_plot(bvid: &str, intro: &str) -> String {
|
||||||
format!(
|
format!(
|
||||||
r#"原始视频:<a href="https://www.bilibili.com/video/{}/">{}</a><br/><br/>{}"#,
|
r#"原始视频:<a href="https://www.bilibili.com/video/{}/">{}</a><br/><br/>{}"#,
|
||||||
model.bvid, model.bvid, model.intro
|
bvid, bvid, intro,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,10 +264,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
NFOSerializer(ModelWrapper::Video(&video), NFOMode::MOVIE)
|
NFO::Movie((&video).into()).generate_nfo().await.unwrap(),
|
||||||
.generate_nfo(&NFOTimeType::PubTime)
|
|
||||||
.await
|
|
||||||
.unwrap(),
|
|
||||||
r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
<movie>
|
<movie>
|
||||||
<plot><![CDATA[原始视频:<a href="https://www.bilibili.com/video/BV1nWcSeeEkV/">BV1nWcSeeEkV</a><br/><br/>intro]]></plot>
|
<plot><![CDATA[原始视频:<a href="https://www.bilibili.com/video/BV1nWcSeeEkV/">BV1nWcSeeEkV</a><br/><br/>intro]]></plot>
|
||||||
@@ -249,18 +274,15 @@ mod tests {
|
|||||||
<name>1</name>
|
<name>1</name>
|
||||||
<role>upper_name</role>
|
<role>upper_name</role>
|
||||||
</actor>
|
</actor>
|
||||||
<year>2033</year>
|
<year>2022</year>
|
||||||
<genre>tag1</genre>
|
<genre>tag1</genre>
|
||||||
<genre>tag2</genre>
|
<genre>tag2</genre>
|
||||||
<uniqueid type="bilibili">BV1nWcSeeEkV</uniqueid>
|
<uniqueid type="bilibili">BV1nWcSeeEkV</uniqueid>
|
||||||
<aired>2033-03-03</aired>
|
<aired>2022-02-02</aired>
|
||||||
</movie>"#,
|
</movie>"#,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
NFOSerializer(ModelWrapper::Video(&video), NFOMode::TVSHOW)
|
NFO::TVShow((&video).into()).generate_nfo().await.unwrap(),
|
||||||
.generate_nfo(&NFOTimeType::FavTime)
|
|
||||||
.await
|
|
||||||
.unwrap(),
|
|
||||||
r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
<tvshow>
|
<tvshow>
|
||||||
<plot><![CDATA[原始视频:<a href="https://www.bilibili.com/video/BV1nWcSeeEkV/">BV1nWcSeeEkV</a><br/><br/>intro]]></plot>
|
<plot><![CDATA[原始视频:<a href="https://www.bilibili.com/video/BV1nWcSeeEkV/">BV1nWcSeeEkV</a><br/><br/>intro]]></plot>
|
||||||
@@ -278,10 +300,7 @@ mod tests {
|
|||||||
</tvshow>"#,
|
</tvshow>"#,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
NFOSerializer(ModelWrapper::Video(&video), NFOMode::UPPER)
|
NFO::Upper((&video).into()).generate_nfo().await.unwrap(),
|
||||||
.generate_nfo(&NFOTimeType::FavTime)
|
|
||||||
.await
|
|
||||||
.unwrap(),
|
|
||||||
r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
<person>
|
<person>
|
||||||
<plot/>
|
<plot/>
|
||||||
@@ -298,10 +317,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
NFOSerializer(ModelWrapper::Page(&page), NFOMode::EPOSODE)
|
NFO::Episode((&page).into()).generate_nfo().await.unwrap(),
|
||||||
.generate_nfo(&NFOTimeType::FavTime)
|
|
||||||
.await
|
|
||||||
.unwrap(),
|
|
||||||
r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
<episodedetails>
|
<episodedetails>
|
||||||
<plot/>
|
<plot/>
|
||||||
@@ -313,3 +329,61 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a video::Model> for Movie<'a> {
|
||||||
|
fn from(video: &'a video::Model) -> Self {
|
||||||
|
Self {
|
||||||
|
name: &video.name,
|
||||||
|
intro: &video.intro,
|
||||||
|
bvid: &video.bvid,
|
||||||
|
upper_id: video.upper_id,
|
||||||
|
upper_name: &video.upper_name,
|
||||||
|
aired: match CONFIG.nfo_time_type {
|
||||||
|
NFOTimeType::FavTime => video.favtime,
|
||||||
|
NFOTimeType::PubTime => video.pubtime,
|
||||||
|
},
|
||||||
|
tags: video
|
||||||
|
.tags
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|tags| serde_json::from_value(tags.clone()).ok()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a video::Model> for TVShow<'a> {
|
||||||
|
fn from(video: &'a video::Model) -> Self {
|
||||||
|
Self {
|
||||||
|
name: &video.name,
|
||||||
|
intro: &video.intro,
|
||||||
|
bvid: &video.bvid,
|
||||||
|
upper_id: video.upper_id,
|
||||||
|
upper_name: &video.upper_name,
|
||||||
|
aired: match CONFIG.nfo_time_type {
|
||||||
|
NFOTimeType::FavTime => video.favtime,
|
||||||
|
NFOTimeType::PubTime => video.pubtime,
|
||||||
|
},
|
||||||
|
tags: video
|
||||||
|
.tags
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|tags| serde_json::from_value(tags.clone()).ok()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a video::Model> for Upper {
|
||||||
|
fn from(video: &'a video::Model) -> Self {
|
||||||
|
Self {
|
||||||
|
upper_id: video.upper_id.to_string(),
|
||||||
|
pubtime: video.pubtime,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a page::Model> for Episode<'a> {
|
||||||
|
fn from(page: &'a page::Model) -> Self {
|
||||||
|
Self {
|
||||||
|
name: &page.name,
|
||||||
|
pid: page.pid.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use crate::utils::model::{
|
|||||||
create_pages, create_videos, filter_unfilled_videos, filter_unhandled_video_pages, update_pages_model,
|
create_pages, create_videos, filter_unfilled_videos, filter_unhandled_video_pages, update_pages_model,
|
||||||
update_videos_model,
|
update_videos_model,
|
||||||
};
|
};
|
||||||
use crate::utils::nfo::{ModelWrapper, NFOMode, NFOSerializer};
|
use crate::utils::nfo::NFO;
|
||||||
use crate::utils::status::{PageStatus, STATUS_OK, VideoStatus};
|
use crate::utils::status::{PageStatus, STATUS_OK, VideoStatus};
|
||||||
|
|
||||||
/// 完整地处理某个视频来源
|
/// 完整地处理某个视频来源
|
||||||
@@ -618,12 +618,12 @@ pub async fn generate_page_nfo(
|
|||||||
return Ok(ExecutionStatus::Skipped);
|
return Ok(ExecutionStatus::Skipped);
|
||||||
}
|
}
|
||||||
let single_page = video_model.single_page.context("single_page is null")?;
|
let single_page = video_model.single_page.context("single_page is null")?;
|
||||||
let nfo_serializer = if single_page {
|
let nfo = if single_page {
|
||||||
NFOSerializer(ModelWrapper::Video(video_model), NFOMode::MOVIE)
|
NFO::Movie(video_model.into())
|
||||||
} else {
|
} else {
|
||||||
NFOSerializer(ModelWrapper::Page(page_model), NFOMode::EPOSODE)
|
NFO::Episode(page_model.into())
|
||||||
};
|
};
|
||||||
generate_nfo(nfo_serializer, nfo_path).await?;
|
generate_nfo(nfo, nfo_path).await?;
|
||||||
Ok(ExecutionStatus::Succeeded)
|
Ok(ExecutionStatus::Succeeded)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -663,8 +663,7 @@ pub async fn generate_upper_nfo(
|
|||||||
if !should_run {
|
if !should_run {
|
||||||
return Ok(ExecutionStatus::Skipped);
|
return Ok(ExecutionStatus::Skipped);
|
||||||
}
|
}
|
||||||
let nfo_serializer = NFOSerializer(ModelWrapper::Video(video_model), NFOMode::UPPER);
|
generate_nfo(NFO::Upper(video_model.into()), nfo_path).await?;
|
||||||
generate_nfo(nfo_serializer, nfo_path).await?;
|
|
||||||
Ok(ExecutionStatus::Succeeded)
|
Ok(ExecutionStatus::Succeeded)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,21 +675,16 @@ pub async fn generate_video_nfo(
|
|||||||
if !should_run {
|
if !should_run {
|
||||||
return Ok(ExecutionStatus::Skipped);
|
return Ok(ExecutionStatus::Skipped);
|
||||||
}
|
}
|
||||||
let nfo_serializer = NFOSerializer(ModelWrapper::Video(video_model), NFOMode::TVSHOW);
|
generate_nfo(NFO::TVShow(video_model.into()), nfo_path).await?;
|
||||||
generate_nfo(nfo_serializer, nfo_path).await?;
|
|
||||||
Ok(ExecutionStatus::Succeeded)
|
Ok(ExecutionStatus::Succeeded)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 创建 nfo_path 的父目录,然后写入 nfo 文件
|
/// 创建 nfo_path 的父目录,然后写入 nfo 文件
|
||||||
async fn generate_nfo(serializer: NFOSerializer<'_>, nfo_path: PathBuf) -> Result<()> {
|
async fn generate_nfo(nfo: NFO<'_>, nfo_path: PathBuf) -> Result<()> {
|
||||||
if let Some(parent) = nfo_path.parent() {
|
if let Some(parent) = nfo_path.parent() {
|
||||||
fs::create_dir_all(parent).await?;
|
fs::create_dir_all(parent).await?;
|
||||||
}
|
}
|
||||||
fs::write(
|
fs::write(nfo_path, nfo.generate_nfo().await?.as_bytes()).await?;
|
||||||
nfo_path,
|
|
||||||
serializer.generate_nfo(&CONFIG.nfo_time_type).await?.as_bytes(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user