mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-07 18:07:47 +08:00
Codex 重置功能和显示修复
This commit is contained in:
@@ -787,6 +787,10 @@ fn parse_codex_reset_credit_timestamp(value: Option<&serde_json::Value>) -> Opti
|
||||
}
|
||||
|
||||
fn codex_reset_credit_detail_items(value: &serde_json::Value) -> Option<&Vec<serde_json::Value>> {
|
||||
if let Some(items) = value.as_array() {
|
||||
return Some(items);
|
||||
}
|
||||
|
||||
first_json_value_by_paths(
|
||||
value,
|
||||
&[
|
||||
@@ -799,6 +803,10 @@ fn codex_reset_credit_detail_items(value: &serde_json::Value) -> Option<&Vec<ser
|
||||
&["rateLimitResetCredits", "data"],
|
||||
&["reset_credits", "credits"],
|
||||
&["resetCredits", "credits"],
|
||||
&["rate_limit_reset_credits"],
|
||||
&["rateLimitResetCredits"],
|
||||
&["reset_credits"],
|
||||
&["resetCredits"],
|
||||
],
|
||||
)
|
||||
.and_then(serde_json::Value::as_array)
|
||||
@@ -833,10 +841,28 @@ fn codex_reset_credit_status(
|
||||
.find_map(|key| coerce_json_string(object.get(*key)))
|
||||
}
|
||||
|
||||
fn codex_reset_credit_is_available(object: &serde_json::Map<String, serde_json::Value>) -> bool {
|
||||
let reset_type = ["reset_type", "resetType"]
|
||||
.iter()
|
||||
.find_map(|key| coerce_json_string(object.get(*key)));
|
||||
if reset_type
|
||||
.as_deref()
|
||||
.is_some_and(|value| !value.trim().eq_ignore_ascii_case("codex_rate_limits"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
codex_reset_credit_status(object).is_none_or(|status| {
|
||||
let status = status.trim();
|
||||
status.eq_ignore_ascii_case("available") || status.eq_ignore_ascii_case("active")
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_codex_reset_credit_detail_item(item: &serde_json::Value) -> Option<serde_json::Value> {
|
||||
let object = item.as_object()?;
|
||||
let id = codex_reset_credit_id(object)?;
|
||||
let display_key = codex_reset_credit_display_key(&id)?;
|
||||
if !codex_reset_credit_is_available(object) {
|
||||
return None;
|
||||
}
|
||||
let expires_at = parse_codex_reset_credit_timestamp(
|
||||
object
|
||||
.get("expires_at")
|
||||
@@ -853,8 +879,12 @@ fn parse_codex_reset_credit_detail_item(item: &serde_json::Value) -> Option<serd
|
||||
);
|
||||
|
||||
let mut out = serde_json::Map::new();
|
||||
out.insert("id".to_string(), json!(id));
|
||||
out.insert("display_key".to_string(), json!(display_key));
|
||||
if let Some(id) = codex_reset_credit_id(object) {
|
||||
if let Some(display_key) = codex_reset_credit_display_key(&id) {
|
||||
out.insert("display_key".to_string(), json!(display_key));
|
||||
}
|
||||
out.insert("id".to_string(), json!(id));
|
||||
}
|
||||
if let Some(status) = codex_reset_credit_status(object) {
|
||||
out.insert("status".to_string(), json!(status));
|
||||
}
|
||||
@@ -869,8 +899,35 @@ pub fn parse_codex_wham_reset_credits_detail_response(
|
||||
value: &serde_json::Value,
|
||||
updated_at_unix_secs: u64,
|
||||
) -> Option<serde_json::Value> {
|
||||
value.as_object()?;
|
||||
let mut credits = codex_reset_credit_detail_items(value)
|
||||
let root = value.as_object();
|
||||
let detail_items = codex_reset_credit_detail_items(value);
|
||||
if root.is_none() && detail_items.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let available_item_count = detail_items
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter_map(serde_json::Value::as_object)
|
||||
.filter(|item| codex_reset_credit_is_available(item))
|
||||
.count();
|
||||
let available_count = root
|
||||
.and_then(codex_reset_credits_available_count)
|
||||
.or_else(|| {
|
||||
root.and_then(|root| {
|
||||
[
|
||||
"available_count",
|
||||
"availableCount",
|
||||
"available",
|
||||
"remaining",
|
||||
"count",
|
||||
]
|
||||
.iter()
|
||||
.find_map(|key| root.get(*key).and_then(coerce_json_u64))
|
||||
})
|
||||
})
|
||||
.or_else(|| detail_items.and_then(|_| u64::try_from(available_item_count).ok()));
|
||||
let mut credits = detail_items
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter_map(parse_codex_reset_credit_detail_item)
|
||||
@@ -881,10 +938,10 @@ pub fn parse_codex_wham_reset_credits_detail_response(
|
||||
.unwrap_or(u64::MAX)
|
||||
});
|
||||
|
||||
let detail_status = if credits.is_empty() {
|
||||
"empty"
|
||||
} else {
|
||||
let detail_status = if available_count.is_some_and(|count| count > 0) {
|
||||
"available"
|
||||
} else {
|
||||
"empty"
|
||||
};
|
||||
let mut reset_credits = serde_json::Map::new();
|
||||
reset_credits.insert("updated_at".to_string(), json!(updated_at_unix_secs));
|
||||
@@ -892,20 +949,8 @@ pub fn parse_codex_wham_reset_credits_detail_response(
|
||||
reset_credits.insert("detail_status".to_string(), json!(detail_status));
|
||||
reset_credits.insert("credits".to_string(), serde_json::Value::Array(credits));
|
||||
|
||||
if let Some(root) = value.as_object() {
|
||||
if let Some(available_count) = codex_reset_credits_available_count(root).or_else(|| {
|
||||
[
|
||||
"available_count",
|
||||
"availableCount",
|
||||
"available",
|
||||
"remaining",
|
||||
"count",
|
||||
]
|
||||
.iter()
|
||||
.find_map(|key| root.get(*key).and_then(coerce_json_u64))
|
||||
}) {
|
||||
reset_credits.insert("available_count".to_string(), json!(available_count));
|
||||
}
|
||||
if let Some(available_count) = available_count {
|
||||
reset_credits.insert("available_count".to_string(), json!(available_count));
|
||||
}
|
||||
|
||||
Some(json!({ "reset_credits": reset_credits }))
|
||||
@@ -2534,6 +2579,61 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_codex_reset_credit_detail_without_explicit_count_or_ids() {
|
||||
let parsed = parse_codex_wham_reset_credits_detail_response(
|
||||
&json!({
|
||||
"rate_limit_reset_credits": [
|
||||
{
|
||||
"resetType": "codex_rate_limits",
|
||||
"status": "available",
|
||||
"expiresAt": "2030-01-02T00:00:00Z"
|
||||
},
|
||||
{
|
||||
"reset_type": "codex_rate_limits",
|
||||
"status": "available"
|
||||
},
|
||||
{
|
||||
"reset_type": "codex_rate_limits",
|
||||
"status": "redeemed",
|
||||
"expires_at": "2030-01-03T00:00:00Z"
|
||||
}
|
||||
]
|
||||
}),
|
||||
1_777_000_000,
|
||||
)
|
||||
.expect("detail array should parse");
|
||||
|
||||
assert_eq!(
|
||||
parsed.pointer("/reset_credits/available_count"),
|
||||
Some(&json!(2u64))
|
||||
);
|
||||
assert_eq!(
|
||||
parsed.pointer("/reset_credits/credits/0/expires_at"),
|
||||
Some(&json!(1_893_542_400u64))
|
||||
);
|
||||
assert_eq!(parsed.pointer("/reset_credits/credits/0/id"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_codex_reset_credit_detail_from_top_level_array() {
|
||||
let parsed = parse_codex_wham_reset_credits_detail_response(
|
||||
&json!([
|
||||
{
|
||||
"status": "available",
|
||||
"expires_at": "2030-01-04T00:00:00Z"
|
||||
}
|
||||
]),
|
||||
1_777_000_000,
|
||||
)
|
||||
.expect("top-level detail array should parse");
|
||||
|
||||
assert_eq!(
|
||||
parsed.pointer("/reset_credits/available_count"),
|
||||
Some(&json!(1u64))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalizes_codex_reset_credit_consume_outcome() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user