move types to it's own crate

This commit is contained in:
Robin Appelman 2025-04-11 01:56:31 +02:00
commit ae681cb75c
7 changed files with 745 additions and 377 deletions

310
types/Cargo.lock generated Normal file
View file

@ -0,0 +1,310 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "deranged"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
dependencies = [
"powerfmt",
"serde",
]
[[package]]
name = "enum_primitive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
dependencies = [
"num-traits 0.1.43",
]
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "num"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits 0.2.19",
]
[[package]]
name = "num-bigint"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3"
dependencies = [
"autocfg",
"num-integer",
"num-traits 0.2.19",
]
[[package]]
name = "num-complex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
dependencies = [
"num-traits 0.2.19",
]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits 0.2.19",
]
[[package]]
name = "num-iter"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [
"autocfg",
"num-integer",
"num-traits 0.2.19",
]
[[package]]
name = "num-rational"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg",
"num-bigint",
"num-integer",
"num-traits 0.2.19",
]
[[package]]
name = "num-traits"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
dependencies = [
"num-traits 0.2.19",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "steamid-ng"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb049f8faa2cba570c5366dbaf88ee5849725b16edb771848639fac92e33673"
dependencies = [
"enum_primitive",
"lazy_static",
"num",
"regex",
"serde",
"serde_derive",
"thiserror",
]
[[package]]
name = "syn"
version = "2.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.3.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
[[package]]
name = "time-macros"
version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "ugc-scraper-types"
version = "0.1.0"
dependencies = [
"serde",
"steamid-ng",
"time",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"

13
types/Cargo.toml Normal file
View file

@ -0,0 +1,13 @@
[package]
name = "ugc-scraper-types"
version = "0.1.0"
edition = "2021"
[dependencies]
steamid-ng = "1.0.0"
serde = { version = "1.0.215", features = ["derive"], optional = true }
time = { version = "0.3.36", features = ["parsing", "macros"] }
[features]
serde = ["dep:serde", "time/serde", "time/formatting"]
default = ["serde"]

393
types/src/lib.rs Normal file
View file

@ -0,0 +1,393 @@
use std::str::FromStr;
pub use steamid_ng::SteamID;
use time::{Date, OffsetDateTime};
#[cfg(feature = "serde")]
mod serde_date {
use serde::de::Error;
use serde::ser::Error as _;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use time::format_description::FormatItem;
use time::macros::format_description;
use time::Date;
const DATE_FORMAT: &[FormatItem<'static>] = format_description!("[year]-[month]-[day]");
pub fn serialize<S: Serializer>(date: &Date, serializer: S) -> Result<S::Ok, S::Error> {
date.format(DATE_FORMAT)
.map_err(S::Error::custom)?
.serialize(serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Date, D::Error> {
let str = <&str>::deserialize(deserializer)?;
Date::parse(str, DATE_FORMAT).map_err(D::Error::custom)
}
pub mod opt {
use super::DATE_FORMAT;
use serde::de::Error;
use serde::ser::Error as _;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use time::Date;
pub fn serialize<S: Serializer>(
option: &Option<Date>,
serializer: S,
) -> Result<S::Ok, S::Error> {
option
.map(|odt| odt.format(DATE_FORMAT))
.transpose()
.map_err(S::Error::custom)?
.serialize(serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Option<Date>, D::Error> {
let str = <Option<&str>>::deserialize(deserializer)?;
match str {
Some(str) => Date::parse(str, DATE_FORMAT)
.map_err(D::Error::custom)
.map(Some),
None => Ok(None),
}
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Player {
pub name: String,
pub avatar: String,
#[cfg_attr(feature = "serde", serde(with = "serde_steam_id_as_string"))]
pub steam_id: SteamID,
pub honors: Vec<Honors>,
pub teams: Vec<TeamMemberShip>,
pub favorite_classes: Vec<Class>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Honors {
pub format: String,
pub season: String,
pub team: String,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TeamMemberShip {
pub team: TeamRef,
pub league: String,
#[cfg_attr(feature = "serde", serde(with = "serde_date"))]
pub since: Date,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TeamRef {
pub name: String,
pub id: u32,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct MembershipHistory {
pub format: String,
pub team: TeamRef,
pub division: String,
#[cfg_attr(feature = "serde", serde(with = "serde_date"))]
pub joined: Date,
#[cfg_attr(feature = "serde", serde(with = "serde_date::opt"))]
pub left: Option<Date>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Team {
pub name: String,
pub tag: String,
pub image: String,
pub format: String,
pub timezone: Option<String>,
pub steam_group: Option<String>,
pub division: String,
pub description: String,
pub titles: Vec<String>,
pub members: Vec<Membership>,
pub results: Vec<Record>,
pub name_changes: Vec<NameChange>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum Class {
Scout,
Soldier,
Pyro,
Demoman,
Heavy,
Medic,
Sniper,
Spy,
}
impl FromStr for Class {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"scout" => Ok(Class::Scout),
"soldier" => Ok(Class::Soldier),
"pyro" => Ok(Class::Pyro),
"demoman" => Ok(Class::Demoman),
"heavy" => Ok(Class::Heavy),
"medic" => Ok(Class::Medic),
"sniper" => Ok(Class::Sniper),
"spy" => Ok(Class::Spy),
_ => Err(()),
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct NameChange {
pub from_tag: String,
pub from: String,
pub to_tag: String,
pub to: String,
#[cfg_attr(feature = "serde", serde(with = "serde_date"))]
pub date: Date,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Membership {
pub name: String,
#[cfg_attr(feature = "serde", serde(with = "serde_steam_id_as_string"))]
pub steam_id: SteamID,
pub role: String,
#[cfg_attr(feature = "serde", serde(with = "time::serde::iso8601"))]
pub since: OffsetDateTime,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Record {
pub season: u32,
pub division: String,
pub wins: u8,
pub losses: u8,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TeamRosterData {
pub steam_group: Option<String>,
pub history: Vec<RosterHistory>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct RosterHistory {
pub name: String,
#[cfg_attr(feature = "serde", serde(with = "serde_steam_id_as_string"))]
pub steam_id: SteamID,
#[cfg_attr(feature = "serde", serde(with = "serde_date"))]
pub joined: Date,
#[cfg_attr(feature = "serde", serde(with = "serde_date::opt"))]
pub left: Option<Date>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TeamSeason {
pub season: u32,
pub matches: Vec<TeamSeasonMatch>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TeamSeasonMatch {
pub division: String,
pub week: u8,
pub date: String,
pub side: String,
pub result: MatchResult,
pub map: String,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum MatchResult {
Played {
id: u32,
opponent: TeamRef,
score: u8,
score_opponent: u8,
match_points: f32,
match_points_opponent: f32,
},
Pending {
id: u32,
opponent: TeamRef,
score: u8,
score_opponent: u8,
},
ByeWeek,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Seasons {
pub mode: String,
pub seasons: Vec<Season>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Season {
pub id: String,
pub name: String,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct MatchInfo {
pub comment: Option<String>,
pub comment_author: Option<String>,
pub team_home: TeamRef,
pub team_away: TeamRef,
pub score_home: u8,
pub score_away: u8,
}
pub enum GameMode {
Highlander,
Sixes,
Fours,
Ultiduo,
}
impl FromStr for GameMode {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"9v9" => Ok(GameMode::Highlander),
"6v6" => Ok(GameMode::Sixes),
"4v4" => Ok(GameMode::Fours),
"2v2" => Ok(GameMode::Ultiduo),
_ => Err(()),
}
}
}
impl GameMode {
pub fn letter(&self) -> char {
match self {
GameMode::Highlander => 'h',
GameMode::Sixes => '6',
GameMode::Fours => '4',
GameMode::Ultiduo => '2',
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Transaction {
pub name: String,
#[cfg_attr(feature = "serde", serde(with = "serde_steam_id_as_string"))]
pub steam_id: SteamID,
pub action: TransactionAction,
pub team: TeamRef,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TransactionAction {
Joined,
Left,
}
/// Tried to parse in invalid transaction action
pub struct MallFormedTransaction {
pub text: String,
}
impl FromStr for TransactionAction {
type Err = MallFormedTransaction;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Joined" => Ok(TransactionAction::Joined),
"Left" => Ok(TransactionAction::Left),
_ => Err(MallFormedTransaction {
text: s.to_string(),
}),
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct MapHistory {
pub current: CurrentSeasonMapList,
pub previous: Vec<PreviousSeasonMapList>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CurrentSeasonMapList {
pub season: u8,
pub maps: Vec<CurrentSeasonMap>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PreviousSeasonMapList {
pub season: u8,
pub maps: Vec<PreviousSeasonMap>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CurrentSeasonMap {
pub week: u8,
pub map: String,
pub date: String,
pub na_date: Option<String>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PreviousSeasonMap {
pub week: u8,
pub map: String,
#[cfg_attr(feature = "serde", serde(with = "serde_date"))]
pub date: Date,
}
#[cfg(feature = "serde")]
mod serde_steam_id_as_string {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use steamid_ng::SteamID;
pub fn serialize<S: Serializer>(steam_id: &SteamID, serializer: S) -> Result<S::Ok, S::Error> {
let id = u64::from(*steam_id);
format!("{id}").serialize(serializer)
}
#[allow(dead_code)]
pub fn deserialize<'de, D>(deserializer: D) -> Result<SteamID, D::Error>
where
D: Deserializer<'de>,
{
let id = u64::deserialize(deserializer)?;
Ok(SteamID::from(id))
}
}