diff --git a/crates/recorder/src/migrations/m20220101_000001_init.rs b/crates/recorder/src/migrations/m20220101_000001_init.rs index dc23580..6026152 100644 --- a/crates/recorder/src/migrations/m20220101_000001_init.rs +++ b/crates/recorder/src/migrations/m20220101_000001_init.rs @@ -43,7 +43,6 @@ impl MigrationTrait for Migration { &[ subscriptions::SubscriptionCategory::Mikan, subscriptions::SubscriptionCategory::Manual, - subscriptions::SubscriptionCategory::Bangumi, ], ) .await?; diff --git a/crates/recorder/src/models/_entities/subscriptions.rs b/crates/recorder/src/models/_entities/subscriptions.rs index 0908b54..50970b7 100644 --- a/crates/recorder/src/models/_entities/subscriptions.rs +++ b/crates/recorder/src/models/_entities/subscriptions.rs @@ -4,12 +4,12 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; #[derive( - Clone, Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize, DeriveDisplay, +Clone, Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize, DeriveDisplay, )] #[sea_orm( - rs_type = "String", - db_type = "Enum", - enum_name = "subscription_category" +rs_type = "String", +db_type = "Enum", +enum_name = "subscription_category" )] #[serde(rename_all = "snake_case")] pub enum SubscriptionCategory { @@ -17,8 +17,6 @@ pub enum SubscriptionCategory { Mikan, #[sea_orm(string_value = "manual")] Manual, - #[sea_orm(string_value = "bangumi")] - Bangumi, } #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] @@ -41,9 +39,9 @@ pub struct Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( - belongs_to = "super::subscribers::Entity", - from = "Column::SubscriberId", - to = "super::subscribers::Column::Id" + belongs_to = "super::subscribers::Entity", + from = "Column::SubscriberId", + to = "super::subscribers::Column::Id" )] Subscriber, #[sea_orm(has_many = "super::bangumi::Entity")] diff --git a/crates/recorder/src/models/downloads.rs b/crates/recorder/src/models/downloads.rs index 497ed45..3575b02 100644 --- a/crates/recorder/src/models/downloads.rs +++ b/crates/recorder/src/models/downloads.rs @@ -1,67 +1,91 @@ -use std::collections::HashMap; -use sea_orm::{prelude::*, ActiveValue, Condition, QuerySelect, SelectColumns}; +use sea_orm::{prelude::*, ActiveValue, Condition, QuerySelect, QueryOrder}; +use sea_orm::sea_query::OnConflict; use crate::models::_entities::downloads::*; use crate::models::prelude::{SubscriptionCategory, subscriptions}; -use crate::subscriptions::mikan::MikanSubscriptionEngine; +use crate::subscriptions::mikan::{MikanSubscriptionEngine, MikanSubscriptionItem}; #[async_trait::async_trait] impl ActiveModelBehavior for ActiveModel {} +impl ActiveModel { + pub fn from_mikan_subscription_item(m: MikanSubscriptionItem, subscription_id: i32) -> Self { + Self { + origin_name: ActiveValue::Set(m.title.clone()), + display_name: ActiveValue::Set(m.title), + subscription_id: ActiveValue::Set(subscription_id), + status: ActiveValue::Set(DownloadStatus::Pending), + mime: ActiveValue::Set(DownloadMime::BitTorrent), + url: ActiveValue::Set(m.url), + all_size: ActiveValue::Set(m.content_length.unwrap_or_default()), + curr_size: ActiveValue::Set(0), + ..Default::default() + } + } +} + impl Model { pub async fn pull_subscription( db: &DatabaseConnection, item: &subscriptions::Model, - ) -> eyre::Result<()> { + ) -> eyre::Result> { match &item.category { SubscriptionCategory::Mikan => { let items = MikanSubscriptionEngine::subscription_items_from_rss_url(&item.source_url). await?; - let items = items.collect::>(); - let mut all_items = items - .into_iter() - .map(|item| (item.url.clone(), item)) - .collect::>(); + let all_items = items.collect::>(); - let existed_items = { + let last_old_id = { Entity::find() - .filter( - Condition::all() - .add(Column::SubscriptionId.eq(item.id)) - .add(Column::Url.is_in(all_items.keys().cloned())) - ) .select_only() - .select_column(Column::Url) - .all(db).await? - }; + .column(Column::Id) + .order_by_desc(Column::Id) + .filter(Column::SubscriptionId.eq(item.id)) + .one(db).await? + }.map(|i| i.id); - for dl in existed_items { - all_items.remove(&dl.url as &str); + if all_items.is_empty() { + return Ok(vec![]); } - let new_items = all_items.into_values().map(|i| { - ActiveModel { - origin_name: ActiveValue::Set(i.title.clone()), - display_name: ActiveValue::Set(i.title), - subscription_id: ActiveValue::Set(item.id), - status: ActiveValue::Set(DownloadStatus::Pending), - mime: ActiveValue::Set(DownloadMime::BitTorrent), - url: ActiveValue::Set(i.url), - all_size: ActiveValue::Set(i.content_length.unwrap_or_default()), - curr_size: ActiveValue::Set(0), - ..Default::default() - } + let new_items = all_items.into_iter().map(|i| { + ActiveModel::from_mikan_subscription_item(i, item.id) }); - Entity::insert_many(new_items) + let insert_result = Entity::insert_many(new_items) + .on_conflict( + OnConflict::column(Column::Url) + .do_nothing() + .to_owned() + ) .exec(db) .await?; + + let insert_ids = Entity::find() + .select_only() + .column(Column::Id) + .filter({ + let mut cond = Condition::all() + .add(Column::SubscriptionId.eq(item.id)) + .add(Column::Id.lte(insert_result.last_insert_id)); + + if let Some(last_old_id) = last_old_id { + cond = cond.add( + Column::Id.gt(last_old_id) + ) + } + + cond + }) + .all(db) + .await?; + + Ok(insert_ids.into_iter().map(|i| i.id).collect::>()) } _ => { todo!("other subscription categories") } } - Ok(()) } }