Database integration and test command
Some checks failed
Build and push container image / build (push) Has been cancelled

This commit is contained in:
toast 2024-01-30 23:17:59 +11:00
parent a94625ad17
commit 5a73154fe9
10 changed files with 262 additions and 11 deletions

128
Cargo.lock generated
View File

@ -392,6 +392,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [ dependencies = [
"block-buffer", "block-buffer",
"crypto-common", "crypto-common",
"subtle",
] ]
[[package]] [[package]]
@ -434,12 +435,24 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.0.1" version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "finl_unicode"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6"
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.28" version = "1.0.28"
@ -643,6 +656,15 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.11" version = "0.2.11"
@ -800,7 +822,7 @@ dependencies = [
[[package]] [[package]]
name = "kon" name = "kon"
version = "0.1.10" version = "0.1.11"
dependencies = [ dependencies = [
"cargo_toml", "cargo_toml",
"gamedig", "gamedig",
@ -811,6 +833,7 @@ dependencies = [
"serenity", "serenity",
"sysinfo", "sysinfo",
"tokio", "tokio",
"tokio-postgres",
"uptime_lib", "uptime_lib",
] ]
@ -854,6 +877,16 @@ version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "md-5"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
"cfg-if",
"digest",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.6.4" version = "2.6.4"
@ -1134,6 +1167,35 @@ dependencies = [
"syn 2.0.46", "syn 2.0.46",
] ]
[[package]]
name = "postgres-protocol"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520"
dependencies = [
"base64",
"byteorder",
"bytes",
"fallible-iterator",
"hmac",
"md-5",
"memchr",
"rand",
"sha2",
"stringprep",
]
[[package]]
name = "postgres-types"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d2234cdee9408b523530a9b6d2d6b373d1db34f6a8e51dc03ded1828d7fb67c"
dependencies = [
"bytes",
"fallible-iterator",
"postgres-protocol",
]
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
version = "0.2.0" version = "0.2.0"
@ -1554,6 +1616,17 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.1" version = "1.4.1"
@ -1631,12 +1704,29 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "stringprep"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6"
dependencies = [
"finl_unicode",
"unicode-bidi",
"unicode-normalization",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.109"
@ -1817,6 +1907,32 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tokio-postgres"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d340244b32d920260ae7448cb72b6e238bddc3d4f7603394e7dd46ed8e48f5b8"
dependencies = [
"async-trait",
"byteorder",
"bytes",
"fallible-iterator",
"futures-channel",
"futures-util",
"log",
"parking_lot",
"percent-encoding",
"phf",
"pin-project-lite",
"postgres-protocol",
"postgres-types",
"rand",
"socket2 0.5.5",
"tokio",
"tokio-util",
"whoami",
]
[[package]] [[package]]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.24.1" version = "0.24.1"
@ -2204,6 +2320,16 @@ version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
[[package]]
name = "whoami"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50"
dependencies = [
"wasm-bindgen",
"web-sys",
]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "kon" name = "kon"
version = "0.1.10" version = "0.1.11"
rust-version = "1.74" rust-version = "1.74"
edition = "2021" edition = "2021"
@ -16,6 +16,7 @@ serde_json = "1.0.113"
serenity = "0.12.0" serenity = "0.12.0"
sysinfo = "0.30.5" sysinfo = "0.30.5"
tokio = { version = "1.35.1", features = ["macros", "signal", "rt-multi-thread"] } tokio = { version = "1.35.1", features = ["macros", "signal", "rt-multi-thread"] }
tokio-postgres = "0.7.10"
uptime_lib = "0.3.0" uptime_lib = "0.3.0"
[[bin]] [[bin]]

View File

@ -7,3 +7,15 @@ services:
env_file: env_file:
- .env - .env
restart: unless-stopped restart: unless-stopped
db:
container_name: kon-database
image: postgres:16.1-alpine3.19
restart: unless-stopped
ports:
- 37930:5432/tcp
volumes:
- /var/lib/docker/volumes/kon-database:/var/lib/postgresql/data:rw
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}

2
run.sh
View File

@ -1,3 +1,3 @@
#!/bin/bash #!/bin/bash
export $(cat .env | xargs) && cargo run export $(grep -v '^#' .env | xargs) && cargo run

View File

@ -1,11 +1,15 @@
use crate::{Error, EMBED_COLOR}; use crate::{
models::mpservers::MPServers,
EMBED_COLOR,
Error
};
use gamedig::protocols::{ use gamedig::protocols::{
valve::{ valve::{
Engine, GatheringSettings, Response Engine, GatheringSettings, Response
}, },
types::TimeoutSettings, types::TimeoutSettings,
valve, valve
}; };
use std::{ use std::{
str::FromStr, str::FromStr,
@ -73,7 +77,7 @@ async fn pms_serverstatus(url: &str) -> Result<Vec<Value>, Error> {
} }
/// Query the server statuses /// Query the server statuses
#[poise::command(slash_command, subcommands("ats", "wg"), subcommand_required)] #[poise::command(slash_command, subcommands("ats", "wg", "fs"), subcommand_required)]
pub async fn status(_: poise::Context<'_, (), Error>) -> Result<(), Error> { pub async fn status(_: poise::Context<'_, (), Error>) -> Result<(), Error> {
Ok(()) Ok(())
} }
@ -133,3 +137,18 @@ pub async fn wg(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> {
Ok(()) Ok(())
} }
/// Retrieve the data from Farming Simulator 22 server
#[poise::command(slash_command, guild_only)]
pub async fn fs(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> {
// let embed = CreateEmbed::new().color(EMBED_COLOR);
let server = MPServers::get_server_ip(ctx.guild_id().unwrap().into(), "testserver").await?;
let ip = server.0;
let md5 = server.1;
ctx.send(CreateReply::default().content(format!("IP: {}\nMD5: {}", ip, md5))).await?;
// ctx.send(CreateReply::default().content("This command is not yet implemented")).await?;
Ok(())
}

View File

@ -0,0 +1,36 @@
use serenity::prelude::TypeMapKey;
use tokio_postgres::{Client, NoTls, Error};
pub struct DatabaseController {
pub client: Client
}
impl TypeMapKey for DatabaseController {
type Value = DatabaseController;
}
impl DatabaseController {
pub async fn new() -> Result<DatabaseController, Error> {
let db_uri = std::env::var("DATABASE_URI").expect("Expected a \"DATABASE_URI\" in the envvar but none was found");
let (client, connection) = tokio_postgres::connect(&db_uri, NoTls).await?;
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("Connection error: {}", e);
}
});
// MPServers
client.batch_execute("
CREATE TABLE IF NOT EXISTS mpservers (
server_name VARCHAR(255) NOT NULL PRIMARY KEY,
guild_owner BIGINT NOT NULL,
is_active BOOLEAN NOT NULL,
ip_address VARCHAR(255) NOT NULL,
md5_code VARCHAR(255) NOT NULL
);
").await?;
Ok(DatabaseController { client })
}
}

