Add profile/news/info commands for store.last-z.com API
profile reads getuserhome.php (power/level/alliance); news and info hit public getsite_new.php / getindex.php. Store private endpoints authenticate with the UID alone as Usertoken — no password needed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
||||
.venv/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.playwright-mcp/
|
||||
|
||||
30
CLAUDE.md
30
CLAUDE.md
@@ -9,12 +9,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Run the CLI
|
||||
python giftcenter.py login
|
||||
python giftcenter.py redeem <gift_code>
|
||||
python giftcenter.py login # account info (gift center)
|
||||
python giftcenter.py redeem <gift_code> # redeem a gift code
|
||||
python giftcenter.py profile # full profile: power/level/alliance
|
||||
python giftcenter.py news # game announcements (no UID needed)
|
||||
python giftcenter.py info # region / latest APK url (no UID needed)
|
||||
|
||||
# Override UID without editing .env
|
||||
python giftcenter.py --uid <uid> login
|
||||
python giftcenter.py --uid <uid> redeem <gift_code>
|
||||
# Override UID without editing .env (on login/redeem/profile)
|
||||
python giftcenter.py --uid <uid> profile
|
||||
```
|
||||
|
||||
## Configuration
|
||||
@@ -23,9 +25,23 @@ UID is read from the `UID` environment variable, typically set in `.env`. The `-
|
||||
|
||||
## Architecture
|
||||
|
||||
Single-file Python CLI (`giftcenter.py`) using `argparse` subcommands:
|
||||
Single-file Python CLI (`giftcenter.py`) using `argparse` subcommands across two backends:
|
||||
|
||||
`giftcenter.last-z.com` (helper: inline `requests` calls):
|
||||
- `login` → `cmd_login()` — GET `/getcodeuser.php?uid=...`, displays account info
|
||||
- `redeem <code>` → `cmd_redeem()` — GET `/code.php` with `Usertoken` header and `uid`/`code` params
|
||||
|
||||
API responses use numeric error codes (`code` field) for login and string error codes (`errorCode` field, value `"ok"` on success) for redemption. Error mappings are in `LOGIN_ERRORS` and `REDEEM_ERRORS` constants. UI text is in Traditional Chinese.
|
||||
`store.last-z.com` (`STORE_URL`):
|
||||
- `profile` → `cmd_profile()` — `store_auth("getuserhome.php", uid)`, prints fields from `PROFILE_FIELDS`
|
||||
- `news` → `cmd_news()` — `store_post("getsite_new.php")` (public, no auth)
|
||||
- `info` → `cmd_info()` — `store_post("getindex.php")` (public, no auth)
|
||||
|
||||
Two store helpers: `store_post(endpoint)` for public endpoints (empty POST body), and
|
||||
`store_auth(endpoint, uid)` for private ones. **Store "auth" is just the UID** — sent as both the
|
||||
`Usertoken` header and the `{uid}` POST body; there is no password. (`getuser.php` is the exception —
|
||||
it needs a recaptcha `loginToken` + AES `signature`, so `profile` uses `getuserhome.php` instead.)
|
||||
Adding more store reads (`getmail.php`, `getuseritem.php`, `gettask_new.php`) is a one-liner via `store_auth`.
|
||||
|
||||
API responses use numeric error codes (`code` field) for login and string error codes (`errorCode`
|
||||
field, value `"ok"` on success) for redemption. Error mappings are in `LOGIN_ERRORS` and
|
||||
`REDEEM_ERRORS` constants. UI text is in Traditional Chinese.
|
||||
|
||||
@@ -11,6 +11,7 @@ from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
BASE_URL = "https://giftcenter.last-z.com"
|
||||
STORE_URL = "https://store.last-z.com"
|
||||
|
||||
LOGIN_ERRORS = {
|
||||
10006: "Token 已過期",
|
||||
@@ -97,6 +98,76 @@ def cmd_redeem(args):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def store_post(endpoint):
|
||||
# store.last-z.com 公開端點,免 token
|
||||
try:
|
||||
resp = requests.post(f"{STORE_URL}/{endpoint}", json={}, timeout=10)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
except requests.RequestException as e:
|
||||
print(f"請求失敗:{e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def cmd_news(args):
|
||||
data = store_post("getsite_new.php")
|
||||
announces = data.get("version_announce", [])
|
||||
if not announces:
|
||||
print("目前沒有公告")
|
||||
return
|
||||
for a in announces:
|
||||
print(f"[{a.get('createTime')}] {a.get('title')}")
|
||||
print(f" 👍 {a.get('like_count', 0)} 👎 {a.get('dislike_count', 0)}")
|
||||
|
||||
|
||||
def cmd_info(args):
|
||||
data = store_post("getindex.php")
|
||||
print(f"地區 : {data.get('clientCountry')}")
|
||||
print(f"APK 下載 : {data.get('apkurl')}")
|
||||
print(f"Token : {data.get('token')}")
|
||||
|
||||
|
||||
def store_auth(endpoint, uid):
|
||||
# store.last-z.com 私人端點只認 UID 當 Usertoken(無密碼)
|
||||
try:
|
||||
resp = requests.post(
|
||||
f"{STORE_URL}/{endpoint}",
|
||||
headers={"Usertoken": uid},
|
||||
json={"uid": uid},
|
||||
timeout=10,
|
||||
)
|
||||
return resp.json()
|
||||
except (requests.RequestException, ValueError) as e:
|
||||
print(f"請求失敗:{e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
PROFILE_FIELDS = {
|
||||
"name": "名稱",
|
||||
"uid": "UID",
|
||||
"baseLevel": "總部等級",
|
||||
"power": "戰力",
|
||||
"likeCount": "點贊量",
|
||||
"armyKill": "殺敵數量",
|
||||
"giftLevel": "送禮等級",
|
||||
"kingWinNum": "稱王次數",
|
||||
"allianceName": "聯盟",
|
||||
"abbr": "聯盟縮寫",
|
||||
}
|
||||
|
||||
|
||||
def cmd_profile(args):
|
||||
uid = args.uid or get_uid()
|
||||
data = store_auth("getuserhome.php", uid)
|
||||
if data.get("code") != 0:
|
||||
print(f"讀取失敗:{data.get('message') or data.get('code')}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
info = data.get("info", {})
|
||||
for key, label in PROFILE_FIELDS.items():
|
||||
if key in info:
|
||||
print(f" {label}\t: {info[key]}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Last-Z Gift Center CLI")
|
||||
parser.add_argument("--uid", help="指定 UID(覆蓋 .env)")
|
||||
@@ -113,6 +184,19 @@ def main():
|
||||
p_redeem.add_argument("--uid", help="指定 UID(覆蓋 .env)")
|
||||
p_redeem.set_defaults(func=cmd_redeem)
|
||||
|
||||
# news
|
||||
p_news = sub.add_parser("news", help="查看遊戲公告")
|
||||
p_news.set_defaults(func=cmd_news)
|
||||
|
||||
# info
|
||||
p_info = sub.add_parser("info", help="查看地區與最新 APK 下載連結")
|
||||
p_info.set_defaults(func=cmd_info)
|
||||
|
||||
# profile
|
||||
p_profile = sub.add_parser("profile", help="顯示完整帳號資料(戰力/等級/聯盟)")
|
||||
p_profile.add_argument("--uid", help="指定 UID(覆蓋 .env)")
|
||||
p_profile.set_defaults(func=cmd_profile)
|
||||
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user