mirror of
https://github.com/IndeecFOX/zapret4rocket.git
synced 2026-07-09 15:59:59 +00:00
Рефакторинг (#11)
Глобальный рефакторинг
Если что-то не работает, виноват он: AloofLibra <87386304+AloofLibra@users.noreply.github.com> 😂
This commit is contained in:
parent
de58e3be9f
commit
602a566923
11 changed files with 1204 additions and 941 deletions
31
.github/workflows/update_recs.yml
vendored
31
.github/workflows/update_recs.yml
vendored
|
|
@ -8,21 +8,38 @@ jobs:
|
|||
update:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Полная история для корректного merge
|
||||
|
||||
- name: Download Data
|
||||
run: |
|
||||
# Качаем CSV с листа Export_TXT
|
||||
curl -L "https://docs.google.com/spreadsheets/d/e/2PACX-1vRuTn6FKfGYrs1p2fjUSRTelUDeA14bDjMePXQWfSUtQEzZ4NPJc5ZqNHtkx1OMUjJSvP6ER9kkDKaO/pub?gid=2004936343&single=true&output=csv" -o recommendations.txt
|
||||
|
||||
# Удаляем кавычки, если Google их добавил (CSV иногда квотирует строки)
|
||||
# Удаляем кавычки, если Google их добавил
|
||||
sed -i 's/"//g' recommendations.txt
|
||||
|
||||
- name: Commit & Push
|
||||
- name: Fetch and merge changes
|
||||
run: |
|
||||
git config user.name "Stats Bot"
|
||||
git config user.email "bot@noreply.github.com"
|
||||
git add recommendations.txt
|
||||
# Коммитим только если есть изменения
|
||||
git commit -m "Update recommendations" || exit 0
|
||||
git push
|
||||
|
||||
# Fetch последних изменений
|
||||
git fetch origin master
|
||||
|
||||
# Пытаемся слить изменения (игнорируем ошибки конфликтов)
|
||||
git merge origin/master --no-commit --no-ff || true
|
||||
|
||||
- name: Force overwrite recommendations.txt
|
||||
run: |
|
||||
# Принудительно добавляем наш файл (игнорируя конфликты)
|
||||
git add recommendations.txt --force
|
||||
|
||||
- name: Complete merge and push
|
||||
run: |
|
||||
# Завершаем merge/commit
|
||||
git diff --cached --quiet || git commit -m "Update recommendations"
|
||||
|
||||
# Пушим изменения
|
||||
git push origin master
|
||||
|
|
|
|||
143
lib/actions.sh
Normal file
143
lib/actions.sh
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
backup_strats() {
|
||||
# Бэкап папки стратегий
|
||||
if [ -d /opt/zapret/extra_strats ]; then
|
||||
echo -e "${yellow}Сделать бэкап /opt/zapret/extra_strats ?${plain}"
|
||||
echo -e "${yellow}5 - Да, Enter - Нет, 0 - отмена${plain}"
|
||||
read -r ans
|
||||
if [ "$ans" = "0" ]; then
|
||||
get_menu # сигнал “отмена/в меню”
|
||||
fi
|
||||
if [ "$ans" = "5" ] || [ "$ans" = "y" ] || [ "$ans" = "Y" ]; then
|
||||
rm -rf /opt/extra_strats 2>/dev/null || true
|
||||
cp -rf /opt/zapret/extra_strats /opt/ || true
|
||||
echo -e "${green}Бэкап extra_strats сохранён в /opt/extra_strats${plain}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Бэкап листа исключений
|
||||
if [ -f /opt/zapret/lists/netrogat.txt ]; then
|
||||
echo -e "${yellow}Сделать бэкап /opt/zapret/lists/netrogat.txt ?${plain}"
|
||||
echo -e "${yellow}5 - Да, Enter - Нет, 0 - отмена и выход в меню${plain}"
|
||||
read -r ans2
|
||||
if [ "$ans2" = "0" ]; then
|
||||
get_menu
|
||||
fi
|
||||
if [ "$ans2" = "5" ] || [ "$ans2" = "y" ] || [ "$ans2" = "Y" ]; then
|
||||
cp -f /opt/zapret/lists/netrogat.txt /opt/netrogat.txt || true
|
||||
echo -e "${green}Бэкап netrogat.txt сохранён в /opt/netrogat.txt${plain}"
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
menu_action_update_config_reset() {
|
||||
echo -e "${yellow}Конфиг обновлен (UTC +0): $(curl -s "https://api.github.com/repos/IndeecFOX/zapret4rocket/commits?path=config.default&per_page=1" | grep '"date"' | head -n1 | cut -d'"' -f4) ${plain}"
|
||||
|
||||
backup_strats
|
||||
|
||||
/opt/zapret/init.d/sysv/zapret stop
|
||||
|
||||
rm -rf /opt/zapret/lists /opt/zapret/extra_strats
|
||||
|
||||
rm -f /opt/zapret/files/fake/http_fake_MS.bin \
|
||||
/opt/zapret/files/fake/quic_{1..7}.bin \
|
||||
/opt/zapret/files/fake/syn_packet.bin \
|
||||
/opt/zapret/files/fake/tls_clienthello_{1..18}.bin \
|
||||
/opt/zapret/files/fake/tls_clienthello_2n.bin \
|
||||
/opt/zapret/files/fake/tls_clienthello_6a.bin \
|
||||
/opt/zapret/files/fake/tls_clienthello_4pda_to.bin
|
||||
|
||||
get_repo
|
||||
|
||||
# Раскомменчивание юзера под keenetic или merlin
|
||||
change_user
|
||||
|
||||
cp -f /opt/zapret/config.default /opt/zapret/config
|
||||
|
||||
/opt/zapret/init.d/sysv/zapret start
|
||||
|
||||
# ВАЖНО: check_access_list — это по сути интерактивный тест (он сам печатает и может ждать Enter),
|
||||
# поэтому лучше вызывать его из get_menu отдельным пунктом ("01"), а не тут.
|
||||
# check_access_list
|
||||
|
||||
echo -e "${green}Config файл обновлён. Листы подбора стратегий и исключений сброшены в дефолт, если не просили сохранить. Фейк файлы обновлены.${plain}"
|
||||
return 0
|
||||
}
|
||||
|
||||
menu_action_toggle_bolvan_ports() {
|
||||
if grep -Eq '^NFQWS_PORTS_UDP=.*443$' "/opt/zapret/config"; then
|
||||
sed -i '76s/443$/443,1400,3478-3481,5349,50000-50099,19294-19344/' /opt/zapret/config
|
||||
sed -i 's/^--skip --filter-udp=50000/--filter-udp=50000/' "/opt/zapret/config"
|
||||
|
||||
rm -f /opt/zapret/init.d/sysv/custom.d/50-discord-media \
|
||||
/opt/zapret/init.d/sysv/custom.d/50-stun4all \
|
||||
/opt/zapret/init.d/openwrt/custom.d/50-stun4all \
|
||||
/opt/zapret/init.d/openwrt/custom.d/50-discord-media
|
||||
|
||||
echo -e "${green}Уход от скриптов bol-van. Выделены порты 50000-50099,1400,3478-3481,5349 и раскомментированы стратегии DS, WA, TG${plain}"
|
||||
|
||||
elif grep -q '443,1400,3478-3481,5349,50000-50099,19294-19344$' "/opt/zapret/config"; then
|
||||
sed -i 's/443,1400,3478-3481,5349,50000-50099,19294-19344$/443/' /opt/zapret/config
|
||||
sed -i 's/^--filter-udp=50000/--skip --filter-udp=50000/' "/opt/zapret/config"
|
||||
|
||||
curl -L -o /opt/zapret/init.d/sysv/custom.d/50-stun4all \
|
||||
https://raw.githubusercontent.com/bol-van/zapret/master/init.d/custom.d.examples.linux/50-stun4all
|
||||
curl -L -o /opt/zapret/init.d/sysv/custom.d/50-discord-media \
|
||||
https://raw.githubusercontent.com/bol-van/zapret/master/init.d/custom.d.examples.linux/50-discord-media
|
||||
|
||||
cp -f /opt/zapret/init.d/sysv/custom.d/50-stun4all /opt/zapret/init.d/openwrt/custom.d/50-stun4all
|
||||
cp -f /opt/zapret/init.d/sysv/custom.d/50-discord-media /opt/zapret/init.d/openwrt/custom.d/50-discord-media
|
||||
|
||||
echo -e "${green}Работа от скриптов bol-van. Вернули строку к виду NFQWS_PORTS_UDP=443 и добавили \"--skip \" в начале строк стратегии войса${plain}"
|
||||
else
|
||||
echo -e "${yellow}Неизвестное состояние строки NFQWS_PORTS_UDP. Проверь конфиг вручную.${plain}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
/opt/zapret/init.d/sysv/zapret restart
|
||||
echo -e "${green}Выполнение переключений завершено.${plain}"
|
||||
return 0
|
||||
}
|
||||
|
||||
menu_action_toggle_fwtype() {
|
||||
if grep -q '^FWTYPE=iptables$' "/opt/zapret/config"; then
|
||||
sed -i 's/^FWTYPE=iptables$/FWTYPE=nftables/' "/opt/zapret/config"
|
||||
/opt/zapret/install_prereq.sh
|
||||
/opt/zapret/init.d/sysv/zapret restart
|
||||
echo -e "${green}Zapret moode: nftables.${plain}"
|
||||
|
||||
elif grep -q '^FWTYPE=nftables$' "/opt/zapret/config"; then
|
||||
sed -i 's/^FWTYPE=nftables$/FWTYPE=iptables/' "/opt/zapret/config"
|
||||
/opt/zapret/install_prereq.sh
|
||||
/opt/zapret/init.d/sysv/zapret restart
|
||||
echo -e "${green}Zapret moode: iptables.${plain}"
|
||||
|
||||
else
|
||||
echo -e "${yellow}Неизвестное состояние строки FWTYPE. Проверь конфиг вручную.${plain}"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
menu_action_toggle_udp_range() {
|
||||
if grep -q '^NFQWS_PORTS_UDP=443' "/opt/zapret/config"; then
|
||||
sed -i 's/^NFQWS_PORTS_UDP=443/NFQWS_PORTS_UDP=1026-65531,443/' "/opt/zapret/config"
|
||||
sed -i 's/^--skip --filter-udp=1026/--filter-udp=1026/' "/opt/zapret/config"
|
||||
echo -e "${green}Стратегия UDP обхода активирована. Выделены порты 1026-65531${plain}"
|
||||
|
||||
elif grep -q '^NFQWS_PORTS_UDP=1026-65531,443' "/opt/zapret/config"; then
|
||||
sed -i 's/^NFQWS_PORTS_UDP=1026-65531,443/NFQWS_PORTS_UDP=443/' "/opt/zapret/config"
|
||||
sed -i 's/^--filter-udp=1026/--skip --filter-udp=1026/' "/opt/zapret/config"
|
||||
echo -e "${green}Стратегия UDP обхода ДЕактивирована. Выделенные порты 1026-65531 убраны${plain}"
|
||||
|
||||
else
|
||||
echo -e "${yellow}Неизвестное состояние строки NFQWS_PORTS_UDP. Проверь конфиг вручную.${plain}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
/opt/zapret/init.d/sysv/zapret restart
|
||||
echo -e "${green}Выполнение переключений завершено.${plain}"
|
||||
return 0
|
||||
}
|
||||
59
lib/netcheck.sh
Normal file
59
lib/netcheck.sh
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# Network / access checks
|
||||
|
||||
get_yt_cluster_domain() {
|
||||
local letters_map_a="u z p k f a 5 0 v q l g b 6 1 w r m h c 7 2 x s n i d 8 3 y t o j e 9 4 -"
|
||||
local letters_map_b="0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z -"
|
||||
|
||||
cluster_codename=$(curl -s --max-time 2 "https://redirector.xn--ngstr-lra8j.com/report_mapping?di=no"| sed -n 's/.*=>[[:space:]]*\([^ (:)]*\).*/\1/p')
|
||||
#Второй раз для пробития нерелевантного ответа
|
||||
cluster_codename=$(curl -s --max-time 2 "https://redirector.xn--ngstr-lra8j.com/report_mapping?di=no"| sed -n 's/.*=>[[:space:]]*\([^ (:)]*\).*/\1/p')
|
||||
|
||||
[ -z "$cluster_codename" ] && {
|
||||
echo "Не удалось получить cluster_codename. Используем тогда rr1---sn-5goeenes.googlevideo.com" >&2
|
||||
echo "rr1---sn-5goeenes.googlevideo.com"
|
||||
return
|
||||
}
|
||||
|
||||
local converted_name=""
|
||||
local i=0
|
||||
while [ $i -lt ${#cluster_codename} ]; do
|
||||
char=$(echo "$cluster_codename" | cut -c$((i+1)))
|
||||
idx=1
|
||||
for a in $letters_map_a; do
|
||||
[ "$a" = "$char" ] && break
|
||||
idx=$((idx+1))
|
||||
done
|
||||
b=$(echo "$letters_map_b" | cut -d' ' -f $idx)
|
||||
converted_name="${converted_name}${b}"
|
||||
i=$((i+1))
|
||||
done
|
||||
|
||||
echo "rr1---sn-${converted_name}.googlevideo.com"
|
||||
}
|
||||
|
||||
check_access() {
|
||||
local TestURL="$1"
|
||||
# Проверка TLS 1.2
|
||||
if curl --tls-max 1.2 --max-time 1 -s -o /dev/null "$TestURL"; then
|
||||
echo -e "${green}Есть ответ по TLS 1.2 (важно для ТВ и т.п.). ${yellow}Тест может быть ошибочен.${plain}"
|
||||
else
|
||||
echo -e "${yellow}Нет ответа по TLS 1.2 (важно для ТВ и т.п.) Таймаут 2сек. ${red}Проверьте доступность вручную. Возможно ошибка теста.${plain}"
|
||||
fi
|
||||
# Проверка TLS 1.3
|
||||
if curl --tlsv1.3 --max-time 1 -s -o /dev/null "$TestURL"; then
|
||||
echo -e "${green}Есть ответ по TLS 1.3 (важно в основном для всего современного) ${yellow}Тест может быть ошибочен.${plain}"
|
||||
else
|
||||
echo -e "${yellow}Нет ответа по TLS 1.3 (важно в основном для всего современного) Таймаут 2сек. ${red}Проверьте доступность вручную. Возможно ошибка теста.${plain}"
|
||||
fi
|
||||
}
|
||||
|
||||
check_access_list() {
|
||||
echo "Проверка доступности youtube.com (YT TCP)"
|
||||
check_access "https://www.youtube.com/"
|
||||
echo "Проверка доступности $(get_yt_cluster_domain) (YT TCP)"
|
||||
check_access "https://$(get_yt_cluster_domain)"
|
||||
echo "Проверка доступности meduza.io (RKN list)"
|
||||
check_access "https://meduza.io"
|
||||
echo "Проверка доступности www.instagram.com (RKN list + нужен рабочий DNS)"
|
||||
check_access "https://www.instagram.com/"
|
||||
}
|
||||
122
lib/premium.sh
Normal file
122
lib/premium.sh
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# ---- ZEFEER PREMIUM (777/999) ----
|
||||
# Сделано исключительно ради мемов. Практического смысла не несёт.
|
||||
PREMIUM_FLAG="$CACHE_DIR/premium.enabled"
|
||||
PREMIUM_TITLE_FILE="$CACHE_DIR/premium.title"
|
||||
|
||||
rand_from_list() {
|
||||
# usage: rand_from_list "a" "b" "c"
|
||||
local n=$#
|
||||
(( n == 0 )) && return 1
|
||||
local idx=$(( (RANDOM % n) + 1 ))
|
||||
eval "echo \"\${$idx}\""
|
||||
}
|
||||
|
||||
spinner_for_seconds() {
|
||||
local seconds="${1:-2}"
|
||||
local msg="${2:-Работаем}"
|
||||
local frames="|/-\\"
|
||||
local i=0
|
||||
local end=$((SECONDS + seconds))
|
||||
|
||||
local _had_tput=0
|
||||
if command -v tput >/dev/null 2>&1; then
|
||||
_had_tput=1
|
||||
tput civis
|
||||
trap 'tput cnorm; trap - EXIT INT TERM' EXIT INT TERM
|
||||
fi
|
||||
|
||||
while (( SECONDS < end )); do
|
||||
i=$(( (i + 1) % 4 ))
|
||||
# \r + \033[2K: в начало строки и стереть строку
|
||||
printf "\r\033[2K%s... [%c]" "$msg" "${frames:$i:1}"
|
||||
sleep 1
|
||||
done
|
||||
printf "\r\033[2K%s... [OK]\n" "$msg"
|
||||
|
||||
if (( _had_tput )); then
|
||||
tput cnorm
|
||||
trap - EXIT INT TERM
|
||||
fi
|
||||
}
|
||||
|
||||
premium_get_or_set_title() {
|
||||
mkdir -p "$CACHE_DIR"
|
||||
if [[ -s "$PREMIUM_TITLE_FILE" ]]; then
|
||||
cat "$PREMIUM_TITLE_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local title
|
||||
title="$(rand_from_list \
|
||||
"Граф Дезинхрона" \
|
||||
"Барон QUIC'а" \
|
||||
"Хранитель Hostlist'ов" \
|
||||
"Лорд --new" \
|
||||
"Грандмастер FakeTLS" \
|
||||
"Архитектор Сплитов" \
|
||||
"Повелитель RST (легальный)" \
|
||||
"Смотрящий за ipset'ом" \
|
||||
"Владыка TTL (ненадолго)" \
|
||||
"Амбассадор «Тест не точен»" \
|
||||
)"
|
||||
echo "$title" > "$PREMIUM_TITLE_FILE"
|
||||
echo "$title"
|
||||
}
|
||||
|
||||
zefeer_premium_777() {
|
||||
mkdir -p "$CACHE_DIR"
|
||||
|
||||
echo -e "${green}Специальный zeefeer premium для Valery ProD, avg97, Xoz, GeGunT, blagodarenya, mikhyan, andric62, Whoze, Necronicle, Andrei_5288515371, Nomand, Dina_turat, Nergalss, Александра, АлександраП, vecheromholodno, ЕвгенияГ, Dyadyabo, skuwakin, izzzgoy, Grigaraz, Reconnaissance, comandante1928, rudnev2028, umad, rutakote, railwayfx, vtokarev1604, Grigaraz, a40letbezurojaya и subzeero452 активирован. Наверное. Так же благодарю поддержавших проект hey_enote, VssA, vladdrazz, Alexey_Tob, Bor1sBr1tva, Azamatstd, iMLT, Qu3Bee, SasayKudasay1, alexander_novikoff, MarsKVV, porfenon123, bobrishe_dazzle, kotov38, Levonkas, DA00001, trin4ik, geodomin, I_ZNA_I и анонимов${plain}"
|
||||
|
||||
if [[ -f "$PREMIUM_FLAG" ]]; then
|
||||
local title
|
||||
title="$(premium_get_or_set_title)"
|
||||
echo -e "${yellow}ZEFEER PREMIUM уже активирован.${plain}"
|
||||
echo -e "Ваш титул: ${green}${title}${plain}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo -e "${yellow}Подключаемся к платёжному шлюзу...${plain}"
|
||||
spinner_for_seconds 2 "Проверяем поддержку проекта"
|
||||
|
||||
# Фальш-результат
|
||||
local verdict
|
||||
verdict="$(rand_from_list \
|
||||
"Транзакция не найдена, но найден хороший человек." \
|
||||
"Оплата не прошла, зато прошли вы. В сердечко." \
|
||||
"Биллинг лежит. Premium — стоит." \
|
||||
"Счёт не выставлялся. Списали уважение." \
|
||||
"Донат не обнаружен. Обнаружена смелость нажать 777." \
|
||||
)"
|
||||
|
||||
echo -e "${green}${verdict}${plain}"
|
||||
|
||||
local title
|
||||
title="$(premium_get_or_set_title)"
|
||||
echo -e "Premium активирован ${green}ヽ(o^ ^o)ノ ${plain}"
|
||||
echo -e "Присвоен титул: ${pink}${title}${plain}"
|
||||
|
||||
: > "$PREMIUM_FLAG"
|
||||
}
|
||||
|
||||
zefeer_space_999() {
|
||||
echo -e "${cyan}Секретный протокол 999: попытка связи с космосом...${plain}"
|
||||
spinner_for_seconds 6 "Наводим тарелку на созвездие Пакетных Потерь"
|
||||
|
||||
local excuse
|
||||
excuse="$(rand_from_list \
|
||||
"Меркурий не в том доме." \
|
||||
"Вспышка на Солнце сбила сигнал." \
|
||||
"Ретроградный NAT. Портал закрыт." \
|
||||
"Слишком много DPI на орбите — сигнал дропнули." \
|
||||
"Космос ответил RST." \
|
||||
"Сигнал ушёл по QUIC, а обратно пришёл по SMTP." \
|
||||
"Спутник занят: обновляет hostlist." \
|
||||
"Астральный ipset переполнен." \
|
||||
"Связь есть, но только с IPv6, а вы в IPv4 настроении." \
|
||||
"Сбой калибровки антенны: /dev/space не найден." \
|
||||
)"
|
||||
|
||||
echo -e "${red}Ошибка связи:${plain} ${yellow}${excuse}${plain}"
|
||||
}
|
||||
# ---- /ZEFEER PREMIUM ----
|
||||
86
lib/provider.sh
Normal file
86
lib/provider.sh
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# ---- Provider detector integration ----
|
||||
# Используем provider.txt как основной источник правды (просто строка "Provider - City")
|
||||
PROVIDER_CACHE="/opt/zapret/extra_strats/cache/provider.txt"
|
||||
PROVIDER_MENU="Не определён"
|
||||
PROVIDER_INIT_DONE=0
|
||||
|
||||
# Вспомогательная функция: делает запрос к API и пишет в файл
|
||||
_detect_api_simple() {
|
||||
# 1. Скачиваем ответ во временный файл (чтобы точно видеть, что пришло)
|
||||
local tmp_file="/tmp/z4r_provider_debug.txt"
|
||||
curl -s --max-time 10 "http://ip-api.com/line?fields=isp,city" > "$tmp_file"
|
||||
|
||||
# 2. Читаем построчно (без пайпов, чтобы не терять код возврата)
|
||||
local p_name=$(head -n 1 "$tmp_file")
|
||||
local p_city=$(head -n 2 "$tmp_file" | tail -n 1)
|
||||
|
||||
# 3. Чистим жестко (оставляем только латиницу, цифры и пробелы)
|
||||
# Удаляем вообще все странные символы
|
||||
p_name=$(echo "$p_name" | tr -cd 'a-zA-Z0-9 ._-')
|
||||
p_city=$(echo "$p_city" | tr -cd 'a-zA-Z0-9 ._-')
|
||||
|
||||
# Убираем дублирование, если API вернул 1 строку
|
||||
if [ "$p_city" = "$p_name" ]; then p_city=""; fi
|
||||
|
||||
# 4. Формируем результат
|
||||
local res="$p_name"
|
||||
if [ -n "$p_city" ]; then
|
||||
res="$res - $p_city"
|
||||
fi
|
||||
|
||||
# 5. Проверка результата перед записью
|
||||
if [ -n "$res" ]; then
|
||||
mkdir -p "$(dirname "$PROVIDER_CACHE")"
|
||||
echo "$res" > "$PROVIDER_CACHE"
|
||||
else
|
||||
echo "DEBUG: Результат парсинга пустой! (Raw: $(cat $tmp_file))" >&2
|
||||
fi
|
||||
|
||||
# Чистим за собой
|
||||
rm -f "$tmp_file"
|
||||
}
|
||||
|
||||
provider_init_once() {
|
||||
[ "$PROVIDER_INIT_DONE" = "1" ] && return 0
|
||||
PROVIDER_INIT_DONE=1
|
||||
|
||||
# Если кэша нет или он пустой — пробуем определить
|
||||
if [ ! -s "$PROVIDER_CACHE" ]; then
|
||||
echo "Определяем провайдера..."
|
||||
_detect_api_simple
|
||||
fi
|
||||
|
||||
# Читаем результат в переменную меню
|
||||
if [ -s "$PROVIDER_CACHE" ]; then
|
||||
PROVIDER_MENU="$(cat "$PROVIDER_CACHE")"
|
||||
else
|
||||
PROVIDER_MENU="Не определён"
|
||||
fi
|
||||
}
|
||||
|
||||
provider_force_redetect() {
|
||||
echo "Обновляем данные о провайдере..."
|
||||
rm -f "$PROVIDER_CACHE"
|
||||
_detect_api_simple
|
||||
|
||||
if [ -s "$PROVIDER_CACHE" ]; then
|
||||
PROVIDER_MENU="$(cat "$PROVIDER_CACHE")"
|
||||
else
|
||||
PROVIDER_MENU="Не удалось определить"
|
||||
fi
|
||||
}
|
||||
|
||||
provider_set_manual_menu() {
|
||||
read -re -p "Провайдер (например MTS/Beeline): " p
|
||||
read -re -p "Город (можно пусто): " c
|
||||
|
||||
local res="$p"
|
||||
[ -n "$c" ] && res="$res - $c"
|
||||
|
||||
mkdir -p "$(dirname "$PROVIDER_CACHE")"
|
||||
echo "$res" > "$PROVIDER_CACHE"
|
||||
PROVIDER_MENU="$res"
|
||||
}
|
||||
# ---- /Provider detector integration ----
|
||||
|
||||
|
||||
63
lib/recommendations.sh
Normal file
63
lib/recommendations.sh
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# ---- Recomendations module ----
|
||||
|
||||
RECS_URL="https://raw.githubusercontent.com/IndeecFOX/zapret4rocket/master/recommendations.txt"
|
||||
RECS_FILE="/opt/zapret/extra_strats/cache/recommendations.txt"
|
||||
|
||||
# 1. Функция обновления базы
|
||||
update_recommendations() {
|
||||
mkdir -p "$(dirname "$RECS_FILE")"
|
||||
|
||||
# Проверка: если файл существует И он моложе 1 дня (24 часа) - выходим.
|
||||
# -mtime -1 означает "изменен менее 1 дня назад"
|
||||
if [ -f "$RECS_FILE" ] && [ -n "$(find "$RECS_FILE" -mtime -1 2>/dev/null)" ]; then
|
||||
# Файл свежий, обновлять не нужно
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Если файла нет или он старый - качаем
|
||||
curl -s --max-time 5 "$RECS_URL" -o "$RECS_FILE" || rm -f "$RECS_FILE"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 2. Функция показа подсказки (Logic + UI)
|
||||
show_hint() {
|
||||
local strat_type="$1" # UDP, TCP, GV или RKN
|
||||
local my_isp=""
|
||||
|
||||
# А. Узнаем провайдера
|
||||
if [ -s "/opt/zapret/extra_strats/cache/provider.txt" ]; then
|
||||
my_isp="$(cat "/opt/zapret/extra_strats/cache/provider.txt")"
|
||||
fi
|
||||
|
||||
# Б. Проверяем наличие базы
|
||||
if [ -z "$my_isp" ] || [ ! -f "$RECS_FILE" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# В. Ищем строку (grep -F для безопасности спецсимволов)
|
||||
local line
|
||||
line="$(grep -F "$my_isp|" "$RECS_FILE" | head -n 1)"
|
||||
[ -z "$line" ] && return 0
|
||||
|
||||
# Г. Парсим (актуальный формат у тебя: ISP|UDP:...|TCP:...|GV:...|RKN:...
|
||||
local part=""
|
||||
case "$strat_type" in
|
||||
"UDP") part="$(echo "$line" | cut -d'|' -f2 | cut -d':' -f2)" ;;
|
||||
"TCP") part="$(echo "$line" | cut -d'|' -f3 | cut -d':' -f2)" ;;
|
||||
"GV") part="$(echo "$line" | cut -d'|' -f4 | cut -d':' -f2)" ;;
|
||||
"RKN") part="$(echo "$line" | cut -d'|' -f5 | cut -d':' -f2)" ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
|
||||
# Д. Выводим
|
||||
if [ -n "$part" ] && [ "$part" != "-" ]; then
|
||||
echo ""
|
||||
echo -e "${cyan}💡 Подсказка:${plain} Пользователи ${green}$my_isp${plain} часто выбирают: ${yellow}$part${plain}"
|
||||
echo -e "Попробуйте начать с них."
|
||||
echo ""
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# ---- /Recomendations module ----
|
||||
203
lib/strategies.sh
Normal file
203
lib/strategies.sh
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
# Функция определяет номер активной стратегии в указанной папке
|
||||
# Использование: get_active_strat_num "/path/to/folder" MAX_COUNT
|
||||
get_active_strat_num() {
|
||||
local folder="$1"
|
||||
local max="$2"
|
||||
local i
|
||||
|
||||
# Перебираем файлы от 1 до MAX
|
||||
for ((i=1; i<=max; i++)); do
|
||||
if [ -s "${folder}/${i}.txt" ]; then
|
||||
echo "$i"
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
# Если ничего не найдено - 0
|
||||
echo "0"
|
||||
}
|
||||
|
||||
# Функция для генерации строки статуса стратегий
|
||||
get_current_strategies_info() {
|
||||
local s_udp=$(get_active_strat_num "/opt/zapret/extra_strats/UDP/YT" 8)
|
||||
local s_tcp=$(get_active_strat_num "/opt/zapret/extra_strats/TCP/YT" 17)
|
||||
local s_gv=$(get_active_strat_num "/opt/zapret/extra_strats/TCP/GV" 17)
|
||||
local s_rkn=$(get_active_strat_num "/opt/zapret/extra_strats/TCP/RKN" 17)
|
||||
|
||||
# Формируем красивую строку. Цвета можно менять.
|
||||
# Функция для окраски: 0 - серый, >0 - зеленый
|
||||
colorize_num() {
|
||||
if [ "$1" == "0" ]; then
|
||||
echo "${gray}Def${plain}"
|
||||
else
|
||||
echo "${green}$1${plain}"
|
||||
fi
|
||||
}
|
||||
|
||||
echo -e "YT_UDP:$(colorize_num "$s_udp") YT_TCP:$(colorize_num "$s_tcp") YT_GV:$(colorize_num "$s_gv") RKN:$(colorize_num "$s_rkn")"
|
||||
}
|
||||
|
||||
#Функция для функции подбора стратегий
|
||||
try_strategies() {
|
||||
local count="$1"
|
||||
local base_path="$2"
|
||||
local list_file="$3"
|
||||
local final_action="$4"
|
||||
|
||||
read -re -p "Введите номер стратегии к которой перейти или Enter: " strat_num
|
||||
if (( strat_num < 1 || strat_num > count )); then
|
||||
echo "Введено значение не из диапазона. Начинаем с 1 стратегии"
|
||||
strat_num=1
|
||||
fi
|
||||
|
||||
# Предварительная очистка всех файлов стратегий в папке
|
||||
for ((clr_txt=1; clr_txt<=count; clr_txt++)); do
|
||||
echo -n > "$base_path/${clr_txt}.txt"
|
||||
done
|
||||
|
||||
# Основной цикл перебора
|
||||
for ((strat_num=strat_num; strat_num<=count; strat_num++)); do
|
||||
|
||||
# Очищаем файл предыдущей стратегии (чтобы не было дублей)
|
||||
if [[ $strat_num -ge 2 ]]; then
|
||||
prev=$((strat_num - 1))
|
||||
echo -n > "$base_path/${prev}.txt"
|
||||
fi
|
||||
|
||||
# Запись в файл текущей стратегии
|
||||
if [[ "$list_file" != "/dev/null" ]]; then
|
||||
# Режим списка (копируем весь файл)
|
||||
cp "$list_file" "$base_path/${strat_num}.txt"
|
||||
else
|
||||
# Режим одного домена
|
||||
echo "$user_domain" > "$base_path/${strat_num}.txt"
|
||||
fi
|
||||
|
||||
echo "Стратегия номер $strat_num активирована"
|
||||
|
||||
# Блок проверки доступности (curl)
|
||||
# Работает только для TCP стратегий
|
||||
if [[ "$count" == "17" ]]; then
|
||||
local TestURL=""
|
||||
|
||||
# ЛОГИКА ВЫБОРА ДОМЕНА ДЛЯ ПРОВЕРКИ
|
||||
if [[ "$user_domain" == "googlevideo.com" ]]; then
|
||||
# 1. Если это GVideo - ищем живой кластер для проверки видеопотока
|
||||
local cluster
|
||||
cluster=$(get_yt_cluster_domain)
|
||||
TestURL="https://$cluster"
|
||||
echo "Проверка доступности (кластер): $cluster"
|
||||
|
||||
elif [[ -z "$user_domain" ]]; then
|
||||
# 2. Если домен пустой (обычный режим YT) - проверяем доступ к самому сайту
|
||||
TestURL="https://www.youtube.com"
|
||||
|
||||
else
|
||||
# 3. Для кастомных доменов и RKN проверяем сам введенный домен
|
||||
TestURL="https://$user_domain"
|
||||
fi
|
||||
|
||||
check_access "$TestURL"
|
||||
fi
|
||||
|
||||
read -re -p "Проверьте работу (1 - сохранить, 0 - отмена, Enter - далее): " answer_strat
|
||||
|
||||
if [[ "$answer_strat" == "1" ]]; then
|
||||
echo "Стратегия $strat_num сохранена."
|
||||
send_stats # Отправка телеметрии (если включена)
|
||||
|
||||
# Если передано дополнительное действие (final_action), выполняем его
|
||||
if [[ -n "$final_action" ]]; then
|
||||
eval "$final_action"
|
||||
fi
|
||||
return
|
||||
|
||||
elif [[ "$answer_strat" == "0" ]]; then
|
||||
# Сброс текущей стратегии при отмене
|
||||
echo -n > "$base_path/${strat_num}.txt"
|
||||
echo "Изменения отменены."
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
# Если цикл закончился, а пользователь ничего не выбрал
|
||||
echo -n > "$base_path/${count}.txt"
|
||||
echo "Все стратегии испробованы. Ничего не подошло."
|
||||
pause_enter
|
||||
return
|
||||
}
|
||||
|
||||
#Сама функция подбора стратегий
|
||||
Strats_Tryer() {
|
||||
local mode_domain="$1"
|
||||
local answer_strat_mode=""
|
||||
local user_domain=""
|
||||
|
||||
# ВАЖНО: теперь Strats_Tryer не рисует меню и не спрашивает режим сам.
|
||||
# Режим выбирается снаружи (strategies_submenu), а сюда приходит либо:
|
||||
# - "1".."4" (режим)
|
||||
# - или строка-домен (режим кастомного домена)
|
||||
|
||||
case "$mode_domain" in
|
||||
"1"|"2"|"3"|"4")
|
||||
answer_strat_mode="$mode_domain"
|
||||
;;
|
||||
*)
|
||||
# Если аргумент не похож на режим — считаем, что это домен
|
||||
answer_strat_mode="5"
|
||||
user_domain="$mode_domain"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$answer_strat_mode" in
|
||||
"1")
|
||||
echo "Подбор для хост-листа YouTube с видеопотоком (UDP QUIC - браузеры, моб. приложения). Ранее заданная стратегия этого листа сброшена в дефолт."
|
||||
#вывод подсказки
|
||||
show_hint "UDP"
|
||||
try_strategies 8 "/opt/zapret/extra_strats/UDP/YT" "/opt/zapret/extra_strats/UDP/YT/List.txt" ""
|
||||
;;
|
||||
"2")
|
||||
echo "Подбор для хост-листа YouTube (TCP - сам интерфейс. Без видео-домена). Ранее заданная стратегия этого листа сброшена в дефолт."
|
||||
#вывод подсказки
|
||||
show_hint "TCP"
|
||||
try_strategies 17 "/opt/zapret/extra_strats/TCP/YT" "/opt/zapret/extra_strats/TCP/YT/List.txt" ""
|
||||
;;
|
||||
"3")
|
||||
echo "Подбор для googlevideo.com (Видеопоток YouTube). Ранее заданная стратегия этого листа сброшена в дефолт."
|
||||
#на всякий случай убираем GV из листа YT
|
||||
[ -f "/opt/zapret/extra_strats/TCP/YT/List.txt" ] && \
|
||||
sed -i '/googlevideo.com/d' "/opt/zapret/extra_strats/TCP/YT/List.txt"
|
||||
user_domain="googlevideo.com"
|
||||
#вывод подсказки
|
||||
show_hint "GV"
|
||||
try_strategies 17 "/opt/zapret/extra_strats/TCP/GV" "/dev/null" ""
|
||||
;;
|
||||
"4")
|
||||
echo "Подбор для хост-листа основных доменов блока RKN. Проверка доступности задана на домен meduza.io. Ранее заданная стратегия этого листа сброшена в дефолт."
|
||||
for numRKN in {1..17}; do
|
||||
echo -n > "/opt/zapret/extra_strats/TCP/RKN/${numRKN}.txt"
|
||||
done
|
||||
user_domain="meduza.io"
|
||||
#вывод подсказки
|
||||
show_hint "RKN"
|
||||
try_strategies 17 "/opt/zapret/extra_strats/TCP/RKN" "/opt/zapret/extra_strats/TCP/RKN/List.txt" ""
|
||||
;;
|
||||
"5")
|
||||
echo "Режим ручного указания домена"
|
||||
# раньше домен спрашивался тут, но теперь ввод домена делается в сабменю
|
||||
if [ -z "$user_domain" ]; then
|
||||
echo "Домен не задан. Отмена."
|
||||
return 0
|
||||
fi
|
||||
echo "Введён домен: $user_domain"
|
||||
|
||||
try_strategies 17 "/opt/zapret/extra_strats/TCP/temp" "/dev/null" \
|
||||
"echo -n > \"/opt/zapret/extra_strats/TCP/temp/\${strat_num}.txt\"; \
|
||||
echo \"$user_domain\" >> \"/opt/zapret/extra_strats/TCP/User/\${strat_num}.txt\""
|
||||
;;
|
||||
*)
|
||||
echo "Пропуск подбора альтернативной стратегии"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
199
lib/submenus.sh
Normal file
199
lib/submenus.sh
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
# submenus.sh
|
||||
# Единый стиль: loop + return на 0/Enter
|
||||
|
||||
#функция меню "1. Сменить стратегии"
|
||||
strategies_submenu() {
|
||||
while true; do
|
||||
local strategies_status
|
||||
strategies_status=$(get_current_strategies_info)
|
||||
clear
|
||||
|
||||
echo -e "${cyan}--- Управление стратегиями ---${plain}"
|
||||
echo -e "${yellow}Подобрать стратегию? (1-5 для подбора, 0 или Enter для отмены)${plain}"
|
||||
echo -e " Текущие стратегии [${strategies_status}]"
|
||||
echo -e
|
||||
|
||||
submenu_item " 1" "YouTube с видеопотоком (UDP QUIC)." "8 вариантов"
|
||||
submenu_item " 2" "YouTube (TCP. Интерфейс)." "17 вариантов"
|
||||
submenu_item " 3" "YouTube (TCP. Видеопоток/GV домен)." "17 вариантов"
|
||||
submenu_item " 4" "RKN (Популярные блокированные сайты. Дискорд в т.ч.)." "17 вариантов"
|
||||
submenu_item " 5" "Отдельный домен." "17 вариантов"
|
||||
submenu_item " 0" "Назад"
|
||||
echo ""
|
||||
|
||||
read -re -p "Ваш выбор: " ans
|
||||
|
||||
case "$ans" in
|
||||
"1"|"2"|"3"|"4")
|
||||
Strats_Tryer "$ans"
|
||||
pause_enter
|
||||
;;
|
||||
"5")
|
||||
local user_domain=""
|
||||
read -re -p "Введите домен (например mydomain.com) или Enter для выхода: " user_domain
|
||||
[ -z "$user_domain" ] && continue
|
||||
Strats_Tryer "$user_domain"
|
||||
pause_enter
|
||||
;;
|
||||
"0"|"")
|
||||
return
|
||||
;;
|
||||
*)
|
||||
echo -e "${yellow}Неверный ввод.${plain}"
|
||||
sleep 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
flowoffload_submenu() {
|
||||
while true; do
|
||||
clear
|
||||
echo -e "${cyan}--- FLOWOFFLOAD ---${plain}"
|
||||
echo "Текущее состояние: $(grep '^FLOWOFFLOAD=' /opt/zapret/config 2>/dev/null)"
|
||||
echo ""
|
||||
|
||||
submenu_item "1" "software (программное ускорение)"
|
||||
submenu_item "2" "hardware (аппаратное NAT)"
|
||||
submenu_item "3" "none (отключено)"
|
||||
submenu_item "4" "donttouch (дефолт)"
|
||||
submenu_item "0" "Назад"
|
||||
echo ""
|
||||
|
||||
read -re -p "Ваш выбор: " ans
|
||||
|
||||
case "$ans" in
|
||||
"1")
|
||||
sed -i 's/^FLOWOFFLOAD=.*/FLOWOFFLOAD=software/' "/opt/zapret/config"
|
||||
/opt/zapret/install_prereq.sh
|
||||
/opt/zapret/init.d/sysv/zapret restart
|
||||
echo -e "${green}FLOWOFFLOAD=software применён.${plain}"
|
||||
pause_enter
|
||||
;;
|
||||
"2")
|
||||
sed -i 's/^FLOWOFFLOAD=.*/FLOWOFFLOAD=hardware/' "/opt/zapret/config"
|
||||
/opt/zapret/install_prereq.sh
|
||||
/opt/zapret/init.d/sysv/zapret restart
|
||||
echo -e "${green}FLOWOFFLOAD=hardware применён.${plain}"
|
||||
pause_enter
|
||||
;;
|
||||
"3")
|
||||
sed -i 's/^FLOWOFFLOAD=.*/FLOWOFFLOAD=none/' "/opt/zapret/config"
|
||||
/opt/zapret/install_prereq.sh
|
||||
/opt/zapret/init.d/sysv/zapret restart
|
||||
echo -e "${green}FLOWOFFLOAD=none применён.${plain}"
|
||||
pause_enter
|
||||
;;
|
||||
"4")
|
||||
sed -i 's/^FLOWOFFLOAD=.*/FLOWOFFLOAD=donttouch/' "/opt/zapret/config"
|
||||
/opt/zapret/install_prereq.sh
|
||||
/opt/zapret/init.d/sysv/zapret restart
|
||||
echo -e "${green}FLOWOFFLOAD=donttouch применён.${plain}"
|
||||
pause_enter
|
||||
;;
|
||||
"0"|"")
|
||||
return
|
||||
;;
|
||||
*)
|
||||
echo -e "${yellow}Неверный ввод.${plain}"
|
||||
sleep 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
tcp443_submenu() {
|
||||
while true; do
|
||||
clear
|
||||
num=$(sed -n '112,128p' /opt/zapret/config | grep -n '^--filter-tcp=443 --hostlist-domains= --' | head -n1 | cut -d: -f1)
|
||||
echo -e "${yellow}Безразборный режим по стратегии: ${plain}$((num ? num : 0))"
|
||||
echo -e "\033[33mС каким номером применить стратегию? (1-17, 0 - отключение безразборного режима, Enter - выход) \033[31mПри активации кастомно подобранные домены будут очищены:${plain}"
|
||||
read -re -p " " answer_bezr
|
||||
|
||||
case "$answer_bezr" in
|
||||
"" )
|
||||
return
|
||||
;;
|
||||
*)
|
||||
if echo "$answer_bezr" | grep -Eq '^[0-9]+$' && [ "$answer_bezr" -ge 0 ] && [ "$answer_bezr" -le 17 ]; then
|
||||
#Отключение
|
||||
for i in $(seq 112 128); do
|
||||
if sed -n "${i}p" /opt/zapret/config | grep -Fq -- '--filter-tcp=443 --hostlist-domains= --h'; then
|
||||
sed -i "${i}s#--filter-tcp=443 --hostlist-domains= --h#--filter-tcp=443 --hostlist-domains=none.dom --h#" /opt/zapret/config
|
||||
/opt/zapret/init.d/sysv/zapret restart
|
||||
echo -e "${green}Выполнена команда перезапуска zapret${plain}"
|
||||
echo "Безразборный режим отключен"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$answer_bezr" -ge 1 ] && [ "$answer_bezr" -le 17 ]; then
|
||||
for f_clear in $(seq 1 17); do
|
||||
echo -n > "/opt/zapret/extra_strats/TCP/User/$f_clear.txt"
|
||||
echo -n > "/opt/zapret/extra_strats/TCP/temp/$f_clear.txt"
|
||||
done
|
||||
sed -i "$((111 + answer_bezr))s/--hostlist-domains=none\.dom/--hostlist-domains=/" /opt/zapret/config
|
||||
/opt/zapret/init.d/sysv/zapret restart
|
||||
echo -e "${green}Выполнена команда перезапуска zapret. ${yellow}Безразборный режим активирован на $answer_bezr стратегии для TCP-443. Проверка доступа к meduza.io${plain}"
|
||||
check_access_list
|
||||
fi
|
||||
read -n 1 -s -r -p "Нажмите любую клавишу для продолжения..."
|
||||
else
|
||||
echo -e "${yellow}Неверный ввод.${plain}"
|
||||
sleep 1
|
||||
pause_enter
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
provider_submenu() {
|
||||
provider_init_once
|
||||
|
||||
while true; do
|
||||
clear
|
||||
echo -e "${cyan}--- Провайдер / подсказки ---${plain}"
|
||||
echo -e "Текущий провайдер: ${green}${PROVIDER_MENU}${plain}"
|
||||
echo ""
|
||||
|
||||
submenu_item "1" "Указать провайдера вручную"
|
||||
submenu_item "2" "Определить провайдера заново (сбросить кэш)"
|
||||
submenu_item "3" "Обновить базу рекомендаций (подсказки)"
|
||||
submenu_item "0" "Назад"
|
||||
echo ""
|
||||
|
||||
read -re -p "Ваш выбор: " ans
|
||||
|
||||
case "$ans" in
|
||||
"1")
|
||||
provider_set_manual_menu
|
||||
sleep 1
|
||||
pause_enter
|
||||
;;
|
||||
"2")
|
||||
provider_force_redetect
|
||||
sleep 1
|
||||
pause_enter
|
||||
;;
|
||||
"3")
|
||||
echo "Обновляем базу рекомендаций..."
|
||||
rm -f "$RECS_FILE"
|
||||
update_recommendations
|
||||
if [ -s "$RECS_FILE" ]; then
|
||||
echo -e "${green}База успешно обновлена!${plain}"
|
||||
else
|
||||
echo -e "${red}Ошибка обновления базы.${plain}"
|
||||
fi
|
||||
sleep 1
|
||||
pause_enter
|
||||
;;
|
||||
"0"|"")
|
||||
return
|
||||
;;
|
||||
*)
|
||||
echo -e "${yellow}Неверный ввод.${plain}"
|
||||
sleep 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
106
lib/telemetry.sh
Normal file
106
lib/telemetry.sh
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
# ---- Telemetry module integration ----
|
||||
# Настройки Google Forms
|
||||
STATS_FORM_ID="1FAIpQLScrUf7Pybm0n61aK8aZuxuAR8KhyNYZ-X0xjSUS8K72SmEhPw"
|
||||
ENTRY_UUID="entry.1346249141"
|
||||
ENTRY_ISP="entry.2008245653"
|
||||
ENTRY_UDP="entry.592144534"
|
||||
ENTRY_TCP="entry.1826276405"
|
||||
ENTRY_GV="entry.1549076812"
|
||||
ENTRY_RKN="entry.1527830884"
|
||||
|
||||
# 2. Пути к файлам (используем простые форматы)
|
||||
CACHE_DIR="/opt/zapret/extra_strats/cache"
|
||||
TELEMETRY_CFG="$CACHE_DIR/telemetry.config"
|
||||
PROVIDER_TXT="$CACHE_DIR/provider.txt"
|
||||
|
||||
# Функция инициализации (Спрашивает пользователя один раз)
|
||||
init_telemetry() {
|
||||
mkdir -p "$CACHE_DIR"
|
||||
local tel_enabled=""
|
||||
local tel_uuid=""
|
||||
|
||||
# 1. Загружаем конфиг, если он есть
|
||||
[ -f "$TELEMETRY_CFG" ] && source "$TELEMETRY_CFG"
|
||||
|
||||
# 2. Если статус еще не задан — спрашиваем
|
||||
if [ -z "$tel_enabled" ]; then
|
||||
echo ""
|
||||
echo -e "${green}Хотите отправлять анонимную статистику (Провайдер + Стратегии)?${plain}"
|
||||
echo -e "Это поможет понять, какие стратегии работают лучше всего."
|
||||
read -p "Разрешить? (y/n): " stats_yn
|
||||
|
||||
case "$stats_yn" in
|
||||
[Yy]*) tel_enabled="1" ;;
|
||||
*) tel_enabled="0" ;;
|
||||
esac
|
||||
|
||||
# Сразу сохраняем выбор
|
||||
echo "tel_enabled=$tel_enabled" > "$TELEMETRY_CFG"
|
||||
echo "tel_uuid=$tel_uuid" >> "$TELEMETRY_CFG"
|
||||
|
||||
if [ "$tel_enabled" == "1" ]; then
|
||||
echo -e "${green}Спасибо! Статистика включена.${plain}"
|
||||
else
|
||||
echo -e "${red}Статистика отключена.${plain}"
|
||||
fi
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
# 3. Генерация UUID (если включено и его нет)
|
||||
if [ "$tel_enabled" == "1" ] && [ -z "$tel_uuid" ]; then
|
||||
# Пытаемся взять системный UUID или генерируем md5 от времени
|
||||
if [ -f /proc/sys/kernel/random/uuid ]; then
|
||||
tel_uuid=$(cat /proc/sys/kernel/random/uuid | cut -c1-8)
|
||||
else
|
||||
tel_uuid=$(date +%s%N | md5sum | head -c 8)
|
||||
fi
|
||||
|
||||
# Перезаписываем конфиг с новым UUID
|
||||
echo "tel_enabled=$tel_enabled" > "$TELEMETRY_CFG"
|
||||
echo "tel_uuid=$tel_uuid" >> "$TELEMETRY_CFG"
|
||||
fi
|
||||
}
|
||||
|
||||
# Функция отправки статистики
|
||||
send_stats() {
|
||||
# Если конфига нет, значит init_telemetry не запускался — выходим
|
||||
[ ! -f "$TELEMETRY_CFG" ] && return 0
|
||||
|
||||
# Читаем переменные (tel_enabled, tel_uuid)
|
||||
source "$TELEMETRY_CFG"
|
||||
|
||||
# Если пользователь запретил — выходим
|
||||
if [ "$tel_enabled" != "1" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 1. Провайдер (Читаем из provider.txt, который создает Provider detector)
|
||||
local my_isp="Unknown"
|
||||
if [ -s "$PROVIDER_TXT" ]; then
|
||||
my_isp=$(cat "$PROVIDER_TXT")
|
||||
else
|
||||
# Фолбек: если provider.txt еще нет, пробуем быстро узнать
|
||||
my_isp=$(curl -s --max-time 3 "http://ip-api.com/line?fields=org" | tr -cd '[:alnum:] ._-')
|
||||
fi
|
||||
|
||||
# Обрезаем до 60 символов и ставим заглушку если пусто
|
||||
my_isp=$(echo "$my_isp" | head -c 60)
|
||||
[ -z "$my_isp" ] && my_isp="Unknown"
|
||||
|
||||
# 2. Определяем номера стратегий
|
||||
local s_udp=$(get_active_strat_num "/opt/zapret/extra_strats/UDP/YT" 8)
|
||||
local s_tcp=$(get_active_strat_num "/opt/zapret/extra_strats/TCP/YT" 17)
|
||||
local s_gv=$(get_active_strat_num "/opt/zapret/extra_strats/TCP/GV" 17)
|
||||
local s_rkn=$(get_active_strat_num "/opt/zapret/extra_strats/TCP/RKN" 17)
|
||||
|
||||
# 3. Отправка в Google Forms (Тихий режим, в фоне &)
|
||||
curl -sL --max-time 10 \
|
||||
-d "$ENTRY_UUID=$tel_uuid" \
|
||||
-d "$ENTRY_ISP=$my_isp" \
|
||||
-d "$ENTRY_UDP=$s_udp" \
|
||||
-d "$ENTRY_TCP=$s_tcp" \
|
||||
-d "$ENTRY_GV=$s_gv" \
|
||||
-d "$ENTRY_RKN=$s_rkn" \
|
||||
"https://docs.google.com/forms/d/e/$STATS_FORM_ID/formResponse" > /dev/null 2>&1 &
|
||||
}
|
||||
# ---- /Telemetry module integration ----
|
||||
14
lib/ui.sh
Normal file
14
lib/ui.sh
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# UI helpers
|
||||
|
||||
pause_enter() {
|
||||
read -re -p "Enter для продолжения" _
|
||||
}
|
||||
|
||||
submenu_item() {
|
||||
echo -e "${green}$1. $2${plain} $3"
|
||||
}
|
||||
|
||||
# Совместимость со старым кодом меню
|
||||
exit_to_menu() {
|
||||
pause_enter
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue