Skip to content

Commit 4053118

Browse files
committed
done with ban_enforcer
1 parent c923972 commit 4053118

File tree

4 files changed

+72
-49
lines changed

4 files changed

+72
-49
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ Either setting environment variables directly, or creating a `.env` file in the
1919
BFOX_RCON_IP=127.0.0.1
2020
BFOX_RCON_PORT=12345
2121
BFOX_RCON_PASSWORD=qw3RTy
22-
BFOX_ADKATS_URI=mysql://username:password@host/database
22+
DATABASE_URL=mysql://username:password@host/database
2323
```

battlefox/src/ban_enforcer.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ use async_trait::async_trait;
55
use battlefield_rcon::bf4::ban_list::{Ban, BanTimeout};
66
use battlefield_rcon::bf4::{Bf4Client, Event, BanListError, PlayerKickError};
77
use battlefield_rcon::rcon::RconResult;
8-
use battlefox_database::better::BfoxDb;
9-
use battlefox_database::entities::sea_orm_active_enums::BanStatus;
10-
use chrono::{Utc, DateTime, TimeZone};
8+
use battlefox_database::better::{BfoxDb, OffsetDateTime, BanStatus};
119
use serde::{Deserialize, Serialize};
1210

1311
use crate::Plugin;
@@ -33,15 +31,16 @@ impl BanEnforcer {
3331
match event {
3432
Event::Authenticated { player } => {
3533
match self.db.get_ban(format!("{}", player.eaid)).await {
36-
Ok(Some((_, ban))) => {
37-
let now = Utc::now();
38-
let ban_end : DateTime<Utc> = Utc.from_utc_datetime(&ban.ban_end_time); // assume our data is UTC.
34+
Ok(Some(ban)) => {
35+
let now = OffsetDateTime::now_utc();
3936

40-
let is_banned_time = now < ban_end;
41-
let is_banned_status = ban.ban_status == BanStatus::Active;
37+
// let ban_end : DateTime<Utc> = Utc.from_utc_datetime(&ban.ban_end_time); // assume our data is UTC.
38+
39+
let is_banned_time = now < ban.end;
40+
let is_banned_status = ban.status == BanStatus::Active;
4241

4342
if is_banned_time != is_banned_status {
44-
warn!("Ban end time and ban_status mismatch for player {player}. All times (assumed) in UTC. Now = {}, ban_end = {}, ban_status = {:?}", &now, &ban_end, ban.ban_status);
43+
warn!("Ban end time and ban_status mismatch for player {player}. All times (assumed) in UTC. Now = {}, ban_end = {}, ban_status = {:?}", &now, &ban.end, ban.status);
4544
}
4645

4746
// ban expiry time is more important than the ban_status column.
@@ -51,21 +50,21 @@ impl BanEnforcer {
5150
match bf4.ban_add(
5251
Ban::Guid(player.eaid),
5352
BanTimeout::Time(Duration::from_secs(1)), // I guess rcon will remove this by itself?
54-
Some("") // reason
53+
Some(ban.reason.clone()) // reason
5554
).await {
5655
Ok(()) => (),
5756
Err(BanListError::BanListFull) => warn!("Ban list is full?!"),
5857
Err(BanListError::NotFound) => unreachable!(),
5958
Err(BanListError::Rcon(rcon_err)) => error!("Failed to tempban player for a second: {rcon_err:?}"),
6059
}
6160

62-
match bf4.kick(player.name, "").await {
61+
match bf4.kick(player.name, ban.reason).await {
6362
Ok(()) => (),
6463
Err(PlayerKickError::PlayerNotFound) => (),
6564
Err(PlayerKickError::Rcon(rcon_err)) => error!("Failed to kick player: {rcon_err:?}"),
6665
}
6766
} else {
68-
debug!("Player {player} is in , but the ban has expired.");
67+
debug!("Player {player} is in adkats_bans, but the ban has expired.");
6968
}
7069
},
7170
Ok(None) => (), // player is not banned

battlefox/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ fn get_rcon_coninfo() -> anyhow::Result<RconConnectionInfo> {
8383
}
8484

8585
fn get_db_coninfo() -> anyhow::Result<String> {
86-
let uri = var("BFOX_ADKATS_URI")
87-
.context("Need to specify AdKats db URI via env var, for example BFOX_ADKATS_URI=\"mysql://username:password@host/database\"")?;
86+
let uri = var("DATABASE_URL")
87+
.context("Need to specify AdKats db URI via env var, for example DATABASE_URL=\"mysql://username:password@host/database\"")?;
8888
Ok(uri)
8989
}
9090

battlefox_database/src/better.rs

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,25 @@
1-
//! A new, better, attempt at battlefox_database with SQLx. Because fuck Diesel.
1+
//! A new, better, attempt at battlefox_database with SQLx. Because Diesel is clunky.
22
//!
33
//! And yet I'm too lazy to get rid of diesel, so that's why I'm just making a `better` module
44
//! instead of rewriting the whole thing.
55
66
// pub struct Config { }
77

8-
use sea_orm::{DatabaseConnection, Database, EntityTrait, QueryFilter, ColumnTrait, DbErr};
8+
use sqlx::mysql::MySqlPoolOptions;
9+
pub use sqlx::types::time::OffsetDateTime; // apparently sqlX uses its own datetime stuff.
910
use thiserror::Error;
10-
11-
use crate::entities::adkats_bans::Entity as AdkatsBans;
12-
use crate::entities::tbl_playerdata::Entity as PlayerData;
13-
use crate::entities::*;
11+
use sqlx::query;
1412

1513
/// Database Connection Pool. Cheap to clone, inner reference counting.
1614
#[derive(Clone)]
1715
pub struct BfoxDb {
18-
db: DatabaseConnection,
16+
db: sqlx::MySqlPool,
1917
}
2018

2119
#[derive(Error, Debug)]
2220
pub enum BfoxDbError {
23-
#[error("Uh oh")]
24-
UhOh,
25-
2621
#[error("{0}")]
27-
DbErr(#[from] DbErr),
22+
DbErr(#[from] sqlx::Error),
2823
}
2924

3025
impl BfoxDb {
@@ -33,8 +28,12 @@ impl BfoxDb {
3328
/// `db_uri` is something like `protocol://username:password@host/database`.
3429
///
3530
/// https://www.sea-ql.org/SeaORM/docs/install-and-config/connection
36-
pub async fn new(db_uri: impl AsRef<str>) -> Result<Self, anyhow::Error> {
37-
let db: DatabaseConnection = Database::connect(db_uri.as_ref()).await?;
31+
pub async fn new(db_uri: impl AsRef<str>) -> Result<Self, BfoxDbError> {
32+
// let db: DatabaseConnection = Database::connect(db_uri.as_ref()).await?;
33+
let db = MySqlPoolOptions::new()
34+
// .max_connections(3)
35+
.connect(db_uri.as_ref())
36+
.await?;
3837

3938
Ok(Self {
4039
db
@@ -46,23 +45,51 @@ impl BfoxDb {
4645
/// - `None` means there is no ban record for the player, i.e. not banned.
4746
/// - `Some((playerdata, ban))` means the player is probably banned, but please still
4847
/// check `ban_status`, `end_time`, just to be sure.
49-
pub async fn get_ban(&self, guid: impl AsRef<str>) -> Result<Option<(tbl_playerdata::Model, adkats_bans::Model)>, BfoxDbError> {
50-
let ban = PlayerData::find()
51-
.filter(tbl_playerdata::Column::Eaguid.eq(guid.as_ref()))
52-
.inner_join(AdkatsBans)
53-
.select_also(AdkatsBans)
54-
.one(&self.db).await?;
55-
56-
let ban = match ban {
57-
None => None,
58-
Some((_, None)) => unreachable!("Impossible for inner_join to return only one of two entities."),
59-
Some((pd, Some(b))) => Some((pd, b)),
60-
};
61-
62-
Ok(ban)
48+
pub async fn get_ban(&self, guid: impl AsRef<str>) -> Result<Option<BanInfo>, BfoxDbError> {
49+
let ban = query!(
50+
"SELECT PlayerID, ClanTag, SoldierName, EAGUID, ban_notes, ban_status, ban_startTime, ban_endTime, record_message
51+
FROM tbl_playerdata AS pd
52+
INNER JOIN adkats_bans AS bans ON pd.PlayerId = bans.player_id
53+
INNER JOIN adkats_records_main AS records ON records.record_id = bans.latest_record_id
54+
WHERE pd.EAGUID = ?;"
55+
, guid.as_ref()).fetch_optional(&self.db).await?;
56+
57+
if let Some(ban) = ban {
58+
let status = match ban.ban_status.as_ref() {
59+
"Active" => BanStatus::Active,
60+
"Expired" => BanStatus::Expired,
61+
"Disabled" => BanStatus::Disabled,
62+
_ => unreachable!("Unknown ban status!")
63+
};
64+
65+
let bi = BanInfo {
66+
start: ban.ban_startTime.assume_utc(),
67+
end: ban.ban_endTime.assume_utc(),
68+
status,
69+
reason: ban.record_message,
70+
};
71+
72+
Ok(Some(bi))
73+
} else {
74+
Ok(None)
75+
}
6376
}
6477
}
6578

79+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
80+
pub enum BanStatus {
81+
Active,
82+
Expired,
83+
Disabled,
84+
}
85+
86+
#[derive(Debug, Clone)]
87+
pub struct BanInfo {
88+
pub start: OffsetDateTime,
89+
pub end: OffsetDateTime,
90+
pub status: BanStatus,
91+
pub reason: String,
92+
}
6693

6794
#[cfg(test)]
6895
mod test {
@@ -72,8 +99,8 @@ mod test {
7299

73100
fn get_db_coninfo() -> anyhow::Result<String> {
74101
dotenv::dotenv()?;
75-
let uri = std::env::var("BFOX_ADKATS_URI")
76-
.context("Need to specify AdKats db URI via env var, for example BFOX_ADKATS_URI=\"mysql://username:password@host/database\"")?;
102+
let uri = std::env::var("DATABASE_URL")
103+
.context("Need to specify AdKats db URI via env var, for example DATABASE_URL=\"mysql://username:password@host/database\"")?;
77104
Ok(uri)
78105
}
79106

@@ -82,11 +109,8 @@ mod test {
82109
async fn test() -> anyhow::Result<()> {
83110
let uri = get_db_coninfo()?;
84111
let db = BfoxDb::new(uri).await?;
85-
86-
let ban = db.get_ban("EA_23497BD31CD2C20EED45BF21542EA2AD").await?;
87-
112+
let ban = db.get_ban("EA_insert your GUID here").await?;
88113
println!("{ban:#?}");
89-
90-
Ok(())
114+
panic!()
91115
}
92116
}

0 commit comments

Comments
 (0)