refactor(models): update data models and remove deprecated IM entities

- Update channel, notification, PR, repo, user, workspace models
- Remove deleted IM models: articles, channel follows, message
  attachments/bookmarks/drafts/edit history/embeds/mentions/pins/
  polls/reactions/threads, saved messages, thread read states
- Add new PR models: review requests, templates
- Add repo release assets model
- Add base_info module for API detail responses
This commit is contained in:
zhenyi
2026-06-10 18:49:37 +08:00
parent 420dedbc1e
commit 9eb77ab98b
50 changed files with 827 additions and 440 deletions
-18
View File
@@ -1,18 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Discussion comment on an article (similar to blog comments).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct ArticleComment {
pub id: Uuid,
pub article_id: Uuid,
pub channel_id: Uuid,
pub author_id: Uuid,
pub parent_comment_id: Option<Uuid>,
pub body: String,
pub edited_at: Option<DateTime<Utc>>,
pub deleted_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
-22
View File
@@ -1,22 +0,0 @@
use crate::models::common::Status;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Tracks a single cross-post delivery when an article is published
/// to a follower channel/workspace.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct ArticleCrossPost {
pub id: Uuid,
pub article_id: Uuid,
pub follow_id: Uuid,
pub target_workspace_id: Uuid,
pub target_channel_id: Option<Uuid>,
pub status: Status,
pub attempts: i32,
pub last_error: Option<String>,
pub sent_at: Option<DateTime<Utc>>,
pub delivered_at: Option<DateTime<Utc>>,
pub failed_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
}
-14
View File
@@ -1,14 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Reaction on an article (emoji reactions, separate from message reactions).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct ArticleReaction {
pub id: Uuid,
pub article_id: Uuid,
pub channel_id: Uuid,
pub user_id: Uuid,
pub content: String,
pub created_at: DateTime<Utc>,
}
-35
View File
@@ -1,35 +0,0 @@
use crate::models::common::{ArticleStatus, JsonValue, Visibility};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Long-form article for announcement/news channels.
/// Unlike a plain Message, an article has a title, cover image,
/// publish lifecycle, and can be cross-posted to followers.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct Article {
pub id: Uuid,
pub channel_id: Uuid,
pub author_id: Uuid,
pub title: String,
pub slug: String,
pub summary: Option<String>,
pub body: String,
pub cover_image_url: Option<String>,
pub status: ArticleStatus,
pub visibility: Visibility,
pub tags: Vec<String>,
pub published_at: Option<DateTime<Utc>>,
pub published_by: Option<Uuid>,
pub scheduled_at: Option<DateTime<Utc>>,
pub unpublished_at: Option<DateTime<Utc>>,
pub views_count: i64,
pub comments_count: i64,
pub reactions_count: i64,
pub cross_posted: bool,
pub cross_posted_from: Option<Uuid>,
pub metadata: Option<JsonValue>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
+63 -1
View File
@@ -1,3 +1,4 @@
use crate::models::base_info::UserBaseInfo;
use crate::models::common::{
ChannelKind, ChannelType, ForumLayout, ForumSortOrder, JsonValue, Visibility,
};
@@ -5,7 +6,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct Channel {
pub id: Uuid,
pub workspace_id: Uuid,
@@ -41,3 +42,64 @@ pub struct Channel {
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct ChannelDetail {
pub id: Uuid,
pub workspace_id: Uuid,
pub repo_id: Option<Uuid>,
pub category_id: Option<Uuid>,
pub creator: UserBaseInfo,
pub name: String,
pub topic: Option<String>,
pub description: Option<String>,
pub channel_type: ChannelType,
pub channel_kind: ChannelKind,
pub visibility: Visibility,
pub position: Option<i32>,
pub nsfw: bool,
pub archived: bool,
pub read_only: bool,
pub bitrate: Option<i32>,
pub user_limit: Option<i32>,
pub rtc_region: Option<String>,
pub parent_channel_id: Option<Uuid>,
pub last_message_id: Option<Uuid>,
pub last_message_at: Option<DateTime<Utc>>,
pub archived_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
impl Channel {
pub fn into_detail(self, creator: UserBaseInfo) -> ChannelDetail {
ChannelDetail {
id: self.id,
workspace_id: self.workspace_id,
repo_id: self.repo_id,
category_id: self.category_id,
creator,
name: self.name,
topic: self.topic,
description: self.description,
channel_type: self.channel_type,
channel_kind: self.channel_kind,
visibility: self.visibility,
position: self.position,
nsfw: self.nsfw,
archived: self.archived,
read_only: self.read_only,
bitrate: self.bitrate,
user_limit: self.user_limit,
rtc_region: self.rtc_region,
parent_channel_id: self.parent_channel_id,
last_message_id: self.last_message_id,
last_message_at: self.last_message_at,
archived_at: self.archived_at,
created_at: self.created_at,
updated_at: self.updated_at,
deleted_at: self.deleted_at,
}
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct ChannelCategory {
pub id: Uuid,
pub workspace_id: Uuid,
-23
View File
@@ -1,23 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Follow relationship on an announcement channel.
/// Allows another workspace or channel to receive cross-posts
/// when articles are published.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct ChannelFollow {
pub id: Uuid,
pub source_channel_id: Uuid,
pub target_workspace_id: Uuid,
pub target_channel_id: Option<Uuid>,
pub webhook_url: Option<String>,
pub webhook_secret_ciphertext: Option<String>,
pub enabled: bool,
pub followed_by: Uuid,
pub unfollowed_at: Option<DateTime<Utc>>,
pub last_delivery_at: Option<DateTime<Utc>>,
pub last_delivery_status: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
+1 -1
View File
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct ChannelMember {
pub id: Uuid,
pub channel_id: Uuid,
@@ -1,4 +1,4 @@
use crate::models::common::{OverwriteTarget, Permission};
use crate::models::common::OverwriteTarget;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
@@ -9,8 +9,8 @@ pub struct ChannelPermissionOverwrite {
pub channel_id: Uuid,
pub target_type: OverwriteTarget,
pub target_id: Uuid,
pub allow: Vec<Permission>,
pub deny: Vec<Permission>,
pub allow: Vec<String>,
pub deny: Vec<String>,
pub created_by: Uuid,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
-23
View File
@@ -1,23 +0,0 @@
use crate::models::common::{JsonValue, MessageType};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct Message {
pub id: Uuid,
pub channel_id: Uuid,
pub author_id: Uuid,
pub thread_id: Option<Uuid>,
pub reply_to_message_id: Option<Uuid>,
pub seq: i64,
pub message_type: MessageType,
pub body: String,
pub metadata: Option<JsonValue>,
pub pinned: bool,
pub system: bool,
pub edited_at: Option<DateTime<Utc>>,
pub deleted_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
-21
View File
@@ -1,21 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageAttachment {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub filename: String,
pub url: String,
pub proxy_url: Option<String>,
pub size_bytes: i64,
pub mime_type: String,
pub width: Option<i32>,
pub height: Option<i32>,
pub duration_ms: Option<i64>,
pub thumbnail_url: Option<String>,
pub blurhash: Option<String>,
pub created_at: DateTime<Utc>,
}
-14
View File
@@ -1,14 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageBookmark {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub user_id: Uuid,
pub note: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
-17
View File
@@ -1,17 +0,0 @@
use crate::models::common::JsonValue;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageDraft {
pub id: Uuid,
pub user_id: Uuid,
pub channel_id: Uuid,
pub thread_id: Option<Uuid>,
pub reply_to_message_id: Option<Uuid>,
pub content: String,
pub attachments: Option<JsonValue>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
-13
View File
@@ -1,13 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageEditHistory {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub previous_body: String,
pub edited_by: Uuid,
pub edited_at: DateTime<Utc>,
}
-34
View File
@@ -1,34 +0,0 @@
use crate::models::common::{EmbedType, JsonValue};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageEmbed {
pub id: Uuid,
pub message_id: Uuid,
pub embed_type: EmbedType,
pub title: Option<String>,
pub description: Option<String>,
pub url: Option<String>,
pub author_name: Option<String>,
pub author_url: Option<String>,
pub author_icon_url: Option<String>,
pub thumbnail_url: Option<String>,
pub thumbnail_width: Option<i32>,
pub thumbnail_height: Option<i32>,
pub image_url: Option<String>,
pub image_width: Option<i32>,
pub image_height: Option<i32>,
pub video_url: Option<String>,
pub video_width: Option<i32>,
pub video_height: Option<i32>,
pub color: Option<i32>,
pub fields: Option<JsonValue>,
pub footer_text: Option<String>,
pub footer_icon_url: Option<String>,
pub provider_name: Option<String>,
pub provider_url: Option<String>,
pub timestamp: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
}
-14
View File
@@ -1,14 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageMention {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub mentioned_user_id: Uuid,
pub mentioned_by: Uuid,
pub read_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
}
-12
View File
@@ -1,12 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessagePin {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub pinned_by: Uuid,
pub pinned_at: DateTime<Utc>,
}
-16
View File
@@ -1,16 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Poll option.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessagePollOption {
pub id: Uuid,
pub poll_id: Uuid,
pub position: i32,
pub text: String,
pub emoji_id: Option<String>,
pub emoji_name: Option<String>,
pub vote_count: i64,
pub created_at: DateTime<Utc>,
}
-13
View File
@@ -1,13 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// User vote record for a poll option.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessagePollVote {
pub id: Uuid,
pub poll_id: Uuid,
pub option_id: Uuid,
pub user_id: Uuid,
pub voted_at: DateTime<Utc>,
}
-22
View File
@@ -1,22 +0,0 @@
use crate::models::common::{JsonValue, PollLayout};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Message poll (similar to Discord Polls).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessagePoll {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub question: String,
pub description: Option<String>,
pub layout: PollLayout,
pub allow_multiselect: bool,
pub duration_hours: Option<i32>,
pub ends_at: Option<DateTime<Utc>>,
pub total_votes: i64,
pub metadata: Option<JsonValue>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
-13
View File
@@ -1,13 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageReaction {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub user_id: Uuid,
pub content: String,
pub created_at: DateTime<Utc>,
}
-27
View File
@@ -1,27 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageThread {
pub id: Uuid,
pub channel_id: Uuid,
pub root_message_id: Uuid,
pub created_by: Uuid,
pub replies_count: i64,
pub participants_count: i64,
pub last_reply_message_id: Option<Uuid>,
pub last_reply_at: Option<DateTime<Utc>>,
pub resolved: bool,
pub resolved_by: Option<Uuid>,
pub resolved_at: Option<DateTime<Utc>>,
// ── Forum post specific ──
pub title: Option<String>,
pub tags: Vec<String>,
pub pinned: bool,
pub locked: bool,
pub rate_limit_per_user: Option<i32>,
pub auto_archive_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
+1 -41
View File
@@ -1,11 +1,6 @@
pub mod article_comments;
pub mod article_cross_posts;
pub mod article_reactions;
pub mod articles;
pub mod channel;
pub mod channel_categories;
pub mod channel_events;
pub mod channel_follows;
pub mod channel_invitations;
pub mod channel_member_roles;
pub mod channel_members;
@@ -17,32 +12,12 @@ pub mod channel_webhooks;
pub mod custom_emojis;
pub mod forum_tags;
pub mod im_integrations;
pub mod message;
pub mod message_attachments;
pub mod message_bookmarks;
pub mod message_drafts;
pub mod message_edit_history;
pub mod message_embeds;
pub mod message_mentions;
pub mod message_pins;
pub mod message_poll_options;
pub mod message_poll_votes;
pub mod message_polls;
pub mod message_reactions;
pub mod message_threads;
pub mod saved_messages;
pub mod stages;
pub mod thread_read_states;
pub mod voice_participants;
pub use article_comments::ArticleComment;
pub use article_cross_posts::ArticleCrossPost;
pub use article_reactions::ArticleReaction;
pub use articles::Article;
pub use channel::Channel;
pub use channel::{Channel, ChannelDetail};
pub use channel_categories::ChannelCategory;
pub use channel_events::ChannelEvent;
pub use channel_follows::ChannelFollow;
pub use channel_invitations::ChannelInvitation;
pub use channel_member_roles::ChannelMemberRole;
pub use channel_members::ChannelMember;
@@ -54,20 +29,5 @@ pub use channel_webhooks::ChannelWebhook;
pub use custom_emojis::CustomEmoji;
pub use forum_tags::ForumTag;
pub use im_integrations::ImIntegration;
pub use message::Message;
pub use message_attachments::MessageAttachment;
pub use message_bookmarks::MessageBookmark;
pub use message_drafts::MessageDraft;
pub use message_edit_history::MessageEditHistory;
pub use message_embeds::MessageEmbed;
pub use message_mentions::MessageMention;
pub use message_pins::MessagePin;
pub use message_poll_options::MessagePollOption;
pub use message_poll_votes::MessagePollVote;
pub use message_polls::MessagePoll;
pub use message_reactions::MessageReaction;
pub use message_threads::MessageThread;
pub use saved_messages::SavedMessage;
pub use stages::Stage;
pub use thread_read_states::ThreadReadState;
pub use voice_participants::VoiceParticipant;
-13
View File
@@ -1,13 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct SavedMessage {
pub id: Uuid,
pub user_id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub note: Option<String>,
pub created_at: DateTime<Utc>,
}
-14
View File
@@ -1,14 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct ThreadReadState {
pub id: Uuid,
pub user_id: Uuid,
pub thread_id: Uuid,
pub channel_id: Uuid,
pub last_read_message_id: Option<Uuid>,
pub last_read_at: Option<DateTime<Utc>>,
pub updated_at: DateTime<Utc>,
}