threads_api/
types.rs

1use serde::Deserialize;
2
3pub(crate) mod internal {
4	use super::{Card, Media, Profile, ProfileDetail};
5
6	#[derive(serde::Deserialize)]
7	pub struct Response<T> {
8		pub data: T,
9	}
10
11	#[derive(serde::Deserialize)]
12	pub struct ProfileResponse {
13		#[serde(rename = "userData")]
14		pub user_data: UserFragment,
15	}
16
17	#[derive(serde::Deserialize)]
18	pub struct ThreadsResponse {
19		#[serde(rename = "mediaData")]
20		pub media_data: ThreadsFragment,
21	}
22
23	#[derive(serde::Deserialize)]
24	pub struct ThreadResponse {
25		pub containing_thread: Thread,
26		pub reply_threads: Vec<Thread>,
27	}
28
29	#[derive(serde::Deserialize)]
30	pub struct LikersResponse {
31		pub likers: Likers,
32	}
33
34	#[derive(serde::Deserialize)]
35	pub struct Likers {
36		pub users: Vec<ProfileDetail>,
37	}
38
39	#[derive(serde::Deserialize)]
40	pub struct UserFragment {
41		pub user: Profile,
42	}
43
44	#[derive(serde::Deserialize)]
45	pub struct ThreadsFragment {
46		pub threads: Vec<Thread>,
47	}
48
49	#[derive(serde::Deserialize)]
50	pub struct Thread {
51		pub id: String,
52		pub thread_items: Vec<ThreadItem>,
53	}
54
55	#[derive(serde::Deserialize)]
56	pub struct ThreadItem {
57		pub post: Post,
58	}
59
60	#[derive(serde::Deserialize)]
61	pub struct Post {
62		pub user: ProfileDetail,
63		#[serde(rename = "image_versions2")]
64		pub images: ImageVersions,
65		pub original_width: u32,
66		pub original_height: u32,
67		pub caption: Caption,
68		pub taken_at: u64,
69		pub like_count: u32,
70		pub text_post_app_info: PostMeta,
71	}
72
73	#[derive(serde::Deserialize)]
74	pub struct PostMeta {
75		pub direct_reply_count: Option<u32>,
76		pub link_preview_attachment: Option<Card>,
77	}
78
79	#[derive(serde::Deserialize)]
80	pub struct Caption {
81		pub text: String,
82	}
83
84	#[derive(serde::Deserialize)]
85	pub struct ImageVersions {
86		pub candidates: Vec<Media>,
87	}
88}
89
90/// Contains the minimum required information to display a profile.
91#[derive(serde::Deserialize)]
92pub struct ProfileDetail {
93	pub profile_pic_url: String,
94	pub username: String,
95	pub is_verified: bool,
96	#[serde(rename = "pk")]
97	pub id: String,
98}
99
100/// Contains all the information available about a profile.
101#[derive(Deserialize)]
102pub struct Profile {
103	#[serde(rename = "pk")]
104	pub id: String,
105	pub is_private: bool,
106	pub profile_pic_url: String,
107	pub username: String,
108	pub is_verified: bool,
109	pub biography: String,
110	pub follower_count: u32,
111	pub bio_links: Vec<Link>,
112	pub full_name: String,
113	pub hd_profile_pic_versions: Vec<Media>,
114}
115
116/// A link to an external website.
117#[derive(Deserialize)]
118pub struct Link {
119	pub url: String,
120}
121
122/// A media item.
123#[derive(Deserialize)]
124pub struct Media {
125	pub url: String,
126	pub width: u32,
127	pub height: u32,
128}
129
130#[derive(Deserialize)]
131pub struct PostResponse {
132	pub post: Thread,
133	pub replies: Vec<Thread>,
134}
135
136#[derive(Deserialize)]
137pub struct Card {
138	pub url: String,
139	pub title: String,
140	pub image_url: String,
141	pub display_url: String,
142	pub favicon_url: Option<String>,
143}
144
145/// A thread of posts.
146#[derive(Deserialize)]
147pub struct Thread {
148	pub id: String,
149	pub items: Vec<ThreadItem>,
150}
151
152impl From<internal::Thread> for Thread {
153	fn from(value: internal::Thread) -> Self {
154		Self {
155			id: value.id,
156			items: value
157				.thread_items
158				.into_iter()
159				.map(|i| i.post.into())
160				.collect(),
161		}
162	}
163}
164
165/// A post in a thread.
166#[derive(Deserialize)]
167pub struct ThreadItem {
168	pub likes: u32,
169	pub text: String,
170	pub published_at: u64,
171	pub images: Vec<Media>,
172	pub user: ProfileDetail,
173	pub replies: Option<u32>,
174	pub link_card: Option<Card>,
175}
176
177impl From<internal::Post> for ThreadItem {
178	fn from(thread: internal::Post) -> Self {
179		Self {
180			user: thread.user,
181			likes: thread.like_count,
182			text: thread.caption.text,
183			published_at: thread.taken_at,
184			images: thread.images.candidates,
185			replies: thread.text_post_app_info.direct_reply_count,
186			link_card: thread.text_post_app_info.link_preview_attachment,
187		}
188	}
189}