Added working message commands

Also fixed up the subscription forwarder which was sending the wrong
type. Oops
This commit is contained in:
2026-05-31 14:16:49 -07:00
parent 0e3600c31f
commit 598a8624f5
6 changed files with 286 additions and 27 deletions
+66
View File
@@ -8,6 +8,7 @@ use diesel_async::AsyncPgConnection;
use diesel_async::RunQueryDsl;//, AsyncConnection};
use diesel_async::pooled_connection::deadpool::Object;
use fedichat::client::{ServerMessage,ServerError,AuthMethod};
use fedichat::message::TaggedMessage;
use rand::distr::{Alphanumeric, SampleString};
use rand::rngs::{SysRng,StdRng};
use rand::prelude::*;
@@ -125,3 +126,68 @@ pub async fn gen_token(mut connection: Object<AsyncPgConnection>, user: String)
}
}
#[instrument(skip_all)]
pub async fn insert_message(
mut connection: Object<AsyncPgConnection>,
message: TaggedMessage,
body: &String,
room_id: &fedichat::RoomId
) -> Result<ServerMessage,ServerError> {
let insertable = models::NewMessage{
room: models::RoomId::from_fedichat(room_id,message.target.0),
body: body.clone(),
signature: message.signature.to_vec(),
client_timestamp: message.client_timestamp.unix_timestamp(),
server_timestamp: message.server_timestamp.unix_timestamp(),
username: message.user.into()
};
let result = diesel::insert_into(schema::messages::table)
.values(&insertable)
.returning(models::Message::as_returning())
.get_result(&mut *connection)
.await;
match result {
// TODO: might need to check this? I don't know what it means
Ok(models::Message{id, ..}) => {
// Oh no type conversion
Ok(ServerMessage::OkMessage(fedichat::message::MessageId(id as u64)))
},
// TODO: Probably actually check the error
Err(_e) => Err(ServerError::UserAlreadyExists)
}
}
// Maybe TODO: There is kind of no point storing the server name as part of the
// message ID right? All messages stored locally are for local rooms
#[instrument(skip_all)]
pub async fn get_messages(
mut connection: Object<AsyncPgConnection>,
room_id_s: fedichat::RoomId,
server: String,
count: u64,
end: fedichat::message::MessageId,
) -> Result<ServerMessage,ServerError> {
use schema::messages::dsl::*;
let result = messages
.filter(room.eq(models::RoomId::from_fedichat(&room_id_s,server)))
.order(id.desc())
.filter(id.lt(end.0 as i64))
.select(models::Message::as_select())
.limit(count as i64)
.load(&mut *connection)
.await;
match result {
// If we have more than 0 rows then authentication is successful
Ok(m) => {
Ok(ServerMessage::Messages(m.into_iter().map(|x| x.into()).collect()))
},
_ => Err(ServerError::Generic)
}
}
+60 -4
View File
@@ -5,6 +5,7 @@ use diesel::expression::AsExpression;
use diesel_derive_composite::Composite;
use diesel::pg::Pg;
use time::OffsetDateTime;
// Gets around broken macro in diesel_derive_composite
type MyArr = diesel::sql_types::Array<diesel::sql_types::BigInt>;
@@ -17,9 +18,26 @@ pub struct UserT {
#[diesel_composite(sql_type = diesel::sql_types::Text)]
pub server: String
}
impl Into<fedichat::User> for UserT {
fn into(self) -> fedichat::User {
fedichat::User {
name: self.name,
server: self.server
}
}
}
impl From<fedichat::User> for UserT {
fn from(other: fedichat::User) -> Self {
UserT {
name: other.name,
server: other.server
}
}
}
#[derive(Debug, Composite, FromSqlRow, AsExpression)]
#[diesel(sql_type = crate::db::schema::sql_types::UserT)]
#[diesel(sql_type = crate::db::schema::sql_types::RoomId)]
pub struct RoomId {
#[diesel_composite(sql_type = MyArr)]
pub coordinates: Vec<i64>,
@@ -27,6 +45,15 @@ pub struct RoomId {
pub server: String
}
impl RoomId {
pub fn from_fedichat(other: &fedichat::RoomId, server: String) -> Self {
RoomId {
coordinates: other.coordinates.clone(),
server
}
}
}
#[derive(Queryable, Selectable)]
#[diesel(table_name = crate::db::schema::groups)]
pub struct Group {
@@ -62,13 +89,42 @@ pub struct NewUser {
pub password: String,
}
#[derive(Queryable, Selectable)]
#[derive(Queryable, Selectable,QueryableByName)]
#[diesel(table_name = crate::db::schema::messages)]
pub struct Messages {
pub struct Message {
pub id: i64,
pub room: RoomId,
pub body: String,
pub signature: String,
pub signature: Vec<u8>,
pub client_timestamp: i64,
pub server_timestamp: i64,
pub username: UserT,
pub edited: Option<bool>
}
impl Into<fedichat::message::TaggedMessage> for Message {
fn into(self) -> fedichat::message::TaggedMessage {
fedichat::message::TaggedMessage {
signature: self.signature.into(),
client_timestamp: OffsetDateTime::from_unix_timestamp(self.client_timestamp).expect("Invalid timestamp conversion"),
server_timestamp: OffsetDateTime::from_unix_timestamp(self.server_timestamp).expect("Invalid timestamp conversion"),
target: fedichat::ServerAddr(self.room.server),
user: self.username.into(),
message: fedichat::client::ClientMessage::Message {
body: self.body,
room_id: fedichat::RoomId{ coordinates: self.room.coordinates},
id: Some(fedichat::message::MessageId(self.id as u64))
}
}
}
}
#[derive(Insertable)]
#[diesel(table_name = crate::db::schema::messages)]
pub struct NewMessage {
pub room: RoomId,
pub body: String,
pub signature: Vec<u8>,
pub client_timestamp: i64,
pub server_timestamp: i64,
pub username: UserT
+1 -1
View File
@@ -31,7 +31,7 @@ diesel::table! {
id -> Int8,
room -> RoomId,
body -> Text,
signature -> Text,
signature -> Bytea,
client_timestamp -> Int8,
server_timestamp -> Int8,
username -> UserT,