handle logs with some broken nulls

This commit is contained in:
Robin Appelman 2024-02-10 12:53:50 +01:00
commit ff82fc9eb8
14 changed files with 13621 additions and 112 deletions

488
Cargo.lock generated
View file

@ -22,6 +22,21 @@ dependencies = [
"memchr",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
@ -31,6 +46,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "anyhow"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]]
name = "atoi"
version = "1.0.0"
@ -52,6 +73,12 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "base64"
version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -87,9 +114,12 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
name = "cc"
version = "1.0.73"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
@ -99,18 +129,37 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
dependencies = [
"libc",
"num-integer",
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits 0.2.15",
"serde",
"time",
"winapi",
"wasm-bindgen",
"windows-targets",
]
[[package]]
name = "console"
version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "cpufeatures"
version = "0.2.2"
@ -150,6 +199,51 @@ dependencies = [
"typenum",
]
[[package]]
name = "darling"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc5d6b04b3fd0ba9926f945895de7d806260a2d7431ba82e7edaecb043c4c6b8"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e48a959bcd5c761246f5d090ebc2fbf7b9cd527a492b07a67510c108f1e7e3"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.48",
]
[[package]]
name = "darling_macro"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77"
dependencies = [
"darling_core",
"quote",
"syn 2.0.48",
]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
"serde",
]
[[package]]
name = "digest"
version = "0.10.3"
@ -196,6 +290,12 @@ dependencies = [
"serde",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "enum_primitive"
version = "0.1.1"
@ -205,12 +305,24 @@ dependencies = [
"num-traits 0.1.43",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "event-listener"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
version = "1.0.1"
@ -309,6 +421,12 @@ dependencies = [
"ahash",
]
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "hashlink"
version = "0.8.0"
@ -360,6 +478,35 @@ dependencies = [
"digest",
]
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.2.3"
@ -379,6 +526,33 @@ checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a"
dependencies = [
"autocfg",
"hashbrown 0.11.2",
"serde",
]
[[package]]
name = "indexmap"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
"serde",
]
[[package]]
name = "insta"
version = "1.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc"
dependencies = [
"console",
"lazy_static",
"linked-hash-map",
"ron",
"serde",
"similar",
"yaml-rust",
]
[[package]]
@ -426,6 +600,12 @@ version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "lock_api"
version = "0.4.7"
@ -449,11 +629,14 @@ dependencies = [
name = "log-analyser"
version = "0.1.0"
dependencies = [
"anyhow",
"chrono",
"dotenv",
"insta",
"main_error",
"serde",
"serde_json",
"serde_with",
"sqlx",
"steamid-ng",
"test-case",
@ -504,7 +687,7 @@ dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
"windows-sys 0.36.1",
]
[[package]]
@ -551,6 +734,12 @@ dependencies = [
"num-traits 0.2.15",
]
[[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.45"
@ -667,50 +856,32 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppv-lite86"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.39"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.18"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@ -797,6 +968,17 @@ dependencies = [
"winapi",
]
[[package]]
name = "ron"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
dependencies = [
"base64 0.13.0",
"bitflags",
"serde",
]
[[package]]
name = "rustls"
version = "0.20.6"
@ -815,7 +997,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9"
dependencies = [
"base64",
"base64 0.13.0",
]
[[package]]
@ -842,22 +1024,22 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.140"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.140"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.48",
]
[[package]]
@ -871,6 +1053,36 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_with"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270"
dependencies = [
"base64 0.21.7",
"chrono",
"hex",
"indexmap 1.8.2",
"indexmap 2.2.2",
"serde",
"serde_derive",
"serde_json",
"serde_with_macros",
"time",
]
[[package]]
name = "serde_with_macros"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "sha-1"
version = "0.10.0"
@ -902,6 +1114,12 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "similar"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21"
[[package]]
name = "smallvec"
version = "1.8.0"
@ -953,7 +1171,7 @@ checksum = "6b69bf218860335ddda60d6ce85ee39f6cf6e5630e300e19757d1de15886a093"
dependencies = [
"ahash",
"atoi",
"base64",
"base64 0.13.0",
"bitflags",
"byteorder",
"bytes",
@ -970,7 +1188,7 @@ dependencies = [
"hex",
"hkdf",
"hmac",
"indexmap",
"indexmap 1.8.2",
"itoa",
"libc",
"log",
@ -1015,7 +1233,7 @@ dependencies = [
"sha2",
"sqlx-core",
"sqlx-rt",
"syn",
"syn 1.0.96",
"url",
]
@ -1055,6 +1273,12 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "subtle"
version = "2.4.1"
@ -1073,25 +1297,47 @@ dependencies = [
]
[[package]]
name = "test-case"
version = "2.2.1"
name = "syn"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07aea929e9488998b64adc414c29fe5620398f01c2e3f58164122b17e567a6d5"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "test-case"
version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8"
dependencies = [
"test-case-macros",
]
[[package]]
name = "test-case-macros"
version = "2.2.1"
name = "test-case-core"
version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c95968eedc6fc4f5c21920e0f4264f78ec5e4c56bb394f319becc1a5830b3e54"
checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
dependencies = [
"cfg-if",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
"syn 2.0.48",
]
[[package]]
name = "test-case-macros"
version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"test-case-core",
]
[[package]]
@ -1111,7 +1357,7 @@ checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.96",
]
[[package]]
@ -1125,13 +1371,33 @@ dependencies = [
[[package]]
name = "time"
version = "0.1.44"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
@ -1176,7 +1442,7 @@ checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.96",
]
[[package]]
@ -1221,7 +1487,7 @@ checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.96",
]
[[package]]
@ -1361,7 +1627,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
"syn",
"syn 1.0.96",
"wasm-bindgen-shared",
]
@ -1383,7 +1649,7 @@ checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.96",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -1455,45 +1721,129 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
"windows_aarch64_msvc 0.36.1",
"windows_i686_gnu 0.36.1",
"windows_i686_msvc 0.36.1",
"windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc 0.36.1",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.52.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]

