Too unmotivated to finalize, will do something else with DB at some point.
All checks were successful
Build and push container image / build (push) Successful in 10m41s
All checks were successful
Build and push container image / build (push) Successful in 10m41s
This commit is contained in:
parent
76ad298af7
commit
776c3e2f1c
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -822,7 +822,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kon"
|
||||
version = "0.1.12"
|
||||
version = "0.1.13"
|
||||
dependencies = [
|
||||
"cargo_toml",
|
||||
"gamedig",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "kon"
|
||||
version = "0.1.12"
|
||||
version = "0.1.13"
|
||||
rust-version = "1.74"
|
||||
edition = "2021"
|
||||
|
||||
|
@ -5,9 +5,15 @@ use crate::{
|
||||
};
|
||||
|
||||
use serenity::{
|
||||
futures::{
|
||||
stream::iter,
|
||||
future::ready,
|
||||
Stream,
|
||||
StreamExt
|
||||
},
|
||||
all::Mentionable,
|
||||
builder::CreateActionRow,
|
||||
builder::CreateEmbed
|
||||
builder::CreateEmbed,
|
||||
};
|
||||
use poise::{
|
||||
CreateReply,
|
||||
@ -46,10 +52,10 @@ pub async fn add(
|
||||
}
|
||||
|
||||
let action_row = CreateActionRow::Buttons(vec![
|
||||
serenity_prelude::CreateButton::new("confirm")
|
||||
serenity_prelude::CreateButton::new("add-confirm")
|
||||
.style(ButtonStyle::Success)
|
||||
.label("Yes"),
|
||||
serenity_prelude::CreateButton::new("cancel")
|
||||
serenity_prelude::CreateButton::new("add-cancel")
|
||||
.style(ButtonStyle::Danger)
|
||||
.label("No")
|
||||
]);
|
||||
@ -76,7 +82,7 @@ pub async fn add(
|
||||
.timeout(std::time::Duration::from_secs(30))
|
||||
.await
|
||||
{
|
||||
if collector.data.custom_id == "confirm" {
|
||||
if collector.data.custom_id == "add-confirm" {
|
||||
let result = Gameservers::add_server(
|
||||
ctx.guild_id().unwrap().into(),
|
||||
server_name.as_str(),
|
||||
@ -93,6 +99,7 @@ pub async fn add(
|
||||
ctx,
|
||||
serenity_prelude::EditMessage::new()
|
||||
.content("*Confirmed, added the server to database*")
|
||||
.embeds(Vec::new())
|
||||
.components(Vec::new())
|
||||
).await?;
|
||||
},
|
||||
@ -101,17 +108,19 @@ pub async fn add(
|
||||
ctx,
|
||||
serenity_prelude::EditMessage::new()
|
||||
.content(format!("*Error adding server to database: {:?}*", y))
|
||||
.embeds(Vec::new())
|
||||
.components(Vec::new())
|
||||
).await?;
|
||||
}
|
||||
}
|
||||
} else if collector.data.custom_id == "cancel" {
|
||||
} else if collector.data.custom_id == "add-cancel" {
|
||||
let mut msg = collector.message.clone();
|
||||
|
||||
msg.edit(
|
||||
ctx,
|
||||
serenity_prelude::EditMessage::new()
|
||||
.content("*Command cancelled*")
|
||||
.embeds(Vec::new())
|
||||
.components(Vec::new())
|
||||
).await?;
|
||||
}
|
||||
@ -122,16 +131,102 @@ pub async fn add(
|
||||
|
||||
/// Remove a game server from the database
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn remove(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> {
|
||||
ctx.send(CreateReply::default().content("Yet to be implemented.")).await?;
|
||||
pub async fn remove(
|
||||
ctx: poise::Context<'_, (), Error>,
|
||||
#[description = "Server name"] #[autocomplete = "ac_server_name"] server_name: String
|
||||
) -> Result<(), Error> {
|
||||
let reply = CreateReply::default()
|
||||
.embed(CreateEmbed::new()
|
||||
.title("Are you sure you want to remove this server?")
|
||||
.description(format!("**Server name:** `{}`", server_name))
|
||||
.color(EMBED_COLOR)
|
||||
)
|
||||
.components(vec![
|
||||
CreateActionRow::Buttons(vec![
|
||||
serenity_prelude::CreateButton::new("delete-confirm")
|
||||
.style(ButtonStyle::Success)
|
||||
.label("Yes"),
|
||||
serenity_prelude::CreateButton::new("delete-cancel")
|
||||
.style(ButtonStyle::Danger)
|
||||
.label("No")
|
||||
])
|
||||
]);
|
||||
|
||||
ctx.send(reply).await?;
|
||||
|
||||
while let Some(collector) = serenity_prelude::ComponentInteractionCollector::new(ctx)
|
||||
.channel_id(ctx.channel_id())
|
||||
.guild_id(ctx.guild_id().unwrap())
|
||||
.author_id(ctx.author().id)
|
||||
.timeout(std::time::Duration::from_secs(30))
|
||||
.await
|
||||
{
|
||||
if collector.data.custom_id == "delete-confirm" {
|
||||
let result = Gameservers::remove_server(ctx.guild_id().unwrap().into(), server_name.as_str()).await;
|
||||
|
||||
let mut msg = collector.message.clone();
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
msg.edit(
|
||||
ctx,
|
||||
serenity_prelude::EditMessage::new()
|
||||
.content("*Confirmed, removed the server from database*")
|
||||
.embeds(Vec::new())
|
||||
.components(Vec::new())
|
||||
).await?;
|
||||
},
|
||||
Err(y) => {
|
||||
msg.edit(
|
||||
ctx,
|
||||
serenity_prelude::EditMessage::new()
|
||||
.content(format!("*Error removing server from database: {:?}*", y))
|
||||
.embeds(Vec::new())
|
||||
.components(Vec::new())
|
||||
).await?;
|
||||
}
|
||||
}
|
||||
} else if collector.data.custom_id == "delete-cancel" {
|
||||
let mut msg = collector.message.clone();
|
||||
|
||||
msg.edit(
|
||||
ctx,
|
||||
serenity_prelude::EditMessage::new()
|
||||
.content("*Command cancelled*")
|
||||
.embeds(Vec::new())
|
||||
.components(Vec::new())
|
||||
).await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Update a game server in the database
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn update(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> {
|
||||
ctx.send(CreateReply::default().content("Yet to be implemented.")).await?;
|
||||
pub async fn update(
|
||||
ctx: poise::Context<'_, (), Error>,
|
||||
#[description = "Server name"] #[autocomplete = "ac_server_name"] server_name: String,
|
||||
#[description = "Game name"] game_name: String,
|
||||
#[description = "Channel"] #[channel_types("Text")] guild_channel: serenity_prelude::GuildChannel,
|
||||
#[description = "IP address"] ip_address: String
|
||||
) -> Result<(), Error> {
|
||||
let result = Gameservers::update_server(
|
||||
ctx.guild_id().unwrap().into(),
|
||||
&server_name,
|
||||
&game_name,
|
||||
guild_channel.id.into(),
|
||||
&ip_address
|
||||
).await;
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
ctx.send(CreateReply::default().content("Updated the server in database.")).await?;
|
||||
},
|
||||
Err(y) => {
|
||||
ctx.send(CreateReply::default().content(format!("Error updating the server in database: {:?}", y))).await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -158,3 +253,22 @@ pub async fn list(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn ac_server_name<'a>(
|
||||
ctx: poise::Context<'_, (), Error>,
|
||||
partial: &'a str
|
||||
) -> impl Stream<Item = String> + 'a {
|
||||
let result = Gameservers::get_server_names(ctx.guild_id().unwrap().into()).await;
|
||||
|
||||
let names = match result {
|
||||
Ok(names_vector) => names_vector,
|
||||
Err(y) => {
|
||||
println!("Error retrieving server names: {:?}", y);
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
iter(names)
|
||||
.filter(move |server_name| ready(server_name.starts_with(partial)))
|
||||
.map(|server_name| server_name.to_string())
|
||||
}
|
||||
|
@ -1,15 +1,20 @@
|
||||
use crate::{
|
||||
models::mpservers::MPServers,
|
||||
Error,
|
||||
EMBED_COLOR,
|
||||
Error
|
||||
models::gameservers::Gameservers,
|
||||
commands::gameserver::ac_server_name
|
||||
};
|
||||
|
||||
use gamedig::protocols::{
|
||||
valve::{
|
||||
Engine, GatheringSettings, Response
|
||||
Engine,
|
||||
Response,
|
||||
GatheringSettings
|
||||
},
|
||||
types::TimeoutSettings,
|
||||
valve
|
||||
valve,
|
||||
minecraft,
|
||||
minecraft::RequestSettings,
|
||||
types::TimeoutSettings
|
||||
};
|
||||
use std::{
|
||||
str::FromStr,
|
||||
@ -22,18 +27,21 @@ use reqwest::{
|
||||
Client,
|
||||
header::USER_AGENT
|
||||
};
|
||||
use tokio::{
|
||||
net::lookup_host,
|
||||
join
|
||||
};
|
||||
use poise::CreateReply;
|
||||
use serenity::builder::CreateEmbed;
|
||||
use once_cell::sync::Lazy;
|
||||
use cargo_toml::Manifest;
|
||||
use serde_json::Value;
|
||||
use tokio::join;
|
||||
|
||||
static PMS_BASE: Lazy<String> = Lazy::new(||
|
||||
var("WG_PMS").expect("Expected a \"WG_PMS\" in the envvar but none was found")
|
||||
);
|
||||
|
||||
fn query_server() -> Result<Response, Error> {
|
||||
fn query_ats_server() -> Result<Response, Error> {
|
||||
let server_ip = var("ATS_SERVER_IP").expect("Expected a \"ATS_SERVER_IP\" in the envvar but none was found");
|
||||
let addr = SocketAddr::from_str(&server_ip).unwrap();
|
||||
let engine = Engine::Source(None);
|
||||
@ -62,6 +70,35 @@ fn query_server() -> Result<Response, Error> {
|
||||
Ok(response?)
|
||||
}
|
||||
|
||||
async fn query_gameserver(ip_address: &str) -> Result<minecraft::JavaResponse, Box<dyn std::error::Error + Send + Sync>> {
|
||||
println!("Querying {}", ip_address);
|
||||
|
||||
let full_address = if ip_address.contains(':') {
|
||||
String::from(ip_address)
|
||||
} else {
|
||||
format!("{}:25565", ip_address)
|
||||
};
|
||||
|
||||
let addr = match SocketAddr::from_str(&full_address) {
|
||||
Ok(addr) => addr,
|
||||
Err(_) => {
|
||||
let mut addrs = lookup_host(&full_address).await?;
|
||||
addrs.next().ok_or("Address lookup failed")?
|
||||
}
|
||||
};
|
||||
|
||||
let response = minecraft::query_java(&addr, None, Some(RequestSettings {
|
||||
hostname: addr.to_string(),
|
||||
protocol_version: -1
|
||||
}));
|
||||
println!("{:?}", response);
|
||||
|
||||
match response {
|
||||
Ok(response) => Ok(response),
|
||||
Err(why) => Err(Box::new(why))
|
||||
}
|
||||
}
|
||||
|
||||
async fn pms_serverstatus(url: &str) -> Result<Vec<Value>, Error> {
|
||||
let bot_version = Manifest::from_path("Cargo.toml").unwrap().package.unwrap().version.unwrap();
|
||||
|
||||
@ -77,7 +114,7 @@ async fn pms_serverstatus(url: &str) -> Result<Vec<Value>, Error> {
|
||||
}
|
||||
|
||||
/// Query the server statuses
|
||||
#[poise::command(slash_command, subcommands("ats", "wg", "fs"), subcommand_required)]
|
||||
#[poise::command(slash_command, subcommands("ats", "wg", "mc"), subcommand_required)]
|
||||
pub async fn status(_: poise::Context<'_, (), Error>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
@ -86,7 +123,7 @@ pub async fn status(_: poise::Context<'_, (), Error>) -> Result<(), Error> {
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn ats(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> {
|
||||
let embed = CreateEmbed::new().color(EMBED_COLOR);
|
||||
match query_server() {
|
||||
match query_ats_server() {
|
||||
Ok(response) => {
|
||||
ctx.send(CreateReply::default()
|
||||
.embed(embed
|
||||
@ -138,17 +175,38 @@ pub async fn wg(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retrieve the data from Farming Simulator 22 server
|
||||
/// Retrieve the server data from given Minecraft Java 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;
|
||||
pub async fn mc(
|
||||
ctx: poise::Context<'_, (), Error>,
|
||||
#[description = "Server name"] #[autocomplete = "ac_server_name"] server_name: String
|
||||
) -> Result<(), Error> {
|
||||
let server = Gameservers::get_server_data(ctx.guild_id().unwrap().into(), &server_name).await;
|
||||
|
||||
ctx.send(CreateReply::default().content(format!("IP: {}\nMD5: {}", ip, md5))).await?;
|
||||
|
||||
// ctx.send(CreateReply::default().content("This command is not yet implemented")).await?;
|
||||
match server {
|
||||
Ok(data) => {
|
||||
let name = &data[0];
|
||||
let game = &data[1];
|
||||
let ip = &data[2];
|
||||
|
||||
let query_result = query_gameserver(ip).await?;
|
||||
ctx.send(CreateReply::default()
|
||||
.embed(CreateEmbed::new()
|
||||
.title(format!("{} Server Status", name))
|
||||
.fields(vec![
|
||||
("Game", format!("{}", game), true),
|
||||
("Players", format!("{}/{}", query_result.players_online, query_result.players_maximum), true),
|
||||
("Version", format!("{}", query_result.game_version), true)
|
||||
])
|
||||
.color(EMBED_COLOR)
|
||||
)
|
||||
).await?;
|
||||
// ctx.send(CreateReply::default().content("aaa")).await?;
|
||||
},
|
||||
Err(why) => {
|
||||
ctx.send(CreateReply::default().content(format!("Error retrieving the server data: {:?}", why))).await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ pub struct Gameservers {
|
||||
pub ip_address: String
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Gameservers {
|
||||
pub async fn list_servers(guild_id: u64) -> Result<Vec<Self>, tokio_postgres::Error> {
|
||||
let client = DatabaseController::new().await?.client;
|
||||
@ -74,7 +73,8 @@ impl Gameservers {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update_name(guild_id: u64, server_name: &str, new_name: &str) -> Result<(), tokio_postgres::Error> {
|
||||
// To be added at some point. Not sure if it's needed.
|
||||
/* pub async fn update_name(guild_id: u64, server_name: &str, new_name: &str) -> Result<(), tokio_postgres::Error> {
|
||||
let client = DatabaseController::new().await?.client;
|
||||
client.execute("
|
||||
UPDATE gameservers
|
||||
@ -83,5 +83,37 @@ impl Gameservers {
|
||||
", &[&new_name, &(guild_id as i64), &server_name]).await?;
|
||||
|
||||
Ok(())
|
||||
} */
|
||||
|
||||
pub async fn get_server_names(guild_id: u64) -> Result<Vec<String>, tokio_postgres::Error> {
|
||||
let client = DatabaseController::new().await?.client;
|
||||
let rows = client.query("
|
||||
SELECT server_name FROM gameservers
|
||||
WHERE guild_owner = $1
|
||||
", &[&(guild_id as i64)]).await?;
|
||||
|
||||
let mut servers = Vec::new();
|
||||
for row in rows {
|
||||
servers.push(row.get("server_name"));
|
||||
}
|
||||
|
||||
Ok(servers)
|
||||
}
|
||||
|
||||
pub async fn get_server_data(guild_id: u64, server_name: &str) -> Result<Vec<String>, tokio_postgres::Error> {
|
||||
let client = DatabaseController::new().await?.client;
|
||||
let rows = client.query("
|
||||
SELECT * FROM gameservers
|
||||
WHERE guild_owner = $1 AND server_name = $2
|
||||
", &[&(guild_id as i64), &server_name]).await?;
|
||||
|
||||
let mut server = Vec::new();
|
||||
for row in rows {
|
||||
server.push(row.get("server_name"));
|
||||
server.push(row.get("game_name"));
|
||||
server.push(row.get("ip_address"))
|
||||
}
|
||||
|
||||
Ok(server)
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1 @@
|
||||
pub mod mpservers;
|
||||
pub mod gameservers;
|
||||
|
@ -1,39 +0,0 @@
|
||||
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")))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user