mastodon.rs
1 use chrono::{DateTime, Utc}; 2 use reqwest::Url; 3 use serde::Deserialize; 4 use tracing::trace; 5 6 use crate::utils; 7 8 pub async fn lookup_account(base_url: &Url, name: &str) -> anyhow::Result<Account> { 9 trace!("fetching account info for {name} on {base_url}"); 10 // https://docs.joinmastodon.org/methods/accounts/#lookup 11 reqwest::Client::new() 12 .get(base_url.join("api/v1/accounts/lookup")?) 13 .query(&[("acct", name)]) 14 .send() 15 .await? 16 .error_for_status()? 17 .json() 18 .await 19 .map_err(Into::into) 20 } 21 22 pub async fn fetch_original_media_posts( 23 base_url: &Url, 24 Id(account_id): Id, 25 Id(min_id): Id, 26 limit: u16, 27 ) -> anyhow::Result<Vec<Post>> { 28 trace!("fetching posts of user {account_id} on {base_url}"); 29 // https://docs.joinmastodon.org/methods/accounts/#statuses 30 reqwest::Client::new() 31 .get(base_url.join(&format!("api/v1/accounts/{account_id}/statuses"))?) 32 .query(&[("min_id", min_id)]) 33 .query(&[("limit", limit)]) 34 .query(&[("only_media", true)]) 35 .query(&[("exclude_replies", true)]) 36 .query(&[("exclude_reblogs", true)]) 37 .send() 38 .await? 39 .error_for_status()? 40 .json() 41 .await 42 .map_err(Into::into) 43 } 44 45 #[derive(Deserialize, Debug)] 46 pub struct Post { 47 pub id: Id, 48 pub url: Url, 49 pub created_at: DateTime<Utc>, 50 pub content: String, 51 pub media_attachments: Vec<MediaAttachment>, 52 pub account: Account, 53 } 54 55 #[derive(Deserialize, Debug)] 56 pub struct Account { 57 pub id: Id, 58 pub username: String, 59 pub url: Url, 60 } 61 62 #[derive(Deserialize, Debug)] 63 pub struct MediaAttachment { 64 pub r#type: AttachmentType, 65 pub url: Url, 66 } 67 68 #[derive(Deserialize, Debug)] 69 #[serde(rename_all = "snake_case")] 70 pub enum AttachmentType { 71 Image, 72 #[serde(other)] 73 Unknown, 74 } 75 76 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize)] 77 pub struct Id(#[serde(with = "utils::serde::via_string")] pub u64);