sorta handle malformed players

This commit is contained in:
Robin Appelman 2023-03-21 20:24:11 +01:00
commit 2d8ede8027
2 changed files with 42 additions and 24 deletions

View file

@ -2,12 +2,14 @@ use crate::event::EventFieldFromStr;
use crate::parsing::find_between_end; use crate::parsing::find_between_end;
use crate::raw_event::{split_player_subject, RawSubject}; use crate::raw_event::{split_player_subject, RawSubject};
use crate::Result; use crate::Result;
use ahash::AHasher;
use enum_iterator::{all, Sequence}; use enum_iterator::{all, Sequence};
use serde::ser::SerializeMap; use serde::ser::SerializeMap;
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use std::str::FromStr; use std::str::FromStr;
use steamid_ng::{AccountType, Instance, SteamID, Universe}; use steamid_ng::{AccountType, Instance, SteamID, Universe};
@ -205,6 +207,7 @@ pub enum SubjectId {
System, System,
World, World,
Console, Console,
MalformedPlayer(u32),
} }
impl SubjectId { impl SubjectId {
@ -221,6 +224,12 @@ impl SubjectId {
} }
} }
fn hash_player_str(s: &str) -> u32 {
let mut hasher = AHasher::default();
s.hash(&mut hasher);
(hasher.finish() & (u32::MAX as u64)) as u32
}
impl TryFrom<&RawSubject<'_>> for SubjectId { impl TryFrom<&RawSubject<'_>> for SubjectId {
type Error = SubjectError; type Error = SubjectError;
@ -232,12 +241,16 @@ impl TryFrom<&RawSubject<'_>> for SubjectId {
return Ok(SubjectId::Player(account_id)); return Ok(SubjectId::Player(account_id));
} }
} }
let (_, user_id, steam_id, _) = split_player_subject(raw) let Ok((_, user_id, steam_id, _)) = split_player_subject(raw) else {
.map_err(|_| SubjectError::InvalidSteamId(raw.to_string()))?; return Ok(SubjectId::MalformedPlayer(hash_player_str(*raw)));
};
if let Ok(steam_id) = SteamID::from_steam2(steam_id) { if let Ok(steam_id) = SteamID::from_steam2(steam_id) {
SubjectId::Player(steam_id.account_id()) SubjectId::Player(steam_id.account_id())
} else { } else {
SubjectId::Bot(user_id.parse().map_err(|_| SubjectError::InvalidUserId)?) user_id
.parse()
.map(SubjectId::Bot)
.unwrap_or_else(|_| SubjectId::MalformedPlayer(hash_player_str(*raw)))
} }
} }
RawSubject::Team(team) => SubjectId::Team(*team), RawSubject::Team(team) => SubjectId::Team(*team),
@ -265,6 +278,7 @@ pub enum SubjectData {
}, },
Console, Console,
World, World,
MalformedPlayer(String),
} }
impl SubjectData { impl SubjectData {
@ -276,6 +290,7 @@ impl SubjectData {
SubjectData::Bot { user_id, .. } => SubjectId::Bot(*user_id), SubjectData::Bot { user_id, .. } => SubjectId::Bot(*user_id),
SubjectData::Console => SubjectId::Console, SubjectData::Console => SubjectId::Console,
SubjectData::World => SubjectId::World, SubjectData::World => SubjectId::World,
SubjectData::MalformedPlayer(raw) => SubjectId::MalformedPlayer(hash_player_str(&raw)),
} }
} }
} }
@ -294,27 +309,30 @@ impl TryFrom<&RawSubject<'_>> for SubjectData {
type Error = SubjectError; type Error = SubjectError;
fn try_from(raw: &RawSubject<'_>) -> Result<Self, Self::Error> { fn try_from(raw: &RawSubject<'_>) -> Result<Self, Self::Error> {
Ok(match raw { fn try_parse_player(raw: &str) -> Result<SubjectData, SubjectError> {
RawSubject::Player(raw) => { let (name, user_id, steam_id, team) =
let (name, user_id, steam_id, team) = split_player_subject(raw).map_err(|_| SubjectError::InvalidUserId)?;
split_player_subject(raw).map_err(|_| SubjectError::InvalidUserId)?; if let Ok(steam_id) =
if let Ok(steam_id) = SteamID::from_steam3(steam_id).or_else(|_| SteamID::from_steam2(steam_id))
SteamID::from_steam3(steam_id).or_else(|_| SteamID::from_steam2(steam_id)) {
{ Ok(SubjectData::Player {
SubjectData::Player { name: name.to_string(),
name: name.to_string(), user_id: user_id.parse().map_err(|_| SubjectError::InvalidUserId)?,
user_id: user_id.parse().map_err(|_| SubjectError::InvalidUserId)?, steam_id,
steam_id, team: team.parse().unwrap_or_default(),
team: team.parse().unwrap_or_default(), })
} } else {
} else { Ok(SubjectData::Bot {
SubjectData::Bot { name: name.to_string(),
name: name.to_string(), user_id: user_id.parse().map_err(|_| SubjectError::InvalidUserId)?,
user_id: user_id.parse().map_err(|_| SubjectError::InvalidUserId)?, team: team.parse().unwrap_or_default(),
team: team.parse().unwrap_or_default(), })
}
}
} }
}
Ok(match raw {
RawSubject::Player(raw) => try_parse_player(raw)
.unwrap_or_else(|_| SubjectData::MalformedPlayer(raw.to_string())),
RawSubject::Team(team) => SubjectData::Team(*team), RawSubject::Team(team) => SubjectData::Team(*team),
RawSubject::System(name) => SubjectData::System(name.to_string()), RawSubject::System(name) => SubjectData::System(name.to_string()),
RawSubject::Console => SubjectData::Console, RawSubject::Console => SubjectData::Console,

View file

@ -99,7 +99,7 @@ pub fn split_player_subject(input: &str) -> Result<(&str, &str, &str, &str)> {
(parts.next(), parts.next(), parts.next(), parts.next()) (parts.next(), parts.next(), parts.next(), parts.next())
{ {
if steam_id.is_empty() || user_id.is_empty() || team.is_empty() { if steam_id.is_empty() || user_id.is_empty() || team.is_empty() {
(name, "0", "", "") return Err(Error::Malformed);
} else { } else {
( (
name, name,