Compare commits

...

2 Commits

Author SHA1 Message Date
410ca2eeef switched to sqlite 2026-06-06 19:43:56 +02:00
05c69d26ed start switch to sqlite 2026-06-06 18:19:29 +02:00
14 changed files with 139 additions and 133 deletions

99
Cargo.lock generated
View File

@ -302,12 +302,6 @@ version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.11.1"
@ -534,13 +528,13 @@ version = "2.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9940fb8467a0a06312218ed384185cb8536aa10d8ec017d0ce7fad2c1bd882d5"
dependencies = [
"bitflags",
"byteorder",
"chrono",
"diesel_derives",
"downcast-rs",
"itoa",
"pq-sys",
"libsqlite3-sys",
"r2d2",
"sqlite-wasm-rs",
"time",
]
[[package]]
@ -611,6 +605,8 @@ dependencies = [
"diesel",
"diesel-enum",
"json",
"num-derive",
"num-traits",
"regex",
"serde",
"thiserror",
@ -721,6 +717,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "foldhash"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
[[package]]
name = "form_urlencoded"
version = "1.2.2"
@ -845,7 +847,16 @@ version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"foldhash",
"foldhash 0.1.5",
]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
dependencies = [
"foldhash 0.2.0",
]
[[package]]
@ -1233,6 +1244,16 @@ version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "libsqlite3-sys"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1"
dependencies = [
"pkg-config",
"vcpkg",
]
[[package]]
name = "linux-raw-sys"
version = "0.12.1"
@ -1305,6 +1326,17 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
[[package]]
name = "num-derive"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@ -1435,17 +1467,6 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24"
[[package]]
name = "pq-sys"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "574ddd6a267294433f140b02a726b0640c43cf7c6f717084684aaa3b285aba61"
dependencies = [
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "prettyplease"
version = "0.2.37"
@ -1535,6 +1556,16 @@ version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "rsqlite-vfs"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c"
dependencies = [
"hashbrown 0.16.1",
"thiserror",
]
[[package]]
name = "rustix"
version = "1.1.4"
@ -1713,6 +1744,18 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "sqlite-wasm-rs"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc3efc0da82635d7e1ced0053bbbfa8c7ab9645d0bf36ceb4f7127bb85315d75"
dependencies = [
"cc",
"js-sys",
"rsqlite-vfs",
"wasm-bindgen",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
@ -1785,11 +1828,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
dependencies = [
"deranged",
"itoa",
"js-sys",
"num-conv",
"powerfmt",
"serde_core",
"time-core",
"time-macros",
]
[[package]]
@ -1798,6 +1843,16 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
[[package]]
name = "time-macros"
version = "0.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "tinystr"
version = "0.8.3"

View File

@ -8,9 +8,11 @@ async-std = "1.13.2"
bollard = "0.21.0"
chrono = "0.4.44"
clap = "4.6.1"
diesel = { version = "2.3.9", features = ["postgres", "r2d2"] }
diesel = { version = "2.3.9", features = ["sqlite", "r2d2", "chrono"] }
diesel-enum = "0.2.1"
json = "0.12.4"
num-derive = "0.4.2"
num-traits = "0.2.19"
regex = "1.12.3"
serde = "1.0.228"
thiserror = "2.0.18"

View File

@ -1,6 +0,0 @@
-- This file was automatically created by Diesel to setup helper functions
-- and other internal bookkeeping. This file is safe to edit, any future
-- changes will be added to existing projects as new migrations.
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
DROP FUNCTION IF EXISTS diesel_set_updated_at();

View File

@ -1,36 +0,0 @@
-- This file was automatically created by Diesel to setup helper functions
-- and other internal bookkeeping. This file is safe to edit, any future
-- changes will be added to existing projects as new migrations.
-- Sets up a trigger for the given table to automatically set a column called
-- `updated_at` whenever the row is modified (unless `updated_at` was included
-- in the modified columns)
--
-- # Example
--
-- ```sql
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
--
-- SELECT diesel_manage_updated_at('users');
-- ```
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
BEGIN
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
BEGIN
IF (
NEW IS DISTINCT FROM OLD AND
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
) THEN
NEW.updated_at := current_timestamp;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

View File

@ -1,11 +1,10 @@
CREATE TABLE "servers" (
"id" BIGSERIAL PRIMARY KEY,
"name" varchar(255) UNIQUE NOT NULL,
"name" varchar(255) UNIQUE NOT NULL PRIMARY KEY,
"last_login" timestamp,
"container_id" varchar(30),
"status" int2 NOT NULL DEFAULT 0,
"status" INT2 NOT NULL DEFAULT 0,
"is_default" bool NOT NULL DEFAULT false,
"redirect_ip" varchar(50)
);
insert into servers (name, last_login, container_id, status, is_default, redirect_ip) values ('potato', now(), null, 1, false, 'play.hypixel.net:25565');
insert into servers (name, last_login, container_id, status, is_default, redirect_ip) values ('potato', datetime(), null, 1, false, 'play.hypixel.net:25565');

View File

@ -3,7 +3,7 @@ use crate::cli::env_settings;
use crate::status::ServerStatus;
use crate::utils::{ validate_name, extract_archive, move_all_elements};
use diesel::{insert_into, prelude::*};
use diesel::prelude::*;
use crate::{DbPool, models};
use crate::schema;
@ -27,21 +27,22 @@ pub fn create_subcommand() -> Command {
pub async fn subcommand(arg: &ArgMatches, pool: DbPool) -> Result<(), String>{
// use schema::servers::dsl::*;
let config = crate::Config::load();
let name = arg.get_one::<String>("NAME").unwrap();
let server_name = arg.get_one::<String>("NAME").unwrap();
if !validate_name(name) {
if !validate_name(server_name) {
return Err("Invalid name provided".to_string());
}
let conn = &mut pool.get().unwrap();
if let Ok(_) = schema::servers::table.filter(schema::servers::name.eq(name)).select(models::Servers::as_select()).first(conn) {
if let Ok(_) = schema::servers::table.filter(schema::servers::name.eq(server_name)).select(models::Servers::as_select()).first(conn) {
return Err("Server with this name already exists".to_string())
}
let path = config.config_path + "/" + name + "/";
let path = config.config_path + "/" + server_name + "/";
create_dir(&path).await.map_err(|e| format!("failed to create the config folder, reason : {}", e))?;
@ -56,14 +57,14 @@ pub async fn subcommand(arg: &ArgMatches, pool: DbPool) -> Result<(), String>{
std::fs::remove_dir_all(path.to_string() + "tmp").map_err(|e| format!("failed to remove the tmp dir, reason : {}", e))?;
}
let new_server = models::CreateServer {
name: name,
let _new_server = models::CreateServer {
name: server_name,
last_login: Some(SystemTime::now()),
container_id: None,
status: ServerStatus::Stopped,
redirect_ip: None
};
insert_into(schema::servers::dsl::servers).values(&new_server).execute(conn).map_err(|e| format!("Failed to insert in db, error : {:?}", e))?;
// insert_into(schema::servers::dsl::servers).values(&new_server).execute(conn).map_err(|e| format!("Failed to insert in db, error : {:?}", e))?;
Ok(())
}

View File

@ -1,6 +1,6 @@
use std::collections::HashMap;
use clap::{ Arg, ArgAction, ArgMatches, parser::ValueSource};
use clap::{ Arg, ArgMatches, parser::ValueSource};
pub fn get_args() -> [Arg; 21] {
[

2
src/docker/mod.rs Normal file
View File

@ -0,0 +1,2 @@
mod start;
pub use start::start_server;

3
src/docker/start.rs Normal file
View File

@ -0,0 +1,3 @@
pub async fn start_server() -> Result<String, String> {
Ok("".to_string())
}

View File

@ -6,7 +6,7 @@
/* By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/05/29 21:22:17 by tomoron #+# #+# */
/* Updated: 2026/06/06 15:37:52 by tomoron ### ########.fr */
/* Updated: 2026/06/06 19:39:47 by tomoron ### ########.fr */
/* */
/* ************************************************************************** */
@ -15,25 +15,25 @@ use minecraft::mc_socket_listen;
use diesel::{prelude::*, r2d2::{ConnectionManager, Pool}};
use std::env;
pub mod schema;
pub mod models;
pub mod status;
pub mod docker;
mod cli;
use cli::*;
mod config;
pub use config::Config;
pub type DbPool = Pool<ConnectionManager<PgConnection>>;
pub type DbPool = Pool<ConnectionManager<SqliteConnection>>;
fn get_connection_pool() -> DbPool {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let database_url = "sqlite:///".to_string() + &Config::load().config_path + "/db.sqlite";
let manager = ConnectionManager::<PgConnection>::new(&database_url);
let manager = ConnectionManager::<SqliteConnection>::new(&database_url);
Pool::builder()
.build(manager)
.unwrap_or_else(|_| panic!("Error creating pool for {}", database_url))

View File

@ -7,7 +7,7 @@ use json::object;
use crate::minecraft::varint::varint_write;
use std::collections::VecDeque;
use chrono::{DateTime, Utc};
use chrono::{DateTime, TimeZone, Utc};
impl Client {
pub async fn status_intent_handle(&self, packet: &mut VecDeque<u8>, packet_id: i32) -> Result<(),String> {
@ -53,7 +53,7 @@ impl Client {
Ok(server) => {
let login = match server.last_login {
Some(date) => {
let datetime: DateTime<Utc> = date.into();
let datetime: DateTime<Utc> = Utc.from_utc_datetime(&date);
format!("{}", datetime.format("%d-%m-%Y at %H:%M").to_string())
},

View File

@ -1,7 +1,7 @@
use std::fmt;
use std::time::SystemTime;
use chrono::{DateTime, Utc};
use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
use diesel::prelude::*;
use serde::Deserialize;
@ -12,11 +12,10 @@ use crate::schema;
#[derive(Queryable, Selectable, Debug)]
#[diesel(table_name = schema::servers)]
#[diesel(check_for_backend(diesel::pg::Pg))]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
pub struct Servers {
pub id: i64,
pub name: String,
pub last_login: Option<SystemTime>,
pub last_login: Option<NaiveDateTime>,
pub container_id: Option<String>,
pub status: ServerStatus,
pub redirect_ip: Option<String>
@ -38,7 +37,7 @@ impl fmt::Display for Servers {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let login = match self.last_login {
Some(date) => {
let datetime: DateTime<Utc> = date.into();
let datetime: DateTime<Utc> = Utc.from_utc_datetime(&date);
format!("{}", datetime.format("%d-%m-%Y at %H:%M").to_string())
},

View File

@ -1,16 +1,12 @@
// @generated automatically by Diesel CLI.
diesel::table! {
servers (id) {
id -> Int8,
#[max_length = 255]
name -> Varchar,
servers (name) {
name -> Text,
last_login -> Nullable<Timestamp>,
#[max_length = 30]
container_id -> Nullable<Varchar>,
status -> Int2,
container_id -> Nullable<Text>,
status -> SmallInt,
is_default -> Bool,
#[max_length = 50]
redirect_ip -> Nullable<Varchar>,
redirect_ip -> Nullable<Text>,
}
}

View File

@ -1,61 +1,52 @@
use diesel::deserialize::{self, FromSql, FromSqlRow};
use diesel::pg::PgValue;
use diesel::expression::AsExpression;
use diesel::pg::Pg;
use diesel::serialize::{self, ToSql, Output};
use diesel::sql_types::SmallInt;
use std::fmt;
use std::io::Write;
use diesel::{deserialize::{FromSql, FromSqlRow}, expression::AsExpression, serialize::{Output, ToSql}, sql_types::SmallInt, sqlite::{Sqlite, SqliteValue}};
#[derive(Debug, Clone, Copy, PartialEq, Eq, AsExpression, FromSqlRow, serde::Serialize, serde::Deserialize)]
use num_traits::FromPrimitive;
use num_derive::FromPrimitive;
use serde::{Deserialize, Serialize};
#[derive(FromSqlRow, Debug, AsExpression, FromPrimitive, Serialize, Deserialize, PartialEq, Clone)]
#[diesel(sql_type = SmallInt)]
#[repr(i16)]
pub enum ServerStatus {
Archived = 0,
Stopped = 1,
Stopping = 2,
Starting = 3,
Running = 4,
Unknown = 5
Unknown = 5,
}
impl ToSql<SmallInt, Pg> for ServerStatus {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
let val = *self as i16;
out.write_all(&val.to_be_bytes())?;
Ok(serialize::IsNull::No)
impl FromSql<SmallInt, Sqlite> for ServerStatus{
fn from_sql(bytes: SqliteValue) -> diesel::deserialize::Result<Self> {
let t = <i16 as FromSql<SmallInt, Sqlite>>::from_sql(bytes)?;
if let Some(status) = ServerStatus::from_i16(t) {
return Ok(status)
}
Ok(ServerStatus::Unknown)
}
}
impl FromSql<SmallInt, Pg> for ServerStatus {
fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
let bytes = value.as_bytes();
if bytes.len() != 2 {
return Err("Invalid length for i16".into());
}
let val = i16::from_be_bytes([bytes[0], bytes[1]]);
match val {
0 => Ok(ServerStatus::Archived),
1 => Ok(ServerStatus::Stopped),
2 => Ok(ServerStatus::Stopping),
3 => Ok(ServerStatus::Starting),
4 => Ok(ServerStatus::Running),
_ => Ok(ServerStatus::Unknown),
}
impl ToSql<SmallInt, Sqlite> for ServerStatus {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> diesel::serialize::Result {
let value: i16 = self.clone() as i16;
out.set_value(value.to_le_bytes().to_vec());
Ok(diesel::serialize::IsNull::No)
}
}
impl fmt::Display for ServerStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let str_status = match self {
ServerStatus::Archived => "archieved",
ServerStatus::Archived => "archived",
ServerStatus::Stopped => "stopped",
ServerStatus::Stopping => "stopping",
ServerStatus::Starting => "starting",
ServerStatus::Running => "running",
ServerStatus::Unknown => "(error : unknown status)"
ServerStatus::Unknown => "(error : unknown status)",
};
write!(f, "{}", str_status)
}