2026年07月归档

codex只能显示有几张重置卡,但具体什么时候到期不显示,然后app里面永远只显示你新获得一张重置卡有效期30天。让人感觉是永久的。其实不然。
根据论坛上看到的别人的介绍,然后让codex自己搓了一个查自己的。实测好用。

#!/usr/bin/env python3

import json
import sys
import urllib.error
import urllib.request
from datetime import datetime, timedelta, timezone
from pathlib import Path


AUTH_PATH = Path.home() / ".codex" / "auth.json"
API_URL = "https://chatgpt.com/backend-api/wham/rate-limit-reset-credits"
BEIJING_TZ = timezone(timedelta(hours=8))


def load_access_token() -> str:
    try:
        data = json.loads(AUTH_PATH.read_text(encoding="utf-8"))
    except FileNotFoundError:
        print(f"未找到认证文件: {AUTH_PATH}", file=sys.stderr)
        sys.exit(1)
    except json.JSONDecodeError:
        print(f"认证文件不是合法 JSON: {AUTH_PATH}", file=sys.stderr)
        sys.exit(1)

    token = data.get("tokens", {}).get("access_token")
    if not token:
        print("认证文件中缺少 tokens.access_token", file=sys.stderr)
        sys.exit(1)
    return token


def parse_utc_to_beijing(value: str) -> str:
    dt = datetime.fromisoformat(value.replace("Z", "+00:00"))
    return dt.astimezone(BEIJING_TZ).strftime("%Y年%-m月%-d日 %H:%M:%S")


def fetch_credits(token: str) -> list[dict]:
    req = urllib.request.Request(
        API_URL,
        headers={
            "Authorization": f"Bearer {token}",
            "Accept": "application/json",
            "User-Agent": "codexreset.py",
        },
    )

    try:
        with urllib.request.urlopen(req, timeout=20) as resp:
            data = json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as err:
        if err.code == 401:
            print("HTTP 401:凭证失效或 Authorization header 不正确", file=sys.stderr)
            sys.exit(1)
        print(f"HTTP {err.code}:请求失败", file=sys.stderr)
        sys.exit(1)
    except urllib.error.URLError as err:
        print(f"网络请求失败:{err.reason}", file=sys.stderr)
        sys.exit(1)

    credits = data.get("credits")
    if not isinstance(credits, list):
        print("接口返回格式异常:缺少 credits 数组", file=sys.stderr)
        sys.exit(1)
    return credits


def main() -> None:
    token = load_access_token()
    credits = fetch_credits(token)

    if not credits:
        print("没有可显示的重置卡。")
        return

    for idx, credit in enumerate(credits, start=1):
        granted_at = credit.get("granted_at")
        expires_at = credit.get("expires_at")
        if not granted_at or not expires_at:
            continue
        print(f"{idx}. 发放时间:{parse_utc_to_beijing(granted_at)}")
        print(f"   过期时间:{parse_utc_to_beijing(expires_at)}")


if __name__ == "__main__":
    main()

运行结果:

root@leb:/usr/local/bin# codexreset.py
1. 发放时间:2026年6月12日 11:56:56
   过期时间:2026年7月12日 11:56:56
2. 发放时间:2026年6月18日 08:33:06
   过期时间:2026年7月18日 08:33:06
3. 发放时间:2026年6月27日 08:07:52
   过期时间:2026年7月27日 08:07:52
4. 发放时间:2026年7月2日 04:28:21
   过期时间:2026年8月1日 04:28:21