1069 lines
36 KiB
Rust
1069 lines
36 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
|
|
pub const RUNTIME_PLATFORM_THEME_LIGHT: &str = "light";
|
|
pub const RUNTIME_PLATFORM_THEME_DARK: &str = "dark";
|
|
pub const SAVE_SNAPSHOT_VERSION: u32 = 2;
|
|
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_SNAPSHOT_SYNC: &str = "snapshot_sync";
|
|
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_POINTS_RECHARGE: &str = "points_recharge";
|
|
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_INVITE_INVITER_REWARD: &str = "invite_inviter_reward";
|
|
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_INVITE_INVITEE_REWARD: &str = "invite_invitee_reward";
|
|
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_ASSET_OPERATION_CONSUME: &str =
|
|
"asset_operation_consume";
|
|
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_ASSET_OPERATION_REFUND: &str = "asset_operation_refund";
|
|
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_REDEEM_CODE_REWARD: &str = "redeem_code_reward";
|
|
pub const BROWSE_HISTORY_THEME_MODE_MARTIAL: &str = "martial";
|
|
pub const BROWSE_HISTORY_THEME_MODE_ARCANE: &str = "arcane";
|
|
pub const BROWSE_HISTORY_THEME_MODE_MACHINA: &str = "machina";
|
|
pub const BROWSE_HISTORY_THEME_MODE_TIDE: &str = "tide";
|
|
pub const BROWSE_HISTORY_THEME_MODE_RIFT: &str = "rift";
|
|
pub const BROWSE_HISTORY_THEME_MODE_MYTHIC: &str = "mythic";
|
|
pub const CUSTOM_WORLD_VISIBILITY_DRAFT: &str = "draft";
|
|
pub const CUSTOM_WORLD_VISIBILITY_PUBLISHED: &str = "published";
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct RuntimeSettingsResponse {
|
|
pub music_volume: f32,
|
|
pub platform_theme: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct PutRuntimeSettingsRequest {
|
|
pub music_volume: f32,
|
|
pub platform_theme: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct SavedGameSnapshotResponse {
|
|
pub version: u32,
|
|
pub saved_at: String,
|
|
pub game_state: serde_json::Value,
|
|
pub bottom_tab: String,
|
|
pub current_story: Option<serde_json::Value>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct PutSavedGameSnapshotRequest {
|
|
pub game_state: serde_json::Value,
|
|
pub bottom_tab: String,
|
|
#[serde(default)]
|
|
pub current_story: Option<serde_json::Value>,
|
|
#[serde(default)]
|
|
pub saved_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
|
pub struct PutRuntimeSaveCheckpointRequest {
|
|
pub session_id: String,
|
|
pub bottom_tab: String,
|
|
#[serde(default)]
|
|
pub saved_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct BasicOkResponse {
|
|
pub ok: bool,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct PlatformBrowseHistoryEntryResponse {
|
|
pub owner_user_id: String,
|
|
pub profile_id: String,
|
|
pub world_name: String,
|
|
pub subtitle: String,
|
|
pub summary_text: String,
|
|
pub cover_image_src: Option<String>,
|
|
pub theme_mode: String,
|
|
pub author_display_name: String,
|
|
pub visited_at: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct PlatformBrowseHistoryWriteEntryRequest {
|
|
pub owner_user_id: String,
|
|
pub profile_id: String,
|
|
pub world_name: String,
|
|
#[serde(default)]
|
|
pub subtitle: Option<String>,
|
|
#[serde(default)]
|
|
pub summary_text: Option<String>,
|
|
#[serde(default)]
|
|
pub cover_image_src: Option<String>,
|
|
#[serde(default)]
|
|
pub theme_mode: Option<String>,
|
|
#[serde(default)]
|
|
pub author_display_name: Option<String>,
|
|
#[serde(default)]
|
|
pub visited_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct PlatformBrowseHistoryBatchSyncRequest {
|
|
pub entries: Vec<PlatformBrowseHistoryWriteEntryRequest>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(untagged)]
|
|
pub enum PlatformBrowseHistoryUpsertRequest {
|
|
Single(PlatformBrowseHistoryWriteEntryRequest),
|
|
Batch(PlatformBrowseHistoryBatchSyncRequest),
|
|
}
|
|
|
|
impl PlatformBrowseHistoryUpsertRequest {
|
|
pub fn into_entries(self) -> Vec<PlatformBrowseHistoryWriteEntryRequest> {
|
|
match self {
|
|
Self::Single(entry) => vec![entry],
|
|
Self::Batch(batch) => batch.entries,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct PlatformBrowseHistoryResponse {
|
|
pub entries: Vec<PlatformBrowseHistoryEntryResponse>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileDashboardSummaryResponse {
|
|
pub wallet_balance: u64,
|
|
pub total_play_time_ms: u64,
|
|
pub played_world_count: u32,
|
|
pub updated_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileWalletLedgerEntryResponse {
|
|
pub id: String,
|
|
pub amount_delta: i64,
|
|
pub balance_after: u64,
|
|
pub source_type: String,
|
|
pub created_at: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileWalletLedgerResponse {
|
|
pub entries: Vec<ProfileWalletLedgerEntryResponse>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileRechargeProductResponse {
|
|
pub product_id: String,
|
|
pub title: String,
|
|
pub price_cents: u64,
|
|
pub kind: String,
|
|
pub points_amount: u64,
|
|
pub bonus_points: u64,
|
|
pub duration_days: u32,
|
|
pub badge_label: String,
|
|
pub description: String,
|
|
pub tier: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileMembershipBenefitResponse {
|
|
pub benefit_name: String,
|
|
pub normal_value: String,
|
|
pub month_value: String,
|
|
pub season_value: String,
|
|
pub year_value: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileMembershipResponse {
|
|
pub status: String,
|
|
pub tier: String,
|
|
pub started_at: Option<String>,
|
|
pub expires_at: Option<String>,
|
|
pub updated_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileRechargeOrderResponse {
|
|
pub order_id: String,
|
|
pub product_id: String,
|
|
pub product_title: String,
|
|
pub kind: String,
|
|
pub amount_cents: u64,
|
|
pub status: String,
|
|
pub payment_channel: String,
|
|
pub paid_at: String,
|
|
pub created_at: String,
|
|
pub points_delta: i64,
|
|
pub membership_expires_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileRechargeCenterResponse {
|
|
pub wallet_balance: u64,
|
|
pub membership: ProfileMembershipResponse,
|
|
pub point_products: Vec<ProfileRechargeProductResponse>,
|
|
pub membership_products: Vec<ProfileRechargeProductResponse>,
|
|
pub benefits: Vec<ProfileMembershipBenefitResponse>,
|
|
pub latest_order: Option<ProfileRechargeOrderResponse>,
|
|
pub has_points_recharged: bool,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CreateProfileRechargeOrderRequest {
|
|
pub product_id: String,
|
|
#[serde(default)]
|
|
pub payment_channel: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CreateProfileRechargeOrderResponse {
|
|
pub order: ProfileRechargeOrderResponse,
|
|
pub center: ProfileRechargeCenterResponse,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileReferralInviteCenterResponse {
|
|
pub invite_code: String,
|
|
pub invite_link_path: String,
|
|
pub invited_count: u32,
|
|
pub rewarded_invite_count: u32,
|
|
pub today_inviter_reward_count: u32,
|
|
pub today_inviter_reward_remaining: u32,
|
|
pub reward_points: u64,
|
|
pub has_redeemed_code: bool,
|
|
pub bound_inviter_user_id: Option<String>,
|
|
pub bound_at: Option<String>,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct RedeemProfileReferralInviteCodeRequest {
|
|
pub invite_code: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct RedeemProfileReferralInviteCodeResponse {
|
|
pub center: ProfileReferralInviteCenterResponse,
|
|
pub invitee_reward_granted: bool,
|
|
pub inviter_reward_granted: bool,
|
|
pub invitee_balance_after: u64,
|
|
pub inviter_balance_after: u64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct RedeemProfileRewardCodeRequest {
|
|
pub code: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct RedeemProfileRewardCodeResponse {
|
|
pub wallet_balance: u64,
|
|
pub amount_granted: u64,
|
|
pub ledger_entry: ProfileWalletLedgerEntryResponse,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct AdminUpsertProfileRedeemCodeRequest {
|
|
pub code: String,
|
|
pub mode: String,
|
|
pub reward_points: u64,
|
|
pub max_uses: u32,
|
|
#[serde(default = "default_true")]
|
|
pub enabled: bool,
|
|
#[serde(default)]
|
|
pub allowed_user_ids: Vec<String>,
|
|
#[serde(default)]
|
|
pub allowed_public_user_codes: Vec<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct AdminDisableProfileRedeemCodeRequest {
|
|
pub code: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileRedeemCodeAdminResponse {
|
|
pub code: String,
|
|
pub mode: String,
|
|
pub reward_points: u64,
|
|
pub max_uses: u32,
|
|
pub global_used_count: u32,
|
|
pub enabled: bool,
|
|
pub allowed_user_ids: Vec<String>,
|
|
pub created_by: String,
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
fn default_true() -> bool {
|
|
true
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfilePlayedWorkSummaryResponse {
|
|
pub world_key: String,
|
|
pub owner_user_id: Option<String>,
|
|
pub profile_id: Option<String>,
|
|
pub world_type: Option<String>,
|
|
pub world_title: String,
|
|
pub world_subtitle: String,
|
|
pub first_played_at: String,
|
|
pub last_played_at: String,
|
|
pub last_observed_play_time_ms: u64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfilePlayStatsResponse {
|
|
pub total_play_time_ms: u64,
|
|
pub played_works: Vec<ProfilePlayedWorkSummaryResponse>,
|
|
pub updated_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileSaveArchiveSummaryResponse {
|
|
pub world_key: String,
|
|
pub owner_user_id: Option<String>,
|
|
pub profile_id: Option<String>,
|
|
pub world_type: Option<String>,
|
|
pub world_name: String,
|
|
pub subtitle: String,
|
|
pub summary_text: String,
|
|
pub cover_image_src: Option<String>,
|
|
pub last_played_at: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileSaveArchiveListResponse {
|
|
pub entries: Vec<ProfileSaveArchiveSummaryResponse>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ProfileSaveArchiveResumeResponse {
|
|
pub entry: ProfileSaveArchiveSummaryResponse,
|
|
pub snapshot: SavedGameSnapshotResponse,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct RuntimeInventorySlotResponse {
|
|
pub slot_id: String,
|
|
pub container_kind: String,
|
|
pub slot_key: String,
|
|
pub item_id: String,
|
|
pub category: String,
|
|
pub name: String,
|
|
pub description: Option<String>,
|
|
pub quantity: u32,
|
|
pub rarity: String,
|
|
pub tags: Vec<String>,
|
|
pub stackable: bool,
|
|
pub stack_key: String,
|
|
pub equipment_slot_id: Option<String>,
|
|
pub source_kind: String,
|
|
pub source_reference_id: Option<String>,
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct RuntimeInventoryStateResponse {
|
|
pub runtime_session_id: String,
|
|
pub actor_user_id: String,
|
|
pub backpack_items: Vec<RuntimeInventorySlotResponse>,
|
|
pub equipment_items: Vec<RuntimeInventorySlotResponse>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldProfileUpsertRequest {
|
|
pub profile: serde_json::Value,
|
|
pub source_agent_session_id: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct GenerateCustomWorldProfileRequest {
|
|
pub setting_text: String,
|
|
#[serde(default)]
|
|
pub creator_intent: Option<serde_json::Value>,
|
|
#[serde(default)]
|
|
pub generation_mode: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldLibraryEntryResponse {
|
|
pub owner_user_id: String,
|
|
pub profile_id: String,
|
|
pub public_work_code: Option<String>,
|
|
pub author_public_user_code: Option<String>,
|
|
pub profile: serde_json::Value,
|
|
pub visibility: String,
|
|
pub published_at: Option<String>,
|
|
pub updated_at: String,
|
|
pub author_display_name: String,
|
|
pub world_name: String,
|
|
pub subtitle: String,
|
|
pub summary_text: String,
|
|
pub cover_image_src: Option<String>,
|
|
pub theme_mode: String,
|
|
pub playable_npc_count: u32,
|
|
pub landmark_count: u32,
|
|
#[serde(default)]
|
|
pub play_count: u32,
|
|
#[serde(default)]
|
|
pub remix_count: u32,
|
|
#[serde(default)]
|
|
pub like_count: u32,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldGalleryCardResponse {
|
|
pub owner_user_id: String,
|
|
pub profile_id: String,
|
|
pub public_work_code: String,
|
|
pub author_public_user_code: String,
|
|
pub visibility: String,
|
|
pub published_at: Option<String>,
|
|
pub updated_at: String,
|
|
pub author_display_name: String,
|
|
pub world_name: String,
|
|
pub subtitle: String,
|
|
pub summary_text: String,
|
|
pub cover_image_src: Option<String>,
|
|
pub theme_mode: String,
|
|
pub playable_npc_count: u32,
|
|
pub landmark_count: u32,
|
|
#[serde(default)]
|
|
pub play_count: u32,
|
|
#[serde(default)]
|
|
pub remix_count: u32,
|
|
#[serde(default)]
|
|
pub like_count: u32,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldLibraryResponse {
|
|
pub entries: Vec<CustomWorldLibraryEntryResponse>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldLibraryMutationResponse {
|
|
pub entry: CustomWorldLibraryEntryResponse,
|
|
pub entries: Vec<CustomWorldLibraryEntryResponse>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldGalleryResponse {
|
|
pub entries: Vec<CustomWorldGalleryCardResponse>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldGalleryDetailResponse {
|
|
pub entry: CustomWorldLibraryEntryResponse,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldWorkSummaryResponse {
|
|
pub work_id: String,
|
|
pub source_type: String,
|
|
pub status: String,
|
|
pub title: String,
|
|
pub subtitle: String,
|
|
pub summary: String,
|
|
pub cover_image_src: Option<String>,
|
|
#[serde(default)]
|
|
pub cover_render_mode: Option<String>,
|
|
#[serde(default)]
|
|
pub cover_character_image_srcs: Vec<String>,
|
|
pub updated_at: String,
|
|
pub published_at: Option<String>,
|
|
pub stage: Option<String>,
|
|
pub stage_label: Option<String>,
|
|
pub playable_npc_count: u32,
|
|
pub landmark_count: u32,
|
|
pub role_visual_ready_count: Option<u32>,
|
|
pub role_animation_ready_count: Option<u32>,
|
|
pub role_asset_summary_label: Option<String>,
|
|
pub session_id: Option<String>,
|
|
pub profile_id: Option<String>,
|
|
pub can_resume: bool,
|
|
pub can_enter_world: bool,
|
|
pub blocker_count: u32,
|
|
pub publish_ready: bool,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldWorksResponse {
|
|
pub items: Vec<CustomWorldWorkSummaryResponse>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CreateCustomWorldAgentSessionRequest {
|
|
#[serde(default)]
|
|
pub seed_text: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct SendCustomWorldAgentMessageRequest {
|
|
pub client_message_id: String,
|
|
pub text: String,
|
|
#[serde(default)]
|
|
pub quick_fill_requested: Option<bool>,
|
|
#[serde(default)]
|
|
pub focus_card_id: Option<String>,
|
|
#[serde(default)]
|
|
pub selected_card_ids: Option<Vec<String>>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldAgentMessageResponse {
|
|
pub id: String,
|
|
pub role: String,
|
|
pub kind: String,
|
|
pub text: String,
|
|
pub created_at: String,
|
|
pub related_operation_id: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldAgentOperationResponse {
|
|
pub operation_id: String,
|
|
#[serde(rename = "type")]
|
|
pub operation_type: String,
|
|
pub status: String,
|
|
pub phase_label: String,
|
|
pub phase_detail: String,
|
|
pub progress: u32,
|
|
pub error: Option<String>,
|
|
pub started_at: Option<String>,
|
|
pub updated_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldDraftCardSummaryResponse {
|
|
pub id: String,
|
|
pub kind: String,
|
|
pub title: String,
|
|
pub subtitle: String,
|
|
pub summary: String,
|
|
pub status: String,
|
|
pub linked_ids: Vec<String>,
|
|
pub warning_count: u32,
|
|
pub asset_status: Option<String>,
|
|
pub asset_status_label: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldDraftCardDetailSectionResponse {
|
|
pub id: String,
|
|
pub label: String,
|
|
pub value: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldDraftCardDetailResponse {
|
|
pub id: String,
|
|
pub kind: String,
|
|
pub title: String,
|
|
pub sections: Vec<CustomWorldDraftCardDetailSectionResponse>,
|
|
pub linked_ids: Vec<String>,
|
|
pub locked: bool,
|
|
pub editable: bool,
|
|
pub editable_section_ids: Vec<String>,
|
|
pub warning_messages: Vec<String>,
|
|
pub asset_status: Option<String>,
|
|
pub asset_status_label: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldAgentCardDetailResponse {
|
|
pub card: CustomWorldDraftCardDetailResponse,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldAgentCheckpointResponse {
|
|
pub checkpoint_id: String,
|
|
pub created_at: String,
|
|
pub label: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldSupportedActionResponse {
|
|
pub action: String,
|
|
pub enabled: bool,
|
|
pub reason: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldResultPreviewBlockerResponse {
|
|
pub id: String,
|
|
pub code: String,
|
|
pub message: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldPublishGateResponse {
|
|
pub profile_id: String,
|
|
pub blockers: Vec<CustomWorldResultPreviewBlockerResponse>,
|
|
pub blocker_count: u32,
|
|
pub publish_ready: bool,
|
|
pub can_enter_world: bool,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldCreationResultViewResponse {
|
|
pub session: CustomWorldAgentSessionSnapshotResponse,
|
|
pub profile: Option<serde_json::Value>,
|
|
pub profile_source: String,
|
|
pub target_stage: String,
|
|
pub generation_view_source: Option<String>,
|
|
pub result_view_source: Option<String>,
|
|
pub can_autosave_library: bool,
|
|
pub can_sync_result_profile: bool,
|
|
pub publish_ready: bool,
|
|
pub can_enter_world: bool,
|
|
pub blocker_count: u32,
|
|
pub recovery_action: String,
|
|
pub recovery_reason: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldAgentSessionSnapshotResponse {
|
|
pub session_id: String,
|
|
pub current_turn: u32,
|
|
pub anchor_content: serde_json::Value,
|
|
pub progress_percent: u32,
|
|
pub last_assistant_reply: Option<String>,
|
|
pub stage: String,
|
|
pub focus_card_id: Option<String>,
|
|
pub creator_intent: serde_json::Value,
|
|
pub creator_intent_readiness: serde_json::Value,
|
|
pub anchor_pack: serde_json::Value,
|
|
pub lock_state: serde_json::Value,
|
|
pub draft_profile: serde_json::Value,
|
|
pub messages: Vec<CustomWorldAgentMessageResponse>,
|
|
pub draft_cards: Vec<CustomWorldDraftCardSummaryResponse>,
|
|
pub pending_clarifications: Vec<serde_json::Value>,
|
|
pub suggested_actions: Vec<serde_json::Value>,
|
|
pub recommended_replies: Vec<String>,
|
|
pub quality_findings: Vec<serde_json::Value>,
|
|
pub asset_coverage: serde_json::Value,
|
|
pub checkpoints: Vec<CustomWorldAgentCheckpointResponse>,
|
|
pub supported_actions: Vec<CustomWorldSupportedActionResponse>,
|
|
pub publish_gate: Option<CustomWorldPublishGateResponse>,
|
|
pub result_preview: Option<serde_json::Value>,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct CustomWorldAgentSessionResponse {
|
|
pub session: CustomWorldAgentSessionSnapshotResponse,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ExecuteCustomWorldAgentActionRequest {
|
|
pub action: String,
|
|
#[serde(default)]
|
|
pub profile_id: Option<String>,
|
|
#[serde(default)]
|
|
pub draft_profile: Option<serde_json::Value>,
|
|
#[serde(default)]
|
|
pub legacy_result_profile: Option<serde_json::Value>,
|
|
#[serde(default)]
|
|
pub setting_text: Option<String>,
|
|
#[serde(default)]
|
|
pub card_id: Option<String>,
|
|
#[serde(default)]
|
|
pub sections: Option<Vec<ExecuteCustomWorldAgentDraftCardSectionPatch>>,
|
|
#[serde(default)]
|
|
pub profile: Option<serde_json::Value>,
|
|
#[serde(default)]
|
|
pub count: Option<u32>,
|
|
#[serde(default)]
|
|
pub role_type: Option<String>,
|
|
#[serde(default)]
|
|
pub prompt_text: Option<String>,
|
|
#[serde(default)]
|
|
pub anchor_card_ids: Option<Vec<String>>,
|
|
#[serde(default)]
|
|
pub role_ids: Option<Vec<String>>,
|
|
#[serde(default)]
|
|
pub role_id: Option<String>,
|
|
#[serde(default)]
|
|
pub portrait_path: Option<String>,
|
|
#[serde(default)]
|
|
pub generated_visual_asset_id: Option<String>,
|
|
#[serde(default)]
|
|
pub generated_animation_set_id: Option<String>,
|
|
#[serde(default)]
|
|
pub animation_map: Option<serde_json::Value>,
|
|
#[serde(default)]
|
|
pub scene_ids: Option<Vec<String>>,
|
|
#[serde(default)]
|
|
pub scene_id: Option<String>,
|
|
#[serde(default)]
|
|
pub scene_kind: Option<String>,
|
|
#[serde(default)]
|
|
pub image_src: Option<String>,
|
|
#[serde(default)]
|
|
pub generated_scene_asset_id: Option<String>,
|
|
#[serde(default)]
|
|
pub generated_scene_prompt: Option<String>,
|
|
#[serde(default)]
|
|
pub generated_scene_model: Option<String>,
|
|
#[serde(default)]
|
|
pub checkpoint_id: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ExecuteCustomWorldAgentDraftCardSectionPatch {
|
|
pub section_id: String,
|
|
pub value: String,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use serde_json::json;
|
|
|
|
#[test]
|
|
fn runtime_settings_request_uses_camel_case_fields() {
|
|
let payload = serde_json::to_value(PutRuntimeSettingsRequest {
|
|
music_volume: 0.42,
|
|
platform_theme: RUNTIME_PLATFORM_THEME_LIGHT.to_string(),
|
|
})
|
|
.expect("payload should serialize");
|
|
|
|
assert_eq!(payload["platformTheme"], json!("light"));
|
|
let music_volume = payload["musicVolume"]
|
|
.as_f64()
|
|
.expect("musicVolume should serialize as number");
|
|
assert!((music_volume - 0.42).abs() < 0.0001);
|
|
}
|
|
|
|
#[test]
|
|
fn browse_history_response_uses_camel_case_fields() {
|
|
let payload = serde_json::to_value(PlatformBrowseHistoryResponse {
|
|
entries: vec![PlatformBrowseHistoryEntryResponse {
|
|
owner_user_id: "owner-1".to_string(),
|
|
profile_id: "profile-1".to_string(),
|
|
world_name: "世界".to_string(),
|
|
subtitle: "".to_string(),
|
|
summary_text: "".to_string(),
|
|
cover_image_src: None,
|
|
theme_mode: BROWSE_HISTORY_THEME_MODE_MYTHIC.to_string(),
|
|
author_display_name: "玩家".to_string(),
|
|
visited_at: "2026-04-21T00:00:00Z".to_string(),
|
|
}],
|
|
})
|
|
.expect("payload should serialize");
|
|
|
|
assert_eq!(payload["entries"][0]["ownerUserId"], json!("owner-1"));
|
|
assert_eq!(payload["entries"][0]["themeMode"], json!("mythic"));
|
|
assert_eq!(
|
|
payload["entries"][0]["visitedAt"],
|
|
json!("2026-04-21T00:00:00Z")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn browse_history_upsert_request_accepts_single_or_batch_shape() {
|
|
let single: PlatformBrowseHistoryUpsertRequest = serde_json::from_value(json!({
|
|
"ownerUserId": "owner-1",
|
|
"profileId": "profile-1",
|
|
"worldName": "世界"
|
|
}))
|
|
.expect("single shape should deserialize");
|
|
let batch: PlatformBrowseHistoryUpsertRequest = serde_json::from_value(json!({
|
|
"entries": [{
|
|
"ownerUserId": "owner-1",
|
|
"profileId": "profile-1",
|
|
"worldName": "世界"
|
|
}]
|
|
}))
|
|
.expect("batch shape should deserialize");
|
|
|
|
assert_eq!(single.into_entries().len(), 1);
|
|
assert_eq!(batch.into_entries().len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn profile_dashboard_response_uses_camel_case_fields() {
|
|
let payload = serde_json::to_value(ProfileDashboardSummaryResponse {
|
|
wallet_balance: 8,
|
|
total_play_time_ms: 16,
|
|
played_world_count: 3,
|
|
updated_at: Some("2026-04-22T10:00:00Z".to_string()),
|
|
})
|
|
.expect("payload should serialize");
|
|
|
|
assert_eq!(payload["walletBalance"], json!(8));
|
|
assert_eq!(payload["totalPlayTimeMs"], json!(16));
|
|
assert_eq!(payload["playedWorldCount"], json!(3));
|
|
assert_eq!(payload["updatedAt"], json!("2026-04-22T10:00:00Z"));
|
|
}
|
|
|
|
#[test]
|
|
fn profile_wallet_ledger_response_uses_camel_case_fields() {
|
|
let payload = serde_json::to_value(ProfileWalletLedgerResponse {
|
|
entries: vec![
|
|
ProfileWalletLedgerEntryResponse {
|
|
id: "ledger-1".to_string(),
|
|
amount_delta: 12,
|
|
balance_after: 80,
|
|
source_type: PROFILE_WALLET_LEDGER_SOURCE_TYPE_SNAPSHOT_SYNC.to_string(),
|
|
created_at: "2026-04-22T10:00:00Z".to_string(),
|
|
},
|
|
ProfileWalletLedgerEntryResponse {
|
|
id: "ledger-2".to_string(),
|
|
amount_delta: 30,
|
|
balance_after: 110,
|
|
source_type: PROFILE_WALLET_LEDGER_SOURCE_TYPE_INVITE_INVITER_REWARD
|
|
.to_string(),
|
|
created_at: "2026-04-22T10:01:00Z".to_string(),
|
|
},
|
|
ProfileWalletLedgerEntryResponse {
|
|
id: "ledger-3".to_string(),
|
|
amount_delta: 30,
|
|
balance_after: 140,
|
|
source_type: PROFILE_WALLET_LEDGER_SOURCE_TYPE_INVITE_INVITEE_REWARD
|
|
.to_string(),
|
|
created_at: "2026-04-22T10:02:00Z".to_string(),
|
|
},
|
|
ProfileWalletLedgerEntryResponse {
|
|
id: "ledger-4".to_string(),
|
|
amount_delta: 60,
|
|
balance_after: 200,
|
|
source_type: PROFILE_WALLET_LEDGER_SOURCE_TYPE_POINTS_RECHARGE.to_string(),
|
|
created_at: "2026-04-22T10:03:00Z".to_string(),
|
|
},
|
|
ProfileWalletLedgerEntryResponse {
|
|
id: "ledger-5".to_string(),
|
|
amount_delta: -1,
|
|
balance_after: 199,
|
|
source_type: PROFILE_WALLET_LEDGER_SOURCE_TYPE_ASSET_OPERATION_CONSUME
|
|
.to_string(),
|
|
created_at: "2026-04-22T10:04:00Z".to_string(),
|
|
},
|
|
ProfileWalletLedgerEntryResponse {
|
|
id: "ledger-6".to_string(),
|
|
amount_delta: 1,
|
|
balance_after: 200,
|
|
source_type: PROFILE_WALLET_LEDGER_SOURCE_TYPE_ASSET_OPERATION_REFUND
|
|
.to_string(),
|
|
created_at: "2026-04-22T10:05:00Z".to_string(),
|
|
},
|
|
],
|
|
})
|
|
.expect("payload should serialize");
|
|
|
|
assert_eq!(payload["entries"][0]["amountDelta"], json!(12));
|
|
assert_eq!(payload["entries"][0]["balanceAfter"], json!(80));
|
|
assert_eq!(
|
|
payload["entries"][0]["sourceType"],
|
|
json!(PROFILE_WALLET_LEDGER_SOURCE_TYPE_SNAPSHOT_SYNC)
|
|
);
|
|
assert_eq!(
|
|
payload["entries"][1]["sourceType"],
|
|
json!(PROFILE_WALLET_LEDGER_SOURCE_TYPE_INVITE_INVITER_REWARD)
|
|
);
|
|
assert_eq!(
|
|
payload["entries"][2]["sourceType"],
|
|
json!(PROFILE_WALLET_LEDGER_SOURCE_TYPE_INVITE_INVITEE_REWARD)
|
|
);
|
|
assert_eq!(
|
|
payload["entries"][3]["sourceType"],
|
|
json!(PROFILE_WALLET_LEDGER_SOURCE_TYPE_POINTS_RECHARGE)
|
|
);
|
|
assert_eq!(
|
|
payload["entries"][4]["sourceType"],
|
|
json!(PROFILE_WALLET_LEDGER_SOURCE_TYPE_ASSET_OPERATION_CONSUME)
|
|
);
|
|
assert_eq!(
|
|
payload["entries"][5]["sourceType"],
|
|
json!(PROFILE_WALLET_LEDGER_SOURCE_TYPE_ASSET_OPERATION_REFUND)
|
|
);
|
|
assert_eq!(
|
|
payload["entries"][0]["createdAt"],
|
|
json!("2026-04-22T10:00:00Z")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn profile_recharge_center_response_uses_camel_case_fields() {
|
|
let payload = serde_json::to_value(ProfileRechargeCenterResponse {
|
|
wallet_balance: 29,
|
|
membership: ProfileMembershipResponse {
|
|
status: "active".to_string(),
|
|
tier: "month".to_string(),
|
|
started_at: Some("2026-04-25T10:00:00Z".to_string()),
|
|
expires_at: Some("2026-05-25T10:00:00Z".to_string()),
|
|
updated_at: Some("2026-04-25T10:00:00Z".to_string()),
|
|
},
|
|
point_products: vec![ProfileRechargeProductResponse {
|
|
product_id: "points_60".to_string(),
|
|
title: "60叙世币".to_string(),
|
|
price_cents: 600,
|
|
kind: "points".to_string(),
|
|
points_amount: 60,
|
|
bonus_points: 60,
|
|
duration_days: 0,
|
|
badge_label: "首充双倍".to_string(),
|
|
description: "首充送60叙世币".to_string(),
|
|
tier: "normal".to_string(),
|
|
}],
|
|
membership_products: vec![],
|
|
benefits: vec![],
|
|
latest_order: None,
|
|
has_points_recharged: false,
|
|
})
|
|
.expect("payload should serialize");
|
|
|
|
assert_eq!(payload["walletBalance"], json!(29));
|
|
assert_eq!(
|
|
payload["membership"]["expiresAt"],
|
|
json!("2026-05-25T10:00:00Z")
|
|
);
|
|
assert_eq!(payload["pointProducts"][0]["productId"], json!("points_60"));
|
|
assert_eq!(payload["pointProducts"][0]["title"], json!("60叙世币"));
|
|
assert_eq!(payload["pointProducts"][0]["priceCents"], json!(600));
|
|
assert_eq!(
|
|
payload["pointProducts"][0]["description"],
|
|
json!("首充送60叙世币")
|
|
);
|
|
assert_eq!(payload["hasPointsRecharged"], json!(false));
|
|
}
|
|
|
|
#[test]
|
|
fn create_profile_recharge_order_request_accepts_optional_channel() {
|
|
let payload: CreateProfileRechargeOrderRequest = serde_json::from_value(json!({
|
|
"productId": "member_month"
|
|
}))
|
|
.expect("request should deserialize");
|
|
|
|
assert_eq!(payload.product_id, "member_month");
|
|
assert_eq!(payload.payment_channel, None);
|
|
}
|
|
|
|
#[test]
|
|
fn profile_play_stats_response_uses_camel_case_fields() {
|
|
let payload = serde_json::to_value(ProfilePlayStatsResponse {
|
|
total_play_time_ms: 18,
|
|
played_works: vec![ProfilePlayedWorkSummaryResponse {
|
|
world_key: "builtin:WUXIA".to_string(),
|
|
owner_user_id: None,
|
|
profile_id: None,
|
|
world_type: Some("WUXIA".to_string()),
|
|
world_title: "武侠世界".to_string(),
|
|
world_subtitle: "".to_string(),
|
|
first_played_at: "2026-04-20T10:00:00Z".to_string(),
|
|
last_played_at: "2026-04-22T10:00:00Z".to_string(),
|
|
last_observed_play_time_ms: 1200,
|
|
}],
|
|
updated_at: Some("2026-04-22T10:00:00Z".to_string()),
|
|
})
|
|
.expect("payload should serialize");
|
|
|
|
assert_eq!(payload["totalPlayTimeMs"], json!(18));
|
|
assert_eq!(
|
|
payload["playedWorks"][0]["worldKey"],
|
|
json!("builtin:WUXIA")
|
|
);
|
|
assert_eq!(
|
|
payload["playedWorks"][0]["lastObservedPlayTimeMs"],
|
|
json!(1200)
|
|
);
|
|
assert_eq!(payload["updatedAt"], json!("2026-04-22T10:00:00Z"));
|
|
}
|
|
|
|
#[test]
|
|
fn runtime_inventory_state_response_uses_camel_case_fields() {
|
|
let payload = serde_json::to_value(RuntimeInventoryStateResponse {
|
|
runtime_session_id: "runtime_001".to_string(),
|
|
actor_user_id: "user_001".to_string(),
|
|
backpack_items: vec![RuntimeInventorySlotResponse {
|
|
slot_id: "invslot_001".to_string(),
|
|
container_kind: "backpack".to_string(),
|
|
slot_key: "invslot_001".to_string(),
|
|
item_id: "consumable_heal_potion".to_string(),
|
|
category: "消耗品".to_string(),
|
|
name: "疗伤药".to_string(),
|
|
description: Some("用于恢复少量气血。".to_string()),
|
|
quantity: 2,
|
|
rarity: "common".to_string(),
|
|
tags: vec!["healing".to_string()],
|
|
stackable: true,
|
|
stack_key: "heal_potion".to_string(),
|
|
equipment_slot_id: None,
|
|
source_kind: "treasure_reward".to_string(),
|
|
source_reference_id: Some("treasure_001".to_string()),
|
|
created_at: "2026-04-22T10:00:00Z".to_string(),
|
|
updated_at: "2026-04-22T10:01:00Z".to_string(),
|
|
}],
|
|
equipment_items: vec![],
|
|
})
|
|
.expect("payload should serialize");
|
|
|
|
assert_eq!(payload["runtimeSessionId"], json!("runtime_001"));
|
|
assert_eq!(payload["actorUserId"], json!("user_001"));
|
|
assert_eq!(payload["backpackItems"][0]["slotId"], json!("invslot_001"));
|
|
assert_eq!(
|
|
payload["backpackItems"][0]["sourceKind"],
|
|
json!("treasure_reward")
|
|
);
|
|
}
|
|
}
|