mirror of
https://github.com/nullishamy/ferri.git
synced 2025-06-28 00:54:17 +00:00
chore: finish types refactor
This commit is contained in:
parent
5f346922f5
commit
77fba1a082
29 changed files with 611 additions and 608 deletions
|
@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
|
|||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::Sqlite;
|
||||
use std::fmt::Debug;
|
||||
use tracing::{event, Level};
|
||||
use tracing::{Level, event};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ActivityType {
|
||||
|
@ -104,7 +104,7 @@ impl<'a> Outbox<'a> {
|
|||
|
||||
pub async fn post<T: Serialize + Debug>(&self, activity: OutgoingActivity<T>) {
|
||||
event!(Level::INFO, ?activity, "activity in outbox");
|
||||
|
||||
|
||||
let raw = RawActivity {
|
||||
context: "https://www.w3.org/ns/activitystreams".to_string(),
|
||||
id: activity.req.id.clone(),
|
||||
|
@ -127,9 +127,11 @@ impl<'a> Outbox<'a> {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
event!(Level::DEBUG,
|
||||
outbox_res, activity = activity.req.id,
|
||||
"got response for outbox dispatch"
|
||||
event!(
|
||||
Level::DEBUG,
|
||||
outbox_res,
|
||||
activity = activity.req.id,
|
||||
"got response for outbox dispatch"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use rsa::{
|
|||
|
||||
use base64::prelude::*;
|
||||
use chrono::Utc;
|
||||
use tracing::{event, Level};
|
||||
use tracing::{Level, event};
|
||||
|
||||
pub struct HttpClient {
|
||||
client: reqwest::Client,
|
||||
|
@ -61,7 +61,7 @@ impl RequestBuilder {
|
|||
|
||||
pub async fn send(self) -> Result<Response, reqwest::Error> {
|
||||
event!(Level::DEBUG, ?self.inner, "sending an http request");
|
||||
|
||||
|
||||
self.inner.send().await
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use tracing::{info, span, Level};
|
||||
use tracing::{Level, info, span};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum QueueMessage {
|
||||
Heartbeat
|
||||
Heartbeat,
|
||||
}
|
||||
|
||||
pub struct RequestQueue {
|
||||
name: &'static str,
|
||||
send: mpsc::Sender<QueueMessage>,
|
||||
recv: mpsc::Receiver<QueueMessage>
|
||||
recv: mpsc::Receiver<QueueMessage>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct QueueHandle {
|
||||
send: mpsc::Sender<QueueMessage>
|
||||
send: mpsc::Sender<QueueMessage>,
|
||||
}
|
||||
|
||||
impl QueueHandle {
|
||||
|
@ -27,33 +27,29 @@ impl QueueHandle {
|
|||
impl RequestQueue {
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
let (send, recv) = mpsc::channel();
|
||||
Self {
|
||||
name,
|
||||
send,
|
||||
recv
|
||||
}
|
||||
Self { name, send, recv }
|
||||
}
|
||||
|
||||
pub fn spawn(self) -> QueueHandle {
|
||||
info!("starting up queue '{}'", self.name);
|
||||
|
||||
|
||||
thread::spawn(move || {
|
||||
info!("queue '{}' up", self.name);
|
||||
let recv = self.recv;
|
||||
|
||||
|
||||
while let Ok(req) = recv.recv() {
|
||||
// FIXME: When we make this do async things we will need to add tokio and
|
||||
// use proper async handled spans as the enter/drop won't work.
|
||||
// See inbox.rs for how we handle that.
|
||||
let s = span!(Level::INFO, "queue", queue_name = self.name);
|
||||
let _enter = s.enter();
|
||||
|
||||
|
||||
info!(?req, "got a message into the queue");
|
||||
|
||||
|
||||
drop(_enter);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
QueueHandle { send: self.send }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ pub struct User {
|
|||
display_name: String,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum UserError {
|
||||
#[error("user `{0}` not found")]
|
||||
|
@ -67,7 +66,10 @@ impl User {
|
|||
format!("https://ferri.amy.mov/users/{}", self.id())
|
||||
}
|
||||
|
||||
pub async fn from_id(uuid: &str, conn: impl sqlx::Executor<'_, Database = Sqlite>) -> Result<User, UserError> {
|
||||
pub async fn from_id(
|
||||
uuid: &str,
|
||||
conn: impl sqlx::Executor<'_, Database = Sqlite>,
|
||||
) -> Result<User, UserError> {
|
||||
let user = sqlx::query!(
|
||||
r#"
|
||||
SELECT u.*, a.id as "actor_own_id", a.inbox, a.outbox
|
||||
|
@ -77,10 +79,10 @@ impl User {
|
|||
"#,
|
||||
uuid
|
||||
)
|
||||
.fetch_one(conn)
|
||||
.await
|
||||
.map_err(|_| UserError::NotFound(uuid.to_string()))?;
|
||||
|
||||
.fetch_one(conn)
|
||||
.await
|
||||
.map_err(|_| UserError::NotFound(uuid.to_string()))?;
|
||||
|
||||
Ok(User {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
|
@ -106,10 +108,10 @@ impl User {
|
|||
"#,
|
||||
username
|
||||
)
|
||||
.fetch_one(conn)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
.fetch_one(conn)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
User {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
|
|
|
@ -14,7 +14,7 @@ impl Config {
|
|||
pub fn host(&self) -> &str {
|
||||
&self.server.host
|
||||
}
|
||||
|
||||
|
||||
pub fn user_url(&self, user_uuid: &str) -> String {
|
||||
format!("{}/users/{}", self.host(), user_uuid)
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ impl Config {
|
|||
pub fn followers_url(&self, user_uuid: &str) -> String {
|
||||
format!("{}/followers", self.user_url(user_uuid))
|
||||
}
|
||||
|
||||
|
||||
pub fn following_url(&self, user_uuid: &str) -> String {
|
||||
format!("{}/following", self.user_url(user_uuid))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
pub mod ap;
|
||||
pub mod config;
|
||||
pub mod types_rewrite;
|
||||
pub mod types;
|
||||
|
||||
use rand::{Rng, distributions::Alphanumeric};
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
use crate::types_rewrite::api;
|
||||
use crate::types_rewrite::ap;
|
||||
use crate::types_rewrite::db;
|
||||
use crate::types::ap;
|
||||
use crate::types::api;
|
||||
use crate::types::db;
|
||||
|
||||
use crate::types_rewrite::{Object, as_context};
|
||||
use crate::types::{Object, ObjectUri, as_context};
|
||||
|
||||
impl From<db::Actor> for ap::Actor {
|
||||
fn from(val: db::Actor) -> ap::Actor {
|
||||
ap::Actor {
|
||||
obj: Object {
|
||||
context: as_context(),
|
||||
id: val.id
|
||||
id: val.id,
|
||||
},
|
||||
inbox: val.inbox,
|
||||
outbox: val.outbox
|
||||
outbox: val.outbox,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ impl From<ap::Actor> for db::Actor {
|
|||
db::Actor {
|
||||
id: val.obj.id,
|
||||
inbox: val.inbox,
|
||||
outbox: val.outbox
|
||||
outbox: val.outbox,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,28 +34,51 @@ impl From<db::User> for api::Account {
|
|||
username: val.username,
|
||||
acct: val.acct,
|
||||
display_name: val.display_name,
|
||||
|
||||
|
||||
locked: false,
|
||||
bot: false,
|
||||
|
||||
|
||||
created_at: val.created_at.to_rfc3339(),
|
||||
attribution_domains: vec![],
|
||||
|
||||
|
||||
note: "".to_string(),
|
||||
url: val.url,
|
||||
|
||||
|
||||
avatar: "https://ferri.amy.mov/assets/pfp.png".to_string(),
|
||||
avatar_static: "https://ferri.amy.mov/assets/pfp.png".to_string(),
|
||||
header: "https://ferri.amy.mov/assets/pfp.png".to_string(),
|
||||
header_static: "https://ferri.amy.mov/assets/pfp.png".to_string(),
|
||||
|
||||
|
||||
followers_count: 0,
|
||||
following_count: 0,
|
||||
statuses_count: 0,
|
||||
last_status_at: val.posts.last_post_at.map(|ts| ts.to_rfc3339()),
|
||||
|
||||
|
||||
emojis: vec![],
|
||||
fields: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<db::User> for ap::Person {
|
||||
fn from(val: db::User) -> ap::Person {
|
||||
ap::Person {
|
||||
obj: Object {
|
||||
context: as_context(),
|
||||
id: ObjectUri(format!("https://ferri.amy.mov/users/{}", val.id.0)),
|
||||
},
|
||||
following: format!("https://ferri.amy.mov/users/{}/following", val.id.0),
|
||||
followers: format!("https://ferri.amy.mov/users/{}/followers", val.id.0),
|
||||
summary: format!("ferri {}", val.username),
|
||||
inbox: format!("https://ferri.amy.mov/users/{}/inbox", val.id.0),
|
||||
outbox: format!("https://ferri.amy.mov/users/{}/outbox", val.id.0),
|
||||
preferred_username: val.display_name,
|
||||
name: val.username,
|
||||
public_key: Some(ap::UserKey {
|
||||
id: format!("https://ferri.amy.mov/users/{}#main-key", val.id.0),
|
||||
owner: format!("https://ferri.amy.mov/users/{}", val.id.0),
|
||||
public_key: include_str!("../../../public.pem").to_string(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
use crate::types_rewrite::{ObjectUuid, ObjectUri, db};
|
||||
use crate::types::{DbError, ObjectUri, ObjectUuid, db};
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use sqlx::SqliteConnection;
|
||||
use tracing::info;
|
||||
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: &str = "%Y-%m-%d %H:%M:%S";
|
||||
|
||||
fn parse_ts(ts: String) -> Option<DateTime<Utc>> {
|
||||
NaiveDateTime::parse_from_str(&ts, SQLITE_TIME_FMT)
|
||||
|
@ -14,8 +13,9 @@ fn parse_ts(ts: String) -> Option<DateTime<Utc>> {
|
|||
|
||||
pub async fn user_by_id(id: ObjectUuid, conn: &mut SqliteConnection) -> Result<db::User, DbError> {
|
||||
info!("fetching user by uuid '{:?}' from the database", id);
|
||||
|
||||
let record = sqlx::query!(r#"
|
||||
|
||||
let record = sqlx::query!(
|
||||
r#"
|
||||
SELECT
|
||||
u.id as "user_id",
|
||||
u.username,
|
||||
|
@ -30,46 +30,54 @@ pub async fn user_by_id(id: ObjectUuid, conn: &mut SqliteConnection) -> Result<d
|
|||
FROM "user" u
|
||||
INNER JOIN "actor" a ON u.actor_id = a.id
|
||||
WHERE u.id = ?1
|
||||
"#, id.0)
|
||||
.fetch_one(&mut *conn)
|
||||
.await
|
||||
.map_err(|e| DbError::FetchError(e.to_string()))?;
|
||||
"#,
|
||||
id.0
|
||||
)
|
||||
.fetch_one(&mut *conn)
|
||||
.await
|
||||
.map_err(|e| DbError::FetchError(e.to_string()))?;
|
||||
|
||||
let follower_count = sqlx::query_scalar!(r#"
|
||||
let follower_count = sqlx::query_scalar!(
|
||||
r#"
|
||||
SELECT COUNT(follower_id)
|
||||
FROM "follow"
|
||||
WHERE followed_id = ?1
|
||||
"#, record.actor_id)
|
||||
.fetch_one(&mut *conn)
|
||||
.await
|
||||
.map_err(|e| DbError::FetchError(e.to_string()))?;
|
||||
"#,
|
||||
record.actor_id
|
||||
)
|
||||
.fetch_one(&mut *conn)
|
||||
.await
|
||||
.map_err(|e| DbError::FetchError(e.to_string()))?;
|
||||
|
||||
let last_post_at = sqlx::query_scalar!(r#"
|
||||
let last_post_at = sqlx::query_scalar!(
|
||||
r#"
|
||||
SELECT datetime(p.created_at)
|
||||
FROM post p
|
||||
WHERE p.user_id = ?1
|
||||
ORDER BY datetime(p.created_at) DESC
|
||||
LIMIT 1
|
||||
"#, record.user_id)
|
||||
.fetch_one(&mut *conn)
|
||||
.await
|
||||
.map_err(|e| DbError::FetchError(e.to_string()))?
|
||||
.and_then(|ts| {
|
||||
info!("parsing timestamp {}", ts);
|
||||
parse_ts(ts)
|
||||
});
|
||||
"#,
|
||||
record.user_id
|
||||
)
|
||||
.fetch_one(&mut *conn)
|
||||
.await
|
||||
.map_err(|e| DbError::FetchError(e.to_string()))?
|
||||
.and_then(|ts| {
|
||||
info!("parsing timestamp {}", ts);
|
||||
parse_ts(ts)
|
||||
});
|
||||
|
||||
let user_created = parse_ts(record.created_at).expect("no db corruption");
|
||||
|
||||
info!("user {:?} has {} followers", id, follower_count);
|
||||
info!("user {:?} last posted {:?}", id, last_post_at);
|
||||
|
||||
|
||||
Ok(db::User {
|
||||
id: ObjectUuid(record.user_id),
|
||||
actor: db::Actor {
|
||||
id: ObjectUri(record.actor_id),
|
||||
inbox: record.inbox,
|
||||
outbox: record.outbox
|
||||
outbox: record.outbox,
|
||||
},
|
||||
acct: record.acct,
|
||||
remote: record.remote,
|
||||
|
@ -77,8 +85,6 @@ pub async fn user_by_id(id: ObjectUuid, conn: &mut SqliteConnection) -> Result<d
|
|||
display_name: record.display_name,
|
||||
created_at: user_created,
|
||||
url: record.url,
|
||||
posts: db::UserPosts {
|
||||
last_post_at
|
||||
}
|
||||
posts: db::UserPosts { last_post_at },
|
||||
})
|
||||
}
|
||||
}
|
45
ferri-main/src/types/make.rs
Normal file
45
ferri-main/src/types/make.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use crate::types::{DbError, db};
|
||||
use sqlx::SqliteConnection;
|
||||
|
||||
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)
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
use thiserror::Error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Debug;
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub mod convert;
|
||||
|
@ -12,10 +12,10 @@ pub enum DbError {
|
|||
#[error("an unknown error occured when creating: {0}")]
|
||||
CreationError(String),
|
||||
#[error("an unknown error occured when fetching: {0}")]
|
||||
FetchError(String)
|
||||
FetchError(String),
|
||||
}
|
||||
|
||||
pub const AS_CONTEXT_RAW: &'static str = "https://www.w3.org/ns/activitystreams";
|
||||
pub const AS_CONTEXT_RAW: &str = "https://www.w3.org/ns/activitystreams";
|
||||
pub fn as_context() -> ObjectContext {
|
||||
ObjectContext::Str(AS_CONTEXT_RAW.to_string())
|
||||
}
|
||||
|
@ -33,6 +33,12 @@ pub struct ObjectUri(pub String);
|
|||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
|
||||
pub struct ObjectUuid(pub String);
|
||||
|
||||
impl Default for ObjectUuid {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectUuid {
|
||||
pub fn new() -> Self {
|
||||
Self(Uuid::new_v4().to_string())
|
||||
|
@ -42,13 +48,13 @@ impl ObjectUuid {
|
|||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
||||
pub struct Object {
|
||||
#[serde(rename = "@context")]
|
||||
context: ObjectContext,
|
||||
id: ObjectUri,
|
||||
pub context: ObjectContext,
|
||||
pub id: ObjectUri,
|
||||
}
|
||||
|
||||
pub mod db {
|
||||
use chrono::{DateTime, Utc};
|
||||
use super::*;
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub struct Actor {
|
||||
|
@ -60,7 +66,7 @@ pub mod db {
|
|||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub struct UserPosts {
|
||||
// User may have no posts
|
||||
pub last_post_at: Option<DateTime<Utc>>
|
||||
pub last_post_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
|
@ -73,86 +79,210 @@ pub mod db {
|
|||
pub remote: bool,
|
||||
pub url: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
|
||||
pub posts: UserPosts
|
||||
|
||||
pub posts: UserPosts,
|
||||
}
|
||||
}
|
||||
|
||||
pub mod ap {
|
||||
use serde::{Serialize, Deserialize};
|
||||
use super::*;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
||||
pub enum ActivityType {
|
||||
Create,
|
||||
Note,
|
||||
Delete,
|
||||
Accept,
|
||||
Announce,
|
||||
Like,
|
||||
Follow,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct MinimalActivity {
|
||||
#[serde(flatten)]
|
||||
pub obj: Object,
|
||||
pub ty: ActivityType,
|
||||
}
|
||||
|
||||
pub type DeleteActivity = BasicActivity;
|
||||
pub type LikeActivity = BasicActivity;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct BasicActivity {
|
||||
#[serde(flatten)]
|
||||
pub obj: Object,
|
||||
|
||||
pub object: String,
|
||||
pub actor: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct CreateActivity {
|
||||
#[serde(flatten)]
|
||||
pub obj: Object,
|
||||
|
||||
pub ty: ActivityType,
|
||||
|
||||
pub object: Post,
|
||||
pub actor: String,
|
||||
pub to: Vec<String>,
|
||||
pub cc: Vec<String>,
|
||||
|
||||
#[serde(rename = "published")]
|
||||
pub ts: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct FollowActivity {
|
||||
#[serde(flatten)]
|
||||
pub obj: Object,
|
||||
|
||||
pub ty: ActivityType,
|
||||
|
||||
pub object: String,
|
||||
pub actor: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct AcceptActivity {
|
||||
#[serde(flatten)]
|
||||
pub obj: Object,
|
||||
|
||||
pub ty: ActivityType,
|
||||
|
||||
pub object: String,
|
||||
pub actor: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct BoostActivity {
|
||||
#[serde(flatten)]
|
||||
pub obj: Object,
|
||||
|
||||
pub ty: ActivityType,
|
||||
|
||||
pub actor: String,
|
||||
pub published: String,
|
||||
pub to: Vec<String>,
|
||||
pub cc: Vec<String>,
|
||||
pub object: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Post {
|
||||
#[serde(flatten)]
|
||||
pub obj: Object,
|
||||
|
||||
pub ty: ActivityType,
|
||||
|
||||
#[serde(rename = "published")]
|
||||
pub ts: String,
|
||||
pub content: String,
|
||||
pub to: Vec<String>,
|
||||
pub cc: Vec<String>,
|
||||
|
||||
#[serde(rename = "attributedTo")]
|
||||
pub attributed_to: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
||||
pub struct Actor {
|
||||
#[serde(flatten)]
|
||||
pub obj: Object,
|
||||
|
||||
|
||||
pub inbox: String,
|
||||
pub outbox: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Person {
|
||||
#[serde(flatten)]
|
||||
pub obj: Object,
|
||||
|
||||
pub following: String,
|
||||
pub followers: String,
|
||||
|
||||
|
||||
pub summary: String,
|
||||
pub inbox: String,
|
||||
pub outbox: String,
|
||||
|
||||
|
||||
pub preferred_username: String,
|
||||
pub name: String,
|
||||
|
||||
|
||||
pub public_key: Option<UserKey>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
||||
pub struct UserKey {
|
||||
pub id: String,
|
||||
pub owner: String,
|
||||
|
||||
|
||||
#[serde(rename = "publicKeyPem")]
|
||||
pub public_key: String,
|
||||
}
|
||||
}
|
||||
|
||||
pub mod api {
|
||||
use serde::{Serialize, Deserialize};
|
||||
use super::*;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// API will not really use actors so treat them as DB actors
|
||||
// until we require specificity
|
||||
pub type Actor = db::Actor;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct CredentialApplication {
|
||||
pub name: String,
|
||||
pub scopes: String,
|
||||
pub redirect_uris: Vec<String>,
|
||||
pub client_id: String,
|
||||
pub client_secret: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct WebfingerLink {
|
||||
pub rel: String,
|
||||
#[serde(rename = "type")]
|
||||
pub ty: Option<String>,
|
||||
pub href: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct WebfingerHit {
|
||||
pub subject: String,
|
||||
pub aliases: Vec<String>,
|
||||
pub links: Vec<WebfingerLink>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
||||
pub struct Account {
|
||||
pub id: ObjectUuid,
|
||||
pub username: String,
|
||||
pub acct: String,
|
||||
pub display_name: String,
|
||||
|
||||
|
||||
pub locked: bool,
|
||||
pub bot: bool,
|
||||
|
||||
|
||||
pub created_at: String,
|
||||
pub attribution_domains: Vec<String>,
|
||||
|
||||
|
||||
pub note: String,
|
||||
pub url: String,
|
||||
|
||||
|
||||
pub avatar: String,
|
||||
pub avatar_static: String,
|
||||
pub header: String,
|
||||
pub header_static: String,
|
||||
|
||||
|
||||
pub followers_count: i64,
|
||||
pub following_count: i64,
|
||||
pub statuses_count: i64,
|
||||
pub last_status_at: Option<String>,
|
||||
|
||||
|
||||
pub emojis: Vec<Emoji>,
|
||||
pub fields: Vec<CustomField>,
|
||||
}
|
||||
|
@ -277,11 +407,11 @@ pub mod api {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
#[test]
|
||||
fn ap_actor_to_db() {
|
||||
let domain = "https://example.com";
|
||||
|
||||
|
||||
let ap = ap::Actor {
|
||||
obj: Object {
|
||||
context: as_context(),
|
||||
|
@ -292,11 +422,14 @@ mod tests {
|
|||
};
|
||||
|
||||
let db: db::Actor = ap.into();
|
||||
|
||||
assert_eq!(db, db::Actor {
|
||||
id: ObjectUri("https://example.com/users/sample".to_string()),
|
||||
inbox: "https://example.com/users/sample/inbox".to_string(),
|
||||
outbox: "https://example.com/users/sample/outbox".to_string(),
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
db,
|
||||
db::Actor {
|
||||
id: ObjectUri("https://example.com/users/sample".to_string()),
|
||||
inbox: "https://example.com/users/sample/inbox".to_string(),
|
||||
outbox: "https://example.com/users/sample/outbox".to_string(),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue