Merge pull request #20 from JRailgun/patch-6 #41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Convert TXT to MRS | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - "*.txt" | |
| workflow_dispatch: | |
| jobs: | |
| convert: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Download mihomo | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="$(curl -fsSL https://github.com/MetaCubeX/mihomo/releases/download/Prerelease-Alpha/version.txt)" | |
| echo "Downloading mihomo version: $VERSION" | |
| curl -fsSL -o mihomo.gz "https://github.com/MetaCubeX/mihomo/releases/download/Prerelease-Alpha/mihomo-linux-amd64-${VERSION}.gz" | |
| gzip -d mihomo.gz | |
| chmod +x mihomo | |
| - name: Sort and convert files | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Optional sorter for domain files in your repo; non-fatal for ip lists | |
| for f in *.txt; do | |
| [ -f "$f" ] || continue | |
| python3 .github/scripts/sort_domains.py "$f" || true | |
| done | |
| # Build normalized input and detect type | |
| cat > /tmp/prepare_rules.py <<'PY' | |
| import ipaddress | |
| import re | |
| import sys | |
| from pathlib import Path | |
| src = Path(sys.argv[1]) | |
| dst = Path(sys.argv[2]) | |
| lines = src.read_text(encoding="utf-8", errors="ignore").splitlines() | |
| out = [] | |
| for raw in lines: | |
| s = raw.strip().replace("\r", "") | |
| if not s: | |
| continue | |
| # remove comments | |
| s = re.sub(r"\s+#.*$", "", s).strip() | |
| if not s: | |
| continue | |
| # yaml header | |
| if s.lower() == "payload:": | |
| continue | |
| # yaml item prefix "- " | |
| s = re.sub(r"^\s*-\s*", "", s).strip() | |
| # strip quotes | |
| if (s.startswith('"') and s.endswith('"')) or (s.startswith("'") and s.endswith("'")): | |
| s = s[1:-1].strip() | |
| if s: | |
| out.append(s) | |
| if not out: | |
| print("EMPTY") | |
| dst.write_text("", encoding="utf-8") | |
| sys.exit(0) | |
| ip_like = 0 | |
| final_ip = [] | |
| final_domain = [] | |
| for s in out: | |
| try: | |
| if "/" in s: | |
| n = ipaddress.ip_network(s, strict=False) | |
| ip_like += 1 | |
| final_ip.append(str(n)) | |
| else: | |
| ip = ipaddress.ip_address(s) | |
| ip_like += 1 | |
| final_ip.append(f"{ip}/32" if ip.version == 4 else f"{ip}/128") | |
| except ValueError: | |
| final_domain.append(s) | |
| # If mostly IP/CIDR -> ipcidr, else domain | |
| ratio = ip_like / len(out) | |
| if ratio >= 0.90: | |
| rule_type = "ipcidr" | |
| final = final_ip | |
| else: | |
| rule_type = "domain" | |
| final = final_domain if final_domain else out | |
| # dedupe keep order | |
| seen = set() | |
| uniq = [] | |
| for x in final: | |
| if x not in seen: | |
| seen.add(x) | |
| uniq.append(x) | |
| dst.write_text("\n".join(uniq) + ("\n" if uniq else ""), encoding="utf-8") | |
| print(rule_type) | |
| PY | |
| SKIP_FILES="processes.txt" | |
| for txt_file in *.txt; do | |
| [ -f "$txt_file" ] || continue | |
| if echo "$SKIP_FILES" | grep -qw "$txt_file"; then | |
| echo "Skipping $txt_file" | |
| continue | |
| fi | |
| base_name="${txt_file%.txt}" | |
| mrs_input="$(mktemp)" | |
| RULE_TYPE="$(python3 /tmp/prepare_rules.py "$txt_file" "$mrs_input")" | |
| if [ "$RULE_TYPE" = "EMPTY" ] || [ ! -s "$mrs_input" ]; then | |
| echo "Warning: No rules in $txt_file" | |
| rm -f "$mrs_input" | |
| continue | |
| fi | |
| echo "Detected type for $txt_file: $RULE_TYPE" | |
| head -10 "$mrs_input" || true | |
| ./mihomo convert-ruleset "$RULE_TYPE" text "$mrs_input" "${base_name}.mrs" | |
| if [ ! -f "${base_name}.mrs" ]; then | |
| echo "Error: ${base_name}.mrs was not created" | |
| rm -f "$mrs_input" | |
| exit 1 | |
| fi | |
| if [ "$RULE_TYPE" = "ipcidr" ]; then | |
| size="$(wc -c < "${base_name}.mrs")" | |
| if [ "$size" -lt 100 ]; then | |
| echo "Error: ${base_name}.mrs too small (${size} bytes)" | |
| rm -f "$mrs_input" | |
| exit 1 | |
| fi | |
| fi | |
| rm -f "$mrs_input" | |
| echo "Converted: $txt_file -> ${base_name}.mrs ($RULE_TYPE)" | |
| done | |
| - name: Commit changes | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --local user.name "github-actions[bot]" | |
| shopt -s nullglob | |
| files=( *.txt *.mrs ) | |
| if [ ${#files[@]} -eq 0 ]; then | |
| echo "No txt/mrs files to add" | |
| exit 0 | |
| fi | |
| git add "${files[@]}" | |
| if git diff --staged --quiet; then | |
| echo "No changes to commit" | |
| else | |
| git commit -m "Auto-convert TXT to MRS (domain + IPv4/IPv6 CIDR)" | |
| git push | |
| fi |