Compare commits

..

No commits in common. "5f346922f5682a89243dfcc2b2a8399f23be7a65" and "d252131e0da1ac51f34370c8f07c4a927c9991e1" have entirely different histories.

13 changed files with 167 additions and 275 deletions

View file

@ -1,18 +1,24 @@
use crate::types_rewrite::{ObjectUuid, ObjectUri, db}; use crate::types_rewrite::{ObjectUuid, ObjectUri, db};
use sqlx::SqliteConnection; use sqlx::SqliteConnection;
use thiserror::Error;
use tracing::info; use tracing::info;
use chrono::{NaiveDateTime, DateTime, Utc}; use chrono::{NaiveDateTime, DateTime, Utc};
use crate::types_rewrite::DbError;
const SQLITE_TIME_FMT: &'static str = "%Y-%m-%d %H:%M:%S"; const SQLITE_TIME_FMT: &'static str = "%Y-%m-%d %H:%M:%S";
#[derive(Debug, Error)]
pub enum FetchError {
#[error("an unknown error occured when fetching: {0}")]
Unknown(String)
}
fn parse_ts(ts: String) -> Option<DateTime<Utc>> { fn parse_ts(ts: String) -> Option<DateTime<Utc>> {
NaiveDateTime::parse_from_str(&ts, SQLITE_TIME_FMT) NaiveDateTime::parse_from_str(&ts, SQLITE_TIME_FMT)
.ok() .ok()
.map(|nt| nt.and_utc()) .map(|nt| nt.and_utc())
} }
pub async fn user_by_id(id: ObjectUuid, conn: &mut SqliteConnection) -> Result<db::User, DbError> { pub async fn user_by_id(id: ObjectUuid, conn: &mut SqliteConnection) -> Result<db::User, FetchError> {
info!("fetching user by uuid '{:?}' from the database", id); info!("fetching user by uuid '{:?}' from the database", id);
let record = sqlx::query!(r#" let record = sqlx::query!(r#"
@ -33,7 +39,7 @@ pub async fn user_by_id(id: ObjectUuid, conn: &mut SqliteConnection) -> Result<d
"#, id.0) "#, id.0)
.fetch_one(&mut *conn) .fetch_one(&mut *conn)
.await .await
.map_err(|e| DbError::FetchError(e.to_string()))?; .map_err(|e| FetchError::Unknown(e.to_string()))?;
let follower_count = sqlx::query_scalar!(r#" let follower_count = sqlx::query_scalar!(r#"
SELECT COUNT(follower_id) SELECT COUNT(follower_id)
@ -42,7 +48,7 @@ pub async fn user_by_id(id: ObjectUuid, conn: &mut SqliteConnection) -> Result<d
"#, record.actor_id) "#, record.actor_id)
.fetch_one(&mut *conn) .fetch_one(&mut *conn)
.await .await
.map_err(|e| DbError::FetchError(e.to_string()))?; .map_err(|e| FetchError::Unknown(e.to_string()))?;
let last_post_at = sqlx::query_scalar!(r#" let last_post_at = sqlx::query_scalar!(r#"
SELECT datetime(p.created_at) SELECT datetime(p.created_at)
@ -53,7 +59,7 @@ pub async fn user_by_id(id: ObjectUuid, conn: &mut SqliteConnection) -> Result<d
"#, record.user_id) "#, record.user_id)
.fetch_one(&mut *conn) .fetch_one(&mut *conn)
.await .await
.map_err(|e| DbError::FetchError(e.to_string()))? .map_err(|e| FetchError::Unknown(e.to_string()))?
.and_then(|ts| { .and_then(|ts| {
info!("parsing timestamp {}", ts); info!("parsing timestamp {}", ts);
parse_ts(ts) parse_ts(ts)

View file

@ -1,30 +0,0 @@
use crate::types_rewrite::db;
use sqlx::SqliteConnection;
use crate::types_rewrite::DbError;
pub async fn new_user(user: db::User, conn: &mut SqliteConnection) -> Result<db::User, DbError> {
let ts = user.created_at.to_rfc3339();
sqlx::query!(r#"
INSERT INTO user (id, acct, url, created_at, remote, username, actor_id, display_name)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)
"#, user.id.0, user.acct, user.url, ts,
user.remote, user.username, user.actor.id.0, user.display_name
)
.execute(conn)
.await
.map_err(|e| DbError::CreationError(e.to_string()))?;
Ok(user)
}
pub async fn new_actor(actor: db::Actor, conn: &mut SqliteConnection) -> Result<db::Actor, DbError> {
sqlx::query!(r#"
INSERT INTO actor (id, inbox, outbox)
VALUES (?1, ?2, ?3)
"#, actor.id.0, actor.inbox, actor.outbox)
.execute(conn)
.await
.map_err(|e| DbError::CreationError(e.to_string()))?;
Ok(actor)
}

View file

@ -1,19 +1,7 @@
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use thiserror::Error;
use std::fmt::Debug;
use uuid::Uuid;
pub mod convert; pub mod convert;
pub mod get; pub mod fetch;
pub mod make;
#[derive(Debug, Error)]
pub enum DbError {
#[error("an unknown error occured when creating: {0}")]
CreationError(String),
#[error("an unknown error occured when fetching: {0}")]
FetchError(String)
}
pub const AS_CONTEXT_RAW: &'static str = "https://www.w3.org/ns/activitystreams"; pub const AS_CONTEXT_RAW: &'static str = "https://www.w3.org/ns/activitystreams";
pub fn as_context() -> ObjectContext { pub fn as_context() -> ObjectContext {
@ -27,18 +15,12 @@ pub enum ObjectContext {
Vec(Vec<serde_json::Value>), Vec(Vec<serde_json::Value>),
} }
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct ObjectUri(pub String); pub struct ObjectUri(pub String);
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct ObjectUuid(pub String); pub struct ObjectUuid(pub String);
impl ObjectUuid {
pub fn new() -> Self {
Self(Uuid::new_v4().to_string())
}
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct Object { pub struct Object {
#[serde(rename = "@context")] #[serde(rename = "@context")]
@ -50,20 +32,20 @@ pub mod db {
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use super::*; use super::*;
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq)]
pub struct Actor { pub struct Actor {
pub id: ObjectUri, pub id: ObjectUri,
pub inbox: String, pub inbox: String,
pub outbox: String, pub outbox: String,
} }
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq)]
pub struct UserPosts { pub struct UserPosts {
// User may have no posts // User may have no posts
pub last_post_at: Option<DateTime<Utc>> pub last_post_at: Option<DateTime<Utc>>
} }
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq)]
pub struct User { pub struct User {
pub id: ObjectUuid, pub id: ObjectUuid,
pub actor: Actor, pub actor: Actor,
@ -171,107 +153,6 @@ pub mod api {
pub value: String, pub value: String,
pub verified_at: Option<String>, pub verified_at: Option<String>,
} }
#[derive(Debug, Serialize, Deserialize)]
pub struct Instance {
pub domain: String,
pub title: String,
pub version: String,
pub source_url: String,
pub description: String,
pub thumbnail: Thumbnail,
pub icon: Vec<Icon>,
pub languages: Vec<String>,
pub configuration: Configuration,
pub registrations: Registrations,
pub contact: Contact,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Configuration {
pub urls: Urls,
pub accounts: Accounts,
pub statuses: Statuses,
pub media_attachments: MediaAttachments,
pub polls: Polls,
pub translation: Translation,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Accounts {
pub max_featured_tags: i64,
pub max_pinned_statuses: i64,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MediaAttachments {
pub supported_mime_types: Vec<String>,
pub description_limit: i64,
pub image_size_limit: i64,
pub image_matrix_limit: i64,
pub video_size_limit: i64,
pub video_frame_rate_limit: i64,
pub video_matrix_limit: i64,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Polls {
pub max_options: i64,
pub max_characters_per_option: i64,
pub min_expiration: i64,
pub max_expiration: i64,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Statuses {
pub max_characters: i64,
pub max_media_attachments: i64,
pub characters_reserved_per_url: i64,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Translation {
pub enabled: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Urls {
pub streaming: String,
pub about: String,
pub privacy_policy: String,
pub terms_of_service: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Contact {
pub email: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Field {
pub name: String,
pub value: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Icon {
pub src: String,
pub size: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Registrations {
pub enabled: bool,
pub approval_required: bool,
pub reason_required: bool,
pub message: Option<String>,
pub min_age: i64,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Thumbnail {
pub url: String,
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -2,7 +2,7 @@ use rocket::{get, serde::json::Json, State};
use crate::Config; use crate::Config;
use main::types_rewrite::api::{ use crate::types::instance::{
Accounts, Configuration, Contact, Instance, MediaAttachments, Polls, Registrations, Statuses, Accounts, Configuration, Contact, Instance, MediaAttachments, Polls, Registrations, Statuses,
Thumbnail, Translation, Urls, Thumbnail, Translation, Urls,
}; };

View file

@ -51,8 +51,7 @@ pub async fn home(
display_name: String, display_name: String,
username: String username: String
} }
// FIXME: query! can't cope with this. returns a type error
let posts = sqlx::query_as::<_, Post>( let posts = sqlx::query_as::<_, Post>(
r#" r#"
WITH RECURSIVE get_home_timeline_with_boosts( WITH RECURSIVE get_home_timeline_with_boosts(
@ -85,6 +84,8 @@ pub async fn home(
.await .await
.unwrap(); .unwrap();
dbg!(&posts);
let mut out = Vec::<TimelineStatus>::new(); let mut out = Vec::<TimelineStatus>::new();
for record in posts.iter() { for record in posts.iter() {
let mut boost: Option<Box<TimelineStatus>> = None; let mut boost: Option<Box<TimelineStatus>> = None;

View file

@ -89,11 +89,11 @@ pub async fn test(
outbound: &State<OutboundQueue>, outbound: &State<OutboundQueue>,
mut db: Connection<Db> mut db: Connection<Db>
) -> &'static str { ) -> &'static str {
use main::types_rewrite::{ObjectUuid, get, api}; use main::types_rewrite::{ObjectUuid, fetch, api};
outbound.0.send(ap::QueueMessage::Heartbeat); outbound.0.send(ap::QueueMessage::Heartbeat);
let id = ObjectUuid("9b9d497b-2731-435f-a929-e609ca69dac9".to_string()); let id = ObjectUuid("9b9d497b-2731-435f-a929-e609ca69dac9".to_string());
let user= dbg!(get::user_by_id(id, &mut **db).await.unwrap()); let user= dbg!(fetch::user_by_id(id, &mut **db).await.unwrap());
let apu: api::Account = user.into(); let apu: api::Account = user.into();
dbg!(apu); dbg!(apu);

View file

@ -1,21 +1,19 @@
use chrono::Local; use chrono::Local;
use tracing::Instrument; use tracing::Instrument;
use main::ap;
use rocket::serde::json::serde_json; use rocket::serde::json::serde_json;
use rocket::{State, post}; use rocket::{State, post};
use rocket_db_pools::Connection; use rocket_db_pools::Connection;
use sqlx::SqliteConnection;
use sqlx::Sqlite; use sqlx::Sqlite;
use url::Url; use url::Url;
use uuid::Uuid; use uuid::Uuid;
use tracing::{event, span, Level, debug, warn, info, error}; use tracing::{event, span, Level, debug, warn, info, error};
use crate::http_wrapper::HttpWrapper; use crate::http_wrapper::HttpWrapper;
use main::types_rewrite::{make, db, ObjectUuid, ObjectUri, self, ap};
use crate::{ use crate::{
Db, Db,
http::HttpClient, http::HttpClient,
types::{content::Post, activity}, types::{Person, content::Post, activity},
}; };
fn handle_delete_activity(activity: activity::DeleteActivity) { fn handle_delete_activity(activity: activity::DeleteActivity) {
@ -23,7 +21,7 @@ fn handle_delete_activity(activity: activity::DeleteActivity) {
} }
async fn create_actor( async fn create_actor(
user: &ap::Person, user: &Person,
actor: &str, actor: &str,
conn: impl sqlx::Executor<'_, Database = Sqlite>, conn: impl sqlx::Executor<'_, Database = Sqlite>,
) { ) {
@ -43,7 +41,7 @@ async fn create_actor(
} }
async fn create_user( async fn create_user(
user: &ap::Person, user: &Person,
actor: &str, actor: &str,
conn: impl sqlx::Executor<'_, Database = Sqlite>, conn: impl sqlx::Executor<'_, Database = Sqlite>,
) { ) {
@ -105,106 +103,36 @@ async fn create_follow(
.unwrap(); .unwrap();
} }
struct RemoteInfo {
acct: String,
web_url: String,
is_remote: bool,
}
fn get_remote_info(actor_url: &str, person: &ap::Person) -> RemoteInfo {
let url = Url::parse(&actor_url).unwrap();
let host = url.host_str().unwrap();
let (acct, remote) = if host != "ferri.amy.mov" {
(format!("{}@{}", person.preferred_username, host), true)
} else {
(person.preferred_username.clone(), false)
};
let url = format!("https://ferri.amy.mov/{}", acct);
RemoteInfo {
acct: acct.to_string(),
web_url: url,
is_remote: remote
}
}
async fn resolve_actor<'a>(
actor_url: &str,
http: &HttpWrapper<'a>,
conn: &mut SqliteConnection
) -> Result<db::User, types_rewrite::DbError> {
let person = {
let res = http.get_person(&actor_url).await;
if let Err(e) = res {
error!("could not load user {}: {}", actor_url, e.to_string());
return Err(types_rewrite::DbError::FetchError(
format!("could not load user {}: {}", actor_url, e.to_string())
))
}
res.unwrap()
};
let user_id = ObjectUuid::new();
let remote_info = get_remote_info(actor_url, &person);
let actor = db::Actor {
id: ObjectUri(actor_url.to_string()),
inbox: person.inbox.clone(),
outbox: person.outbox.clone(),
};
info!("creating actor {}", actor_url);
let actor = make::new_actor(actor.clone(), conn).await.unwrap_or(actor);
info!("creating user {} ({:#?})", remote_info.acct, person);
let user = db::User {
id: user_id,
actor,
username: person.name,
display_name: person.preferred_username,
acct: remote_info.acct,
remote: remote_info.is_remote,
url: remote_info.web_url,
created_at: main::ap::now(),
posts: db::UserPosts {
last_post_at: None
}
};
Ok(make::new_user(user.clone(), conn).await.unwrap_or(user))
}
async fn handle_follow_activity<'a>( async fn handle_follow_activity<'a>(
followed_account: &str, followed_account: &str,
activity: activity::FollowActivity, activity: activity::FollowActivity,
http: HttpWrapper<'a>, http: HttpWrapper<'a>,
mut db: Connection<Db>, mut db: Connection<Db>,
) { ) {
let actor = resolve_actor(&activity.actor, &http, &mut **db) let user = http.get_person(&activity.actor).await;
.await.unwrap(); if let Err(e) = user {
error!("could not load user {}: {}", activity.actor, e.to_string());
info!("{:?} follows {}", actor, followed_account); return
}
let user = user.unwrap();
create_actor(&user, &activity.actor, &mut **db).await;
create_user(&user, &activity.actor, &mut **db).await;
create_follow(&activity, &mut **db).await; create_follow(&activity, &mut **db).await;
let follower = main::ap::User::from_actor_id(&activity.actor, &mut **db).await; let follower = ap::User::from_actor_id(&activity.actor, &mut **db).await;
let followed = main::ap::User::from_id(&followed_account, &mut **db).await.unwrap(); let followed = ap::User::from_id(&followed_account, &mut **db).await.unwrap();
let outbox = main::ap::Outbox::for_user(followed.clone(), http.client()); let outbox = ap::Outbox::for_user(followed.clone(), http.client());
let activity = main::ap::Activity { let activity = ap::Activity {
id: format!("https://ferri.amy.mov/activities/{}", Uuid::new_v4()), id: format!("https://ferri.amy.mov/activities/{}", Uuid::new_v4()),
ty: main::ap::ActivityType::Accept, ty: ap::ActivityType::Accept,
object: activity.id, object: activity.id,
..Default::default() ..Default::default()
}; };
let req = main::ap::OutgoingActivity { let req = ap::OutgoingActivity {
signed_by: format!( signed_by: format!(
"https://ferri.amy.mov/users/{}#main-key", "https://ferri.amy.mov/users/{}#main-key",
followed.username() followed.username()
@ -289,27 +217,24 @@ async fn handle_boost_activity<'a>(
debug!("creating user {}", attribution); debug!("creating user {}", attribution);
create_user(&post_user, &attribution, &mut **db).await; create_user(&post_user, &attribution, &mut **db).await;
let attributed_user = main::ap::User::from_actor_id(&attribution, &mut **db).await; let attributed_user = ap::User::from_actor_id(&attribution, &mut **db).await;
let actor_user = main::ap::User::from_actor_id(&activity.actor, &mut **db).await; let actor_user = ap::User::from_actor_id(&activity.actor, &mut **db).await;
let base_id = main::ap::new_id(); let base_id = ap::new_id();
let now = main::ap::new_ts(); let now = ap::new_ts();
let reblog_id = main::ap::new_id(); let reblog_id = ap::new_id();
let attr_id = attributed_user.id(); let attr_id = attributed_user.id();
// HACK: ON CONFLICT is to avoid duplicate remote posts coming in
// check this better in future
sqlx::query!(" sqlx::query!("
INSERT INTO post (id, uri, user_id, content, created_at) INSERT INTO post (id, uri, user_id, content, created_at)
VALUES (?1, ?2, ?3, ?4, ?5) VALUES (?1, ?2, ?3, ?4, ?5)
ON CONFLICT(uri) DO NOTHING
", reblog_id, post.id, attr_id, post.content, post.ts) ", reblog_id, post.id, attr_id, post.content, post.ts)
.execute(&mut **db) .execute(&mut **db)
.await .await
.unwrap(); .unwrap();
let uri = format!("https://ferri.amy.mov/users/{}/posts/{}", actor_user.id(), base_id); let uri = format!("https://ferri.amy.mov/users/{}/posts/{}", actor_user.id(), post.id);
let user_id = actor_user.id(); let user_id = actor_user.id();
sqlx::query!(" sqlx::query!("
@ -344,7 +269,7 @@ async fn handle_create_activity<'a>(
debug!("creating user {}", activity.actor); debug!("creating user {}", activity.actor);
create_user(&user, &activity.actor, &mut **db).await; create_user(&user, &activity.actor, &mut **db).await;
let user = main::ap::User::from_actor_id(&activity.actor, &mut **db).await; let user = ap::User::from_actor_id(&activity.actor, &mut **db).await;
debug!("user created {:?}", user); debug!("user created {:?}", user);
let user_id = user.id(); let user_id = user.id();

View file

@ -1,7 +1,7 @@
use thiserror::Error; use thiserror::Error;
use tracing::{error, event, Level}; use tracing::{error, event, Level};
use crate::http::HttpClient; use crate::http::HttpClient;
use main::types_rewrite::ap; use crate::types::Person;
use std::fmt::Debug; use std::fmt::Debug;
pub struct HttpWrapper<'a> { pub struct HttpWrapper<'a> {
@ -65,7 +65,7 @@ impl <'a> HttpWrapper<'a> {
Ok(decoded.unwrap()) Ok(decoded.unwrap())
} }
pub async fn get_person(&self, url: &str) -> Result<ap::Person, HttpError> { pub async fn get_person(&self, url: &str) -> Result<Person, HttpError> {
self.get("Person", url).await self.get("Person", url).await
} }
} }

View file

@ -2,7 +2,6 @@ use rocket::serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Default)] #[derive(Serialize, Deserialize, Debug, Default)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
#[deprecated]
pub struct Post { pub struct Post {
// FIXME: This is because Masto sends an array but we don't care // FIXME: This is because Masto sends an array but we don't care
#[serde(rename = "@context")] #[serde(rename = "@context")]

View file

@ -0,0 +1,115 @@
use rocket::serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Instance {
pub domain: String,
pub title: String,
pub version: String,
pub source_url: String,
pub description: String,
pub thumbnail: Thumbnail,
pub icon: Vec<Icon>,
pub languages: Vec<String>,
pub configuration: Configuration,
pub registrations: Registrations,
pub contact: Contact,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Configuration {
pub urls: Urls,
pub accounts: Accounts,
pub statuses: Statuses,
pub media_attachments: MediaAttachments,
pub polls: Polls,
pub translation: Translation,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Accounts {
pub max_featured_tags: i64,
pub max_pinned_statuses: i64,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct MediaAttachments {
pub supported_mime_types: Vec<String>,
pub description_limit: i64,
pub image_size_limit: i64,
pub image_matrix_limit: i64,
pub video_size_limit: i64,
pub video_frame_rate_limit: i64,
pub video_matrix_limit: i64,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Polls {
pub max_options: i64,
pub max_characters_per_option: i64,
pub min_expiration: i64,
pub max_expiration: i64,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Statuses {
pub max_characters: i64,
pub max_media_attachments: i64,
pub characters_reserved_per_url: i64,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Translation {
pub enabled: bool,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Urls {
pub streaming: String,
pub about: String,
pub privacy_policy: String,
pub terms_of_service: String,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Contact {
pub email: String,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Field {
pub name: String,
pub value: String,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Icon {
pub src: String,
pub size: String,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Registrations {
pub enabled: bool,
pub approval_required: bool,
pub reason_required: bool,
pub message: Option<String>,
pub min_age: i64,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Thumbnail {
pub url: String,
}

View file

@ -1,5 +1,6 @@
pub mod activity; pub mod activity;
pub mod content; pub mod content;
pub mod instance;
pub mod oauth; pub mod oauth;
pub mod webfinger; pub mod webfinger;
@ -8,7 +9,6 @@ use rocket::serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
#[deprecated]
pub struct UserKey { pub struct UserKey {
pub id: String, pub id: String,
pub owner: String, pub owner: String,
@ -19,7 +19,6 @@ pub struct UserKey {
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
#[deprecated]
pub struct Person { pub struct Person {
// FIXME: This is because Masto sends an array but we don't care // FIXME: This is because Masto sends an array but we don't care
#[serde(rename = "@context")] #[serde(rename = "@context")]

View file

@ -5,7 +5,6 @@ use rocket::{
#[derive(Serialize, Deserialize, Debug, FromForm, Clone)] #[derive(Serialize, Deserialize, Debug, FromForm, Clone)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
#[deprecated]
pub struct App { pub struct App {
pub client_name: String, pub client_name: String,
pub redirect_uris: Vec<String>, pub redirect_uris: Vec<String>,
@ -14,7 +13,6 @@ pub struct App {
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
#[deprecated]
pub struct CredentialApplication { pub struct CredentialApplication {
pub name: String, pub name: String,
pub scopes: String, pub scopes: String,

View file

@ -2,7 +2,6 @@ use rocket::serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
#[deprecated]
pub struct Link { pub struct Link {
pub rel: String, pub rel: String,
#[serde(rename = "type")] #[serde(rename = "type")]
@ -12,7 +11,6 @@ pub struct Link {
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
#[deprecated]
pub struct WebfingerResponse { pub struct WebfingerResponse {
pub subject: String, pub subject: String,
pub aliases: Vec<String>, pub aliases: Vec<String>,