init
This commit is contained in:
89
.idea/workspace.xml
generated
89
.idea/workspace.xml
generated
@@ -12,56 +12,27 @@
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="b2b598c9-ef0b-4cbc-8852-cfbc8ce3920e" name="Changes" comment="init">
|
||||
<change afterPath="$PROJECT_DIR$/src/utils/config.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/utils/logger.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/utils/toolbox.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/mod.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/models/_channel_user.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/models/_server_user.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/models/attachment.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/models/category.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/models/channel.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/models/message.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/models/mod.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/models/server.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/models/user.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/repositories/_server_user_repository.rs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/db/repositories/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Cargo.lock" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.lock" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Cargo.toml" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.toml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/app/app.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/app.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/app/conf.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/app/mod.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/core/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/http/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/domain/client.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/domain/event.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/domain/mod.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/domain/models.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/domain/user.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/lib.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/main.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http_routes/channel.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http_routes/master.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http_routes/message.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http_routes/mod.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http_routes/sub_server.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http_routes/user.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http_routes/websocket.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/mod.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/protocol.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/udp.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/udp_back.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/runtime/dispatcher.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/runtime/mod.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/migrations/001_init.sqlite.sql" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/mod.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/models/channel.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/models/link_sub_server_user.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/models/message.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/models/mod.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/models/sub_server.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/models/user.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/channel_repository.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/link_sub_server_user_repository.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/message_repository.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/mod.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/sub_server_repository.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/user_repository.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/session/client.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/session/mod.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/store_service.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/utils/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/network/http/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http/server.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/network/http/server.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/network/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/db/repositories/_channel_user_repository.rs" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -115,13 +86,15 @@
|
||||
"org.rust.cargo.project.model.PROJECT_DISCOVERY": "true",
|
||||
"org.rust.cargo.project.model.impl.CargoExternalSystemProjectAware.subscribe.first.balloon": "",
|
||||
"org.rust.first.attach.projects": "true",
|
||||
"settings.editor.selected.configurable": "ml.llm.LLMConfigurable",
|
||||
"settings.editor.selected.configurable": "preferences.pluginManager",
|
||||
"to.speed.mode.migration.done": "true",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="\\wsl.localhost\Debian\home\Nell\linux_dev\ox_speak_server\src" />
|
||||
<recent name="\\wsl.localhost\Debian\home\Nell\linux_dev\ox_speak_server\src\store\db" />
|
||||
<recent name="\\wsl.localhost\Debian\home\Nell\linux_dev\ox_speak_server\src\app\http" />
|
||||
<recent name="\\wsl.localhost\Debian\home\Nell\linux_dev\ox_speak_server\src\network" />
|
||||
</key>
|
||||
@@ -180,7 +153,11 @@
|
||||
<workItem from="1758380522178" duration="7468000" />
|
||||
<workItem from="1758439568539" duration="4787000" />
|
||||
<workItem from="1758951672825" duration="25708000" />
|
||||
<workItem from="1759042700460" duration="11051000" />
|
||||
<workItem from="1759042700460" duration="16518000" />
|
||||
<workItem from="1759562385229" duration="218000" />
|
||||
<workItem from="1759562619209" duration="13323000" />
|
||||
<workItem from="1759649037947" duration="3578000" />
|
||||
<workItem from="1759657715670" duration="10824000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="init">
|
||||
<option name="closed" value="true" />
|
||||
@@ -190,7 +167,23 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1756218076891</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="2" />
|
||||
<task id="LOCAL-00002" summary="init">
|
||||
<option name="closed" value="true" />
|
||||
<created>1759077528343</created>
|
||||
<option name="number" value="00002" />
|
||||
<option name="presentableId" value="LOCAL-00002" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1759077528343</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00003" summary="init">
|
||||
<option name="closed" value="true" />
|
||||
<created>1759077533456</created>
|
||||
<option name="number" value="00003" />
|
||||
<option name="presentableId" value="LOCAL-00003" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1759077533456</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="4" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
|
||||
740
Cargo.lock
generated
740
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -29,4 +29,6 @@ tower = "0.5"
|
||||
tower-http = "0.6"
|
||||
hyper = "1.7"
|
||||
|
||||
sea-orm = { version = "1.1", features = [ "sqlx-sqlite", "runtime-tokio", "macros" ] }
|
||||
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-rustls", "sqlite", "postgres", "mysql", "uuid", "chrono", "migrate"] }
|
||||
uuid = { version = "1.18", features = ["v4", "v7", "serde"] }
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
use std::net::SocketAddr;
|
||||
use crate::app::http::router::configure_routes;
|
||||
use crate::network::http::server::HttpServer;
|
||||
use crate::network::udp::server::UdpServer;
|
||||
use crate::utils::config::Config;
|
||||
use crate::utils::logger::ContextLogger;
|
||||
@@ -24,8 +26,16 @@ impl App {
|
||||
}
|
||||
};
|
||||
|
||||
let http_server = match HttpServer::new("127.0.0.1:8080") {
|
||||
Ok(http_server) => http_server,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("Failed to create HTTP server: {}", e)))
|
||||
}
|
||||
};
|
||||
|
||||
let context = Context {
|
||||
udp_server
|
||||
udp_server,
|
||||
http_server,
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
@@ -34,8 +44,18 @@ impl App {
|
||||
logger
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn run(self) -> io::Result<()> {
|
||||
self.logger.info("Starting application");
|
||||
self.context.udp_server.run().await?;
|
||||
|
||||
self.context.http_server.run().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct Context {
|
||||
udp_server: UdpServer
|
||||
udp_server: UdpServer,
|
||||
http_server: HttpServer
|
||||
}
|
||||
57
src/db/context.rs
Normal file
57
src/db/context.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
use crate::db::{AttachmentRepository, CategoryRepository, ChannelRepository, ChannelUser, ChannelUserRepository, MessageRepository, ServerRepository, ServerUser, ServerUserRepository, UserRepository};
|
||||
use crate::utils::logger::ContextLogger;
|
||||
|
||||
struct Repositories {
|
||||
server_repository: ServerRepository,
|
||||
category_repository: CategoryRepository,
|
||||
channel_repository: ChannelRepository,
|
||||
user_repository: UserRepository,
|
||||
message_repository: MessageRepository,
|
||||
attachment_repository: AttachmentRepository,
|
||||
|
||||
server_user: ServerUserRepository,
|
||||
channel_user: ChannelUserRepository
|
||||
}
|
||||
|
||||
pub struct DbContext {
|
||||
pool: Arc<SqlitePool>,
|
||||
|
||||
repositories: Arc<Repositories>,
|
||||
|
||||
// logger
|
||||
logger: ContextLogger,
|
||||
}
|
||||
|
||||
impl DbContext {
|
||||
pub async fn new(database_url: &str) -> Result<Self, sqlx::Error> {
|
||||
let logger = ContextLogger::new("DB");
|
||||
|
||||
logger.info(&format!("Creating DB context on {}", database_url));
|
||||
let pool = SqlitePool::connect(database_url).await?;
|
||||
logger.info("DB context created");
|
||||
let pool = Arc::new(pool);
|
||||
|
||||
let repositories = Arc::new(Repositories {
|
||||
server_repository: ServerRepository::new(pool.clone()),
|
||||
category_repository: CategoryRepository::new(pool.clone()),
|
||||
channel_repository: ChannelRepository::new(pool.clone()),
|
||||
user_repository: UserRepository::new(pool.clone()),
|
||||
message_repository: MessageRepository::new(pool.clone()),
|
||||
attachment_repository: AttachmentRepository::new(pool.clone()),
|
||||
server_user: ServerUserRepository::new(pool.clone()),
|
||||
channel_user: ChannelUserRepository::new(pool.clone())
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
pool,
|
||||
repositories,
|
||||
logger,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn repositories(&self) -> Arc<Repositories> {
|
||||
self.repositories.clone()
|
||||
}
|
||||
}
|
||||
6
src/db/mod.rs
Normal file
6
src/db/mod.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
pub mod models;
|
||||
pub mod repositories;
|
||||
mod context;
|
||||
|
||||
pub use models::*;
|
||||
pub use repositories::*;
|
||||
29
src/db/models/_channel_user.rs
Normal file
29
src/db/models/_channel_user.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::FromRow;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
|
||||
pub struct ChannelUser {
|
||||
pub id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub username: Option<String>,
|
||||
pub joined_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub last_read_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl ChannelUser {
|
||||
pub fn new(channel_id: Uuid, user_id: Uuid) -> Self {
|
||||
Self {
|
||||
id: Uuid::now_v7(),
|
||||
channel_id,
|
||||
user_id,
|
||||
username: None,
|
||||
joined_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
last_read_at: Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/db/models/_server_user.rs
Normal file
28
src/db/models/_server_user.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::FromRow;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
|
||||
pub struct ServerUser {
|
||||
pub id: Uuid,
|
||||
pub server_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
#[sqlx(default)]
|
||||
pub username: Option<String>,
|
||||
pub joined_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl ServerUser {
|
||||
pub fn new(server_id: Uuid, user_id: Uuid) -> Self {
|
||||
Self {
|
||||
id: Uuid::now_v7(),
|
||||
server_id,
|
||||
user_id,
|
||||
username: None,
|
||||
joined_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/db/models/attachment.rs
Normal file
27
src/db/models/attachment.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::FromRow;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
|
||||
pub struct Attachment {
|
||||
pub id: Uuid,
|
||||
pub message_id: Uuid,
|
||||
pub filename: String,
|
||||
pub file_size: i64,
|
||||
pub mime_type: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Attachment {
|
||||
pub fn new(message_id: Uuid, filename: String, file_size: i64, mime_type: String) -> Self {
|
||||
Self {
|
||||
id: Uuid::new_v4(),
|
||||
message_id,
|
||||
filename,
|
||||
file_size,
|
||||
mime_type,
|
||||
created_at: Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/db/models/category.rs
Normal file
25
src/db/models/category.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::FromRow;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
|
||||
pub struct Category {
|
||||
pub id: Uuid,
|
||||
pub server_id: Uuid,
|
||||
pub name: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Category {
|
||||
pub fn new(server_id: Uuid, name: String) -> Self {
|
||||
Self {
|
||||
id: Uuid::now_v7(),
|
||||
server_id,
|
||||
name,
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
56
src/db/models/channel.rs
Normal file
56
src/db/models/channel.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize)]
|
||||
pub struct Channel {
|
||||
pub id: Uuid, // Blob(16) sqlite
|
||||
#[sqlx(default)]
|
||||
pub server_id: Option<Uuid>,
|
||||
#[sqlx(default)]
|
||||
pub category_id: Option<Uuid>,
|
||||
#[sqlx(default)]
|
||||
pub position: i32,
|
||||
#[sqlx(rename = "type")]
|
||||
pub channel_type: ChannelType,
|
||||
pub name: Option<String>, // Not necessary for DMs
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::Type)]
|
||||
#[sqlx(type_name = "text")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ChannelType {
|
||||
Text,
|
||||
Voice,
|
||||
Dm
|
||||
}
|
||||
|
||||
impl Channel {
|
||||
pub fn new_server_channel(server_id: Uuid, name: String, channel_type: ChannelType) -> Self {
|
||||
Self {
|
||||
id: Uuid::now_v7(),
|
||||
server_id: Some(server_id),
|
||||
category_id: None,
|
||||
position: 0,
|
||||
channel_type,
|
||||
name: Some(name),
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_dm_channel() -> Self {
|
||||
Self {
|
||||
id: Uuid::now_v7(),
|
||||
server_id: None,
|
||||
category_id: None,
|
||||
channel_type: ChannelType::Dm,
|
||||
name: None,
|
||||
position: 0,
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/db/models/message.rs
Normal file
41
src/db/models/message.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::FromRow;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
|
||||
pub struct Message {
|
||||
pub id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub content: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub edited_at: DateTime<Utc>,
|
||||
pub reply_to_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn new(channel_id: Uuid, user_id: Uuid, content: String) -> Self {
|
||||
Self {
|
||||
id: Uuid::now_v7(),
|
||||
channel_id,
|
||||
user_id,
|
||||
content,
|
||||
created_at: Utc::now(),
|
||||
edited_at: Utc::now(),
|
||||
reply_to_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_reply(channel_id: Uuid, user_id: Uuid, content: String, reply_to_id: Uuid) -> Self {
|
||||
Self {
|
||||
id: Uuid::now_v7(),
|
||||
channel_id,
|
||||
user_id,
|
||||
content,
|
||||
created_at: Utc::now(),
|
||||
edited_at: Utc::now(),
|
||||
reply_to_id: Some(reply_to_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/db/models/mod.rs
Normal file
17
src/db/models/mod.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
mod user;
|
||||
mod server;
|
||||
mod _server_user;
|
||||
mod channel;
|
||||
mod category;
|
||||
mod _channel_user;
|
||||
mod message;
|
||||
mod attachment;
|
||||
|
||||
pub use user::*;
|
||||
pub use server::*;
|
||||
pub use channel::*;
|
||||
pub use category::*;
|
||||
pub use message::*;
|
||||
pub use attachment::*;
|
||||
pub use _server_user::*;
|
||||
pub use _channel_user::*;
|
||||
25
src/db/models/server.rs
Normal file
25
src/db/models/server.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::FromRow;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, FromRow, Serialize, Deserialize)]
|
||||
pub struct Server {
|
||||
pub id: Uuid, // Blob(16) sqlite
|
||||
pub username: String,
|
||||
pub password: Option<String>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
pub fn new(username: String, password: Option<String>) -> Self {
|
||||
Self {
|
||||
id: Uuid::now_v7(),
|
||||
username,
|
||||
password,
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/db/models/user.rs
Normal file
25
src/db/models/user.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::FromRow;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, FromRow, Serialize, Deserialize)]
|
||||
pub struct User {
|
||||
pub id: Uuid, // Blob(16) sqlite
|
||||
pub username: String,
|
||||
pub pub_key: String, // TEXT
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn new(username: String, pub_key: String) -> Self {
|
||||
Self {
|
||||
id: Uuid::now_v7(),
|
||||
username,
|
||||
pub_key,
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/db/repositories/_channel_user_repository.rs
Normal file
14
src/db/repositories/_channel_user_repository.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
pub struct ChannelUserRepository {
|
||||
pool: Arc<SqlitePool>
|
||||
}
|
||||
|
||||
impl ChannelUserRepository {
|
||||
pub fn new(pool: Arc<SqlitePool>) -> Self {
|
||||
Self {
|
||||
pool
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/db/repositories/_server_user_repository.rs
Normal file
14
src/db/repositories/_server_user_repository.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
pub struct ServerUserRepository {
|
||||
pool: Arc<SqlitePool>
|
||||
}
|
||||
|
||||
impl ServerUserRepository {
|
||||
pub fn new(pool: Arc<SqlitePool>) -> Self {
|
||||
Self {
|
||||
pool
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/db/repositories/attachment_repository.rs
Normal file
14
src/db/repositories/attachment_repository.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
pub struct AttachmentRepository {
|
||||
pool: Arc<SqlitePool>
|
||||
}
|
||||
|
||||
impl AttachmentRepository {
|
||||
pub fn new(pool: Arc<SqlitePool>) -> Self {
|
||||
Self {
|
||||
pool
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/db/repositories/category_repository.rs
Normal file
14
src/db/repositories/category_repository.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
pub struct CategoryRepository{
|
||||
pool: Arc<SqlitePool>
|
||||
}
|
||||
|
||||
impl CategoryRepository {
|
||||
pub fn new(pool: Arc<SqlitePool>) -> Self {
|
||||
Self {
|
||||
pool
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/db/repositories/channel_repository.rs
Normal file
15
src/db/repositories/channel_repository.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
pub struct ChannelRepository {
|
||||
pool: Arc<SqlitePool>
|
||||
}
|
||||
|
||||
|
||||
impl ChannelRepository {
|
||||
pub fn new(pool: Arc<SqlitePool>) -> Self {
|
||||
Self {
|
||||
pool
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/db/repositories/message_repository.rs
Normal file
15
src/db/repositories/message_repository.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
pub struct MessageRepository{
|
||||
pool: Arc<SqlitePool>
|
||||
}
|
||||
|
||||
|
||||
impl MessageRepository {
|
||||
pub fn new(pool: Arc<SqlitePool>) -> Self {
|
||||
Self {
|
||||
pool
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/db/repositories/mod.rs
Normal file
17
src/db/repositories/mod.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
mod _channel_user_repository;
|
||||
mod _server_user_repository;
|
||||
mod user_repository;
|
||||
mod server_repository;
|
||||
mod channel_repository;
|
||||
mod category_repository;
|
||||
mod message_repository;
|
||||
mod attachment_repository;
|
||||
|
||||
pub use user_repository::*;
|
||||
pub use server_repository::*;
|
||||
pub use channel_repository::*;
|
||||
pub use category_repository::*;
|
||||
pub use message_repository::*;
|
||||
pub use attachment_repository::*;
|
||||
pub use _server_user_repository::*;
|
||||
pub use _channel_user_repository::*;
|
||||
15
src/db/repositories/server_repository.rs
Normal file
15
src/db/repositories/server_repository.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
pub struct ServerRepository{
|
||||
pool: Arc<SqlitePool>
|
||||
}
|
||||
|
||||
|
||||
impl ServerRepository {
|
||||
pub fn new(pool: Arc<SqlitePool>) -> Self {
|
||||
Self{
|
||||
pool
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/db/repositories/user_repository.rs
Normal file
14
src/db/repositories/user_repository.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
use sqlx::{SqlitePool};
|
||||
|
||||
pub struct UserRepository {
|
||||
pool: Arc<SqlitePool>
|
||||
}
|
||||
|
||||
impl UserRepository {
|
||||
pub fn new(pool: Arc<SqlitePool>) -> Self {
|
||||
Self {
|
||||
pool
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,4 @@
|
||||
pub mod utils;
|
||||
pub mod network;
|
||||
pub mod app;
|
||||
pub mod store;
|
||||
pub mod db;
|
||||
@@ -1 +1 @@
|
||||
mod server;
|
||||
pub mod server;
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::io;
|
||||
use std::net::SocketAddr;
|
||||
use axum::{Router, routing::get, http::StatusCode, Json};
|
||||
use axum::{Router};
|
||||
use tokio::net::TcpListener;
|
||||
use crate::utils::logger::ContextLogger;
|
||||
|
||||
@@ -20,34 +20,13 @@ impl HttpServer {
|
||||
Ok(Self { bind_addr, logger })
|
||||
}
|
||||
|
||||
pub async fn run(self) -> io::Result<()> {
|
||||
pub async fn run(self, router: Router) -> io::Result<()> {
|
||||
self.logger.info(&format!("Starting HTTP server on {}", self.bind_addr));
|
||||
|
||||
let listener = TcpListener::bind(self.bind_addr).await?;
|
||||
let app = create_app(self.logger.clone());
|
||||
|
||||
axum::serve(listener, app)
|
||||
axum::serve(listener, router)
|
||||
.await
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
|
||||
}
|
||||
}
|
||||
|
||||
fn create_app(logger: ContextLogger) -> Router {
|
||||
Router::new()
|
||||
.route("/", get(|| async { "OX Speak Server - HTTP API" }))
|
||||
.route("/health", get(|| async { StatusCode::OK }))
|
||||
.route("/api/status", get(status_handler))
|
||||
.with_state(logger)
|
||||
}
|
||||
|
||||
async fn status_handler(
|
||||
axum::extract::State(logger): axum::extract::State<ContextLogger>
|
||||
) -> Json<serde_json::Value> {
|
||||
logger.info("Status endpoint called");
|
||||
|
||||
Json(serde_json::json!({
|
||||
"status": "ok",
|
||||
"service": "ox-speak-server",
|
||||
"workers": tokio::runtime::Handle::current().metrics().num_workers()
|
||||
}))
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
pub mod udp;
|
||||
mod http;
|
||||
pub mod http;
|
||||
Reference in New Issue
Block a user