mirror of
https://github.com/MingweiSamuel/Riven.git
synced 2024-12-25 10:26:31 +00:00
fix: regen, updates to fix bad match data
https://github.com/RiotGames/developer-relations/issues/898
This commit is contained in:
parent
ff6a3af9e1
commit
95c3ccbe0b
10 changed files with 157 additions and 13 deletions
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
@ -7,5 +7,9 @@
|
|||
"RUST_LOG": "riven=debug"
|
||||
}
|
||||
}
|
||||
],
|
||||
"rust-analyzer.cargo.features": [
|
||||
"nightly",
|
||||
"deny-unknown"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -31,5 +31,38 @@ pub enum GameType {
|
|||
TUTORIAL_GAME,
|
||||
}
|
||||
|
||||
impl GameType {
|
||||
/// https://github.com/RiotGames/developer-relations/issues/898
|
||||
pub(crate) fn serialize_empty<S>(
|
||||
val: &Option<Self>,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::ser::Serializer,
|
||||
{
|
||||
use serde::ser::Serialize;
|
||||
if let Some(val) = val {
|
||||
val.serialize(serializer)
|
||||
} else {
|
||||
"".serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// https://github.com/RiotGames/developer-relations/issues/898
|
||||
pub(crate) fn deserialize_empty<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<Self>, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
use serde::de::IntoDeserializer;
|
||||
let opt = Option::<String>::deserialize(deserializer)?;
|
||||
match opt.as_deref() {
|
||||
None | Some("") => Ok(None),
|
||||
Some(s) => Self::deserialize(s.into_deserializer()).map(Some)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
|
|
@ -49,10 +49,17 @@ macro_rules! serde_strum_unknown {
|
|||
<&str>::deserialize(deserializer)
|
||||
.map(Into::into)
|
||||
.and_then(|item| match item {
|
||||
Self::UNKNOWN(unknown) => Err(serde::de::Error::unknown_variant(
|
||||
Self::UNKNOWN(unknown) => {
|
||||
if unknown.is_empty() {
|
||||
// https://github.com/RiotGames/developer-relations/issues/898
|
||||
Ok(Self::UNKNOWN(unknown))
|
||||
} else {
|
||||
Err(serde::de::Error::unknown_variant(
|
||||
&*unknown,
|
||||
<Self as strum::VariantNames>::VARIANTS,
|
||||
)),
|
||||
))
|
||||
}
|
||||
}
|
||||
other => Ok(other),
|
||||
})
|
||||
}
|
||||
|
@ -151,7 +158,8 @@ macro_rules! newtype_enum {
|
|||
{
|
||||
<$repr>::deserialize(deserializer).map(Into::into)
|
||||
.and_then(|item: Self| {
|
||||
if !item.is_known() {
|
||||
// Exception for id zero: https://github.com/RiotGames/developer-relations/issues/898
|
||||
if 0 != item.0 && !item.is_known() {
|
||||
Err(serde::de::Error::custom(format!(
|
||||
"Unknown integer enum variant: {} (\"deny-unknown-enum-variants-integers\" feature is enabled).\nExpected one of the following: {:?}",
|
||||
item, Self::ALL_KNOWN
|
||||
|
|
|
@ -56,3 +56,36 @@ pub use team::*;
|
|||
|
||||
mod tier;
|
||||
pub use tier::*;
|
||||
|
||||
/// https://github.com/RiotGames/developer-relations/issues/898
|
||||
pub(crate) fn serialize_empty_string_none<S, T>(
|
||||
val: &Option<T>,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::ser::Serializer,
|
||||
T: serde::ser::Serialize,
|
||||
{
|
||||
use serde::ser::Serialize;
|
||||
if let Some(val) = val {
|
||||
val.serialize(serializer)
|
||||
} else {
|
||||
"".serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// https://github.com/RiotGames/developer-relations/issues/898
|
||||
pub(crate) fn deserialize_empty_string_none<'de, D, T>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<T>, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
T: serde::de::Deserialize<'de>,
|
||||
{
|
||||
use serde::de::{Deserialize, IntoDeserializer};
|
||||
let opt = Option::<String>::deserialize(deserializer)?;
|
||||
match opt.as_deref() {
|
||||
None | Some("") => Ok(None),
|
||||
Some(s) => T::deserialize(s.into_deserializer()).map(Some),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
///////////////////////////////////////////////
|
||||
|
||||
// http://www.mingweisamuel.com/riotapi-schema/tool/
|
||||
// Version ba7699aed741222f2431e1f3e4ba42c3ac302510
|
||||
// Version 031d3e7fc343bd86d82c45559fc79d3a87fa1b82
|
||||
|
||||
//! Automatically generated endpoint handles.
|
||||
#![allow(clippy::let_and_return, clippy::too_many_arguments)]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
///////////////////////////////////////////////
|
||||
|
||||
// http://www.mingweisamuel.com/riotapi-schema/tool/
|
||||
// Version ba7699aed741222f2431e1f3e4ba42c3ac302510
|
||||
// Version 031d3e7fc343bd86d82c45559fc79d3a87fa1b82
|
||||
|
||||
//! Metadata about the Riot API and Riven.
|
||||
//!
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
///////////////////////////////////////////////
|
||||
|
||||
// http://www.mingweisamuel.com/riotapi-schema/tool/
|
||||
// Version ba7699aed741222f2431e1f3e4ba42c3ac302510
|
||||
// Version 031d3e7fc343bd86d82c45559fc79d3a87fa1b82
|
||||
|
||||
#![allow(missing_docs)]
|
||||
|
||||
|
@ -999,7 +999,11 @@ pub mod match_v5 {
|
|||
#[serde(rename = "gameStartTimestamp")]
|
||||
pub game_start_timestamp: i64,
|
||||
#[serde(rename = "gameType")]
|
||||
pub game_type: crate::consts::GameType,
|
||||
///
|
||||
/// Will be `None` if empty string is returned: https://github.com/RiotGames/developer-relations/issues/898
|
||||
#[serde(serialize_with = "crate::consts::serialize_empty_string_none")]
|
||||
#[serde(deserialize_with = "crate::consts::deserialize_empty_string_none")]
|
||||
pub game_type: Option<crate::consts::GameType>,
|
||||
/// The first two parts can be used to determine the patch a game was played on.
|
||||
#[serde(rename = "gameVersion")]
|
||||
pub game_version: String,
|
||||
|
@ -2203,7 +2207,8 @@ pub mod match_v5 {
|
|||
#[serde(rename = "events")]
|
||||
pub events: std::vec::Vec<MatchTimelineInfoFrameEvent>,
|
||||
#[serde(rename = "participantFrames")]
|
||||
pub participant_frames: MatchTimelineInfoFrameParticipantFrames,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub participant_frames: Option<MatchTimelineInfoFrameParticipantFrames>,
|
||||
#[serde(rename = "timestamp")]
|
||||
pub timestamp: i32,
|
||||
}
|
||||
|
|
|
@ -29,5 +29,38 @@ pub enum GameType {
|
|||
}}
|
||||
}
|
||||
|
||||
impl GameType {
|
||||
/// https://github.com/RiotGames/developer-relations/issues/898
|
||||
pub(crate) fn serialize_empty<S>(
|
||||
val: &Option<Self>,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::ser::Serializer,
|
||||
{
|
||||
use serde::ser::Serialize;
|
||||
if let Some(val) = val {
|
||||
val.serialize(serializer)
|
||||
} else {
|
||||
"".serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// https://github.com/RiotGames/developer-relations/issues/898
|
||||
pub(crate) fn deserialize_empty<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<Self>, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
use serde::de::IntoDeserializer;
|
||||
let opt = Option::<String>::deserialize(deserializer)?;
|
||||
match opt.as_deref() {
|
||||
None | Some("") => Ok(None),
|
||||
Some(s) => Self::deserialize(s.into_deserializer()).map(Some)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
|
|
@ -68,6 +68,12 @@ pub mod {{= dotUtils.changeCase.snakeCase(endpoint) }} {
|
|||
#[serde(serialize_with = "crate::consts::Champion::serialize_result")]
|
||||
#[serde(deserialize_with = "crate::consts::Champion::deserialize_result")]
|
||||
pub {{= name }}: Result<crate::consts::Champion, std::num::TryFromIntError>,
|
||||
{{?? 'gameType' === propKey && 'Info' === schemaName && 'match-v5' === endpoint }}
|
||||
///
|
||||
/// Will be `None` if empty string is returned: https://github.com/RiotGames/developer-relations/issues/898
|
||||
#[serde(serialize_with = "crate::consts::serialize_empty_string_none")]
|
||||
#[serde(deserialize_with = "crate::consts::deserialize_empty_string_none")]
|
||||
pub {{= name }}: Option<{{= dotUtils.stringifyType(prop, {}) }}>,
|
||||
{{??}}
|
||||
pub {{= name }}: {{= dotUtils.stringifyType(prop, { optional }) }},
|
||||
{{?}}
|
||||
|
|
|
@ -227,6 +227,23 @@ pub async fn match_v5_get(
|
|||
.champion()
|
||||
.map_err(|e| format!("Failed to determine match {} champion: {}", matche, e))?;
|
||||
}
|
||||
|
||||
{
|
||||
let game_id = m.info.game_id;
|
||||
if 0 == game_id {
|
||||
eprintln!(
|
||||
"Match {} `game_id` is zero, skipping remaining tests (see https://github.com/RiotGames/developer-relations/issues/898).",
|
||||
matche
|
||||
);
|
||||
return Ok(());
|
||||
} else if matche[(matche.find('_').unwrap() + 1)..] != game_id.to_string() {
|
||||
return Err(format!(
|
||||
"Match {} timeline number ID should match `game_id` {}.",
|
||||
matche, game_id
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if m.info.teams.is_empty() {
|
||||
return Err(format!("Match {} should have teams.", matche));
|
||||
}
|
||||
|
@ -256,12 +273,17 @@ pub async fn match_v5_get_timeline(
|
|||
return Err(format!("Match {} should have participants.", matche));
|
||||
}
|
||||
if let Some(game_id) = m.info.game_id {
|
||||
if matche[(matche.find('_').unwrap() + 1)..] != game_id.to_string() {
|
||||
return Err(format!("Match {} number ID should match.", matche));
|
||||
if 0 == game_id {
|
||||
eprintln!("Match {} timeline `game_id` is zero (see https://github.com/RiotGames/developer-relations/issues/898).", matche);
|
||||
} else if matche[(matche.find('_').unwrap() + 1)..] != game_id.to_string() {
|
||||
return Err(format!(
|
||||
"Match {} timeline number ID should match `game_id` {}.",
|
||||
matche, game_id
|
||||
));
|
||||
}
|
||||
}
|
||||
if m.info.frames.is_empty() {
|
||||
return Err(format!("Match {} timleine should have frames.", matche));
|
||||
return Err(format!("Match {} timeline should have frames.", matche));
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue