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#[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#[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#[derive(Deserialize)]
118pub struct Link {
119 pub url: String,
120}
121
122#[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#[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#[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}