hexagonal?
parent
312d6c98cf
commit
eb23143739
|
|
@ -103,6 +103,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.4"
|
||||
|
|
@ -1122,6 +1128,7 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
|||
name = "memejoin-rs"
|
||||
version = "0.2.2-alpha"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"axum",
|
||||
"axum-extra",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.100"
|
||||
async-trait = "0.1.72"
|
||||
axum = { version = "0.6.9", features = ["headers", "multipart"] }
|
||||
axum-extra = { version = "0.7.5", features = ["cookie-private", "cookie"] }
|
||||
|
|
|
|||
12
flake.lock
12
flake.lock
|
|
@ -36,11 +36,11 @@
|
|||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1736320768,
|
||||
"narHash": "sha256-nIYdTAiKIGnFNugbomgBJR+Xv5F1ZQU+HfaBqJKroC0=",
|
||||
"lastModified": 1744536153,
|
||||
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4bc9c909d9ac828a039f288cf872d16d38185db8",
|
||||
"rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -62,11 +62,11 @@
|
|||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743682350,
|
||||
"narHash": "sha256-S/MyKOFajCiBm5H5laoE59wB6w0NJ4wJG53iAPfYW3k=",
|
||||
"lastModified": 1759718104,
|
||||
"narHash": "sha256-TbkLsgdnXHUXR4gOQBmhxkEE9ne+eHmX1chZHWRogy0=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "c4a8327b0f25d1d81edecbb6105f74d7cf9d7382",
|
||||
"rev": "edea9f33f9a03f615ad3609a40fbcefe0ec835ca",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
};
|
||||
});
|
||||
local-rust = (pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain).override {
|
||||
extensions = [ "rust-analysis" ];
|
||||
extensions = [ "rust-analyzer" "rust-src" ];
|
||||
};
|
||||
in
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
pub mod models;
|
||||
pub mod ports;
|
||||
pub mod service;
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
pub struct GuildId(u64);
|
||||
pub struct ExternalGuildId(u64);
|
||||
pub struct UserName(String);
|
||||
pub struct ChannelName(String);
|
||||
pub struct IntroId(i32);
|
||||
|
||||
pub struct Guild {
|
||||
id: GuildId,
|
||||
|
||||
name: String,
|
||||
sound_delay: u32,
|
||||
external_id: ExternalGuildId,
|
||||
|
||||
channels: Vec<Channel>,
|
||||
users: Vec<User>,
|
||||
}
|
||||
|
||||
pub struct User {
|
||||
user: UserName,
|
||||
channel_intros: HashMap<ChannelName, Vec<Intro>>,
|
||||
}
|
||||
|
||||
pub struct Channel {
|
||||
name: ChannelName,
|
||||
}
|
||||
|
||||
pub struct Intro {
|
||||
id: IntroId,
|
||||
|
||||
name: String,
|
||||
filename: String,
|
||||
}
|
||||
|
||||
pub struct CreateGuildRequest {
|
||||
name: String,
|
||||
sound_delay: u32,
|
||||
external_id: ExternalGuildId,
|
||||
}
|
||||
|
||||
pub struct CreateUserRequest {
|
||||
user: UserName,
|
||||
}
|
||||
|
||||
pub struct CreateChannelRequest {
|
||||
guild_id: GuildId,
|
||||
channel_name: ChannelName,
|
||||
}
|
||||
|
||||
pub struct AddIntroToGuildRequest {
|
||||
guild_id: GuildId,
|
||||
name: String,
|
||||
volume: i32,
|
||||
filename: String,
|
||||
}
|
||||
|
||||
pub struct AddIntroToUserRequest {
|
||||
user: UserName,
|
||||
guild_id: GuildId,
|
||||
channel_name: ChannelName,
|
||||
intro_id: IntroId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CreateGuildError {
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CreateUserError {
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CreateChannelError {
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AddIntroToGuildError {
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AddIntroToUserError {
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GetGuildError {
|
||||
#[error("Guild not found")]
|
||||
NotFound,
|
||||
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
pub mod guild;
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
use super::models::guild::{
|
||||
AddIntroToGuildError, AddIntroToGuildRequest, AddIntroToUserError, AddIntroToUserRequest,
|
||||
Channel, CreateChannelError, CreateChannelRequest, CreateGuildError, CreateGuildRequest,
|
||||
CreateUserError, CreateUserRequest, GetGuildError, Guild, GuildId, User,
|
||||
};
|
||||
|
||||
pub trait IntroToolService {
|
||||
async fn create_guild(&self, req: CreateGuildRequest) -> Result<Guild, CreateGuildError>;
|
||||
async fn create_user(&self, req: CreateUserRequest) -> Result<User, CreateUserError>;
|
||||
async fn create_channel(
|
||||
&self,
|
||||
req: CreateChannelRequest,
|
||||
) -> Result<Channel, CreateChannelError>;
|
||||
|
||||
async fn add_intro_to_guild(
|
||||
&self,
|
||||
req: AddIntroToGuildRequest,
|
||||
) -> Result<(), AddIntroToGuildError>;
|
||||
|
||||
async fn add_intro_to_user(
|
||||
&self,
|
||||
req: AddIntroToUserRequest,
|
||||
) -> Result<(), AddIntroToUserError>;
|
||||
}
|
||||
|
||||
pub trait IntroToolRepository {
|
||||
async fn get_guild(&self, guild_id: GuildId) -> Result<Guild, GetGuildError>;
|
||||
|
||||
async fn create_guild(&self, req: CreateGuildRequest) -> Result<Guild, CreateGuildError>;
|
||||
async fn create_user(&self, req: CreateUserRequest) -> Result<User, CreateUserError>;
|
||||
async fn create_channel(
|
||||
&self,
|
||||
req: CreateChannelRequest,
|
||||
) -> Result<Channel, CreateChannelError>;
|
||||
|
||||
async fn add_intro_to_guild(
|
||||
&self,
|
||||
req: AddIntroToGuildRequest,
|
||||
) -> Result<(), AddIntroToGuildError>;
|
||||
|
||||
async fn add_intro_to_user(
|
||||
&self,
|
||||
req: AddIntroToUserRequest,
|
||||
) -> Result<(), AddIntroToUserError>;
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
use crate::lib::domain::intro_tool::ports::{IntroToolRepository, IntroToolService};
|
||||
|
||||
use super::models;
|
||||
|
||||
pub struct Service<R>
|
||||
where
|
||||
R: IntroToolRepository,
|
||||
{
|
||||
repo: R,
|
||||
}
|
||||
|
||||
impl<R> Service<R>
|
||||
where
|
||||
R: IntroToolRepository,
|
||||
{
|
||||
pub fn new(repo: R) -> Self {
|
||||
Self { repo }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> IntroToolService for Service<R>
|
||||
where
|
||||
R: IntroToolRepository,
|
||||
{
|
||||
async fn create_guild(
|
||||
&self,
|
||||
req: models::guild::CreateGuildRequest,
|
||||
) -> Result<models::guild::Guild, models::guild::CreateGuildError> {
|
||||
self.repo.create_guild(req).await
|
||||
}
|
||||
|
||||
async fn create_user(
|
||||
&self,
|
||||
req: models::guild::CreateUserRequest,
|
||||
) -> Result<models::guild::User, models::guild::CreateUserError> {
|
||||
self.repo.create_user(req).await
|
||||
}
|
||||
|
||||
async fn create_channel(
|
||||
&self,
|
||||
req: models::guild::CreateChannelRequest,
|
||||
) -> Result<models::guild::Channel, models::guild::CreateChannelError> {
|
||||
self.repo.create_channel(req).await
|
||||
}
|
||||
|
||||
async fn add_intro_to_guild(
|
||||
&self,
|
||||
req: models::guild::AddIntroToGuildRequest,
|
||||
) -> Result<(), models::guild::AddIntroToGuildError> {
|
||||
self.repo.add_intro_to_guild(req).await
|
||||
}
|
||||
|
||||
async fn add_intro_to_user(
|
||||
&self,
|
||||
req: models::guild::AddIntroToUserRequest,
|
||||
) -> Result<(), models::guild::AddIntroToUserError> {
|
||||
self.repo.add_intro_to_user(req).await
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
pub mod intro_tool;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
pub mod domain;
|
||||
pub mod inbound;
|
||||
pub mod outbound;
|
||||
|
|
@ -0,0 +1 @@
|
|||
pub mod sqlite;
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
use crate::lib::domain::intro_tool::{
|
||||
models::guild::{
|
||||
self, AddIntroToGuildError, AddIntroToGuildRequest, AddIntroToUserRequest, Channel,
|
||||
CreateChannelError, CreateChannelRequest, CreateGuildError, CreateGuildRequest,
|
||||
CreateUserError, CreateUserRequest, GetGuildError, Guild, GuildId, User,
|
||||
},
|
||||
ports::IntroToolRepository,
|
||||
};
|
||||
|
||||
pub struct Sqlite {}
|
||||
|
||||
impl Sqlite {
|
||||
pub fn new(path: &str) -> Result<Self, std::io::Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntroToolRepository for Sqlite {
|
||||
async fn get_guild(&self, guild_id: GuildId) -> Result<Guild, GetGuildError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn create_guild(&self, req: CreateGuildRequest) -> Result<Guild, CreateGuildError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn create_user(&self, req: CreateUserRequest) -> Result<User, CreateUserError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn create_channel(
|
||||
&self,
|
||||
req: CreateChannelRequest,
|
||||
) -> Result<Channel, CreateChannelError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn add_intro_to_guild(
|
||||
&self,
|
||||
req: AddIntroToGuildRequest,
|
||||
) -> Result<(), AddIntroToGuildError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn add_intro_to_user(
|
||||
&self,
|
||||
req: AddIntroToUserRequest,
|
||||
) -> Result<(), guild::AddIntroToUserError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
65
src/main.rs
65
src/main.rs
|
|
@ -2,6 +2,8 @@
|
|||
// #![feature(proc_macro_hygiene)]
|
||||
// #![feature(async_closure)]
|
||||
|
||||
mod lib;
|
||||
|
||||
mod auth;
|
||||
mod db;
|
||||
mod htmx;
|
||||
|
|
@ -28,6 +30,8 @@ use serenity::prelude::*;
|
|||
use songbird::SerenityInit;
|
||||
use tracing::*;
|
||||
|
||||
use crate::lib::domain::intro_tool;
|
||||
use crate::lib::outbound;
|
||||
use crate::settings::Settings;
|
||||
|
||||
enum HandlerMessage {
|
||||
|
|
@ -312,37 +316,52 @@ async fn spawn_bot(db: Arc<tokio::sync::Mutex<db::Database>>) {
|
|||
#[instrument]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
dotenv::dotenv().ok();
|
||||
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let settings = serde_json::from_str::<Settings>(
|
||||
&std::fs::read_to_string("config/settings.json").expect("no config/settings.json"),
|
||||
)
|
||||
.expect("error parsing settings file");
|
||||
info!("{settings:?}");
|
||||
|
||||
let (run_api, run_bot) = (settings.run_api, settings.run_bot);
|
||||
let db = Arc::new(tokio::sync::Mutex::new(
|
||||
db::Database::new("./config/db.sqlite").expect("couldn't open sqlite db"),
|
||||
));
|
||||
let db = outbound::sqlite::Sqlite::new(".config/db.sqlite").expect("couldn't open sqlite db");
|
||||
let service = intro_tool::service::Service::new(db);
|
||||
|
||||
{
|
||||
// attempt to initialize the database with the schema
|
||||
let db = db.lock().await;
|
||||
db.init().expect("couldn't init db");
|
||||
}
|
||||
|
||||
if run_api {
|
||||
spawn_api(db.clone());
|
||||
}
|
||||
if run_bot {
|
||||
spawn_bot(db).await;
|
||||
}
|
||||
|
||||
info!("spawned background tasks");
|
||||
|
||||
let _ = tokio::signal::ctrl_c().await;
|
||||
info!("Received Ctrl-C, shuttdown down.");
|
||||
// TODO: http server
|
||||
|
||||
Ok(())
|
||||
|
||||
// dotenv::dotenv().ok();
|
||||
//
|
||||
// tracing_subscriber::fmt::init();
|
||||
//
|
||||
// let settings = serde_json::from_str::<Settings>(
|
||||
// &std::fs::read_to_string("config/settings.json").expect("no config/settings.json"),
|
||||
// )
|
||||
// .expect("error parsing settings file");
|
||||
// info!("{settings:?}");
|
||||
//
|
||||
// let (run_api, run_bot) = (settings.run_api, settings.run_bot);
|
||||
// let db = Arc::new(tokio::sync::Mutex::new(
|
||||
// db::Database::new("./config/db.sqlite").expect("couldn't open sqlite db"),
|
||||
// ));
|
||||
//
|
||||
// {
|
||||
// // attempt to initialize the database with the schema
|
||||
// let db = db.lock().await;
|
||||
// db.init().expect("couldn't init db");
|
||||
// }
|
||||
//
|
||||
// if run_api {
|
||||
// spawn_api(db.clone());
|
||||
// }
|
||||
// if run_bot {
|
||||
// spawn_bot(db).await;
|
||||
// }
|
||||
//
|
||||
// info!("spawned background tasks");
|
||||
//
|
||||
// let _ = tokio::signal::ctrl_c().await;
|
||||
// info!("Received Ctrl-C, shuttdown down.");
|
||||
//
|
||||
// Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue