Skip to content

Build SingBox Configs #51

Build SingBox Configs

Build SingBox Configs #51

Workflow file for this run

name: Build SingBox Configs
on:
schedule:
- cron: "*/30 * * * *"
timezone: "Europe/Moscow"
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Build configs
run: |
SUB=$(curl -s "https://raw.githack.com/igareck/vpn-configs-for-russia/main/Vless-Reality-White-Lists-Rus-Mobile.txt" | tr -d '\r')
ALL=$(echo "$SUB" | grep -E '^(vless|vmess|trojan)://' | grep -Evi 'raw')
RUSSIA=$(echo "$ALL" | grep -Ei 'russia' || true)
NON_RUSSIA=$(echo "$ALL" | grep -Evi 'russia' | shuf || true)
make_config_variant () {
SIZE=$1
TARGET_RU_COUNT=$2
OUT=$3
VARIANT=$4 # для отладки, можно использовать разный seed или просто перемешивать по-разному
# Перемешиваем русские ключи для каждого варианта
RUSSIA_SHUFFLED=$(echo "$RUSSIA" | shuf)
# Берем целевое количество русских из перемешанного списка
RU=$(echo "$RUSSIA_SHUFFLED" | head -n "$TARGET_RU_COUNT")
RU_COUNT=$(echo "$RU" | grep -c . || true)
# Если русских меньше цели, добираем из NON_RUSSIA
NEED=$((SIZE - RU_COUNT))
NONRU=""
if [ "$NEED" -gt 0 ]; then
# Для fallback варианта берем другие нерусские ключи (уже перемешаны глобально)
NONRU=$(echo "$NON_RUSSIA" | head -n "$NEED")
# Удаляем использованные нерусские ключи, чтобы следующие конфиги не повторялись
if [ "$NEED" -gt 0 ]; then
USED_NONRU=$(echo "$NONRU" | sed 's/[\/&]/\\&/g' | sed 's/^/^/; s/$/$/')
NON_RUSSIA=$(echo "$NON_RUSSIA" | grep -vFf <(echo "$NONRU"))
fi
fi
# Финальный список и перемешиваем его для разнообразия
FINAL=$(printf "%s\n%s\n" "$RU" "$NONRU" | grep . | shuf)
echo "Building $OUT with $(echo "$FINAL" | grep -c .) nodes..."
echo " - Russian nodes: $RU_COUNT"
echo " - Non-Russian nodes: $(echo "$NONRU" | grep -c . || echo 0)"
echo " - Variant: $VARIANT"
jq -n --arg input "$FINAL" '{
core: "singbox",
input: $input,
options: {
addTun: true,
addSocks: true,
genClashSecret: false,
useExtended: false
}
}' \
| curl -sS -X POST "https://api.web2core.workers.dev/" \
-H "Content-Type: application/json" \
--data-binary @- \
> "$OUT"
}
make_foreign () {
SIZE=$1
OUT=$2
FOREIGN=$(echo "$NON_RUSSIA" | shuf | head -n "$SIZE")
# Удаляем использованные
USED_FOREIGN=$(echo "$FOREIGN" | sed 's/[\/&]/\\&/g' | sed 's/^/^/; s/$/$/')
NON_RUSSIA=$(echo "$NON_RUSSIA" | grep -vFf <(echo "$FOREIGN"))
jq -n --arg input "$FOREIGN" '{
core: "singbox",
input: $input,
options: {
addTun: true,
addSocks: true,
genClashSecret: false,
useExtended: false
}
}' \
| curl -sS -X POST "https://api.web2core.workers.dev/" \
-H "Content-Type: application/json" \
--data-binary @- \
> "$OUT"
}
# Восстанавливаем оригинальные списки для каждого размера конфига,
# чтобы конфиги разных размеров были независимы
# Для 5-ки (5 узлов, хотим 4-5 русских)
RUSSIA=$(echo "$ALL" | grep -Ei 'russia' || true)
NON_RUSSIA=$(echo "$ALL" | grep -Evi 'russia' | shuf || true)
make_config_variant 5 4 config5.json "primary"
RUSSIA=$(echo "$ALL" | grep -Ei 'russia' || true)
NON_RUSSIA=$(echo "$ALL" | grep -Evi 'russia' | shuf || true)
make_config_variant 5 4 config5_b.json "fallback"
# Для 7-ки (7 узлов, хотим 6-7 русских)
RUSSIA=$(echo "$ALL" | grep -Ei 'russia' || true)
NON_RUSSIA=$(echo "$ALL" | grep -Evi 'russia' | shuf || true)
make_config_variant 7 6 config7.json "primary"
RUSSIA=$(echo "$ALL" | grep -Ei 'russia' || true)
NON_RUSSIA=$(echo "$ALL" | grep -Evi 'russia' | shuf || true)
make_config_variant 7 6 config7_b.json "fallback"
# Для 10-ки (10 узлов, хотим 8-10 русских)
RUSSIA=$(echo "$ALL" | grep -Ei 'russia' || true)
NON_RUSSIA=$(echo "$ALL" | grep -Evi 'russia' | shuf || true)
make_config_variant 10 8 config10.json "primary"
RUSSIA=$(echo "$ALL" | grep -Ei 'russia' || true)
NON_RUSSIA=$(echo "$ALL" | grep -Evi 'russia' | shuf || true)
make_config_variant 10 8 config10_b.json "fallback"
# Иностранные конфиги
RUSSIA=$(echo "$ALL" | grep -Ei 'russia' || true)
NON_RUSSIA=$(echo "$ALL" | grep -Evi 'russia' | shuf || true)
make_foreign 5 config5_foreign.json
RUSSIA=$(echo "$ALL" | grep -Ei 'russia' || true)
NON_RUSSIA=$(echo "$ALL" | grep -Evi 'russia' | shuf || true)
make_foreign 10 config10_foreign.json
# ---------------- PATCH URLTEST ----------------
patch_interval () {
FILE=$1
INTERVAL=$2
echo "Patching $FILE -> interval=$INTERVAL"
jq --arg interval "$INTERVAL" '
(.outbounds[] | select(.type=="urltest") | .interval) = $interval |
(.outbounds[] | select(.type=="urltest") | .tolerance) = 50
' "$FILE" > tmp.json && mv tmp.json "$FILE"
}
# 5-series → 1m
patch_interval config5.json "1m"
patch_interval config5_b.json "1m"
patch_interval config5_foreign.json "1m"
# all others → 2m
patch_interval config7.json "2m"
patch_interval config7_b.json "2m"
patch_interval config10.json "2m"
patch_interval config10_b.json "2m"
patch_interval config10_foreign.json "2m"
- name: Commit configs
run: |
git config user.name "github-actions"
git config user.email "actions@github.com"
git add config*.json
git commit -m "auto update sing-box configs" || exit 0
git push
# === НОВЫЙ ШАГ ДЛЯ ЗАГРУЗКИ НА ЯНДЕКС.ДИСК ===
- name: Upload to Yandex Disk via WebDAV
env:
YA_LOGIN: ${{ secrets.YANDEX_NAME }}
YA_PASS: ${{ secrets.YANDEX_TOKEN }}
run: |
# Кодируем логин:пароль в base64 (правильный способ для WebDAV) [citation:3][citation:9]
AUTH_HEADER=$(echo -n "$YA_LOGIN:$YA_PASS" | base64)
# Создаём папку
curl -s -X MKCOL "https://webdav.yandex.ru/SingBox_Configs/" \
-H "Authorization: Basic $AUTH_HEADER"
# Загружаем файлы
for file in config*.json; do
echo "Uploading $file..."
curl -s -T "$file" "https://webdav.yandex.ru/SingBox_Configs/$file" \
-H "Authorization: Basic $AUTH_HEADER"
done