use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RiskType {
Slide,
Gobang,
Icon,
Ai,
Svg,
}
impl RiskType {
pub fn as_str(&self) -> &'static str {
match self {
RiskType::Slide => "slide",
RiskType::Gobang => "gobang",
RiskType::Icon => "icon",
RiskType::Ai => "ai",
RiskType::Svg => "svg",
}
}
}
impl std::fmt::Display for RiskType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecCode {
pub captcha_id: String,
pub lot_number: String,
pub pass_token: String,
pub gen_time: String,
pub captcha_output: String,
}
#[derive(Debug, Deserialize)]
pub struct GeetestResponse<T> {
pub status: String,
pub data: Option<T>,
#[serde(default)]
pub code: Option<String>,
#[serde(default)]
pub msg: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct LoadResponse {
pub lot_number: String,
pub payload: String,
pub process_token: String,
pub pt: String,
pub pow_detail: PowDetail,
#[serde(default)]
pub slice: Option<String>,
#[serde(default)]
pub bg: Option<String>,
#[serde(default)]
pub ques: Option<serde_json::Value>,
#[serde(default)]
pub imgs: Option<String>,
#[serde(default)]
pub svg: Option<String>,
#[serde(default)]
pub prompt: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct PowDetail {
pub hashfunc: String,
pub version: String,
pub bits: u32,
pub datetime: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct PowResult {
pub pow_msg: String,
pub pow_sign: String,
}
#[derive(Debug, Deserialize)]
pub struct VerifyResponse {
pub seccode: Option<SecCode>,
#[serde(default)]
pub result: Option<String>,
#[serde(default, deserialize_with = "deserialize_optional_string_or_int")]
pub score: Option<String>,
#[serde(default)]
pub payload: Option<String>,
#[serde(default)]
pub process_token: Option<String>,
#[serde(default, deserialize_with = "deserialize_optional_string_or_int")]
pub payload_protocol: Option<String>,
#[serde(default)]
pub lot_number: Option<String>,
}
fn deserialize_optional_string_or_int<'de, D>(
deserializer: D,
) -> std::result::Result<Option<String>, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::{self, Visitor};
struct StringOrIntVisitor;
impl<'de> Visitor<'de> for StringOrIntVisitor {
type Value = Option<String>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a string, integer, or null")
}
fn visit_none<E>(self) -> std::result::Result<Self::Value, E>
where
E: de::Error,
{
Ok(None)
}
fn visit_unit<E>(self) -> std::result::Result<Self::Value, E>
where
E: de::Error,
{
Ok(None)
}
fn visit_str<E>(self, v: &str) -> std::result::Result<Self::Value, E>
where
E: de::Error,
{
Ok(Some(v.to_string()))
}
fn visit_string<E>(self, v: String) -> std::result::Result<Self::Value, E>
where
E: de::Error,
{
Ok(Some(v))
}
fn visit_i64<E>(self, v: i64) -> std::result::Result<Self::Value, E>
where
E: de::Error,
{
Ok(Some(v.to_string()))
}
fn visit_u64<E>(self, v: u64) -> std::result::Result<Self::Value, E>
where
E: de::Error,
{
Ok(Some(v.to_string()))
}
}
deserializer.deserialize_any(StringOrIntVisitor)
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CachedConstants {
pub version: String,
pub fetched_at: chrono::DateTime<chrono::Utc>,
pub mapping: String,
pub abo: HashMap<String, String>,
pub device_id: String,
}
#[derive(Debug, Clone)]
pub struct Constants {
pub mapping: String,
pub abo: HashMap<String, String>,
pub device_id: String,
}
impl From<CachedConstants> for Constants {
fn from(cached: CachedConstants) -> Self {
Self {
mapping: cached.mapping,
abo: cached.abo,
device_id: cached.device_id,
}
}
}