1
src/controllers/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod database;

View File

@ -1,25 +1,32 @@
mod commands; mod commands;
mod controllers;
mod models;
use std::env::var;
use poise::serenity_prelude::{self as serenity}; use poise::serenity_prelude::{self as serenity};
use std::{
env::var,
error
};
use serenity::{ use serenity::{
builder::{ builder::{
CreateMessage, CreateMessage,
CreateEmbed, CreateEmbed,
CreateEmbedAuthor CreateEmbedAuthor
}, },
Context,
Ready,
ClientBuilder, ClientBuilder,
GatewayIntents GatewayIntents
}; };
type Error = Box<dyn std::error::Error + Send + Sync>; type Error = Box<dyn error::Error + Send + Sync>;
pub static EMBED_COLOR: i32 = 0x5a99c7; pub static EMBED_COLOR: i32 = 0x5a99c7;
static BOT_READY_NOTIFY: u64 = 865673694184996888; static BOT_READY_NOTIFY: u64 = 865673694184996888;
async fn on_ready( async fn on_ready(
ctx: &serenity::Context, ctx: &Context,
ready: &serenity::Ready, ready: &Ready,
framework: &poise::Framework<(), Error> framework: &poise::Framework<(), Error>
) -> Result<(), Error> { ) -> Result<(), Error> {
println!("Connected to API as {}", ready.user.name); println!("Connected to API as {}", ready.user.name);
@ -52,6 +59,7 @@ async fn on_ready(
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let token = var("DISCORD_TOKEN").expect("Expected a \"DISCORD_TOKEN\" in the envvar but none was found"); let token = var("DISCORD_TOKEN").expect("Expected a \"DISCORD_TOKEN\" in the envvar but none was found");
let db = controllers::database::DatabaseController::new().await.expect("Failed to connect to database");
let framework = poise::Framework::builder() let framework = poise::Framework::builder()
.options(poise::FrameworkOptions { .options(poise::FrameworkOptions {
@ -67,12 +75,20 @@ async fn main() {
}; };
println!("[{}] {} ran /{}", get_guild_name, ctx.author().name, ctx.command().qualified_name) println!("[{}] {} ran /{}", get_guild_name, ctx.author().name, ctx.command().qualified_name)
}), }),
initialize_owners: true,
..Default::default() ..Default::default()
}) })
.setup(|ctx, ready, framework| Box::pin(on_ready(ctx, ready, framework))) .setup(|ctx, ready, framework| Box::pin(on_ready(ctx, ready, framework)))
.build(); .build();
let mut client = ClientBuilder::new(token, GatewayIntents::GUILDS).framework(framework).await.expect("Error creating client"); let mut client = ClientBuilder::new(token, GatewayIntents::GUILDS)
.framework(framework)
.await.expect("Error creating client");
{
let mut data = client.data.write().await;
data.insert::<controllers::database::DatabaseController>(db);
}
if let Err(why) = client.start().await { if let Err(why) = client.start().await {
println!("Client error: {:?}", why); println!("Client error: {:?}", why);

1
src/models/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod mpservers;

39
src/models/mpservers.rs Normal file
View File

@ -0,0 +1,39 @@
use crate::controllers::database::DatabaseController;
// #[derive(Debug)]
pub struct MPServers {
pub server_name: String,
pub guild_owner: i64,
pub is_active: bool,
pub ip_address: String,
pub md5_code: String
}
#[allow(dead_code)]
impl MPServers {
pub async fn get_servers(guild_id: u64) -> Result<Self, tokio_postgres::Error> {
let client = DatabaseController::new().await?.client;
let row = client.query_one("
SELECT * FROM mpservers
WHERE guild_owner = $1
", &[&(guild_id as i64)]).await?;
Ok(Self {
server_name: row.get("server_name"),
guild_owner: row.get("guild_owner"),
is_active: row.get("is_active"),
ip_address: row.get("ip_address"),
md5_code: row.get("md5_code")
})
}
pub async fn get_server_ip(guild_id: u64, server_name: &str) -> Result<(String, String), tokio_postgres::Error> {
let client = DatabaseController::new().await?.client;
let row = client.query_one("
SELECT ip_address, md5_code FROM mpservers
WHERE guild_owner = $1 AND server_name = $2
", &[&(guild_id as i64), &server_name]).await?;
Ok((row.get("ip_address"), row.get("md5_code")))
}
}