use std::str::FromStr;
use serde_json::Value;
use crate::{impl_str_enum, utils::error::Error};
#[derive(Clone, Debug)]
#[repr(u8)]
pub enum GestureType {
Rock = 0,
Scissors = 1,
Paper = 2,
}
#[derive(Clone, Debug)]
pub enum RedPacketType {
Random,
Average,
Specify,
Heartbeat,
RockPaperScissors,
}
#[derive(Clone, Debug)]
pub struct RedPacket {
pub r#type: RedPacketType,
pub money: u32,
pub count: u32,
pub msg: String,
pub recivers: Vec<String>,
pub gesture: Option<GestureType>,
}
#[derive(Clone, Debug)]
#[allow(non_snake_case)]
pub struct RedPacketGot {
pub userId: String,
pub userName: String,
pub avatar: String,
pub userMoney: u32,
pub time: String,
}
#[derive(Clone, Debug)]
#[allow(non_snake_case)]
pub struct RedPacketMessage {
pub msgType: String,
pub count: u32,
pub got: u32,
pub money: u32,
pub msg: String,
pub senderId: String,
pub GestureType: Option<GestureType>,
pub recivers: Vec<String>,
pub who: Vec<RedPacketGot>,
}
#[derive(Clone, Debug)]
#[allow(non_snake_case)]
pub struct RedPacketBase {
pub count: u32,
pub gesture: Option<GestureType>,
pub got: u32,
pub msg: String,
pub userName: String,
pub userAvatarURL: String,
}
#[derive(Clone, Debug)]
pub struct RedPacketInfo {
pub info: RedPacketBase,
pub recivers: Vec<String>,
pub who: Vec<RedPacketGot>,
}
#[derive(Clone, Debug)]
#[allow(non_snake_case)]
pub struct RedPacketStatusMsg {
pub oId: String,
pub count: u32,
pub got: u32,
pub whoGive: String,
pub whoGot: Vec<String>,
pub avatarURL20: String,
pub avatarURL48: String,
pub avatarURL210: String,
}
impl RedPacketStatusMsg {
pub fn from_value(data: &Value) -> Result<Self, Error> {
Ok(RedPacketStatusMsg {
oId: data["oId"]
.as_str()
.ok_or_else(|| Error::Parse("Missing oId in RedPacketStatusMsg".to_string()))?
.to_string(),
count: data["count"].as_u64().ok_or_else(|| {
Error::Parse("Missing or invalid count in RedPacketStatusMsg".to_string())
})? as u32,
got: data["got"].as_u64().ok_or_else(|| {
Error::Parse("Missing or invalid got in RedPacketStatusMsg".to_string())
})? as u32,
whoGive: data["whoGive"]
.as_str()
.ok_or_else(|| Error::Parse("Missing whoGive in RedPacketStatusMsg".to_string()))?
.to_string(),
whoGot: if let Some(who_got_array) = data["whoGot"].as_array() {
who_got_array
.iter()
.filter_map(|v| v.as_str().map(|s| s.to_string()))
.collect()
} else {
data["whoGot"]
.as_str()
.map(|s| vec![s.to_string()])
.unwrap_or_default()
},
avatarURL20: data["userAvatarURL20"]
.as_str()
.ok_or_else(|| {
Error::Parse("Missing userAvatarURL20 in RedPacketStatusMsg".to_string())
})?
.to_string(),
avatarURL48: data["userAvatarURL48"]
.as_str()
.ok_or_else(|| {
Error::Parse("Missing userAvatarURL48 in RedPacketStatusMsg".to_string())
})?
.to_string(),
avatarURL210: data["userAvatarURL210"]
.as_str()
.ok_or_else(|| {
Error::Parse("Missing userAvatarURL210 in RedPacketStatusMsg".to_string())
})?
.to_string(),
})
}
}
impl Default for RedPacket {
fn default() -> Self {
RedPacket {
r#type: RedPacketType::Random,
money: 32,
count: 1,
msg: "摸鱼者, 事竟成!".to_string(),
recivers: Vec::new(),
gesture: None,
}
}
}
impl RedPacket {
pub fn from_value(data: &Value) -> Result<Self, Error> {
Ok(RedPacket {
r#type: RedPacketType::from_str(
data["type"]
.as_str()
.ok_or_else(|| Error::Parse("Missing type in RedPacket".to_string()))?,
)
.map_err(|_| Error::Parse("Invalid type in RedPacket".to_string()))?,
money: data["money"]
.as_u64()
.ok_or_else(|| Error::Parse("Missing or invalid money in RedPacket".to_string()))?
as u32,
count: data["count"]
.as_u64()
.ok_or_else(|| Error::Parse("Missing or invalid count in RedPacket".to_string()))?
as u32,
msg: data["msg"]
.as_str()
.ok_or_else(|| Error::Parse("Missing msg in RedPacket".to_string()))?
.to_string(),
recivers: if let Some(recivers_array) = data["recivers"].as_array() {
recivers_array
.iter()
.filter_map(|v| v.as_str().map(|s| s.to_string()))
.collect()
} else {
Vec::new()
},
gesture: if let Some(gesture_str) = data["gesture"].as_str() {
Some(
GestureType::from_str(gesture_str)
.map_err(|_| Error::Parse("Invalid gesture in RedPacket".to_string()))?,
)
} else {
None
},
})
}
}
impl RedPacketMessage {
pub fn from_value(data: &Value) -> Result<Self, Error> {
Ok(RedPacketMessage {
msgType: data["msgType"]
.as_str()
.ok_or_else(|| Error::Parse("Missing msgType in RedPacketMessage".to_string()))?
.to_string(),
count: data["count"].as_u64().ok_or_else(|| {
Error::Parse("Missing or invalid count in RedPacketMessage".to_string())
})? as u32,
got: data["got"].as_u64().ok_or_else(|| {
Error::Parse("Missing or invalid got in RedPacketMessage".to_string())
})? as u32,
money: data["money"].as_u64().ok_or_else(|| {
Error::Parse("Missing or invalid money in RedPacketMessage".to_string())
})? as u32,
msg: data["msg"]
.as_str()
.ok_or_else(|| Error::Parse("Missing msg in RedPacketMessage".to_string()))?
.to_string(),
senderId: data["senderId"]
.as_str()
.ok_or_else(|| Error::Parse("Missing senderId in RedPacketMessage".to_string()))?
.to_string(),
GestureType: if let Some(gesture_str) = data["gesture"].as_str() {
Some(
GestureType::from_str(gesture_str).map_err(|_| {
Error::Parse("Invalid gesture in RedPacketMessage".to_string())
})?,
)
} else {
None
},
recivers: if let Some(recivers_array) = data["recivers"].as_array() {
recivers_array
.iter()
.filter_map(|v| v.as_str().map(|s| s.to_string()))
.collect()
} else {
Vec::new()
},
who: if let Some(who_array) = data["who"].as_array() {
let mut got_list = Vec::new();
for item in who_array {
got_list.push(RedPacketGot {
userId: item["userId"]
.as_str()
.ok_or_else(|| Error::Parse("Missing userId in who".to_string()))?
.to_string(),
userName: item["userName"]
.as_str()
.ok_or_else(|| Error::Parse("Missing userName in who".to_string()))?
.to_string(),
avatar: item["avatar"]
.as_str()
.ok_or_else(|| Error::Parse("Missing avatar in who".to_string()))?
.to_string(),
userMoney: item["userMoney"].as_u64().ok_or_else(|| {
Error::Parse("Missing or invalid userMoney in who".to_string())
})? as u32,
time: item["time"]
.as_str()
.ok_or_else(|| Error::Parse("Missing time in who".to_string()))?
.to_string(),
});
}
got_list
} else {
Vec::new()
},
})
}
}
impl RedPacketBase {
pub fn from_value(data: &Value) -> Result<Self, Error> {
Ok(RedPacketBase {
count: data["count"].as_u64().ok_or_else(|| {
Error::Parse("Missing or invalid count in RedPacketBase".to_string())
})? as u32,
gesture: if let Some(gesture_str) = data["gesture"].as_str() {
Some(
GestureType::from_str(gesture_str).map_err(|_| {
Error::Parse("Invalid gesture in RedPacketBase".to_string())
})?,
)
} else {
None
},
got: data["got"].as_u64().ok_or_else(|| {
Error::Parse("Missing or invalid got in RedPacketBase".to_string())
})? as u32,
msg: data["msg"]
.as_str()
.ok_or_else(|| Error::Parse("Missing msg in RedPacketBase".to_string()))?
.to_string(),
userName: data["userName"]
.as_str()
.ok_or_else(|| Error::Parse("Missing userName in RedPacketBase".to_string()))?
.to_string(),
userAvatarURL: data["userAvatarURL"]
.as_str()
.ok_or_else(|| Error::Parse("Missing userAvatarURL in RedPacketBase".to_string()))?
.to_string(),
})
}
}
impl RedPacketInfo {
pub fn from_value(data: &Value) -> Result<Self, Error> {
let info_data = &data["info"];
let info = RedPacketBase::from_value(info_data)?;
let recivers = if let Some(recivers_array) = data["recivers"].as_array() {
recivers_array
.iter()
.filter_map(|v| v.as_str().map(|s| s.to_string()))
.collect()
} else {
Vec::new()
};
let who = if let Some(who_array) = data["who"].as_array() {
let mut got_list = Vec::new();
for item in who_array {
got_list.push(RedPacketGot {
userId: item["userId"]
.as_str()
.ok_or_else(|| Error::Parse("Missing userId in who".to_string()))?
.to_string(),
userName: item["userName"]
.as_str()
.ok_or_else(|| Error::Parse("Missing userName in who".to_string()))?
.to_string(),
avatar: item["avatar"]
.as_str()
.ok_or_else(|| Error::Parse("Missing avatar in who".to_string()))?
.to_string(),
userMoney: item["userMoney"].as_u64().ok_or_else(|| {
Error::Parse("Missing or invalid userMoney in who".to_string())
})? as u32,
time: item["time"]
.as_str()
.ok_or_else(|| Error::Parse("Missing time in who".to_string()))?
.to_string(),
});
}
got_list
} else {
Vec::new()
};
Ok(RedPacketInfo {
info,
recivers,
who,
})
}
}
impl_str_enum!(GestureType {
Rock => "石头",
Scissors => "剪刀",
Paper => "布",
});
impl_str_enum!(RedPacketType {
Random => "random",
Average => "average",
Specify => "specify",
Heartbeat => "heartbeat",
RockPaperScissors => "rockPaperScissors",
});