feat: start on CRUD ops for new types

This commit is contained in:
nullishamy 2025-04-28 23:21:59 +01:00
parent d252131e0d
commit e6b654a0b3
Signed by: amy
SSH key fingerprint: SHA256:WmV0uk6WgAQvDJlM8Ld4mFPHZo02CLXXP5VkwQ5xtyk
6 changed files with 149 additions and 32 deletions

View file

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

View file

@ -0,0 +1,30 @@
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,7 +1,19 @@
use serde::{Serialize, Deserialize};
use thiserror::Error;
use std::fmt::Debug;
use uuid::Uuid;
pub mod convert;
pub mod fetch;
pub mod get;
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 fn as_context() -> ObjectContext {
@ -15,12 +27,18 @@ pub enum ObjectContext {
Vec(Vec<serde_json::Value>),
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct ObjectUri(pub String);
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct ObjectUuid(pub String);
impl ObjectUuid {
pub fn new() -> Self {
Self(Uuid::new_v4().to_string())
}
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct Object {
#[serde(rename = "@context")]
@ -32,20 +50,20 @@ pub mod db {
use chrono::{DateTime, Utc};
use super::*;
#[derive(Debug, Eq, PartialEq)]
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Actor {
pub id: ObjectUri,
pub inbox: String,
pub outbox: String,
}
#[derive(Debug, Eq, PartialEq)]
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct UserPosts {
// User may have no posts
pub last_post_at: Option<DateTime<Utc>>
}
#[derive(Debug, Eq, PartialEq)]
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct User {
pub id: ObjectUuid,
pub actor: Actor,