shared/domain/user/
public_user.rs

1//! Types for public users.
2
3use 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/// A lite profile for other Users to view
19#[derive(Debug, Serialize, Deserialize, Clone)]
20#[serde(rename_all = "camelCase")]
21pub struct PublicUser {
22    /// User Id
23    pub id: UserId,
24
25    /// Username of User
26    pub username: String,
27
28    /// First name of User
29    pub given_name: String,
30
31    /// Lastname of User
32    pub family_name: String,
33
34    /// Profile image of User
35    pub profile_image: Option<ImageId>,
36
37    /// following this user or not
38    pub following: bool,
39
40    /// Bio of User
41    #[serde(default)]
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub bio: Option<String>, // only here if bio_public is true
44
45    /// Badge associated with User
46    #[serde(default)]
47    pub badge: Option<UserBadge>,
48
49    /// Language spoken of User
50    #[serde(default)]
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub languages_spoken: Option<Vec<String>>, // only here if languages_spoken_public is true
53
54    /// Organization of User
55    #[serde(default)]
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub organization: Option<String>, // only here if organization_public is true
58
59    /// Persona of User
60    #[serde(default)]
61    #[serde(skip_serializing_if = "Option::is_none")]
62    pub persona: Option<Vec<String>>, // only here if persona_public is true
63
64    /// Country of User
65    #[serde(default)]
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub country_short: Option<String>, // only here if country_public is true
68
69    /// Country of User
70    #[serde(default)]
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub country_long: Option<String>, // only here if country_public is true
73
74    /// Circles associated with User
75    #[serde(default)]
76    pub circles: Vec<CircleId>,
77
78    /// Number of Jigs
79    #[serde(default)]
80    pub jig_count: u64,
81
82    /// Number of Resources
83    #[serde(default)]
84    pub resource_count: u64,
85
86    /// Number of Courses
87    #[serde(default)]
88    pub course_count: u64,
89
90    /// Number of playlists
91    #[serde(default)]
92    pub playlist_count: u64,
93
94    /// Total number of assets
95    #[serde(default)]
96    pub total_asset_count: u64,
97}
98
99make_path_parts!(PublicUserBrowsePath => "/v1/user/public/browse");
100
101/// Query for [`Browse`](crate::api::endpoints::user::public_user::Browse).
102#[derive(Serialize, Deserialize, Clone, Debug, Default)]
103#[serde(rename_all = "camelCase")]
104pub struct UserBrowseQuery {
105    /// The page number
106    #[serde(default)]
107    #[serde(skip_serializing_if = "Option::is_none")]
108    pub page: Option<u32>,
109
110    /// The hits per page to be returned
111    pub page_limit: Option<u32>,
112
113    /// Circle's that has user joined
114    #[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    /// Order by sort
121    #[serde(default)]
122    #[serde(skip_serializing_if = "Option::is_none")]
123    pub order_by: Option<OrderBy>,
124
125    /// Optional filter for user badges
126    ///
127    #[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/// A lite profile for other Users to view
135#[derive(Debug, Serialize, Deserialize, Clone)]
136#[serde(rename_all = "camelCase")]
137pub struct BrowsePublicUserResponse {
138    /// User Id
139    pub users: Vec<PublicUser>,
140    /// Pages
141    pub pages: u32,
142    /// Number of users with profiles
143    pub total_user_count: u64,
144}
145
146make_path_parts!(PublicUserSearchPath => "/v1/user/public");
147
148/// Query for [`Browse`](crate::api::endpoints::user::Search).
149#[derive(Serialize, Deserialize, Clone, Debug, Default)]
150#[serde(rename_all = "camelCase")]
151pub struct SearchPublicUserQuery {
152    /// The query string.
153    #[serde(default)]
154    #[serde(skip_serializing_if = "String::is_empty")]
155    pub q: String,
156
157    /// The page number of the Circles to get.
158    #[serde(default)]
159    #[serde(skip_serializing_if = "Option::is_none")]
160    pub page: Option<u32>,
161
162    /// Optionally filter by User's Id
163    #[serde(default)]
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub user_id: Option<UserOrMe>,
166
167    /// Optionally filter by the user's username
168    #[serde(default)]
169    #[serde(skip_serializing_if = "Option::is_none")]
170    pub username: Option<String>,
171
172    /// Optionally filter by the user's name
173    #[serde(default)]
174    #[serde(skip_serializing_if = "Option::is_none")]
175    pub name: Option<String>,
176
177    /// Optionally filter by the user's spoken language(s)
178    #[serde(default)]
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub languages_spoken: Option<Vec<String>>,
181
182    /// Optionally filter by the user's organization
183    #[serde(default)]
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub organization: Option<String>,
186
187    /// Optionally filter by the user's persona(s)
188    #[serde(default)]
189    #[serde(skip_serializing_if = "Option::is_none")]
190    pub persona: Option<Vec<String>>,
191
192    /// Optionally filter by the user's bio
193    #[serde(default)]
194    #[serde(skip_serializing_if = "Option::is_none")]
195    pub bio: Option<String>,
196
197    /// The hits per page to be returned
198    #[serde(default)]
199    #[serde(skip_serializing_if = "Option::is_none")]
200    pub page_limit: Option<u32>,
201}
202
203/// A lite profile for other Users to view
204#[derive(Debug, Serialize, Deserialize, Clone)]
205#[serde(rename_all = "camelCase")]
206pub struct SearchPublicUserResponse {
207    /// User Id
208    pub users: Vec<PublicUser>,
209    /// Number of pages
210    pub pages: u32,
211    /// Number of User profiles
212    pub total_user_count: u64,
213}
214
215make_path_parts!(BrowsePublicUserJigsPath => "/v1/user/{}/public/jig/browse" => UserId);
216
217/// Query for [`Browse`](crate::api::endpoints::user::public_user::BrowseUserJigs).
218#[derive(Serialize, Deserialize, Clone, Debug, Default)]
219#[serde(rename_all = "camelCase")]
220pub struct BrowsePublicUserJigsQuery {
221    /// The page number of the User Jigs to fetch.
222    #[serde(default)]
223    #[serde(skip_serializing_if = "Option::is_none")]
224    pub page: Option<u32>,
225
226    /// The hits per page to be returned
227    #[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/// Query for [`Browse`](crate::api::endpoints::user::public_user::BrowseUserResources).
235#[derive(Serialize, Deserialize, Clone, Debug, Default)]
236#[serde(rename_all = "camelCase")]
237pub struct BrowsePublicUserResourcesQuery {
238    /// The page number of the User Resources to fetch.
239    #[serde(default)]
240    #[serde(skip_serializing_if = "Option::is_none")]
241    pub page: Option<u32>,
242
243    /// The hits per page to be returned
244    #[serde(default)]
245    #[serde(skip_serializing_if = "Option::is_none")]
246    pub page_limit: Option<u32>,
247}
248
249/// Response for Browsing a User's Additional Resources
250#[derive(Debug, Serialize, Deserialize, Clone)]
251#[serde(rename_all = "camelCase")]
252pub struct BrowsePublicUserResourcesResponse {
253    /// The Additional Resources returned
254    pub resources: Vec<AdditionalResource>,
255
256    /// The number of pages found.
257    pub pages: u32,
258
259    /// The total number of additional resources belonging to user
260    pub total_resource_count: u64,
261}
262
263make_path_parts!(BrowsePublicUserPlaylistsPath => "/v1/user/{}/public/playlist/browse" => UserId);
264
265/// Query for [`Browse`](crate::api::endpoints::user::public_user::BrowseUserPlaylists).
266#[derive(Serialize, Deserialize, Clone, Debug, Default)]
267#[serde(rename_all = "camelCase")]
268pub struct BrowsePublicUserPlaylistsQuery {
269    /// The page number of the User Playlists to fetch.
270    #[serde(default)]
271    #[serde(skip_serializing_if = "Option::is_none")]
272    pub page: Option<u32>,
273
274    /// The hits per page to be returned
275    #[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/// Query for [`Browse`](crate::api::endpoints::user::public_user::BrowseFollowers).
283#[derive(Serialize, Deserialize, Clone, Debug, Default)]
284#[serde(rename_all = "camelCase")]
285pub struct BrowsePublicUserFollowersQuery {
286    /// The page number of the User Followers to fetch.
287    #[serde(default)]
288    #[serde(skip_serializing_if = "Option::is_none")]
289    pub page: Option<u32>,
290
291    /// The hits per page to be returned
292    #[serde(default)]
293    #[serde(skip_serializing_if = "Option::is_none")]
294    pub page_limit: Option<u32>,
295}
296
297/// Browse User's followers
298#[derive(Debug, Serialize, Deserialize, Clone)]
299#[serde(rename_all = "camelCase")]
300pub struct BrowsePublicUserFollowersResponse {
301    /// The follower profiles returned
302    pub followers: Vec<PublicUser>,
303
304    /// The number of pages found.
305    pub pages: u32,
306
307    /// The total number of followers found
308    pub total_follower_count: u64,
309}
310
311make_path_parts!(BrowsePublicUserFollowingPath => "/v1/user/{}/public/following/browse" => UserId);
312
313/// Query for [`Browse`](crate::api::endpoints::user::public_user::BrowseFollowing).
314#[derive(Serialize, Deserialize, Clone, Debug, Default)]
315#[serde(rename_all = "camelCase")]
316pub struct BrowsePublicUserFollowingsQuery {
317    /// The page number of the Public User Followers to fetch.
318    #[serde(default)]
319    #[serde(skip_serializing_if = "Option::is_none")]
320    pub page: Option<u32>,
321
322    /// The hits per page to be returned
323    #[serde(default)]
324    #[serde(skip_serializing_if = "Option::is_none")]
325    pub page_limit: Option<u32>,
326}
327
328/// Browse User's followings
329#[derive(Debug, Serialize, Deserialize, Clone)]
330#[serde(rename_all = "camelCase")]
331pub struct BrowsePublicUserFollowingResponse {
332    /// The Public User Profiles of followings
333    pub followings: Vec<PublicUser>,
334
335    /// The number of pages found.
336    pub pages: u32,
337
338    /// The total number of followings found
339    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/// Sort browse results by timestamp
347#[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    /// Order Asset by asset count
353    #[strum(serialize = "AssetCount")]
354    AssetCount = 0,
355}