147 lines
5.3 KiB
Rust
147 lines
5.3 KiB
Rust
use std::collections::HashSet;
|
||
use std::sync::Arc;
|
||
|
||
use anyhow::Result;
|
||
use axum::Router;
|
||
use axum::extract::{Extension, Query};
|
||
use axum::routing::get;
|
||
use bili_sync_entity::*;
|
||
use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, QuerySelect};
|
||
|
||
use crate::api::request::{FollowedCollectionsRequest, FollowedUppersRequest};
|
||
use crate::api::response::{
|
||
CollectionWithSubscriptionStatus, CollectionsResponse, FavoriteWithSubscriptionStatus, FavoritesResponse,
|
||
UpperWithSubscriptionStatus, UppersResponse,
|
||
};
|
||
use crate::api::wrapper::{ApiError, ApiResponse};
|
||
use crate::bilibili::{BiliClient, Me};
|
||
|
||
pub(super) fn router() -> Router {
|
||
Router::new()
|
||
.route("/me/favorites", get(get_created_favorites))
|
||
.route("/me/collections", get(get_followed_collections))
|
||
.route("/me/uppers", get(get_followed_uppers))
|
||
}
|
||
|
||
/// 获取当前用户创建的收藏夹
|
||
pub async fn get_created_favorites(
|
||
Extension(db): Extension<Arc<DatabaseConnection>>,
|
||
Extension(bili_client): Extension<Arc<BiliClient>>,
|
||
) -> Result<ApiResponse<FavoritesResponse>, ApiError> {
|
||
let me = Me::new(bili_client.as_ref());
|
||
let bili_favorites = me.get_created_favorites().await?;
|
||
|
||
let favorites = if let Some(bili_favorites) = bili_favorites {
|
||
// b 站收藏夹相关接口使用的所谓 “fid” 其实是该处的 id,即 fid + mid 后两位
|
||
let bili_fids: Vec<_> = bili_favorites.iter().map(|fav| fav.id).collect();
|
||
|
||
let subscribed_fids: Vec<i64> = favorite::Entity::find()
|
||
.select_only()
|
||
.column(favorite::Column::FId)
|
||
.filter(favorite::Column::FId.is_in(bili_fids))
|
||
.into_tuple()
|
||
.all(db.as_ref())
|
||
.await?;
|
||
let subscribed_set: HashSet<i64> = subscribed_fids.into_iter().collect();
|
||
|
||
bili_favorites
|
||
.into_iter()
|
||
.map(|fav| FavoriteWithSubscriptionStatus {
|
||
title: fav.title,
|
||
media_count: fav.media_count,
|
||
// api 返回的 id 才是真实的 fid
|
||
fid: fav.id,
|
||
mid: fav.mid,
|
||
subscribed: subscribed_set.contains(&fav.id),
|
||
})
|
||
.collect()
|
||
} else {
|
||
vec![]
|
||
};
|
||
|
||
Ok(ApiResponse::ok(FavoritesResponse { favorites }))
|
||
}
|
||
|
||
/// 获取当前用户收藏的合集
|
||
pub async fn get_followed_collections(
|
||
Extension(db): Extension<Arc<DatabaseConnection>>,
|
||
Extension(bili_client): Extension<Arc<BiliClient>>,
|
||
Query(params): Query<FollowedCollectionsRequest>,
|
||
) -> Result<ApiResponse<CollectionsResponse>, ApiError> {
|
||
let me = Me::new(bili_client.as_ref());
|
||
let (page_num, page_size) = (params.page_num.unwrap_or(1), params.page_size.unwrap_or(50));
|
||
let bili_collections = me.get_followed_collections(page_num, page_size).await?;
|
||
|
||
let collections = if let Some(collection_list) = bili_collections.list {
|
||
let bili_sids: Vec<_> = collection_list.iter().map(|col| col.id).collect();
|
||
|
||
let subscribed_ids: Vec<i64> = collection::Entity::find()
|
||
.select_only()
|
||
.column(collection::Column::SId)
|
||
.filter(collection::Column::SId.is_in(bili_sids))
|
||
.into_tuple()
|
||
.all(db.as_ref())
|
||
.await?;
|
||
let subscribed_set: HashSet<i64> = subscribed_ids.into_iter().collect();
|
||
|
||
collection_list
|
||
.into_iter()
|
||
.map(|col| CollectionWithSubscriptionStatus {
|
||
title: col.title,
|
||
sid: col.id,
|
||
mid: col.mid,
|
||
invalid: col.state == 1,
|
||
subscribed: subscribed_set.contains(&col.id),
|
||
})
|
||
.collect()
|
||
} else {
|
||
vec![]
|
||
};
|
||
|
||
Ok(ApiResponse::ok(CollectionsResponse {
|
||
collections,
|
||
total: bili_collections.count,
|
||
}))
|
||
}
|
||
|
||
/// 获取当前用户关注的 UP 主
|
||
pub async fn get_followed_uppers(
|
||
Extension(db): Extension<Arc<DatabaseConnection>>,
|
||
Extension(bili_client): Extension<Arc<BiliClient>>,
|
||
Query(params): Query<FollowedUppersRequest>,
|
||
) -> Result<ApiResponse<UppersResponse>, ApiError> {
|
||
let me = Me::new(bili_client.as_ref());
|
||
let (page_num, page_size) = (params.page_num.unwrap_or(1), params.page_size.unwrap_or(20));
|
||
let bili_uppers = me.get_followed_uppers(page_num, page_size).await?;
|
||
|
||
let bili_uid: Vec<_> = bili_uppers.list.iter().map(|upper| upper.mid).collect();
|
||
|
||
let subscribed_ids: Vec<i64> = submission::Entity::find()
|
||
.select_only()
|
||
.column(submission::Column::UpperId)
|
||
.filter(submission::Column::UpperId.is_in(bili_uid))
|
||
.into_tuple()
|
||
.all(db.as_ref())
|
||
.await?;
|
||
let subscribed_set: HashSet<i64> = subscribed_ids.into_iter().collect();
|
||
|
||
let uppers = bili_uppers
|
||
.list
|
||
.into_iter()
|
||
.map(|upper| UpperWithSubscriptionStatus {
|
||
mid: upper.mid,
|
||
// 官方没有提供字段,但是可以使用这种方式简单判断下
|
||
invalid: upper.uname == "账号已注销" && upper.face == "https://i0.hdslb.com/bfs/face/member/noface.jpg",
|
||
uname: upper.uname,
|
||
face: upper.face,
|
||
sign: upper.sign,
|
||
subscribed: subscribed_set.contains(&upper.mid),
|
||
})
|
||
.collect();
|
||
|
||
Ok(ApiResponse::ok(UppersResponse {
|
||
uppers,
|
||
total: bili_uppers.total,
|
||
}))
|
||
}
|