use crate::{AppService, error::AppError}; use chrono::Utc; use models::users::user_relation; use sea_orm::*; use serde::{Deserialize, Serialize}; use session::Session; use uuid::Uuid; #[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)] pub struct SubscriptionInfo { pub id: i64, pub user_uid: Uuid, pub target_uid: Uuid, pub subscribed_at: chrono::DateTime, pub is_active: bool, } impl From for SubscriptionInfo { fn from(sub: user_relation::Model) -> Self { SubscriptionInfo { id: sub.id, user_uid: sub.user, target_uid: sub.target, subscribed_at: sub.created_at, is_active: true, // user_relation doesn't have is_active, we treat follow as active } } } impl AppService { pub async fn user_subscribe_target( &self, context: Session, target: String, ) -> Result<(), AppError> { let user_uid = context.user().ok_or(AppError::Unauthorized)?; let target_user = self.utils_find_user_by_username(target).await?; let target_uid = target_user.uid; let existing = user_relation::Entity::find() .filter(user_relation::Column::User.eq(user_uid)) .filter(user_relation::Column::Target.eq(target_uid)) .filter(user_relation::Column::RelationType.eq("follow")) .one(&self.db) .await?; if existing.is_some() { return Err(AppError::NotFound("Already subscribed".to_string())); } let subscription = user_relation::ActiveModel { user: Set(user_uid), target: Set(target_uid), relation_type: Set("follow".to_string()), created_at: Set(Utc::now()), ..Default::default() }; subscription.insert(&self.db).await?; Ok(()) } pub async fn user_unsubscribe_target( &self, context: Session, target: String, ) -> Result<(), AppError> { let user_uid = context.user().ok_or(AppError::Unauthorized)?; let target_user = self.utils_find_user_by_username(target).await?; let target_uid = target_user.uid; user_relation::Entity::delete_many() .filter(user_relation::Column::User.eq(user_uid)) .filter(user_relation::Column::Target.eq(target_uid)) .filter(user_relation::Column::RelationType.eq("follow")) .exec(&self.db) .await?; Ok(()) } pub async fn user_is_subscribed_to_target( &self, context: Session, target: String, ) -> Result { let user_uid = context.user().ok_or(AppError::Unauthorized)?; let target_user = self.utils_find_user_by_username(target).await?; let target_uid = target_user.uid; let subscription = user_relation::Entity::find() .filter(user_relation::Column::User.eq(user_uid)) .filter(user_relation::Column::Target.eq(target_uid)) .filter(user_relation::Column::RelationType.eq("follow")) .one(&self.db) .await?; Ok(subscription.is_some()) } pub async fn user_get_subscribers( &self, _context: Session, target: String, ) -> Result, AppError> { let target_user = self.utils_find_user_by_username(target).await?; let target_uid = target_user.uid; let subscribers = user_relation::Entity::find() .filter(user_relation::Column::Target.eq(target_uid)) .filter(user_relation::Column::RelationType.eq("follow")) .order_by_desc(user_relation::Column::CreatedAt) .all(&self.db) .await?; Ok(subscribers .into_iter() .map(SubscriptionInfo::from) .collect()) } pub async fn user_get_subscription_count( &self, _context: Session, username: String, ) -> Result { let user_uid = self.utils_find_user_by_username(username).await?.uid; let count = user_relation::Entity::find() .filter(user_relation::Column::User.eq(user_uid)) .filter(user_relation::Column::RelationType.eq("follow")) .count(&self.db) .await?; Ok(count) } pub async fn user_get_subscriber_count( &self, _context: Session, target: String, ) -> Result { let target_user = self.utils_find_user_by_username(target).await?; let target_uid = target_user.uid; let count = user_relation::Entity::find() .filter(user_relation::Column::Target.eq(target_uid)) .filter(user_relation::Column::RelationType.eq("follow")) .count(&self.db) .await?; Ok(count) } }