adenosine/app_bsky/
mod.rs

1/// app.bsky types (manually entered)
2use serde_json::Value;
3
4#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
5pub struct Subject {
6    pub uri: String,
7    // TODO: CID is required
8    pub cid: Option<String>,
9}
10
11#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
12pub struct StrongRef {
13    pub uri: String,
14    pub cid: String,
15}
16
17/// Generic over Re-post and Like
18#[allow(non_snake_case)]
19#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
20pub struct RefRecord {
21    pub subject: Subject,
22    pub createdAt: String,
23}
24
25#[allow(non_snake_case)]
26#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
27pub struct FollowSubject {
28    pub did: String,
29}
30
31#[allow(non_snake_case)]
32#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
33pub struct FollowRecord {
34    pub subject: FollowSubject,
35    pub createdAt: String,
36}
37
38#[allow(non_snake_case)]
39#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
40pub struct ProfileRecord {
41    pub displayName: Option<String>,
42    pub description: Option<String>,
43    pub avatar: Option<Blob>,
44    pub banner: Option<Blob>,
45    // TODO: self-labels
46}
47
48#[allow(non_snake_case)]
49#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
50pub struct Label {
51    pub src: String,
52    pub uri: String,
53    pub cid: Option<String>,
54    pub val: String,
55    pub neg: Option<bool>,
56    pub cts: String,
57}
58
59#[allow(non_snake_case)]
60#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
61pub struct ProfileView {
62    pub did: String,
63    pub handle: String,
64    pub displayName: Option<String>,
65    pub description: Option<String>,
66    pub avatar: Option<String>,
67    pub indexedAt: Option<String>,
68    pub viewer: Option<ViewerState>,
69    pub labels: Option<Vec<Label>>,
70}
71
72#[allow(non_snake_case)]
73#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
74pub struct ViewerState {
75    pub muted: Option<bool>,
76    pub mutedByList: Option<Value>, // TODO
77    pub blockedBy: Option<bool>,
78    pub blocking: Option<String>,
79    pub following: Option<String>,
80    pub followedBy: Option<String>,
81}
82
83#[allow(non_snake_case)]
84#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
85pub struct ProfileViewBasic {
86    pub did: String,
87    pub handle: String,
88    pub displayName: Option<String>,
89    pub avatar: Option<String>,
90    pub viewer: Option<Value>,
91    pub labels: Option<Vec<Label>>,
92}
93
94#[allow(non_snake_case)]
95#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
96pub struct ProfileViewDetailed {
97    pub did: String,
98    pub handle: String,
99    pub displayName: Option<String>,
100    pub description: Option<String>,
101    pub avatar: Option<String>,
102    pub banner: Option<String>,
103    pub followersCount: u64,
104    pub followsCount: u64,
105    pub postsCount: u64,
106    pub indexedAt: Option<String>,
107    pub viewer: Option<ViewerState>,
108    pub labels: Option<Vec<Label>>,
109}
110
111/// for Timeline or AuthorFeed
112#[allow(non_snake_case)]
113#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
114pub struct GenericFeed {
115    pub cursor: Option<String>,
116    pub feed: Vec<FeedViewPost>,
117}
118/* XXX:
119#[allow(non_snake_case)]
120#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
121pub struct User {
122    pub did: String,
123    pub handle: String,
124    pub displayName: Option<String>,
125}
126*/
127
128#[allow(non_snake_case)]
129#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
130pub struct PostView {
131    pub uri: String,
132    pub cid: String,
133    pub author: ProfileViewBasic,
134    pub record: PostRecord,
135    pub embed: Option<PostEmbedView>,
136    pub replyCount: u64,
137    pub repostCount: u64,
138    pub likeCount: u64,
139    pub indexedAt: String,
140    pub viewer: Option<Value>,
141    pub labels: Option<Vec<Label>>,
142}
143
144#[allow(non_snake_case)]
145#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
146pub struct ThreadViewPost {
147    // TODO: doing this as the intersetion of #threadViewPost and #notFoundPost. actually it is
148    // supposed to be a union type
149    // #notFoundPost fields (uri and notFound actually required)
150    pub uri: Option<String>,
151    pub notFound: Option<bool>,
152    // #blockedPost fields (uri and blocked actually required)
153    pub blocked: Option<bool>,
154    pub author: Option<Value>,
155    // #threadViewPost fields (post actually required)
156    pub post: Option<PostView>,
157    pub parent: Option<Box<ThreadViewPost>>,
158    pub replies: Option<Vec<ThreadViewPost>>,
159}
160
161#[allow(non_snake_case)]
162#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
163pub struct FeedViewPost {
164    pub post: PostView,
165    pub reply: Option<ReplyRef>,
166    // TODO: this could extend to other "reasons" in the future
167    pub reason: Option<ReasonRepost>,
168}
169
170#[allow(non_snake_case)]
171#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
172pub struct ReasonRepost {
173    pub by: ProfileViewBasic,
174    pub indexedAt: String,
175}
176
177#[allow(non_snake_case)]
178#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
179pub struct PostRecord {
180    pub text: String,
181    pub entities: Option<Vec<PostEntity>>,
182    pub facets: Option<Vec<RichtextFacet>>,
183    pub reply: Option<ReplyRef>,
184    pub embed: Option<PostEmbed>,
185    pub langs: Option<Vec<String>>,
186    pub labels: Option<Vec<String>>,
187    pub createdAt: Option<String>,
188}
189
190#[allow(non_snake_case)]
191#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
192pub struct ReplyRef {
193    // TODO: these should be StrongRef
194    pub parent: Subject,
195    pub root: Subject,
196}
197
198#[allow(non_snake_case)]
199#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
200pub struct RichtextFacet {
201    pub index: ByteSlice,
202    pub features: Vec<FacetFeature>,
203}
204
205#[allow(non_snake_case)]
206#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
207pub struct FacetFeature {
208    // TODO: this is a hack; actually separate mention and link types
209    pub did: Option<String>,
210    pub uri: Option<String>,
211}
212
213#[allow(non_snake_case)]
214#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
215pub struct ByteSlice {
216    pub byteStart: u64,
217    pub byteEnd: u64,
218}
219
220#[allow(non_snake_case)]
221#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
222pub struct PostEntity {
223    pub index: TextSlice,
224    pub r#type: String,
225    pub value: String,
226}
227
228#[allow(non_snake_case)]
229#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
230pub struct TextSlice {
231    pub start: u64,
232    pub end: u64,
233}
234
235#[allow(non_snake_case)]
236#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
237pub struct PostEmbed {
238    pub external: Option<EmbedExternal>,
239    pub images: Option<Vec<EmbedImage>>,
240    pub record: Option<StrongRef>,
241    pub recordWithMedia: Option<Value>, // TODO
242}
243
244#[allow(non_snake_case)]
245#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
246pub struct PostEmbedView {
247    pub images: Option<Vec<EmbedImageView>>,
248    pub external: Option<EmbedExternalView>,
249    pub record: Option<Value>,          // TODO
250    pub recordWithMedia: Option<Value>, // TODO
251}
252
253#[allow(non_snake_case)]
254#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
255pub struct EmbedExternal {
256    pub uri: String,
257    pub title: String,
258    pub description: String,
259    pub thumb: Option<Blob>,
260}
261
262#[allow(non_snake_case)]
263#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
264pub struct EmbedExternalView {
265    pub uri: String,
266    pub title: String,
267    pub description: String,
268    pub thumb: Option<String>,
269}
270
271#[allow(non_snake_case)]
272#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
273pub struct EmbedImage {
274    pub image: Blob,
275    pub alt: String,
276}
277
278#[allow(non_snake_case)]
279#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
280pub struct Blob {
281    #[serde(rename = "$type")]
282    pub blob_type: Option<String>,
283    #[serde(rename = "ref")]
284    pub link: Option<CidLink>,
285    pub cid: Option<String>, // deprecated
286    pub mimeType: String,
287    pub size: Option<u64>,
288}
289
290#[allow(non_snake_case)]
291#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
292pub struct CidLink {
293    #[serde(rename = "$link")]
294    pub cid: String,
295}
296
297#[allow(non_snake_case)]
298#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
299pub struct EmbedImageView {
300    pub thumb: String,
301    pub fullsize: String,
302    pub alt: String,
303}
304
305#[allow(non_snake_case)]
306#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
307pub struct PostThread {
308    pub thread: ThreadViewPost,
309}
310
311/* XXX
312#[allow(non_snake_case)]
313#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
314pub struct FollowTarget {
315    // TODO: nested follow list?
316    pub subject: Subject,
317    pub did: String,
318    pub handle: String,
319    pub displayName: Option<String>,
320    pub createdAt: Option<String>,
321    pub indexedAt: String,
322}
323*/
324
325#[allow(non_snake_case)]
326#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
327pub struct FollowList {
328    pub subject: Subject,
329    pub cursor: Option<String>,
330    pub follows: Vec<ProfileView>,
331}