182 lines
5.7 KiB
Rust
182 lines
5.7 KiB
Rust
use chrono::{DateTime, Utc};
|
|
use sqlx::{FromRow, Row};
|
|
use sqlx::sqlite::SqliteRow;
|
|
use tarpc::serde::{Deserialize, Serialize};
|
|
|
|
use realm_shared::types::ErrorCode;
|
|
|
|
use crate::types::MessageData::*;
|
|
|
|
#[tarpc::service]
|
|
pub trait RealmChat {
|
|
async fn test(name: String) -> String;
|
|
|
|
async fn get_info() -> ServerInfo;
|
|
async fn is_user_admin(stoken: String) -> bool;
|
|
async fn is_user_owner(stoken: String) -> bool;
|
|
|
|
async fn join_server(stoken: String, userid: String) -> Result<User, ErrorCode>;
|
|
async fn leave_server(stoken: String, userid: String) -> Result<(), ErrorCode>;
|
|
|
|
//NOTE: Any user authorized as themselves
|
|
async fn send_message(stoken: String, message: Message) -> Result<Message, ErrorCode>;
|
|
async fn start_typing(stoken: String, userid: String, roomid: String) -> ErrorCode;
|
|
async fn stop_typing(stoken: String, userid: String, roomid: String) -> ErrorCode;
|
|
async fn keep_typing(stoken: String, userid: String, roomid: String) -> ErrorCode; //NOTE: If a keep alive hasn't been received in 5 seconds, stop typing
|
|
|
|
//NOTE: Any user can call, if they are in the server
|
|
async fn get_message(stoken: String, userid: String, id: i64) -> Result<Message, ErrorCode>;
|
|
async fn get_messages_since(stoken: String, userid: String, time: DateTime<Utc>) -> Result<Vec<Message>, ErrorCode>;
|
|
async fn get_all_direct_replies(stoken: String, userid: String, head: i64) -> Result<Vec<Message>, ErrorCode>;
|
|
async fn get_reply_chain(stoken: String, userid: String, head: Message, depth: u8) -> Result<ReplyChain, ErrorCode>;
|
|
async fn get_rooms(stoken: String, userid: String) -> Result<Vec<Room>, ErrorCode>;
|
|
async fn get_room(stoken: String, userid: String, roomid: String) -> Result<Room, ErrorCode>;
|
|
async fn get_user(userid: String) -> Result<User, ErrorCode>;
|
|
async fn get_users() -> Result<Vec<User>, ErrorCode>;
|
|
async fn create_room(stoken: String, userid: String, room: Room) -> Result<Room, ErrorCode>;
|
|
async fn delete_room(stoken: String, userid: String, roomid: String) -> Result<(), ErrorCode>;
|
|
async fn promote_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>;
|
|
async fn demote_user(stoken: String, owner_userid: String, userid: String) -> Result<(), ErrorCode>;
|
|
async fn kick_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>;
|
|
async fn ban_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>;
|
|
async fn pardon_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>;
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ServerInfo {
|
|
pub server_id: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
|
|
pub struct Message {
|
|
pub id: i64,
|
|
pub timestamp: DateTime<Utc>,
|
|
pub user: User,
|
|
pub room: Room,
|
|
#[sqlx(flatten)]
|
|
pub data: MessageData,
|
|
}
|
|
|
|
pub trait FromRows<R: Row>: Sized {
|
|
fn from_rows(rows: Vec<R>) -> Result<Vec<Self>, sqlx::Error>;
|
|
}
|
|
|
|
impl FromRows<SqliteRow> for Message {
|
|
fn from_rows(rows: Vec<SqliteRow>) -> sqlx::Result<Vec<Self>> {
|
|
let mut messages = Vec::new();
|
|
|
|
for row in rows {
|
|
messages.push(Message::from_row(&row)?);
|
|
}
|
|
|
|
Ok(messages)
|
|
}
|
|
}
|
|
|
|
impl FromRow<'_, SqliteRow> for Message {
|
|
fn from_row(row: &SqliteRow) -> sqlx::Result<Self> {
|
|
Ok(Self {
|
|
id: row.try_get("id")?,
|
|
timestamp: row.try_get("timestamp")?,
|
|
user: User {
|
|
id: row.try_get("user_id")?,
|
|
userid: row.try_get("user_userid")?,
|
|
name: row.try_get("user_name")?,
|
|
owner: row.try_get("user_owner")?,
|
|
admin: row.try_get("user_admin")?,
|
|
},
|
|
room: Room {
|
|
id: row.try_get("room_id")?,
|
|
roomid: row.try_get("room_roomid")?,
|
|
admin_only_send: row.try_get("room_admin_only_send")?,
|
|
admin_only_view: row.try_get("room_admin_only_view")?,
|
|
},
|
|
data: match row.try_get("msg_type")? {
|
|
"text" => Text(row.try_get("msg_text")?),
|
|
"attachment" => Attachment(Attachment {
|
|
|
|
}),
|
|
"reply" => Reply(Reply {
|
|
referencing_id: row.try_get("referencing_id")?,
|
|
text: row.try_get("msg_text")?,
|
|
}),
|
|
"edit" => Edit(Edit {
|
|
referencing_id: row.try_get("referencing_id")?,
|
|
text: row.try_get("msg_text")?,
|
|
}),
|
|
"reaction" => Reaction(Reaction {
|
|
referencing_id: row.try_get("referencing_id")?,
|
|
emoji: row.try_get("emoji")?,
|
|
}),
|
|
"redaction" => Redaction(Redaction {
|
|
referencing_id: row.try_get("referencing_id")?,
|
|
}),
|
|
_ => { panic!() }
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
//TODO: Maybe have multipart messages
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub enum MessageData {
|
|
Text(String),
|
|
Attachment(Attachment),
|
|
Reply(Reply),
|
|
Edit(Edit), //NOTE: Have to be the owner of the referencing_guid
|
|
Reaction(Reaction),
|
|
Redaction(Redaction), //NOTE: Have to be the owner of the referencing_guid
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub struct Attachment {
|
|
//TODO
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub struct Reply {
|
|
pub referencing_id: i64,
|
|
pub text: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub struct Edit {
|
|
pub referencing_id: i64,
|
|
pub text: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub struct Reaction {
|
|
pub referencing_id: i64,
|
|
pub emoji: String
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub struct Redaction {
|
|
pub referencing_id: i64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, FromRow, PartialEq)]
|
|
pub struct User {
|
|
pub id: i64,
|
|
pub userid: String,
|
|
pub name: String,
|
|
pub owner: bool,
|
|
pub admin: bool,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, FromRow, PartialEq)]
|
|
pub struct Room {
|
|
pub id: i64,
|
|
pub roomid: String,
|
|
pub admin_only_send: bool,
|
|
pub admin_only_view: bool,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ReplyChain {
|
|
pub message: Message,
|
|
pub replies: Option<Vec<ReplyChain>>,
|
|
}
|
|
|