Skip to content

Sync and Convert Game Rules with Fixed IPv4 #222

Sync and Convert Game Rules with Fixed IPv4

Sync and Convert Game Rules with Fixed IPv4 #222

Workflow file for this run

name: Sync and Convert Game Rules with Fixed IPv4
on:
schedule:
- cron: '0 18 * * *' # 北京时间 02:00 执行
workflow_dispatch:
permissions:
contents: write
jobs:
game_rules:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm install fs-extra yaml
- name: Fetch Game Rules
run: |
mkdir -p tmp_repo
git clone --depth=1 --filter=blob:none --sparse https://github.com/FQrabbit/SSTap-Rule.git tmp_repo
cd tmp_repo
git sparse-checkout set rules
cp -r rules/* ../rules/Game/
cd ..
rm -rf tmp_repo
- name: Convert Rules to YAML with Fixed IPv4
run: |
node <<'EOF'
const fs = require('fs-extra');
const path = require('path');
const inDir = 'rules/Game';
const outDir = 'rules/Game';
function isPrivateIP(ip) {
return /^(10\..*|172\.(1[6-9]|2[0-9]|3[01])\..*|192\.168\..*|169\.254\..*|22[4-9]\..*|2[3-5][0-9]\..*)$/.test(ip);
}
function fixIPv4(line) {
const cidrMatch = line.match(/\/(\d+)$/);
const cidr = cidrMatch ? parseInt(cidrMatch[1],10) : 32;
const parts = line.split('/');
let ip = parts[0];
const suffix = parts[1] || '';
let octets = ip.split('.').map(n => n.trim());
while(octets.length < 4) octets.push('0');
for (let i=0;i<octets.length;i++) {
let num = parseInt(octets[i],10);
if (isNaN(num)) num = 0;
octets[i] = num.toString();
}
if (cidr === 24) {
// 第四段置0,第三段截取不超过三位
let third = parseInt(octets[2],10);
let thirdStr = third.toString();
if (thirdStr.length > 3) {
octets[2] = thirdStr.slice(0,3);
} else if (thirdStr.length > 2) {
octets[2] = thirdStr.slice(0,2);
} else {
octets[2] = thirdStr;
}
octets[3] = '0';
} else if (cidr === 32) {
// 第三段末两位为第三段,剩余为第四段,如果第四段为空就1
let third = parseInt(octets[2],10);
let thirdStr = third.toString();
if (thirdStr.length <= 2) {
octets[2] = thirdStr;
octets[3] = '1';
} else {
octets[2] = thirdStr.slice(0,2);
octets[3] = thirdStr.slice(2) || '1';
}
}
return octets.join('.') + '/' + cidr;
}
async function walk(dir) {
let files = [];
for (const f of await fs.readdir(dir)) {
const fullPath = path.join(dir, f);
const stat = await fs.stat(fullPath);
if (stat.isDirectory()) {
files = files.concat(await walk(fullPath));
} else if (f.endsWith('.rules')) {
files.push(fullPath);
}
}
return files;
}
async function main() {
await fs.ensureDir(outDir);
const files = await walk(inDir);
for (const file of files) {
const content = await fs.readFile(file, 'utf8');
const lines = content.split(/\r?\n/).filter(l => l && !l.startsWith('#'));
const payload = lines
.map(fixIPv4)
.filter(line => !isPrivateIP(line));
const baseName = path.basename(file, '.rules') + '.yaml';
const outPath = path.join(outDir, baseName);
await fs.writeFile(outPath, 'payload:\n' + payload.map(l => ` - '${l}'`).join('\n'));
console.log(`Generated YAML: ${outPath}`);
}
}
main().catch(e => { console.error(e); process.exit(1); });
EOF
- name: Commit and Push Changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if ls rules/Game/*.yaml 1> /dev/null 2>&1; then
git add rules/Game/*.yaml
git commit -m "Updated Game rules with fixed IPv4" --allow-empty
git push
else
echo "No YAML files generated, skipping commit."
fi