fix: add sync subscription webui and check credential web ui

This commit is contained in:
2025-06-08 00:36:59 +08:00
parent 946d4e8c2c
commit d2aab7369d
46 changed files with 1120 additions and 195 deletions

View File

@@ -1,4 +1,4 @@
use std::{fmt::Debug, ops::Deref, sync::Arc};
use std::{fmt::Debug, ops::Deref};
use fetch::{HttpClient, HttpClientTrait};
use maplit::hashmap;
@@ -136,7 +136,7 @@ impl MikanClient {
pub async fn submit_credential_form(
&self,
ctx: Arc<dyn AppContextTrait>,
ctx: &dyn AppContextTrait,
subscriber_id: i32,
credential_form: MikanCredentialForm,
) -> RecorderResult<credential_3rd::Model> {
@@ -149,7 +149,7 @@ impl MikanClient {
subscriber_id: Set(subscriber_id),
..Default::default()
}
.try_encrypt(ctx.clone())
.try_encrypt(ctx)
.await?;
let credential: credential_3rd::Model = am.save(db).await?.try_into_model()?;
@@ -158,8 +158,9 @@ impl MikanClient {
pub async fn sync_credential_cookies(
&self,
ctx: Arc<dyn AppContextTrait>,
ctx: &dyn AppContextTrait,
credential_id: i32,
subscriber_id: i32,
) -> RecorderResult<()> {
let cookies = self.http_client.save_cookie_store_to_json()?;
if let Some(cookies) = cookies {
@@ -167,19 +168,20 @@ impl MikanClient {
cookies: Set(Some(cookies)),
..Default::default()
}
.try_encrypt(ctx.clone())
.try_encrypt(ctx)
.await?;
credential_3rd::Entity::update_many()
.set(am)
.filter(credential_3rd::Column::Id.eq(credential_id))
.filter(credential_3rd::Column::SubscriberId.eq(subscriber_id))
.exec(ctx.db())
.await?;
}
Ok(())
}
pub async fn fork_with_credential(
pub async fn fork_with_userpass_credential(
&self,
userpass_credential: UserPassCredential,
) -> RecorderResult<Self> {
@@ -204,10 +206,13 @@ impl MikanClient {
pub async fn fork_with_credential_id(
&self,
ctx: Arc<dyn AppContextTrait>,
ctx: &dyn AppContextTrait,
credential_id: i32,
subscriber_id: i32,
) -> RecorderResult<Self> {
let credential = credential_3rd::Model::find_by_id(ctx.clone(), credential_id).await?;
let credential =
credential_3rd::Model::find_by_id_and_subscriber_id(ctx, credential_id, subscriber_id)
.await?;
if let Some(credential) = credential {
if credential.credential_type != Credential3rdType::Mikan {
return Err(RecorderError::Credential3rdError {
@@ -219,7 +224,8 @@ impl MikanClient {
let userpass_credential: UserPassCredential =
credential.try_into_userpass_credential(ctx)?;
self.fork_with_credential(userpass_credential).await
self.fork_with_userpass_credential(userpass_credential)
.await
} else {
Err(RecorderError::from_db_record_not_found(
DbErr::RecordNotFound(format!("credential={credential_id} not found")),
@@ -249,7 +255,7 @@ impl HttpClientTrait for MikanClient {}
#[cfg(test)]
mod tests {
#![allow(unused_variables)]
use std::assert_matches::assert_matches;
use std::{assert_matches::assert_matches, sync::Arc};
use rstest::{fixture, rstest};
use tracing::Level;
@@ -297,8 +303,10 @@ mod tests {
let credential_form = build_testing_mikan_credential_form();
let subscriber_id = 1;
let credential_model = mikan_client
.submit_credential_form(app_ctx.clone(), 1, credential_form.clone())
.submit_credential_form(app_ctx.as_ref(), subscriber_id, credential_form.clone())
.await?;
let expected_username = &credential_form.username;
@@ -322,7 +330,7 @@ mod tests {
);
let mikan_client = mikan_client
.fork_with_credential_id(app_ctx.clone(), credential_model.id)
.fork_with_credential_id(app_ctx.as_ref(), credential_model.id, subscriber_id)
.await?;
mikan_client.login().await?;

View File

@@ -2,7 +2,7 @@ use fetch::HttpClientConfig;
use serde::{Deserialize, Serialize};
use url::Url;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MikanConfig {
pub http_client: HttpClientConfig,
pub base_url: Url,

View File

@@ -387,6 +387,7 @@ impl MikanSeasonSubscription {
ctx,
mikan_season_flow_url,
credential_id,
self.get_subscriber_id(),
)
}

View File

@@ -917,10 +917,11 @@ pub fn scrape_mikan_bangumi_meta_stream_from_season_flow_url(
ctx: Arc<dyn AppContextTrait>,
mikan_season_flow_url: Url,
credential_id: i32,
subscriber_id: i32,
) -> impl Stream<Item = RecorderResult<MikanBangumiMeta>> {
try_stream! {
let mikan_base_url = ctx.mikan().base_url().clone();
let mikan_client = ctx.mikan().fork_with_credential_id(ctx.clone(), credential_id).await?;
let mikan_client = ctx.mikan().fork_with_credential_id(ctx.as_ref(), credential_id, subscriber_id).await?;
let content = fetch_html(&mikan_client, mikan_season_flow_url.clone()).await?;
@@ -940,7 +941,7 @@ pub fn scrape_mikan_bangumi_meta_stream_from_season_flow_url(
mikan_client
.sync_credential_cookies(ctx.clone(), credential_id)
.sync_credential_cookies(ctx.as_ref(), credential_id, subscriber_id)
.await?;
for bangumi_index in bangumi_indices_meta {
@@ -969,7 +970,7 @@ pub fn scrape_mikan_bangumi_meta_stream_from_season_flow_url(
}
mikan_client
.sync_credential_cookies(ctx, credential_id)
.sync_credential_cookies(ctx.as_ref(), credential_id, subscriber_id)
.await?;
}
}
@@ -978,11 +979,13 @@ pub async fn scrape_mikan_bangumi_meta_list_from_season_flow_url(
ctx: Arc<dyn AppContextTrait>,
mikan_season_flow_url: Url,
credential_id: i32,
subscriber_id: i32,
) -> RecorderResult<Vec<MikanBangumiMeta>> {
let stream = scrape_mikan_bangumi_meta_stream_from_season_flow_url(
ctx,
mikan_season_flow_url,
credential_id,
subscriber_id,
);
pin_mut!(stream);
@@ -1160,7 +1163,7 @@ mod test {
let mikan_client = build_testing_mikan_client(mikan_base_url.clone())
.await?
.fork_with_credential(build_testing_mikan_credential())
.fork_with_userpass_credential(build_testing_mikan_credential())
.await?;
mikan_client.login().await?;
@@ -1268,8 +1271,14 @@ mod test {
let mikan_client = app_ctx.mikan();
let subscriber_id = 1;
let credential = mikan_client
.submit_credential_form(app_ctx.clone(), 1, build_testing_mikan_credential_form())
.submit_credential_form(
app_ctx.as_ref(),
subscriber_id,
build_testing_mikan_credential_form(),
)
.await?;
let mikan_season_flow_url =
@@ -1279,6 +1288,7 @@ mod test {
app_ctx.clone(),
mikan_season_flow_url,
credential.id,
subscriber_id,
);
pin_mut!(bangumi_meta_stream);