View file

@ -14,9 +14,14 @@ dotenv = "0.15.0"
main_error = "0.1.2"
tokio = { version = "1.20.0", features = ["macros", "time"] }
serde = { version = "1.0.140", features = ["derive"] }
serde_with = "3.6.1"
serde_json = "1.0.82"
chrono = { version = "0.4.19", features = ["serde"] }
steamid-ng = "1.0.0"
test-case = "2.2.1"
tracing = "0.1.35"
tracing-subscriber = "0.3.15"
anyhow = "1.0.79"
[dev-dependencies]
insta = { version = "1.34.0", features = ["ron"] }
test-case = "3.3.1"

11
flake.lock generated
View file

@ -47,13 +47,16 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 0,
"narHash": "sha256-WbZKCf6g4+dljZ6Z866SGZzNA+WWjXt4Lc7td4zsRkw=",
"path": "/nix/store/vavqvhqw8x42kqb1m3wkcys65jvvnl5i-source",
"type": "path"
"lastModified": 1707514827,
"narHash": "sha256-Y+wqFkvikpE1epCx57PsGw+M1hX5aY5q/xgk+ebDwxI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "20f65b86b6485decb43c5498780c223571dd56ef",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "release-23.11",
"type": "indirect"
}
},

View file

@ -1,5 +1,6 @@
{
inputs = {
nixpkgs.url = "nixpkgs/release-23.11";
flake-utils.url = "github:numtide/flake-utils";
naersk.url = "github:nix-community/naersk";
};
@ -27,7 +28,7 @@
# `nix develop`
devShell = pkgs.mkShell {
nativeBuildInputs = with pkgs; [rustc cargo bacon cargo-edit cargo-outdated];
nativeBuildInputs = with pkgs; [rustc cargo bacon cargo-edit cargo-outdated cargo-insta];
};
}
)

View file

