feat(domain): models

This commit is contained in:
2026-05-14 03:18:49 +02:00
parent 94a3f414e4
commit 4b8d1027c1
14 changed files with 238 additions and 1 deletions

View File

@@ -0,0 +1 @@
// filled in Task 4

View File

@@ -1,3 +1,8 @@
pub mod errors; pub mod errors;
pub mod events;
pub mod models;
pub mod ports;
pub mod value_objects; pub mod value_objects;
// remaining modules added in later tasks
#[cfg(any(test, feature = "test-helpers"))]
pub mod testing;

View File

@@ -0,0 +1,11 @@
use chrono::{DateTime, Utc};
use crate::value_objects::{ApiKeyId, UserId};
#[derive(Debug, Clone)]
pub struct ApiKey {
pub id: ApiKeyId,
pub user_id: UserId,
pub key_hash: String,
pub name: String,
pub created_at: DateTime<Utc>,
}

View File

@@ -0,0 +1,40 @@
use crate::models::{user::User, thought::Thought};
use crate::value_objects::UserId;
#[derive(Debug, Clone)]
pub struct UserSummary {
pub id: UserId,
pub username: String,
pub display_name: Option<String>,
pub avatar_url: Option<String>,
pub bio: Option<String>,
pub thought_count: i64,
pub follower_count: i64,
pub following_count: i64,
}
#[derive(Debug, Clone)]
pub struct FeedEntry {
pub thought: Thought,
pub author: User,
pub like_count: i64,
pub boost_count: i64,
pub reply_count: i64,
pub liked_by_viewer: bool,
pub boosted_by_viewer: bool,
}
#[derive(Debug, Clone)]
pub struct PageParams { pub page: u64, pub per_page: u64 }
impl PageParams {
pub fn offset(&self) -> i64 { ((self.page.saturating_sub(1)) * self.per_page) as i64 }
pub fn limit(&self) -> i64 { self.per_page as i64 }
}
#[derive(Debug, Clone)]
pub struct Paginated<T> {
pub items: Vec<T>,
pub total: i64,
pub page: u64,
pub per_page: u64,
}

View File

@@ -0,0 +1,9 @@
pub mod api_key;
pub mod feed;
pub mod notification;
pub mod remote_actor;
pub mod social;
pub mod tag;
pub mod thought;
pub mod top_friend;
pub mod user;

View File

@@ -0,0 +1,24 @@
use chrono::{DateTime, Utc};
use crate::value_objects::{NotificationId, UserId, ThoughtId};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NotificationType { Like, Boost, Follow, Mention, Reply }
impl NotificationType {
pub fn from_str(s: &str) -> Self {
match s { "like" => Self::Like, "boost" => Self::Boost, "follow" => Self::Follow, "mention" => Self::Mention, _ => Self::Reply }
}
pub fn as_str(&self) -> &str {
match self { Self::Like => "like", Self::Boost => "boost", Self::Follow => "follow", Self::Mention => "mention", Self::Reply => "reply" }
}
}
#[derive(Debug, Clone)]
pub struct Notification {
pub id: NotificationId,
pub user_id: UserId,
pub notification_type: NotificationType,
pub from_user_id: Option<UserId>,
pub thought_id: Option<ThoughtId>,
pub read: bool,
pub created_at: DateTime<Utc>,
}

View File

@@ -0,0 +1,12 @@
use chrono::{DateTime, Utc};
#[derive(Debug, Clone)]
pub struct RemoteActor {
pub url: String,
pub handle: String,
pub display_name: Option<String>,
pub inbox_url: String,
pub shared_inbox_url: Option<String>,
pub public_key: String,
pub last_fetched_at: DateTime<Utc>,
}

View File

