Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backend/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ members = ["worker", "rest-api"]

[workspace.dependencies]
repository = { path = "./crates/repository" }
minecraft-pinger = "0.1.8"
minecraft-pinger = "0.1.10"

log = "0.4.*"
env_logger = "0.11.*"
Expand Down
65 changes: 40 additions & 25 deletions backend/crates/repository/src/duplicate_detection.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use sha2::{Sha256, Digest};
use hickory_resolver::TokioResolver;
use std::net::IpAddr;
use hickory_proto::rr::RData;
use serde_json::Value;
use std::sync::LazyLock;
use crate::error::RepositoryError;
use crate::models::server::Server;
use crate::repository::Repository;
use hickory_proto::rr::RData;
use hickory_resolver::TokioResolver;
use serde_json::Value;
use sha2::{Digest, Sha256};
use std::net::IpAddr;
use std::sync::LazyLock;

const SIGNAL_WEIGHTS_FAVICON: u32 = 50;
const SIGNAL_WEIGHTS_ENDPOINT: u32 = 40;
Expand All @@ -16,9 +16,8 @@ const SIGNAL_WEIGHTS_VERSION: u32 = 8;
const DUPLICATE_THRESHOLD: u32 = 75;
const SHARED_ENDPOINT_LIMIT: u32 = 2;

static DNS_RESOLVER: LazyLock<Option<TokioResolver>> = LazyLock::new(|| {
TokioResolver::builder_tokio().ok()?.build().ok()
});
static DNS_RESOLVER: LazyLock<Option<TokioResolver>> =
LazyLock::new(|| TokioResolver::builder_tokio().ok()?.build().ok());

