Skip to main content

pickcat_api_collection/dto/
topic.rs

1//! 主题与内容 DTO。
2
3use serde::{Deserialize, Serialize};
4
5use super::user::{PageInfoDTO, TopicAuthorDTO, UserSubjectInfoDTO, UserSubjectTagDTO};
6
7/// 主题列表项;与用户主页的主题列表项是同一结构。
8pub type TopicListItemDTO = UserSubjectInfoDTO;
9
10/// `GET /api/v1/topic-recommendations`:主题列表项额外带 `reason`。
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct RecommendedTopicDTO {
13    #[serde(flatten)]
14    pub topic: UserSubjectInfoDTO,
15    /// 推荐原因,如 `PINNED` / `TRENDING`。
16    pub reason: String,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(rename_all = "camelCase")]
21pub struct TopicRecommendationsDTO {
22    pub strategy: String,
23    pub items: Vec<RecommendedTopicDTO>,
24    pub page_info: PageInfoDTO,
25}
26
27// ---------------------------------------------------------------------------
28// 楼层
29// ---------------------------------------------------------------------------
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct PostViewerCapabilitiesDTO {
34    pub can_edit: bool,
35    pub can_like: bool,
36    pub can_bookmark: bool,
37    pub can_report: bool,
38    pub can_select_answer: bool,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
42#[serde(rename_all = "camelCase")]
43pub struct PostViewerStateDTO {
44    pub liked: bool,
45    pub bookmark_id: Option<String>,
46    pub selected_answer: bool,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
50#[serde(rename_all = "camelCase")]
51pub struct TopicPostDTO {
52    pub id: String,
53    pub topic_id: String,
54    pub post_number: u64,
55    pub reply_to_post_number: Option<u64>,
56    pub deleted: bool,
57    pub children: Vec<TopicPostDTO>,
58    pub current_revision: u64,
59    pub like_count: u64,
60    pub pinned: bool,
61    pub cooked_html: String,
62    pub author: TopicAuthorDTO,
63    pub created_at: String,
64    pub edited_at: Option<String>,
65    pub viewer_capabilities: PostViewerCapabilitiesDTO,
66    pub viewer_state: PostViewerStateDTO,
67}
68
69// ---------------------------------------------------------------------------
70// 主题详情
71// ---------------------------------------------------------------------------
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
74#[serde(rename_all = "camelCase")]
75pub struct TopicViewerCapabilitiesDTO {
76    pub can_edit: bool,
77    pub can_reply: bool,
78    pub can_delete: bool,
79    pub can_bookmark: bool,
80    pub can_close: bool,
81    pub can_reopen: bool,
82    pub can_pin_globally: bool,
83    pub pinnable_tag_ids: Vec<String>,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
87#[serde(rename_all = "camelCase")]
88pub struct TopicViewerStateDTO {
89    pub bookmark_id: Option<String>,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
93#[serde(rename_all = "camelCase")]
94pub struct TopicDetailDTO {
95    pub id: String,
96    pub title: String,
97    pub kind: String,
98    pub author: TopicAuthorDTO,
99    pub tags: Vec<UserSubjectTagDTO>,
100    pub reply_count: u64,
101    pub view_count: u64,
102    pub like_count: u64,
103    pub bookmark_count: u64,
104    /// 所属合集,结构未文档化。
105    pub collection: Option<serde_json::Value>,
106    pub closed_at: Option<String>,
107    /// 关闭操作人;文档标注为 DateTime/String,实际类型未验证。
108    pub closed_by: Option<serde_json::Value>,
109    pub pinned: bool,
110    pub pinned_globally: bool,
111    pub pinned_tag_id: Option<String>,
112    pub pinned_at: Option<String>,
113    pub pinned_until: Option<String>,
114    pub last_activity_at: String,
115    pub created_at: String,
116    pub edited_at: Option<String>,
117    pub updated_at: String,
118    pub first_post: TopicPostDTO,
119    pub replies_truncated: bool,
120    /// 主题事件流,结构未文档化。
121    pub events: Vec<serde_json::Value>,
122    pub events_truncated: bool,
123    pub viewer_capabilities: TopicViewerCapabilitiesDTO,
124    pub viewer_state: TopicViewerStateDTO,
125}
126
127// ---------------------------------------------------------------------------
128// 发布主题 / 回帖
129// ---------------------------------------------------------------------------
130
131/// 发布主题首楼(`POST /api/v1/posts`)。
132#[derive(Debug, Clone, Serialize, Deserialize)]
133#[serde(rename_all = "camelCase")]
134pub struct CreateTopicDTO {
135    pub title: String,
136    pub markdown: String,
137    pub kind: String,
138    pub tag_ids: Vec<String>,
139}
140
141/// 发布回帖(`POST /api/v1/posts`)。`reply_to_post_number` 用于楼中楼。
142#[derive(Debug, Clone, Serialize, Deserialize)]
143#[serde(rename_all = "camelCase")]
144pub struct CreateReplyDTO {
145    pub topic_id: String,
146    pub markdown: String,
147    #[serde(skip_serializing_if = "Option::is_none")]
148    pub reply_to_post_number: Option<u64>,
149}
150
151/// `POST /api/v1/posts` 的 202 响应(异步审核受理)。
152#[derive(Debug, Clone, Serialize, Deserialize)]
153#[serde(rename_all = "camelCase")]
154pub struct CreatePostResponseDTO {
155    pub submission_id: String,
156    pub topic_id: String,
157    pub post_id: String,
158    pub status: String,
159}
160
161// ---------------------------------------------------------------------------
162// 投稿审核
163// ---------------------------------------------------------------------------
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
166#[serde(rename_all = "camelCase")]
167pub struct PostSubmissionDTO {
168    pub id: String,
169    pub status: String,
170    pub content_role: String,
171    /// 提交内容原样回显,随 `content_role` 变化,结构未固定。
172    pub request: serde_json::Value,
173    pub risk_level: Option<String>,
174    pub topic_id: String,
175    pub post_id: String,
176    pub post_number: u64,
177    pub base_revision: Option<String>,
178    pub created_at: String,
179    pub updated_at: String,
180}