@ -1,6 +1,6 @@
use serde::Deserialize;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Eq, PartialEq)]
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Serialize, Eq, PartialEq)]
#[sqlx(type_name = "team")]
#[sqlx(rename_all = "lowercase")]
pub enum TeamId {
@ -16,7 +16,7 @@ impl Default for TeamId {
}
}
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Eq, PartialEq)]
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Serialize, Eq, PartialEq)]
#[serde(rename_all = "lowercase")]
#[sqlx(rename_all = "lowercase")]
#[sqlx(type_name = "class_type")]
@ -51,7 +51,7 @@ pub enum GameMode {
Other,
}
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Eq, PartialEq)]
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Serialize, Eq, PartialEq)]
pub enum EventType {
Charge,
PointCap,
@ -61,7 +61,7 @@ pub enum EventType {
Other,
}
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Hash, Eq, PartialEq)]
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Serialize, Hash, Eq, PartialEq)]
#[serde(rename_all = "lowercase")]
#[sqlx(rename_all = "lowercase")]
pub enum Medigun {

View file

@ -1,10 +1,11 @@
mod data;
mod database;
mod normalized;
mod raw;
pub mod raw;
use crate::database::{store_log, upgrade};
use crate::normalized::NormalizedLog;
use anyhow::{Context, Error};
use main_error::MainError;
use sqlx::pool::PoolOptions;
use sqlx::PgPool;
@ -26,19 +27,27 @@ async fn main() -> Result<(), MainError> {
}
}
async fn normalize(database_url: &str, raw_database_url: &str) -> Result<(), MainError> {
async fn normalize(database_url: &str, raw_database_url: &str) -> Result<(), Error> {
let pool = PoolOptions::new()
.max_connections(2)
.connect(database_url)
.await?;
.await
.context("Failed to connect to log database")?;
let raw_pool = PoolOptions::new()
.max_connections(2)
.connect(raw_database_url)
.await?;
.await
.context("Failed to connect to raw log database")?;
let max = get_max_log(&raw_pool).await?;
let old = get_min_old_stored_log(&pool, VERSION).await?;
let from = get_max_stored_log(&pool).await?;
let max = get_max_log(&raw_pool)
.await
.context("Failed to get max raw log")?;
let old = get_min_old_stored_log(&pool, VERSION)
.await
.context("Failed to get min processed old log")?;
let from = get_max_stored_log(&pool)
.await
.context("Failed to get min processed log")?;
if let Some(old) = old {
for id in old..=from {
@ -63,7 +72,7 @@ async fn normalize(database_url: &str, raw_database_url: &str) -> Result<(), Mai
Ok(())
}
async fn get_min_old_stored_log(pool: &PgPool, version: i16) -> Result<Option<i32>, MainError> {
async fn get_min_old_stored_log(pool: &PgPool, version: i16) -> Result<Option<i32>, Error> {
Ok(sqlx::query!(
r#"SELECT MIN(id) as "id" from logs WHERE version < $1"#,
version
@ -73,7 +82,7 @@ async fn get_min_old_stored_log(pool: &PgPool, version: i16) -> Result<Option<i3
.and_then(|row| row.id))
}
async fn get_max_stored_log(pool: &PgPool) -> Result<i32, MainError> {
async fn get_max_stored_log(pool: &PgPool) -> Result<i32, Error> {
Ok(sqlx::query!(r#"SELECT MAX(id) as id from logs"#)
.fetch_one(pool)
.await?
@ -81,7 +90,7 @@ async fn get_max_stored_log(pool: &PgPool) -> Result<i32, MainError> {
.unwrap_or_default())
}
async fn get_max_log(pool: &PgPool) -> Result<i32, MainError> {
async fn get_max_log(pool: &PgPool) -> Result<i32, Error> {
let row: (i32,) = sqlx::query_as(r#"SELECT MAX(id) as id from logs_raw"#)
.fetch_one(pool)
.await?;
@ -89,12 +98,13 @@ async fn get_max_log(pool: &PgPool) -> Result<i32, MainError> {
}
#[instrument(skip(pool))]
async fn get_log(pool: &PgPool, id: i32) -> Result<Option<NormalizedLog>, MainError> {
async fn get_log(pool: &PgPool, id: i32) -> Result<Option<NormalizedLog>, Error> {
let row: (serde_json::Value,) =
sqlx::query_as(r#"SELECT json as id from logs_raw where id = $1"#)
.bind(id)
.fetch_one(pool)
.await?;
.await
.context("failed to get raw log")?;
if is_valid(&row.0) {
match serde_json::from_value(row.0) {
@ -114,7 +124,7 @@ async fn get_log(pool: &PgPool, id: i32) -> Result<Option<NormalizedLog>, MainEr
if formatted_err.starts_with("invalid type: floating point") {
return Ok(None);
}
Err(err.into())
Err(err).context("failed parse raw log")
}
}
} else {

View file

@ -1,10 +1,11 @@
use crate::data::{Class, Medigun, TeamId};
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DefaultOnNull};
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use steamid_ng::SteamID;
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RawLog {
#[serde(default)]
pub version: u8,
@ -28,71 +29,100 @@ pub struct RawLog {
pub kill_streaks: Option<Vec<KillStreak>>,
}
#[derive(Debug, Clone, Deserialize, Default)]
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
#[serde(rename_all = "PascalCase")]
pub struct Teams {
pub red: Team,
pub blue: Team,
}
#[derive(Debug, Clone, Deserialize, Default)]
#[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct Team {
#[serde_as(deserialize_as = "DefaultOnNull")]
pub score: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub kills: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub deaths: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub dmg: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub charges: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub drops: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub firstcaps: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub caps: u32,
}
#[derive(Debug, Clone, Deserialize)]
#[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Player {
pub class_stats: Vec<ClassStat>,
pub team: Option<TeamId>,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub kills: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub deaths: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub assists: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub suicides: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub dmg: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub dmg_real: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub dt: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub dt_real: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub hr: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub lks: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub ubers: u32,
#[serde(default)]
pub ubertypes: HashMap<Medigun, u32>,
pub drops: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub medkits: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub medkits_hp: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub backstabs: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub headshots: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub headshots_hit: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub heal: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub cpc: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub ic: u32,
pub medicstat: Option<MedicStats>,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct MedicStats {
pub advantages_lost: u32,
pub biggest_advantage_list: u16,
@ -104,34 +134,47 @@ pub struct MedicStats {
pub avg_uber_length: f32,
}
#[derive(Debug, Clone, Deserialize)]
#[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ClassStat {
#[serde(rename = "type")]
pub class: Class,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub kills: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub assists: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub deaths: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub dmg: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub total_time: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
pub weapon: HashMap<String, WeaponStat>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum RawWeaponStats {
Kills(u32),
Stats {
#[serde_as(deserialize_as = "DefaultOnNull")]
kills: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
dmg: i64,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)]
avg_dmg: f32,
#[serde_as(deserialize_as = "DefaultOnNull")]
shots: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
hits: u32,
},
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(from = "RawWeaponStats")]
pub struct WeaponStat {
pub kills: u32,
@ -176,7 +219,7 @@ impl From<RawWeaponStats> for WeaponStat {
}
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Round {
#[serde(default)]
pub start_time: u64,
@ -191,13 +234,16 @@ pub struct Round {
pub events: Vec<Event>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RoundPlayer {
#[serde_as(deserialize_as = "DefaultOnNull")]
pub kills: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub dmg: u32,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type")]
#[serde(rename_all = "snake_case")]
pub enum Event {
@ -246,7 +292,7 @@ impl Event {
}
}
#[derive(Debug, Clone, Deserialize, Default)]
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct ClassNumbers {
#[serde(default)]
pub scout: u32,
@ -268,14 +314,14 @@ pub struct ClassNumbers {
pub spy: u32,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ChatMessage {
pub steamid: ChatFrom,
pub name: String,
pub msg: String,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
#[serde(try_from = "String")]
pub enum ChatFrom {
@ -295,7 +341,7 @@ impl TryFrom<String> for ChatFrom {
}
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Info {
pub map: String,
pub total_length: u32,
@ -340,14 +386,14 @@ pub struct Info {
pub teams: Option<Teams>,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Uploader {
pub id: SteamID,
pub name: String,
pub info: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct KillStreak {
pub steamid: SteamID,
pub streak: i32,
@ -364,14 +410,24 @@ mod tests {
#[test_case("134389.json")]
#[test_case("550237.json")]
#[test_case("2522305.json")]
#[test_case("3578739.json")]
fn test_parse(file: &str) {
let content = fs::read_to_string(format!("tests/data/{}", file)).unwrap();
let parsed: RawLog = serde_json::from_str(&content).unwrap();
assert!(parsed.teams.is_some() || parsed.info.teams.is_some());
assert!(parsed.rounds.is_some() || parsed.info.rounds.is_some());
for round in parsed.rounds.or(parsed.info.rounds).unwrap() {
for round in parsed
.rounds
.as_ref()
.or(parsed.info.rounds.as_ref())
.unwrap()
{
assert!(round.flat_team.is_some() || round.team.is_some());
}
insta::with_settings!({sort_maps => true, snapshot_path => "../tests/data/snapshots"}, {
insta::assert_ron_snapshot!(file, parsed);
});
}
}

1806
tests/data/3578739.json Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file