1use crate::{
4 api::endpoints::PathPart,
5 domain::{
6 additional_resource::AdditionalResource, asset::UserOrMe, circle::CircleId,
7 csv_encode_uuids, from_csv, image::ImageId, to_csv, user::UserId,
8 },
9};
10use macros::make_path_parts;
11use serde::{Deserialize, Serialize};
12use strum_macros::Display;
13
14use super::UserBadge;
15
16make_path_parts!(PublicUserGetPath => "/v1/user/{}/public" => UserId);
17
18#[derive(Debug, Serialize, Deserialize, Clone)]
20#[serde(rename_all = "camelCase")]
21pub struct PublicUser {
22 pub id: UserId,
24
25 pub username: String,
27
28 pub given_name: String,
30
31 pub family_name: String,
33
34 pub profile_image: Option<ImageId>,
36
37 pub following: bool,
39
40 #[serde(default)]
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub bio: Option<String>, #[serde(default)]
47 pub badge: Option<UserBadge>,
48
49 #[serde(default)]
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub languages_spoken: Option<Vec<String>>, #[serde(default)]
56 #[serde(skip_serializing_if = "Option::is_none")]
57 pub organization: Option<String>, #[serde(default)]
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub persona: Option<Vec<String>>, #[serde(default)]
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub country_short: Option<String>, #[serde(default)]
71 #[serde(skip_serializing_if = "Option::is_none")]
72 pub country_long: Option<String>, #[serde(default)]
76 pub circles: Vec<CircleId>,
77
78 #[serde(default)]
80 pub jig_count: u64,
81
82 #[serde(default)]
84 pub resource_count: u64,
85
86 #[serde(default)]
88 pub course_count: u64,
89
90 #[serde(default)]
92 pub playlist_count: u64,
93
94 #[serde(default)]
96 pub total_asset_count: u64,
97}
98
99make_path_parts!(PublicUserBrowsePath => "/v1/user/public/browse");
100
101#[derive(Serialize, Deserialize, Clone, Debug, Default)]
103#[serde(rename_all = "camelCase")]
104pub struct UserBrowseQuery {
105 #[serde(default)]
107 #[serde(skip_serializing_if = "Option::is_none")]
108 pub page: Option<u32>,
109
110 pub page_limit: Option<u32>,
112
113 #[serde(default)]
115 #[serde(serialize_with = "csv_encode_uuids")]
116 #[serde(deserialize_with = "from_csv")]
117 #[serde(skip_serializing_if = "Vec::is_empty")]
118 pub circles: Vec<CircleId>,
119
120 #[serde(default)]
122 #[serde(skip_serializing_if = "Option::is_none")]
123 pub order_by: Option<OrderBy>,
124
125 #[serde(default)]
128 #[serde(serialize_with = "to_csv")]
129 #[serde(deserialize_with = "from_csv")]
130 #[serde(skip_serializing_if = "Vec::is_empty")]
131 pub badge: Vec<UserBadge>,
132}
133
134#[derive(Debug, Serialize, Deserialize, Clone)]
136#[serde(rename_all = "camelCase")]
137pub struct BrowsePublicUserResponse {
138 pub users: Vec<PublicUser>,
140 pub pages: u32,
142 pub total_user_count: u64,
144}
145
146make_path_parts!(PublicUserSearchPath => "/v1/user/public");
147
148#[derive(Serialize, Deserialize, Clone, Debug, Default)]
150#[serde(rename_all = "camelCase")]
151pub struct SearchPublicUserQuery {
152 #[serde(default)]
154 #[serde(skip_serializing_if = "String::is_empty")]
155 pub q: String,
156
157 #[serde(default)]
159 #[serde(skip_serializing_if = "Option::is_none")]
160 pub page: Option<u32>,
161
162 #[serde(default)]
164 #[serde(skip_serializing_if = "Option::is_none")]
165 pub user_id: Option<UserOrMe>,
166
167 #[serde(default)]
169 #[serde(skip_serializing_if = "Option::is_none")]
170 pub username: Option<String>,
171
172 #[serde(default)]
174 #[serde(skip_serializing_if = "Option::is_none")]
175 pub name: Option<String>,
176
177 #[serde(default)]
179 #[serde(skip_serializing_if = "Option::is_none")]
180 pub languages_spoken: Option<Vec<String>>,
181
182 #[serde(default)]
184 #[serde(skip_serializing_if = "Option::is_none")]
185 pub organization: Option<String>,
186
187 #[serde(default)]
189 #[serde(skip_serializing_if = "Option::is_none")]
190 pub persona: Option<Vec<String>>,
191
192 #[serde(default)]
194 #[serde(skip_serializing_if = "Option::is_none")]
195 pub bio: Option<String>,
196
197 #[serde(default)]
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub page_limit: Option<u32>,
201}
202
203#[derive(Debug, Serialize, Deserialize, Clone)]
205#[serde(rename_all = "camelCase")]
206pub struct SearchPublicUserResponse {
207 pub users: Vec<PublicUser>,
209 pub pages: u32,
211 pub total_user_count: u64,
213}
214
215make_path_parts!(BrowsePublicUserJigsPath => "/v1/user/{}/public/jig/browse" => UserId);
216
217#[derive(Serialize, Deserialize, Clone, Debug, Default)]
219#[serde(rename_all = "camelCase")]
220pub struct BrowsePublicUserJigsQuery {
221 #[serde(default)]
223 #[serde(skip_serializing_if = "Option::is_none")]
224 pub page: Option<u32>,
225
226 #[serde(default)]
228 #[serde(skip_serializing_if = "Option::is_none")]
229 pub page_limit: Option<u32>,
230}
231
232make_path_parts!(BrowsePublicUserResourcesPath => "/v1/user/{}/public/resource/browse" => UserId);
233
234#[derive(Serialize, Deserialize, Clone, Debug, Default)]
236#[serde(rename_all = "camelCase")]
237pub struct BrowsePublicUserResourcesQuery {
238 #[serde(default)]
240 #[serde(skip_serializing_if = "Option::is_none")]
241 pub page: Option<u32>,
242
243 #[serde(default)]
245 #[serde(skip_serializing_if = "Option::is_none")]
246 pub page_limit: Option<u32>,
247}
248
249#[derive(Debug, Serialize, Deserialize, Clone)]
251#[serde(rename_all = "camelCase")]
252pub struct BrowsePublicUserResourcesResponse {
253 pub resources: Vec<AdditionalResource>,
255
256 pub pages: u32,
258
259 pub total_resource_count: u64,
261}
262
263make_path_parts!(BrowsePublicUserPlaylistsPath => "/v1/user/{}/public/playlist/browse" => UserId);
264
265#[derive(Serialize, Deserialize, Clone, Debug, Default)]
267#[serde(rename_all = "camelCase")]
268pub struct BrowsePublicUserPlaylistsQuery {
269 #[serde(default)]
271 #[serde(skip_serializing_if = "Option::is_none")]
272 pub page: Option<u32>,
273
274 #[serde(default)]
276 #[serde(skip_serializing_if = "Option::is_none")]
277 pub page_limit: Option<u32>,
278}
279
280make_path_parts!(BrowsePublicUserFollowersPath => "/v1/user/{}/public/follower/browse" => UserId);
281
282#[derive(Serialize, Deserialize, Clone, Debug, Default)]
284#[serde(rename_all = "camelCase")]
285pub struct BrowsePublicUserFollowersQuery {
286 #[serde(default)]
288 #[serde(skip_serializing_if = "Option::is_none")]
289 pub page: Option<u32>,
290
291 #[serde(default)]
293 #[serde(skip_serializing_if = "Option::is_none")]
294 pub page_limit: Option<u32>,
295}
296
297#[derive(Debug, Serialize, Deserialize, Clone)]
299#[serde(rename_all = "camelCase")]
300pub struct BrowsePublicUserFollowersResponse {
301 pub followers: Vec<PublicUser>,
303
304 pub pages: u32,
306
307 pub total_follower_count: u64,
309}
310
311make_path_parts!(BrowsePublicUserFollowingPath => "/v1/user/{}/public/following/browse" => UserId);
312
313#[derive(Serialize, Deserialize, Clone, Debug, Default)]
315#[serde(rename_all = "camelCase")]
316pub struct BrowsePublicUserFollowingsQuery {
317 #[serde(default)]
319 #[serde(skip_serializing_if = "Option::is_none")]
320 pub page: Option<u32>,
321
322 #[serde(default)]
324 #[serde(skip_serializing_if = "Option::is_none")]
325 pub page_limit: Option<u32>,
326}
327
328#[derive(Debug, Serialize, Deserialize, Clone)]
330#[serde(rename_all = "camelCase")]
331pub struct BrowsePublicUserFollowingResponse {
332 pub followings: Vec<PublicUser>,
334
335 pub pages: u32,
337
338 pub total_following_count: u64,
340}
341
342make_path_parts!(PublicUserFollowPath => "/v1/user/{}/follow" => UserId);
343
344make_path_parts!(PublicUserUnfollowPath => "/v1/user/{}/unfollow" => UserId);
345
346#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Debug, Display)]
348#[cfg_attr(feature = "backend", derive(sqlx::Type))]
349#[serde(rename_all = "camelCase")]
350#[repr(i16)]
351pub enum OrderBy {
352 #[strum(serialize = "AssetCount")]
354 AssetCount = 0,
355}