name: Update GFWList Rules on: schedule: - cron: '0 0 * * *' workflow_dispatch: branches: - master jobs: update: runs-on: ubuntu-slim if: github.ref == 'refs/heads/master' steps: - name: Checkout repository uses: actions/checkout@v5 with: fetch-depth: 0 ref: master - name: Set up Python uses: actions/setup-python@v6 with: python-version: '3.x' - name: Parse GFWList run: python scripts/gfwlist_parser.py - name: Download mihomo run: | MAX_RETRIES=5 RETRY_DELAY=10 for ((i=1; i<=MAX_RETRIES; i++)); do echo "Attempt $i/$MAX_RETRIES to download mihomo..." if TAG=$(curl -s --fail https://api.github.com/repos/MetaCubeX/mihomo/releases/latest | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/'); then echo "Latest mihomo version: $TAG" if curl -L --fail -o mihomo.gz "https://github.com/MetaCubeX/mihomo/releases/download/${TAG}/mihomo-linux-amd64-${TAG}.gz"; then echo "Download succeeded" if gzip -d mihomo.gz; then chmod +x mihomo rm -f mihomo.gz echo "mihomo extracted and ready" exit 0 else echo "Failed to extract mihomo.gz" fi else echo "Download failed (HTTP error)" fi else echo "Failed to fetch latest release info" fi if [ $i -lt $MAX_RETRIES ]; then echo "Retrying in $RETRY_DELAY seconds..." sleep $RETRY_DELAY fi done echo "ERROR: All download attempts failed" exit 1 - name: Convert to mrs format run: | mkdir -p Clash/mrs convert_file() { local type=$1 local format=$2 local input_file=$3 local output_file=$4 local MAX_RETRIES=3 for ((i=1; i<=MAX_RETRIES; i++)); do echo "[Attempt $i/$MAX_RETRIES] Converting $input_file ($type)" if ./mihomo convert-ruleset "$type" "$format" "$input_file" "$output_file"; then echo "Success: $input_file -> $output_file" return 0 else echo "Warning: Conversion failed for $input_file (Attempt $i/$MAX_RETRIES)" if [ $i -lt $MAX_RETRIES ]; then sleep 3 fi fi done echo "ERROR: Failed to convert $input_file after $MAX_RETRIES attempts" return 1 } # 检查 YAML 文件是否有有效内容(排除 payload: 和空行/注释行) has_yaml_content() { local file=$1 local content_lines=$(sed '/^payload:$/d; /^#/d; /^$/d' "$file" | wc -l) [ "$content_lines" -gt 0 ] } # 检查 LIST 文件是否有有效内容(排除注释和空行) has_list_content() { local file=$1 local content_lines=$(sed '/^#/d; /^$/d' "$file" | wc -l) [ "$content_lines" -gt 0 ] } # 处理所有分离文件(包括生成的和已存在的) for file in Clash/Providers/*_domain.yaml Clash/Providers/*_ip.yaml Clash/Providers/Ruleset/*_domain.yaml Clash/Providers/Ruleset/*_ip.yaml; do if [ -f "$file" ]; then filename=$(basename "$file") if has_yaml_content "$file"; then if [[ "$filename" == *"_domain.yaml" ]]; then base=$(basename "$file" _domain.yaml) convert_file "domain" "yaml" "$file" "Clash/mrs/${base}_domain.mrs" elif [[ "$filename" == *"_ip.yaml" ]]; then base=$(basename "$file" _ip.yaml) convert_file "ipcidr" "yaml" "$file" "Clash/mrs/${base}_ip.mrs" fi else echo "Skipping empty or invalid file: $file" fi fi done for file in Clash/Ruleset/*_domain.list Clash/Ruleset/*_ip.list; do if [ -f "$file" ]; then filename=$(basename "$file") if has_list_content "$file"; then if [[ "$filename" == *"_domain.list" ]]; then base=$(basename "$file" _domain.list) convert_file "domain" "text" "$file" "Clash/mrs/${base}_domain.mrs" elif [[ "$filename" == *"_ip.list" ]]; then base=$(basename "$file" _ip.list) convert_file "ipcidr" "text" "$file" "Clash/mrs/${base}_ip.mrs" fi else echo "Skipping empty or invalid file: $file" fi fi done echo "Conversion completed" # 清理临时文件 rm -f Clash/Providers/*_domain.yaml Clash/Providers/*_ip.yaml rm -f Clash/Providers/Ruleset/*_domain.yaml Clash/Providers/Ruleset/*_ip.yaml rm -f Clash/Ruleset/*_domain.list Clash/Ruleset/*_ip.list # 清理 mihomo 二进制文件 rm -f mihomo echo "Temporary files cleaned up" - name: Get current datetime id: datetime run: echo "datetime=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT - name: Commit and push changes uses: EndBug/add-and-commit@v9 with: message: '[AutoUpdate] Update GFWList rules and mrs files - ${{ env.DATETIME }}' push: true env: DATETIME: ${{ steps.datetime.outputs.datetime }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}