use crate::chat::{
events::{
BattleMissionResultEvent, ChallengeMissionResultEvent, EventMeta, MissionEvent,
MissionTotalEvent,
},
parser::{
raw::{ParseError, ParseResult, RawMessage},
types::{
AbstractMissionData, BattleMissionResultPayload, ChallengeMissionResultPayload,
MissionGiftPayload, MissionGiftTotalPayload,
},
util::normalize_user_id,
},
types::MissionType,
};
pub enum ParsedMissionEvent {
Mission(MissionEvent),
MissionTotal(MissionTotalEvent),
BattleNotice(BattleMissionResultEvent),
ChallengeNotice(ChallengeMissionResultEvent),
}
pub fn parse_mission_event(raw: RawMessage) -> ParseResult<ParsedMissionEvent> {
let raw_json = raw.field(0)?.to_string();
let abs_json: AbstractMissionData =
serde_json::from_str(&raw_json).map_err(|err| ParseError::InvalidJson {
code: raw.code,
index: 0,
reason: err.to_string(),
})?;
let message_type = abs_json.message_type.as_str();
match message_type {
"GIFT" | "CHALLENGE_GIFT" => {
let e = parse_gift_event(&raw, &raw_json, message_type)?;
Ok(ParsedMissionEvent::Mission(e))
}
"SETTLE" | "CHALLENGE_SETTLE" => {
let e = parse_gift_total_event(raw, &raw_json, message_type)?;
Ok(ParsedMissionEvent::MissionTotal(e))
}
"NOTICE" => {
let e = parse_battle_result(raw, &raw_json)?;
Ok(ParsedMissionEvent::BattleNotice(e))
}
"CHALLENGE_NOTICE" => {
let e = parse_challenge_result(raw, &raw_json)?;
Ok(ParsedMissionEvent::ChallengeNotice(e))
}
_ => Err(ParseError::Protocol("미션 이벤트 파싱 실패".to_string())),
}
}
fn parse_gift_event(raw: &RawMessage, body: &str, message_type: &str) -> ParseResult<MissionEvent> {
let p: MissionGiftPayload =
serde_json::from_str(body).map_err(|err| ParseError::InvalidJson {
code: raw.code,
index: 0,
reason: err.to_string(),
})?;
Ok(MissionEvent {
meta: EventMeta {
received_time: raw.received_time,
},
from: normalize_user_id(&p.user_id),
from_label: p.label,
amount: p.amount as u32,
mission_type: if message_type == "CHALLENGE_GIFT" {
MissionType::Challenge
} else {
MissionType::Battle
},
})
}
fn parse_gift_total_event(
raw: RawMessage,
body: &str,
message_type: &str,
) -> ParseResult<MissionTotalEvent> {
let p: MissionGiftTotalPayload =
serde_json::from_str(body).map_err(|err| ParseError::InvalidJson {
code: raw.code,
index: 0,
reason: err.to_string(),
})?;
Ok(MissionTotalEvent {
meta: EventMeta {
received_time: raw.received_time,
},
mission_type: if message_type == "CHALLENGE_SETTLE" {
MissionType::Challenge
} else {
MissionType::Battle
},
amount: p.amount as u32,
})
}
fn parse_battle_result(raw: RawMessage, body: &str) -> ParseResult<BattleMissionResultEvent> {
let p: BattleMissionResultPayload =
serde_json::from_str(body).map_err(|err| ParseError::InvalidJson {
code: raw.code,
index: 0,
reason: err.to_string(),
})?;
Ok(BattleMissionResultEvent {
meta: EventMeta {
received_time: raw.received_time,
},
is_draw: p.draw,
winner: p.winner,
title: p.title,
})
}
fn parse_challenge_result(raw: RawMessage, body: &str) -> ParseResult<ChallengeMissionResultEvent> {
let p: ChallengeMissionResultPayload =
serde_json::from_str(body).map_err(|err| ParseError::InvalidJson {
code: raw.code,
index: 0,
reason: err.to_string(),
})?;
Ok(ChallengeMissionResultEvent {
meta: EventMeta {
received_time: raw.received_time,
},
is_success: p.status == "SUCCESS",
title: p.title,
})
}