#!/usr/bin/env bash # glm-quota — Check Zhipu AI (GLM) API quota # # Usage: # glm-quota # show quota # glm-quota -v # show raw JSON response # # Setup API key (macOS Keychain): # security add-generic-password -a "$USER" -s GLM_API_KEY -w "YOUR_API_KEY" # Setup API key (Arch/Linux — libsecret): # echo "YOUR_API_KEY" | secret-tool store --label "GLM API Key" service GLM_API_KEY KEY_NAME="GLM_API_KEY" URL="https://open.bigmodel.cn/api/monitor/usage/quota/limit" # ===== OS DETECTION ===== if [ -f /etc/arch-release ]; then OS="arch" elif [ "$(uname -s)" = "Darwin" ]; then OS="macos" else OS="linux" fi # ===== COLORS ===== GREEN="\033[1;32m" CYAN="\033[1;36m" YELLOW="\033[1;33m" RED="\033[1;31m" DIM="\033[2m" RESET="\033[0m" # ===== ARGS ===== VERBOSE=0 ONELINE=0 while [[ $# -gt 0 ]]; do case "$1" in -v) VERBOSE=1 ;; -1) ONELINE=1 ;; esac shift done # ===== LOAD TOKEN ===== if [ -n "${!KEY_NAME}" ]; then API_TOKEN="${!KEY_NAME}" else case "$OS" in macos) API_TOKEN=$(security find-generic-password -a "$USER" -s "$KEY_NAME" -w 2>/dev/null | tr -d '\n') ;; arch) API_TOKEN=$(secret-tool lookup service "$KEY_NAME" 2>/dev/null | tr -d '\n') ;; *) API_TOKEN=$(secret-tool lookup service "$KEY_NAME" 2>/dev/null | tr -d '\n') ;; esac fi if [ -z "$API_TOKEN" ]; then echo -e "${RED}❌ API token not found ($KEY_NAME)${RESET}" >&2 exit 1 fi # ===== CALL API ===== RESPONSE=$(curl -s -H "Authorization: $API_TOKEN" "$URL") if [ "$VERBOSE" -eq 1 ]; then echo -e "${YELLOW}🔧 Raw response:${RESET}" echo "$RESPONSE" | jq . echo "" fi # ===== PARSE ===== SUCCESS=$(echo "$RESPONSE" | jq -r '.success // false') if [ "$SUCCESS" != "true" ]; then echo -e "${RED}❌ API request failed${RESET}" echo "$RESPONSE" | jq . exit 1 fi LEVEL=$(echo "$RESPONSE" | jq -r '.data.level // "unknown"') # Extract TOKENS_LIMIT using jq in one shot read -r T_PERCENT T_RESET T_NUM < <(echo "$RESPONSE" | jq -r ' .data.limits[] | select(.type == "TOKENS_LIMIT") | "\(.percentage // 0) \(.nextResetTime // 0) \(.number // 5)" ') # Extract TIME_LIMIT (web search) in one shot read -r R_USAGE R_CURRENT R_REMAINING R_PERCENT R_RESET < <(echo "$RESPONSE" | jq -r ' .data.limits[] | select(.type == "TIME_LIMIT") | "\(.usage // 0) \(.currentValue // 0) \(.remaining // 0) \(.percentage // 0) \(.nextResetTime // 0)" ') # Convert millisecond timestamps to human readable format_ms() { local ms="$1" if [ -n "$ms" ] && [ "$ms" -gt 0 ] 2>/dev/null; then local sec=$((ms / 1000)) case "$OS" in macos) date -r "$sec" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$ms" ;; *) date -d "@$sec" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$ms" ;; esac else echo "N/A" fi } T_RESET_HUMAN=$(format_ms "$T_RESET") R_RESET_HUMAN=$(format_ms "$R_RESET") # ===== DISPLAY ===== NOW=$(date +%s) RESET_SEC=$((T_RESET / 1000)) DIFF=$((RESET_SEC - NOW)) REMAIN="" if [ "$DIFF" -gt 0 ]; then H=$((DIFF / 3600)) M=$(((DIFF % 3600) / 60)) if [ "$H" -gt 0 ]; then REMAIN=" (${H}h${M}m)" else REMAIN=" (${M}m)" fi fi ICON=$(awk -v p="$T_PERCENT" 'BEGIN { if (p < 50) print "🟢"; else if (p > 80) print "🔴"; else print "🟡" }') if [ "$ONELINE" -eq 1 ]; then echo "GLM: ${T_PERCENT}%${REMAIN}${ICON}" exit 0 fi echo "GLM: ${T_PERCENT}%${REMAIN}${ICON}" echo "---" echo "✅ Account: ${LEVEL}" echo "Time Limit: ${T_NUM}h rolling" echo " Usage: ${T_PERCENT}%" echo " Next Reset: $T_RESET_HUMAN" if [ -n "$R_USAGE" ] && [ "$R_USAGE" != "0" ]; then echo "Web Search Limit: monthly" echo " Used: ${R_CURRENT}/${R_USAGE} (${R_PERCENT}%)" echo " Reset: ${R_RESET_HUMAN}" fi