soup-sdk 0.3.5

채팅 이벤트 수신 SDK
Documentation
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,
    })
}