@@ -0,0 +1,47 @@
use chrono::{DateTime, Utc};
use crate::value_objects::{UserId, ThoughtId, LikeId, BoostId};
#[derive(Debug, Clone)]
pub struct Like {
pub id: LikeId,
pub user_id: UserId,
pub thought_id: ThoughtId,
pub ap_id: Option<String>,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone)]
pub struct Boost {
pub id: BoostId,
pub user_id: UserId,
pub thought_id: ThoughtId,
pub ap_id: Option<String>,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FollowState { Pending, Accepted, Rejected }
impl FollowState {
pub fn from_str(s: &str) -> Self {
match s { "pending" => Self::Pending, "rejected" => Self::Rejected, _ => Self::Accepted }
}
pub fn as_str(&self) -> &str {
match self { Self::Pending => "pending", Self::Accepted => "accepted", Self::Rejected => "rejected" }
}
}
#[derive(Debug, Clone)]
pub struct Follow {
pub follower_id: UserId,
pub following_id: UserId,
pub state: FollowState,
pub ap_id: Option<String>,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone)]
pub struct Block {
pub blocker_id: UserId,
pub blocked_id: UserId,
pub created_at: DateTime<Utc>,
}

View File

@@ -0,0 +1,2 @@
#[derive(Debug, Clone)]
pub struct Tag { pub id: i32, pub name: String }

View File

@@ -0,0 +1,45 @@
use chrono::{DateTime, Utc};
use crate::value_objects::{ThoughtId, UserId, Content};
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum Visibility {
Public, Followers, Unlisted, Direct,
}
impl Visibility {
pub fn from_str(s: &str) -> Self {
match s { "followers" => Self::Followers, "unlisted" => Self::Unlisted, "direct" => Self::Direct, _ => Self::Public }
}
pub fn as_str(&self) -> &str {
match self { Self::Public => "public", Self::Followers => "followers", Self::Unlisted => "unlisted", Self::Direct => "direct" }
}
}
#[derive(Debug, Clone)]
pub struct Thought {
pub id: ThoughtId,
pub user_id: UserId,
pub content: Content,
pub in_reply_to_id: Option<ThoughtId>,
pub in_reply_to_url: Option<String>,
pub ap_id: Option<String>,
pub visibility: Visibility,
pub content_warning: Option<String>,
pub sensitive: bool,
pub local: bool,
pub created_at: DateTime<Utc>,
pub updated_at: Option<DateTime<Utc>>,
}
impl Thought {
pub fn new_local(
id: ThoughtId, user_id: UserId, content: Content,
in_reply_to_id: Option<ThoughtId>, visibility: Visibility,
content_warning: Option<String>, sensitive: bool,
) -> Self {
Self {
id, user_id, content, in_reply_to_id, in_reply_to_url: None, ap_id: None,
visibility, content_warning, sensitive, local: true,
created_at: Utc::now(), updated_at: None,
}
}
}

View File

@@ -0,0 +1,4 @@
use crate::value_objects::UserId;
#[derive(Debug, Clone)]
pub struct TopFriend { pub user_id: UserId, pub friend_id: UserId, pub position: i16 }

View File

@@ -0,0 +1,35 @@
use chrono::{DateTime, Utc};
use crate::value_objects::{UserId, Username, Email, PasswordHash};
#[derive(Debug, Clone)]
pub struct User {
pub id: UserId,
pub username: Username,
pub email: Email,
pub password_hash: PasswordHash,
pub display_name: Option<String>,
pub bio: Option<String>,
pub avatar_url: Option<String>,
pub header_url: Option<String>,
pub custom_css: Option<String>,
pub local: bool,
pub ap_id: Option<String>,
pub inbox_url: Option<String>,
pub public_key: Option<String>,
pub private_key: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
impl User {
pub fn new_local(id: UserId, username: Username, email: Email, password_hash: PasswordHash) -> Self {
let now = Utc::now();
Self {
id, username, email, password_hash,
display_name: None, bio: None, avatar_url: None, header_url: None,
custom_css: None, local: true, ap_id: None, inbox_url: None,
public_key: None, private_key: None,
created_at: now, updated_at: now,
}
}
}

View File

@@ -0,0 +1 @@
// filled in Task 4

View File

@@ -0,0 +1 @@
// filled in Task 4