name: 服务状态检测

on:
# 当修改 main 分支的内容时自动执行该流程
  push:
    branches:
       - main
#定时循环每2个小时
  schedule:
   - cron: "0 */2 * * *"
  workflow_dispatch:

env:
  TZ: Asia/Shanghai

#设置仓库的读写权限
permissions:
  contents: write
  pull-requests: write
  actions: write
  issues: write
  
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: delete-workflow
        uses: Mattraks/delete-workflow-runs@main
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          retain_days: 0
          keep_minimum_runs: 0
      - name: install network tools
        run: |
          sudo -E apt-get -y update
          sudo -E apt-get install -y net-tools
          sudo timedatectl set-timezone Asia/Shanghai
          
      - name: check server status
        id: check-server-status
        run: |
          set +e

          create_issue() {
            #检查Issue是否已存在
            issue_title="🛑 $1-$2-$3-$4 离线了"
            
            current_date=$(date '+%Y年%m月%d日 %H:%M:%S')
            RESPONSE=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
              -H "Accept: application/vnd.github.v3+json" \
              https://api.github.com/repos/${{ github.repository }}/issues?state=open)
            ISSUE_EXISTS=$(echo "$RESPONSE" | jq -r --arg TITLE "$issue_title" '.[] | select(.title == $TITLE) | .title')
            if [ -n "$ISSUE_EXISTS" ]; then
              return
            else
              echo "未找到相同的 Issue，创建issue通知。"
            fi
            # 调用 GitHub API 创建 Issue
            curl -X POST \
              -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
              -H "Accept: application/vnd.github.v3+json" \
              https://api.github.com/repos/${{ github.repository }}/issues \
              -d "{\"title\": \"${issue_title}\", \"body\": \"### ${current_date} \\n\\n 🛑 $1  $2  $3  $4  离线了😫\"}"
            echo -e "已成功创建新的 Issue: $issue_title  \n\n### ${current_date} \n\n 🛑 $1  $2  $3  $4  离线了😫"
          }
          close_issue() {
            issue_title="🛑 $1-$2-$3-$4 离线了"
            # 获取所有 Open 状态的 Issue
            RESPONSE=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
              -H "Accept: application/vnd.github.v3+json" \
              https://api.github.com/repos/${{ github.repository }}/issues?state=open)

            # 查找相同标题的 Issue ID
            ISSUE_ID=$(echo "$RESPONSE" | jq -r --arg TITLE "$issue_title" '.[] | select(.title == $TITLE) | .number')
            current_date=$(date '+%Y年%m月%d日 %H:%M:%S')
            if [ -n "$ISSUE_ID" ]; then
                echo "找到${issue_title}的 Issue ID: $ISSUE_ID。"
            else
                return
            fi
            # 回复指定内容到 Issue
            curl -X POST \
              -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
              -H "Accept: application/vnd.github.v3+json" \
              https://api.github.com/repos/${{ github.repository }}/issues/${ISSUE_ID}/comments \
              -d "{\"body\": \"### ${current_date} \\n\\n 🟢 $1  $2  $3  $4 已经恢复正常运行了✅\"}"
            
            # 调用 GitHub API 关闭 Issue
            curl -X PATCH \
              -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
              -H "Accept: application/vnd.github.v3+json" \
              https://api.github.com/repos/${{ github.repository }}/issues/${ISSUE_ID} \
              -d "{\"state\": \"closed\"}"
            echo "已关闭 【${issue_title}】 Issue ID: $ISSUE_ID。"
          }
          rm README.md && touch README.md
          
          echo "# 服务状态" | tee -a README.md
          echo -e "[![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2F${{ github.repository_owner }}%2Fserver-status&count_bg=%2395C10D&title_bg=%23555555&icon=github.svg&icon_color=%238DC409&title=%E8%AE%BF%E9%97%AE%E6%95%B0&edge_flat=false)](https://hits.seeyoufarm.com)![hello](https://views.whatilearened.today/views/github/${GITHUB_REPOSITORY}.svg)![](https://pgy.us.kg/?id=svg)![](http://s4.serv00.com:8828/?id=svg)<p><img src="http://ip.cnqq.cloudns.ch/" width="400" onerror=\"this.style.display='none';\"></p>\n" | tee -a README.md >/dev/null 2>&1
          echo "> 这个[README](https://github.com/${GITHUB_REPOSITORY})每5小时由Github action生成一次." | tee -a README.md
          echo "## 上次更新时间：" | tee -a README.md
          date "+%Y年%m月%d日 %H:%M:%S" | tee -a README.md
          echo "## 公共节点状态： " | tee -a README.md
          echo "公共节点仅用于测试，对于生产，请设置您自己的节点." | tee -a README.md
          echo "" | tee -a README.md
          echo "|服务名称|协议|服务器地址|端口|备注信息|IPV4/IPV6|**状态**|历史状态|" |tee -a README.md
          echo "|--|--|--|--|--|--|--|--|" |tee -a README.md
          
          # 读取 server.txt 文件并遍历每一行
          awk '{print $0}' server.txt | while IFS=' ' read -r name protocol address port region ipv; do
          # 排除以 # 开头的行和空行
          if [[ -z "$name" || "$name" =~ ^# ]]; then
              continue  # 如果是空行或以 # 开头的行，跳过当前循环
          fi
          # 判断 $4 是否是端口（检查是否为纯数字且范围在 1-65535）
          if [[ ! "$port" =~ ^[0-9]+$ || "$port" -lt 1 || "$port" -gt 65535 ]]; then
              ipv="$region"    # 将 $5 的值赋给 $6
              region="$port"   # 将 $4 的值赋给 $5
              port=""          # 将 $5 清空
          fi
          # 判断是否需要填充地区信息
          if [[ -z "$ipv" && "$region" =~ ^(V4|v4|IPv4|v4/v6|ipv4|ipv4/ipv6|v6|IPv6|ipv6|v4/v6|ipv4/v6)$ ]]; then
              # 如果 $6 为空且 $5 中包含 IPV4/IPV6 标识，认为备注信息为空
              ipv="$region"   # 将 $5 的值赋给 $6，即标识 IP 类型
              region=""       # 将备注信息清空
          fi
          # 判断协议类型
          if [[ "$protocol" == "HTTP" || "$protocol" == "http" || "$protocol" == "HTTPS" || "$protocol" == "https" ]]; then
              # 测试 HTTP/HTTPS 连接是否正常
              if [[ "$port" != "" ]]; then
                  # 如果有端口号，则添加端口
                  response_code=$(curl -Lks -w "%{http_code}" -o /dev/null "$protocol://$address:$port")
                  name="[$name](${protocol}://${address}:${port})"
              else
                  # 没有端口号，直接使用默认端口
                  response_code=$(curl -Lks -w "%{http_code}" -o /dev/null "$protocol://$address")
                  name="[$name](${protocol}://${address})"
              fi
        
              if [[ "$response_code" -eq 200 ]]; then
                  status="正常✅"
              else
                  status="离线❌"
              fi
          elif [[ "$protocol" == "TCP" || "$protocol" == "tcp" || "$protocol" == "ws" || "$protocol" == "WS" || "$protocol" == "WSS" || "$protocol" == "wss" ]]; then
              # TCP协议
              nc -v -w 3 -z "$address" "$port" &>/dev/null
              if [[ $? -eq 0 ]]; then
                  status="正常✅"
              else
                  status="离线❌"
              fi
          else
              status="未知⚠️"
          fi

          # 更新历史记录文件
          [ ! -d "history" ] && mkdir -p history
          history_file="history/${protocol}-${address}-${port}.txt"
          [ ! -f "$history_file" ] && touch "$history_file"
          echo "$(date '+%Y年%m月%d日 %H:%M:%S')： $status" >> "$history_file"
          tail -n 10 "$history_file" > "$history_file.temp" && mv "$history_file.temp" "$history_file"

          # 生成历史状态显示
          history_status=$(tail -n 10 "$history_file" | awk '{if($3=="正常✅") printf "🟩"; else if($3=="未知⚠️") printf "🟨"; else printf "🟥"}')
          green_count=$(echo "$history_status" | grep -o "🟩" | wc -l)
          #total_count=$(echo "$history_status" | wc -m)
          #total_count=$((total_count - 1)) # 去除换行符
          total_count=$(echo "$history_status" | wc -c)
          #emoji表情占4个字节
          total_count=$((total_count / 4))
          percentage=$((green_count * 100 / total_count))
          
          if [[ "$status" = "正常✅" || "$status" = "未知⚠️" ]] ; then
            echo "|$name|$protocol|$address|$port|$region|$ipv|$status|[${history_status}]($history_file) $percentage%|" |tee -a README.md >/dev/null 2>&1
            #关闭issue
            close_issue "${name}" "${protocol}" "${address}" "${port}"
          else 
            echo "|$name|<span style="color:red">$protocol</span>|<span style="color:red">$address</span>|<span style="color:red">$port</span>|<span style="color:red">$region</span>|<span style="color:red">$ipv</span>|<span style="color:red">离线</span>❌|[${history_status}]($history_file) <span style="color:red">$percentage%</span>|" | tee -a README.md >/dev/null 2>&1
            #创建issue通知
            create_issue "${name}" "${protocol}" "${address}" "${port}"
          fi
          done
      - name: Commit files
        run: |
          git config --local user.email "github-actions@github.com"
          git config --local user.name "github-actions"
          git add .
          git commit -m "更新服务状态 ： $(date '+%Y-%m-%d %H:%M:%S')" -a
      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
          force_with_lease: true
      - name: 自用更新
        if: github.repository_owner == 'lmq8267' # 判断仓库所有者是否是 lmq8267 才执行
        env:
          #读取环境变量
          SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
          USER: ${{ secrets.SERVER }}
          CMD: ${{ secrets.CMD }}
        run: |
          #远程ssh执行更新命令
          sudo apt-get install -y sshpass
          sshpass -p "${{ secrets.SSH_PRIVATE_KEY }}" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "${{ secrets.SERVER }}" "${{ secrets.CMD }}"

  keepalive-workflow:
    name: keepalive
    runs-on: ubuntu-latest
    permissions:
      actions: write
      contents: write
    steps:
      - uses: actions/checkout@v4
      - uses: gautamkrishnar/keepalive-workflow@v2
        #with:
          #use_api: true