Add skill for gameplay entry type workflows

This commit is contained in:
2026-05-04 02:32:38 +08:00
parent 49aad7311c
commit 34aecdddf1
77 changed files with 5997 additions and 110 deletions

View File

@@ -15,6 +15,16 @@ pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_ASSET_OPERATION_REFUND: &str = "asse
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_REDEEM_CODE_REWARD: &str = "redeem_code_reward";
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_PUZZLE_AUTHOR_INCENTIVE_CLAIM: &str =
"puzzle_author_incentive_claim";
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_DAILY_TASK_REWARD: &str = "daily_task_reward";
pub const PROFILE_TASK_CYCLE_DAILY: &str = "daily";
pub const PROFILE_TASK_STATUS_INCOMPLETE: &str = "incomplete";
pub const PROFILE_TASK_STATUS_CLAIMABLE: &str = "claimable";
pub const PROFILE_TASK_STATUS_CLAIMED: &str = "claimed";
pub const PROFILE_TASK_STATUS_DISABLED: &str = "disabled";
pub const TRACKING_SCOPE_KIND_SITE: &str = "site";
pub const TRACKING_SCOPE_KIND_WORK: &str = "work";
pub const TRACKING_SCOPE_KIND_MODULE: &str = "module";
pub const TRACKING_SCOPE_KIND_USER: &str = "user";
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";
@@ -295,6 +305,92 @@ pub struct RedeemProfileRewardCodeResponse {
pub ledger_entry: ProfileWalletLedgerEntryResponse,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ProfileTaskItemResponse {
pub task_id: String,
pub title: String,
pub description: String,
pub event_key: String,
pub cycle: String,
pub threshold: u32,
pub progress_count: u32,
pub reward_points: u64,
pub status: String,
pub day_key: i64,
pub claimed_at: Option<String>,
pub updated_at: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ProfileTaskCenterResponse {
pub day_key: i64,
pub wallet_balance: u64,
pub tasks: Vec<ProfileTaskItemResponse>,
pub updated_at: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ClaimProfileTaskRewardResponse {
pub task_id: String,
pub day_key: i64,
pub reward_points: u64,
pub wallet_balance: u64,
pub ledger_entry: ProfileWalletLedgerEntryResponse,
pub center: ProfileTaskCenterResponse,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ProfileTaskConfigAdminResponse {
pub task_id: String,
pub title: String,
pub description: String,
pub event_key: String,
pub cycle: String,
pub scope_kind: String,
pub threshold: u32,
pub reward_points: u64,
pub enabled: bool,
pub sort_order: i32,
pub created_by: String,
pub created_at: String,
pub updated_by: String,
pub updated_at: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ProfileTaskConfigAdminListResponse {
pub entries: Vec<ProfileTaskConfigAdminResponse>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AdminUpsertProfileTaskConfigRequest {
pub task_id: String,
pub title: String,
#[serde(default)]
pub description: Option<String>,
pub event_key: String,
pub cycle: String,
pub scope_kind: String,
pub threshold: u32,
pub reward_points: u64,
#[serde(default = "default_true")]
pub enabled: bool,
#[serde(default)]
pub sort_order: Option<i32>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AdminDisableProfileTaskConfigRequest {
pub task_id: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AdminUpsertProfileRedeemCodeRequest {
@@ -339,6 +435,12 @@ pub struct ProfileRedeemCodeAdminResponse {
pub updated_at: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ProfileRedeemCodeAdminListResponse {
pub entries: Vec<ProfileRedeemCodeAdminResponse>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ProfileInviteCodeAdminResponse {
@@ -349,6 +451,12 @@ pub struct ProfileInviteCodeAdminResponse {
pub updated_at: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ProfileInviteCodeAdminListResponse {
pub entries: Vec<ProfileInviteCodeAdminResponse>,
}
fn default_true() -> bool {
true
}
@@ -958,6 +1066,13 @@ mod tests {
.to_string(),
created_at: "2026-04-22T10:06:00Z".to_string(),
},
ProfileWalletLedgerEntryResponse {
id: "ledger-9".to_string(),
amount_delta: 10,
balance_after: 212,
source_type: PROFILE_WALLET_LEDGER_SOURCE_TYPE_DAILY_TASK_REWARD.to_string(),
created_at: "2026-04-22T10:07:00Z".to_string(),
},
],
})
.expect("payload should serialize");
@@ -996,12 +1111,66 @@ mod tests {
payload["entries"][7]["sourceType"],
json!(PROFILE_WALLET_LEDGER_SOURCE_TYPE_PUZZLE_AUTHOR_INCENTIVE_CLAIM)
);
assert_eq!(
payload["entries"][8]["sourceType"],
json!(PROFILE_WALLET_LEDGER_SOURCE_TYPE_DAILY_TASK_REWARD)
);
assert_eq!(
payload["entries"][0]["createdAt"],
json!("2026-04-22T09:59:00Z")
);
}
#[test]
fn profile_task_center_response_uses_camel_case_fields() {
let payload = serde_json::to_value(ProfileTaskCenterResponse {
day_key: 20576,
wallet_balance: 18,
tasks: vec![ProfileTaskItemResponse {
task_id: "daily_login".to_string(),
title: "每日登录".to_string(),
description: "".to_string(),
event_key: "daily_login".to_string(),
cycle: PROFILE_TASK_CYCLE_DAILY.to_string(),
threshold: 1,
progress_count: 1,
reward_points: 10,
status: PROFILE_TASK_STATUS_CLAIMABLE.to_string(),
day_key: 20576,
claimed_at: None,
updated_at: "2026-05-03T00:00:00Z".to_string(),
}],
updated_at: "2026-05-03T00:00:00Z".to_string(),
})
.expect("payload should serialize");
assert_eq!(payload["walletBalance"], json!(18));
assert_eq!(payload["tasks"][0]["taskId"], json!("daily_login"));
assert_eq!(payload["tasks"][0]["rewardPoints"], json!(10));
assert_eq!(
payload["tasks"][0]["status"],
json!(PROFILE_TASK_STATUS_CLAIMABLE)
);
}
#[test]
fn admin_task_config_request_accepts_defaults() {
let payload: AdminUpsertProfileTaskConfigRequest = serde_json::from_value(json!({
"taskId": "daily_login",
"title": "每日登录",
"eventKey": "daily_login",
"cycle": "daily",
"scopeKind": "user",
"threshold": 1,
"rewardPoints": 10
}))
.expect("request should deserialize");
assert_eq!(payload.description, None);
assert_eq!(payload.enabled, true);
assert_eq!(payload.sort_order, None);
}
#[test]
fn profile_recharge_center_response_uses_camel_case_fields() {
let payload = serde_json::to_value(ProfileRechargeCenterResponse {