#[derive(Debug, Clone)]
pub struct ServerFingerprint {
Expand All @@ -44,7 +43,9 @@ impl DuplicateDetectionService {
Some(idx) => favicon[idx + 1..].trim(),
None => favicon.trim(),
};
if base64.is_empty() { return None; }
if base64.is_empty() {
return None;
}

let mut hasher = Sha256::new();
hasher.update(base64.as_bytes());
Expand Down Expand Up @@ -98,7 +99,9 @@ impl DuplicateDetectionService {
normalized.push_str(word);
}

if normalized.chars().count() < 4 { return None; }
if normalized.chars().count() < 4 {
return None;
}

let mut hasher = Sha256::new();
hasher.update(normalized.as_bytes());
Expand All @@ -118,13 +121,17 @@ impl DuplicateDetectionService {
let mut target_port = port;

if let Ok(srv) = resolver.srv_lookup(&srv_name).await {
let best_srv = srv.answers().iter().filter_map(|record| {
if let RData::SRV(srv) = &record.data {
Some(srv)
} else {
None
}
}).min_by_key(|r| r.priority);
let best_srv = srv
.answers()
.iter()
.filter_map(|record| {
if let RData::SRV(srv) = &record.data {
Some(srv)
} else {
None
}
})
.min_by_key(|r| r.priority);

if let Some(best) = best_srv {
target_host = best.target.to_utf8().trim_end_matches('.').to_string();
Expand Down Expand Up @@ -162,7 +169,9 @@ impl DuplicateDetectionService {

let mut endpoint_trusted = false;
if let Some(endpoint) = resolved_endpoint {
let count = repository.count_resolved_endpoints(endpoint, exclude_id).await?;
let count = repository
.count_resolved_endpoints(endpoint, exclude_id)
.await?;
endpoint_trusted = count < SHARED_ENDPOINT_LIMIT;
}

Expand All @@ -174,11 +183,17 @@ impl DuplicateDetectionService {
return Ok(None);
}

let candidates = repository.find_servers(
favicon_hash.as_deref(),
if endpoint_trusted { resolved_endpoint.as_deref() } else { None },
motd_hash.as_deref(),
).await?;
let candidates = repository
.find_servers(
favicon_hash.as_deref(),
if endpoint_trusted {
resolved_endpoint.as_deref()
} else {
None
},
motd_hash.as_deref(),
)
.await?;

let mut best: Option<DuplicateMatch> = None;

Expand Down Expand Up @@ -233,4 +248,4 @@ impl DuplicateDetectionService {

Ok(best)
}
}
}
4 changes: 2 additions & 2 deletions backend/crates/repository/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub enum RepositoryError {
SQL(#[from] Error),

#[error("SQLx migration error : {0}")]
Migration(#[from] MigrateError)
Migration(#[from] MigrateError),
}

impl RepositoryError {
Expand All @@ -19,4 +19,4 @@ impl RepositoryError {
false
}
}
}
}
6 changes: 3 additions & 3 deletions backend/crates/repository/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod models;
pub mod repository;
pub mod duplicate_detection;
pub mod error;
pub mod models;
pub mod postgres;
pub mod error;
pub mod repository;
10 changes: 5 additions & 5 deletions backend/crates/repository/src/models/alert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ pub struct Alert {
pub id: u32,
pub user_id: String,
pub server_id: u32,

pub alert_type: AlertType,
pub player_threshold: Option<u32>,
pub is_active: bool,

pub created_at: OffsetDateTime,
}

Expand All @@ -31,11 +31,11 @@ pub struct AlertRow {
pub id: i32,
pub user_id: String,
pub server_id: i32,

pub alert_type: AlertType,
pub player_threshold: Option<i32>,
pub is_active: bool,

pub created_at: OffsetDateTime,
}

Expand All @@ -57,7 +57,7 @@ impl From<AlertRow> for Alert {
pub struct DraftAlert {
pub user_id: String,
pub server_id: u32,

pub alert_type: AlertType,
pub player_threshold: Option<u32>,
pub is_active: bool,
Expand Down
4 changes: 2 additions & 2 deletions backend/crates/repository/src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod alert;
pub mod mojang;
pub mod record;
pub mod server;
pub mod alert;
pub mod web_push;
pub mod mojang;
8 changes: 4 additions & 4 deletions backend/crates/repository/src/models/record.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use serde::{Deserialize, Serialize};
use time::{OffsetDateTime};
use time::OffsetDateTime;

#[derive(Serialize, Deserialize)]
pub struct RecordData(pub Vec<i64>, pub Vec<u32>);
pub struct RecordData(pub Vec<i64>, pub Vec<i32>);

impl RecordData {
pub fn into_binary(self) -> Vec<u8> {
let (timestamps, values) = (self.0, self.1);
let len = timestamps.len() as u32;

let mut bytes = Vec::with_capacity(4 + 8 + (len as usize * 8));

// Write the number of items
bytes.extend_from_slice(&len.to_le_bytes());

Expand Down Expand Up @@ -46,5 +46,5 @@ pub struct Record {

#[serde(with = "time::serde::timestamp")]
pub date: OffsetDateTime,
pub value: u32
pub value: i32,
}
10 changes: 6 additions & 4 deletions backend/crates/repository/src/models/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct Server {
#[serde(skip_serializing_if = "Option::is_none")]
pub last_favicon: Option<String>,
pub last_status: Option<ServerStatus>,
pub last_connected: Option<u32>,
pub last_connected: Option<i32>,
pub last_version: Option<String>,
pub last_max_players: Option<i32>,
pub last_motd: Option<Value>,
Expand Down Expand Up @@ -91,9 +91,11 @@ impl From<ServerRow> for Server {

last_favicon: row.last_favicon,
last_status: row.last_status,
last_connected: row.last_connected.map(|v| v as u32),
last_connected: row.last_connected,
last_version: row.last_version.map(|v| v.to_string()),
last_motd: row.last_motd.as_deref()
last_motd: row
.last_motd
.as_deref()
.and_then(|s| serde_json::from_str(s).ok()),
last_max_players: row.last_max_players,
last_ping_time: row.last_ping_time.map(|v| v as u32),
Expand Down Expand Up @@ -122,7 +124,7 @@ pub enum ServerStatus {
#[serde(rename_all = "lowercase")]
pub enum ServerType {
Java,
Bedrock
Bedrock,
}

#[derive(Serialize, Deserialize, Debug)]
Expand Down
Loading
Loading