Files
asd-backend/scripts/check-members.sh

202 lines
7.6 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# ===========================================
# 检查会员订阅情况
# ===========================================
# 用法:
# ./check-members.sh # 生产数据库
# ./check-members.sh --dev # 开发数据库 (milkydata_dev)
# ./check-members.sh --dev --json # JSON 格式输出
# ===========================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
ENV_FILE="$PROJECT_ROOT/.env"
# ---- 颜色 ----
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# ---- 参数 ----
DB_NAME="milkydata"
OUTPUT_JSON=false
while [[ $# -gt 0 ]]; do
case "$1" in
--dev) DB_NAME="milkydata_dev"; shift ;;
--json) OUTPUT_JSON=true; shift ;;
--help|-h)
echo "用法: $0 [--dev] [--json]"
echo " --dev 查询开发数据库 (milkydata_dev)"
echo " --json JSON 格式输出"
exit 0
;;
*) echo "未知参数: $1"; exit 1 ;;
esac
done
# ---- 获取 SSH 配置 ----
SSH_HOST=$(grep '^SSH_SERVER=' "$ENV_FILE" 2>/dev/null | head -1 | cut -d'=' -f2- | tr -d '"' | tr -d "'" | xargs)
if [ -z "$SSH_HOST" ]; then
echo "${RED}❌ 未找到 SSH_SERVER 配置,请检查 $ENV_FILE${NC}"
exit 1
fi
echo -e "${CYAN}══════════════════════════════════════${NC}"
echo -e "${CYAN} 会员订阅状态检查${NC}"
echo -e "${CYAN} 数据库: ${BOLD}$DB_NAME${NC}"
echo -e "${CYAN} 时间: $(date '+%Y-%m-%d %H:%M:%S')${NC}"
echo -e "${CYAN}══════════════════════════════════════${NC}"
echo ""
# ---- 总览 ----
SQL_OVERVIEW=$(cat <<'SQL'
SELECT
COUNT(*) AS total_users,
COUNT(*) FILTER (WHERE is_member = true) AS total_members,
COUNT(*) FILTER (WHERE is_member = true AND membership_expires_at > NOW()) AS active_members,
COUNT(*) FILTER (WHERE is_member = true AND membership_expires_at <= NOW()) AS expired_members,
COUNT(*) FILTER (WHERE is_member = true AND membership_expires_at IS NULL) AS permanent_members,
COUNT(*) FILTER (WHERE is_member = true
AND membership_expires_at IS NOT NULL
AND membership_expires_at > NOW()
AND membership_expires_at <= NOW() + INTERVAL '7 days') AS expiring_7d,
COUNT(*) FILTER (WHERE is_member = true
AND membership_expires_at IS NOT NULL
AND membership_expires_at > NOW()
AND membership_expires_at <= NOW() + INTERVAL '30 days') AS expiring_30d
FROM users;
SQL
)
OVERVIEW=$(ssh "$SSH_HOST" "psql -d $DB_NAME -At -c \"$SQL_OVERVIEW\"" 2>/dev/null) || {
echo -e "${RED}❌ SSH 连接失败: $SSH_HOST${NC}"
exit 1
}
IFS='|' read -r total_users total_members active_members expired_members permanent_members expiring_7d expiring_30d <<< "$OVERVIEW"
# ---- 活跃会员列表 ----
SQL_LIST=$(cat <<'SQL'
SELECT
id,
COALESCE(openid, 'N/A') AS openid,
COALESCE(nickname, CONCAT('用户 #', id)) AS display_name,
membership_expires_at::date AS expires_on,
CASE
WHEN membership_expires_at IS NULL THEN '永久'
WHEN membership_expires_at <= NOW() THEN '已过期'
ELSE CONCAT('剩 ', EXTRACT(DAY FROM membership_expires_at - NOW()), ' 天')
END AS status,
CASE
WHEN membership_expires_at IS NULL THEN 99999
WHEN membership_expires_at <= NOW() THEN -1
ELSE EXTRACT(DAY FROM membership_expires_at - NOW())::int
END AS days_left
FROM users
WHERE is_member = true
ORDER BY
CASE WHEN membership_expires_at IS NULL THEN 0 ELSE 1 END,
membership_expires_at DESC;
SQL
)
MEMBER_LIST=$(ssh "$SSH_HOST" "psql -d $DB_NAME -AqtF'|' -c \"$SQL_LIST\"" 2>/dev/null)
# ---- 近期到期的活跃会员 ----
SQL_EXPIRING=$(cat <<'SQL'
SELECT
id,
COALESCE(nickname, CONCAT('用户 #', id)) AS display_name,
membership_expires_at::date AS expires_on,
EXTRACT(DAY FROM membership_expires_at - NOW())::int AS days_left
FROM users
WHERE is_member = true
AND membership_expires_at IS NOT NULL
AND membership_expires_at > NOW()
AND membership_expires_at <= NOW() + INTERVAL '7 days'
ORDER BY membership_expires_at;
SQL
)
EXPIRING_LIST=$(ssh "$SSH_HOST" "psql -d $DB_NAME -AqtF'|' -c \"$SQL_EXPIRING\"" 2>/dev/null)
# ---- JSON 输出 ----
if [ "$OUTPUT_JSON" = true ]; then
cat <<JSON
{
"db": "$DB_NAME",
"time": "$(date --iso-8601=seconds)",
"total_users": $total_users,
"total_members": $total_members,
"active_members": $active_members,
"expired_members": $expired_members,
"permanent_members": $permanent_members,
"expiring_within_7d": $expiring_7d,
"expiring_within_30d": $expiring_30d,
"members": [
JSON
FIRST=true
while IFS='|' read -r id openid name expires_on status days_left; do
[ -z "$id" ] && continue
[ "$FIRST" = true ] || echo ","
FIRST=false
cat <<JSON
{ "id": $id, "name": "$name", "expires_on": "${expires_on:-永久}", "status": "$status", "days_left": ${days_left:-0} }
JSON
done <<< "$MEMBER_LIST"
echo ""
echo " ]"
echo "}"
exit 0
fi
# ---- 表格输出 ----
echo -e "${BOLD}📊 总览${NC}"
echo -e " ${GREEN}总用户数: ${BOLD}$total_users${NC}"
echo -e " ${CYAN}会员总数: ${BOLD}$total_members${NC}(占总用户 $(( total_users > 0 ? total_members * 100 / total_users : 0 ))%"
echo -e " ${GREEN}活跃会员: ${BOLD}$active_members${NC}(已付费且未过期)"
echo -e " ${YELLOW}已过期会员: ${BOLD}$expired_members${NC}"
echo -e " ${BOLD}永久会员: ${BOLD}$permanent_members${NC}"
echo ""
echo -e " ${YELLOW}7 天内到期: ${BOLD}$expiring_7d${NC}"
echo -e " ${YELLOW}30 天内到期: ${BOLD}$expiring_30d${NC}"
echo ""
# ---- 活跃会员列表 ----
if [ -n "$MEMBER_LIST" ]; then
echo -e "${BOLD}📋 会员列表${NC}"
printf " ${CYAN}%-4s %-22s %-12s %s${NC}\n" "ID" "名称" "到期日" "状态"
echo " ─────────────────────────────────────────────"
while IFS='|' read -r id openid name expires_on status days_left; do
[ -z "$id" ] && continue
if [ "$status" = "永久" ]; then
printf " %-4d %-22s %-12s %s\n" "$id" "${name:0:22}" "永久" "🔒 永久"
elif [ "$status" = "已过期" ]; then
printf " %-4d %-22s %-12s %s\n" "$id" "${name:0:22}" "$expires_on" "$status"
elif [ "$days_left" -le 7 ]; then
printf " %-4d %-22s %-12s %s\n" "$id" "${name:0:22}" "$expires_on" "⚠️ $status"
else
printf " %-4d %-22s %-12s %s\n" "$id" "${name:0:22}" "$expires_on" "$status"
fi
done <<< "$MEMBER_LIST"
echo ""
fi
# ---- 近期到期提醒 ----
if [ -n "$EXPIRING_LIST" ]; then
echo -e "${BOLD}⏰ 近期到期7 天内)${NC}"
while IFS='|' read -r id name expires_on days_left; do
[ -z "$id" ] && continue
echo -e " ${YELLOW}⚠️ 用户 #$id${name})将于 $expires_on 到期,剩余 ${days_left}${NC}"
done <<< "$EXPIRING_LIST"
echo ""
fi
echo -e "${CYAN}══════════════════════════════════════${NC}"