39 Commits

Author SHA1 Message Date
CherretGit
bfdd7a0a76 fix service status 2025-10-31 02:38:47 +07:00
CherretGit
47f314cd19 Add zapret binary version 2025-10-30 22:47:05 +07:00
white
10fdf4c227 remove bin-ver, add root checks on start and stop 2025-10-30 17:20:54 +03:00
CherretGit
784a248c11 stop_service command, fix 2025-10-30 18:41:47 +07:00
CherretGit
192d846a12 await 2025-10-30 04:09:37 +07:00
CherretGit
87a6b72aee move paths to constants (again) 2025-10-30 03:32:52 +07:00
sqlerrorthing
7ea4a516be daemonize 2025-10-29 23:12:53 +03:00
CherretGit
4b9e60336b Revert "move paths to constants"
This reverts commit 51af644b5f.
2025-10-30 03:08:03 +07:00
CherretGit
51af644b5f move paths to constants 2025-10-30 02:57:22 +07:00
sqlerrorthing
0f5492a29a move zapret from libs/ 2025-10-29 07:50:10 +08:00
sqlerrorthing
a16796a699 recode 2025-10-29 07:46:08 +08:00
sqlerrorthing
19a8ccd384 generate bindings 2025-10-29 07:26:32 +08:00
sqlerrorthing
58d0fdbab3 add rerun 2025-10-29 07:00:49 +08:00
sqlerrorthing
3c0488f629 working! 2025-10-29 06:58:55 +08:00
sqlerrorthing
3e009479c8 idk rename main 2025-10-29 06:08:28 +08:00
sqlerrorthing
3b66cc8136 suppress fucking C warnings 2025-10-29 05:26:09 +08:00
sqlerrorthing
db724d8667 Merge remote-tracking branch 'upstream/rust' into fix/shitcode
# Conflicts:
#	rust/src/main.rs
2025-10-29 05:20:04 +08:00
sqlerrorthing
a1a2961628 fire and forget 2025-10-29 05:05:44 +08:00
sqlerrorthing
e91cb00eec spawn blocking 2025-10-29 05:00:27 +08:00
sqlerrorthing
227db9b7fd right linking 2025-10-29 04:52:48 +08:00
white
c9b4a722c1 i give up 2025-10-28 23:25:34 +03:00
white
021fc6f53e trying to implement rust 2025-10-28 22:21:24 +03:00
egor-white
d3dbf4ddc5 Update update's.json and changelog 2025-10-16 13:28:26 +00:00
egor-white
0213c239fc Update workflow.yml 2025-10-16 16:27:40 +03:00
egor-white
2d90aea5ca Update workflow.yml 2025-10-16 16:25:56 +03:00
egor-white
e62336e253 Update workflow.yml 2025-10-16 16:22:15 +03:00
CherretGit
dd78b59a68 Update customize.sh 2025-10-12 14:16:55 +07:00
CherretGit
0a0c3fd80b Update customize.sh 2025-10-12 14:12:46 +07:00
CherretGit
3a7c40f167 Update service.sh 2025-10-12 14:10:05 +07:00
CherretGit
9ef7c70f78 ipsets 2025-09-30 22:27:19 +07:00
CherretGit
534f3a733a fix autostart 2025-09-30 22:24:49 +07:00
egor-white
ccaac37b52 Update README.md 2025-09-18 18:50:36 +03:00
egor-white
c2db7fbdac Update README.md 2025-09-18 18:49:37 +03:00
CherretGit
ea92b6cf6f Update workflow_without_post.yml 2025-08-21 17:52:15 +07:00
CherretGit
0fbcd24088 Update workflow.yml 2025-08-21 17:51:40 +07:00
CherretGit
45017d35b2 Update changelog.md 2025-08-21 17:47:01 +07:00
CherretGit
718ed43ef8 Update update's.json and changelog 2025-08-21 10:43:50 +00:00
CherretGit
6318977857 Add files via upload 2025-08-21 17:43:01 +07:00
CherretGit
e3effc3292 Update update's.json and changelog 2025-08-21 10:41:45 +00:00
24 changed files with 2136 additions and 109 deletions

View File

@@ -4,23 +4,23 @@ on:
workflow_dispatch:
inputs:
tag:
description: 'Tag for the release (x.x.x)'
description: "Tag for the release (x.x.x)"
required: true
type: string
version:
description: 'Module version (x.x)'
description: "Module version (x.x)"
required: true
type: string
version_code:
description: 'Module version code (xx)'
description: "Module version code (xx)"
required: true
type: string
release_name:
description: 'Release Name'
description: "Release Name"
required: true
type: string
release_changes:
description: 'Release Changes'
description: "Release Changes"
required: true
type: string
@@ -31,7 +31,7 @@ jobs:
- uses: actions/checkout@v4
- name: Make build dirs
run: mkdir -p zaprett/system/bin zaprett-hosts/system/bin zaprett-tv/system/bin zaprett/system/etc/zaprett/lists zapret-latest out lists zapret-hosts/system/etc/zaprett/lists zapret-tv/system/etc/zaprett/lists
run: mkdir -p zaprett/system/bin zaprett-hosts/system/bin zaprett-tv/system/bin zaprett/system/etc/zaprett/lists zapret-latest out lists zapret-hosts/system/etc/zaprett/lists zapret-tv/system/etc/zaprett/lists
- name: Download latest zapret binaries
run: |
@@ -61,15 +61,15 @@ jobs:
cp zapret-latest/binaries/linux-mips/nfqws zaprett/system/bin/nfqws_mips
cp zapret-latest/binaries/linux-mipsel/nfqws zaprett/system/bin/nfqws_mipsel
cp -a src/* zaprett/
cp -a src-module/* zaprett/
#copy all files to another distributions
cp -r zaprett/* zaprett-hosts/
cp -r zaprett/* zaprett-tv/
- name: Download and copy actual lists
run: |
wget https://raw.githubusercontent.com/CherretGit/zaprett-hosts-repo/refs/heads/main/lists/list-youtube.txt -O lists/list-youtube.txt
wget https://raw.githubusercontent.com/CherretGit/zaprett-hosts-repo/refs/heads/main/lists/list-discord.txt -O lists/list-discord.txt
wget https://raw.githubusercontent.com/CherretGit/zaprett-repo/refs/heads/main/lists/include/list-youtube.txt -O lists/list-youtube.txt
wget https://raw.githubusercontent.com/CherretGit/zaprett-repo/refs/heads/main/lists/include/list-discord.txt -O lists/list-discord.txt
cp lists/list-youtube.txt zaprett/system/etc/zaprett/lists/
cp lists/list-youtube.txt zaprett-hosts/system/etc/zaprett/lists/
@@ -79,7 +79,7 @@ jobs:
cp lists/list-discord.txt zaprett-hosts/system/etc/zaprett/lists/
cp hosts/hosts zaprett-hosts/system/etc
- name: Create module.prop
run: |
cat > zaprett/module.prop <<EOF
@@ -87,31 +87,31 @@ jobs:
name=zaprett
version=${{ inputs.version }}
versionCode=${{ inputs.version_code }}
author=egor-white, Huananzhi X99, Cherret
author=egor-white, Cherret
description=Ускорение CDN серверов Google. ТГК: https://t.me/zaprett_module
updateJson=https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/update.json
EOF
cat > zaprett-hosts/module.prop <<EOF
id=zaprett
name=zaprett-hosts
version=${{ inputs.version }}
versionCode=${{ inputs.version_code }}
author=egor-white, Huananzhi X99, Cherret
author=egor-white, Cherret
description=Ускорение CDN серверов Google. ТГК: https://t.me/zaprett_module
updateJson=https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/update-extended.json
updateJson=https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/update-hosts.json
EOF
cat > zaprett-tv/module.prop <<EOF
id=zaprett
name=zaprett-tv
version=${{ inputs.version }}
versionCode=${{ inputs.version_code }}
author=egor-white, Huananzhi X99, Cherret
author=egor-white, Cherret
description=Ускорение CDN серверов Google. ТГК: https://t.me/zaprett_module
updateJson=https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/update-tv.json
EOF
- name: Tree files
run: |
tree zaprett/ zaprett-hosts/ zaprett-tv/
@@ -124,7 +124,7 @@ jobs:
mv zaprett.zip out/
mv zaprett-hosts.zip out/
mv zaprett-tv.zip out/
- name: Create release
uses: softprops/action-gh-release@v2
with:
@@ -136,7 +136,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Update changelog
run: echo "${{ inputs.release_changes}}" > changelog.md
- name: Update update.json
run: |
cat > update.json <<EOF
@@ -167,8 +167,8 @@ jobs:
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "Update update's.json and changelog"
file_pattern: 'update.json update_hosts.json update_tv.json changelog.md'
file_pattern: "update.json update_hosts.json update_tv.json changelog.md"
- name: Send bot post
env:
MESSAGE_TEXT: |
@@ -185,4 +185,3 @@ jobs:
-d parse_mode=HTML \
-d disable_web_page_preview=true \
--data-urlencode "text=$MESSAGE_TEXT"

View File

@@ -4,23 +4,23 @@ on:
workflow_dispatch:
inputs:
tag:
description: 'Tag for the release (x.x.x)'
description: "Tag for the release (x.x.x)"
required: true
type: string
version:
description: 'Module version (x.x)'
description: "Module version (x.x)"
required: true
type: string
version_code:
description: 'Module version code (xx)'
description: "Module version code (xx)"
required: true
type: string
release_name:
description: 'Release Name'
description: "Release Name"
required: true
type: string
release_changes:
description: 'Release Changes'
description: "Release Changes"
required: true
type: string
@@ -31,7 +31,7 @@ jobs:
- uses: actions/checkout@v4
- name: Make build dirs
run: mkdir -p zaprett/system/bin zaprett-hosts/system/bin zaprett-tv/system/bin zaprett/system/etc/zaprett/lists zapret-latest out lists zapret-hosts/system/etc/zaprett/lists zapret-tv/system/etc/zaprett/lists
run: mkdir -p zaprett/system/bin zaprett-hosts/system/bin zaprett-tv/system/bin zaprett/system/etc/zaprett/lists zapret-latest out lists zapret-hosts/system/etc/zaprett/lists zapret-tv/system/etc/zaprett/lists
- name: Download latest zapret binaries
run: |
@@ -61,15 +61,15 @@ jobs:
cp zapret-latest/binaries/linux-mips/nfqws zaprett/system/bin/nfqws_mips
cp zapret-latest/binaries/linux-mipsel/nfqws zaprett/system/bin/nfqws_mipsel
cp -a src/* zaprett/
cp -a src-module/* zaprett/
#copy all files to another distributions
cp -r zaprett/* zaprett-hosts/
cp -r zaprett/* zaprett-tv/
- name: Download and copy actual lists
run: |
wget https://raw.githubusercontent.com/CherretGit/zaprett-hosts-repo/refs/heads/main/lists/list-youtube.txt -O lists/list-youtube.txt
wget https://raw.githubusercontent.com/CherretGit/zaprett-hosts-repo/refs/heads/main/lists/list-discord.txt -O lists/list-discord.txt
wget https://raw.githubusercontent.com/CherretGit/zaprett-repo/refs/heads/main/lists/include/list-youtube.txt -O lists/list-youtube.txt
wget https://raw.githubusercontent.com/CherretGit/zaprett-repo/refs/heads/main/lists/include/list-discord.txt -O lists/list-discord.txt
cp lists/list-youtube.txt zaprett/system/etc/zaprett/lists/
cp lists/list-youtube.txt zaprett-hosts/system/etc/zaprett/lists/
@@ -79,7 +79,7 @@ jobs:
cp lists/list-discord.txt zaprett-hosts/system/etc/zaprett/lists/
cp hosts/hosts zaprett-hosts/system/etc
- name: Create module.prop
run: |
cat > zaprett/module.prop <<EOF
@@ -87,31 +87,31 @@ jobs:
name=zaprett
version=${{ inputs.version }}
versionCode=${{ inputs.version_code }}
author=egor-white, Huananzhi X99, Cherret
author=egor-white, Cherret
description=Ускорение CDN серверов Google. ТГК: https://t.me/zaprett_module
updateJson=https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/update.json
EOF
cat > zaprett-hosts/module.prop <<EOF
id=zaprett
name=zaprett-hosts
version=${{ inputs.version }}
versionCode=${{ inputs.version_code }}
author=egor-white, Huananzhi X99, Cherret
author=egor-white, Cherret
description=Ускорение CDN серверов Google. ТГК: https://t.me/zaprett_module
updateJson=https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/update-extended.json
updateJson=https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/update-hosts.json
EOF
cat > zaprett-tv/module.prop <<EOF
id=zaprett
name=zaprett-tv
version=${{ inputs.version }}
versionCode=${{ inputs.version_code }}
author=egor-white, Huananzhi X99, Cherret
author=egor-white, Cherret
description=Ускорение CDN серверов Google. ТГК: https://t.me/zaprett_module
updateJson=https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/update-tv.json
EOF
- name: Tree files
run: |
tree zaprett/ zaprett-hosts/ zaprett-tv/
@@ -124,7 +124,7 @@ jobs:
mv zaprett.zip out/
mv zaprett-hosts.zip out/
mv zaprett-tv.zip out/
- name: Create release
uses: softprops/action-gh-release@v2
with:
@@ -136,7 +136,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Update changelog
run: echo "${{ inputs.release_changes}}" > changelog.md
- name: Update update.json
run: |
cat > update.json <<EOF
@@ -167,4 +167,4 @@ jobs:
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "Update update's.json and changelog"
file_pattern: 'update.json update_hosts.json update_tv.json changelog.md'
file_pattern: "update.json update_hosts.json update_tv.json changelog.md"

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
target

9
.gitmodules vendored Normal file
View File

@@ -0,0 +1,9 @@
[submodule "rust/libs/zapret"]
path = rust/libs/zapret
url = https://github.com/bol-van/zapret.git
[submodule "rust/crates/libnfqws/libs/zapret"]
path = rust/crates/libnfqws/libs/zapret
url = https://github.com/bol-van/zapret.git
[submodule "rust/crates/libnfqws/zapret"]
path = rust/crates/libnfqws/zapret
url = https://github.com/bol-van/zapret.git

View File

@@ -14,5 +14,26 @@
+ Работать с листами и стратегиями
+ Предлагать обновления через Magisk/KSU/KSU Next/APatch
## Какую версию модуля выбрать?
В актуальных релизах есть 3 версии модуля, а именно:
- zaprett.zip
- zaprett-hosts.zip
- zaprett-tv.zip
Основные их отличия представленны в таблице ниже.
Для устройств на Android TV **рекомендуется использовать именно TV версию** из-за некоторых особенностей работы этой ОС.
|Версия|Списки|/etc/hosts|
|------|------|----------|
|zaprett|list-youtube.txt, list-discord.txt|:x: Нет|
|zaprett-tv|list-youtube.txt|:x: Нет|
|zaprett-hosts|list-youtube.txt,list-discord.txt|:white_check_mark: Есть|
## Что такое /etc/hosts?
Говоря грубо, это файл, который влияет на работу нейросетей и других недоступных сервисов, перенаправляя ваш траффик на сторонние сервера.
Если вы используете модули, которые подменяют этот файл (например, всевозможные блокировщики рекламы и разблокировщики нейросетей), выбирайте версию <big>**без hosts**</big>, иначе модули будут конфликтовать друг с другом.
::: warning
Сервера, используемые в качестве прокси и указанные в файле hosts нам неподконтрольны, мы не несём за них отвественность, используйте с осторожностью
:::
Создано - [egor-white](https://t.me/cheesedroid), [Cherret](https://t.me/Cherret), [MT6833](https://t.me/MT6833).

View File

@@ -1 +1 @@
Небольшие изменения в customize.sh
Список изменений: ● Обновление бинарников zapret до версии 72.1 ● Добавлена поддержка ipset ● Исправление автозапуска

View File

@@ -1,35 +1,215 @@
127.0.0.1 localhost
::1 ip6-localhost
89.108.98.20 chatgpt.com
134.0.118.88 ab.chatgpt.com
89.108.98.20 auth.openai.com
89.108.98.20 auth0.openai.com
89.108.98.20 platform.openai.com
89.108.98.20 cdn.oaistatic.com
89.108.98.20 files.oaiusercontent.com
89.108.98.20 cdn.auth0.com
89.108.98.20 tcr9i.chat.openai.com
89.108.98.20 webrtc.chatgpt.com
89.108.98.20 android.chat.openai.com
89.108.98.20 gemini.google.com
89.108.98.20 aistudio.google.com
89.108.98.20 ai.google
89.108.98.20 assistant-s3-pa.googleapis.com
89.108.98.20 generativelanguage.googleapis.com
89.108.98.20 alkalimakersuite-pa.clients6.google.com
64.233.162.188 mtalk.google.com
89.108.98.20 copilot.microsoft.com
89.108.98.20 sydney.bing.com
89.108.98.20 edgeservices.bing.com
89.108.98.20 claude.ai
89.108.98.20 aitestkitchen.withgoogle.com
89.108.98.20 aisandbox-pa.googleapis.com
89.108.98.20 o.pki.goog
89.108.98.20 labs.google
89.108.98.20 notebooklm.google
89.108.98.20 notebooklm.google.com
89.108.98.20 www.notion.so
89.108.98.20 www.googleapis.com
89.108.98.20 proactivebackend-pa.googleapis.com
89.108.98.20 grok.com
89.108.98.20 assets.grok.com
# Дополнение к zapret:
157.240.245.174 instagram.com
157.240.245.174 www.instagram.com
157.240.245.174 b.i.instagram.com
157.240.245.174 z-p42-chat-e2ee-ig.facebook.com
157.240.245.174 help.instagram.com
3.66.189.153 protonmail.com
3.66.189.153 mail.proton.me
64.233.164.198 yt3.ggpht.com
52.223.13.41 tracker.openbittorrent.com
# ChatGPT, OpenAI:
204.12.192.222 chatgpt.com
204.12.192.222 ab.chatgpt.com
204.12.192.222 auth.openai.com
204.12.192.222 auth0.openai.com
204.12.192.222 platform.openai.com
204.12.192.222 cdn.oaistatic.com
204.12.192.222 files.oaiusercontent.com
204.12.192.222 cdn.auth0.com
204.12.192.222 tcr9i.chat.openai.com
204.12.192.222 webrtc.chatgpt.com
204.12.192.219 android.chat.openai.com
204.12.192.222 api.openai.com
204.12.192.221 operator.chatgpt.com
204.12.192.222 sora.chatgpt.com
204.12.192.222 sora.com
204.12.192.222 sora.chatgpt.com
204.12.192.222 videos.openai.com
# Сервисы Google:
204.12.192.222 gemini.google.com
204.12.192.222 aistudio.google.com
204.12.192.222 generativelanguage.googleapis.com
204.12.192.222 aitestkitchen.withgoogle.com
204.12.192.219 aisandbox-pa.googleapis.com
204.12.192.222 webchannel-alkalimakersuite-pa.clients6.google.com
204.12.192.221 alkalimakersuite-pa.clients6.google.com
204.12.192.221 assistant-s3-pa.googleapis.com
204.12.192.222 proactivebackend-pa.googleapis.com
204.12.192.222 o.pki.goog
204.12.192.222 labs.google
204.12.192.222 notebooklm.google
204.12.192.222 notebooklm.google.com
204.12.192.222 jules.google.com
204.12.192.222 stitch.withgoogle.com
# Microsoft Copilot, Microsoft Rewards, Xbox, Xbox Cloud Gaming:
204.12.192.222 copilot.microsoft.com
204.12.192.222 sydney.bing.com
204.12.192.222 edgeservices.bing.com
204.12.192.221 rewards.bing.com
204.12.192.222 xsts.auth.xboxlive.com
204.12.192.222 xgpuwebf2p.gssv-play-prod.xboxlive.com
204.12.192.222 xgpuweb.gssv-play-prod.xboxlive.com
# Spotify:
204.12.192.222 api.spotify.com
204.12.192.222 xpui.app.spotify.com
204.12.192.222 appresolve.spotify.com
204.12.192.222 login5.spotify.com
204.12.192.222 login.app.spotify.com
204.12.192.222 encore.scdn.co
204.12.192.222 ap-gew1.spotify.com
204.12.192.222 gew1-spclient.spotify.com
204.12.192.222 spclient.wg.spotify.com
204.12.192.222 api-partner.spotify.com
204.12.192.222 aet.spotify.com
204.12.192.222 www.spotify.com
204.12.192.222 accounts.spotify.com
204.12.192.221 open.spotify.com
# GitHub Copilot:
204.12.192.222 api.github.com
204.12.192.222 api.individual.githubcopilot.com
204.12.192.222 proxy.individual.githubcopilot.com
# JetBrains:
50.7.85.221 datalore.jetbrains.com
107.150.34.100 plugins.jetbrains.com
204.12.192.222 download.jetbrains.com
# ElevenLabs:
204.12.192.222 elevenlabs.io
204.12.192.222 api.us.elevenlabs.io
204.12.192.222 elevenreader.io
204.12.192.222 api.elevenlabs.io
204.12.192.222 help.elevenlabs.io
# Truth Social
204.12.192.221 truthsocial.com
204.12.192.221 static-assets-1.truthsocial.com
# Grok
204.12.192.222 grok.com
204.12.192.222 accounts.x.ai
204.12.192.222 assets.grok.com
# Tidal
204.12.192.222 api.tidal.com
204.12.192.222 listen.tidal.com
204.12.192.222 login.tidal.com
204.12.192.222 auth.tidal.com
204.12.192.222 link.tidal.com
204.12.192.222 dd.tidal.com
204.12.192.222 resources.tidal.com
204.12.192.221 images.tidal.com
204.12.192.222 fsu.fa.tidal.com
204.12.192.222 geolocation.onetrust.com
204.12.192.222 api.squareup.com
204.12.192.222 api-global.squareup.com
# Clash Royale, Clash of Clans, Brawl Stars
3.160.212.81 cdn.id.supercell.com
18.172.112.81 security.id.supercell.com
45.95.233.23 accounts.supercell.com
18.66.195.96 game-assets.clashroyaleapp.com
51.158.190.98 game.clashroyaleapp.com
3.162.38.39 game-assets.clashofclans.com
70.34.251.56 gamea.clashofclans.com
108.157.194.81 clashofclans.inbox.supercell.com
179.43.168.109 game.brawlstarsgame.com
18.239.69.129 game-assets.brawlstarsgame.com
204.12.192.222 store.supercell.com
# DeepL
204.12.192.222 deepl.com
204.12.192.222 www.deepl.com
204.12.192.222 www2.deepl.com
204.12.192.222 login-wall.deepl.com
204.12.192.219 w.deepl.com
204.12.192.222 s.deepl.com
204.12.192.222 dict.deepl.com
204.12.192.222 ita-free.www.deepl.com
204.12.192.222 write-free.www.deepl.com
204.12.192.222 experimentation.deepl.com
# Deezer
204.12.192.220 deezer.com
204.12.192.220 www.deezer.com
204.12.192.220 dzcdn.net
204.12.192.220 payment.deezer.com
# Weather.com
204.12.192.220 weather.com
204.12.192.220 upsx.weather.com
# Guilded
204.12.192.219 guilded.gg
204.12.192.219 www.guilded.gg
# Fitbit
204.12.192.219 api.fitbit.com
204.12.192.219 fitbit-pa.googleapis.com
204.12.192.219 fitbitvestibuleshim-pa.googleapis.com
204.12.192.219 fitbit.google.com
# 4PDA
185.246.223.127 4pda.to
185.246.223.127 app.4pda.to
185.246.223.127 s.4pda.to
185.246.223.127 appbk.4pda.to
45.81.252.72 cs11a0a.4pda.ws
185.234.59.26 cs7f6c.4pda.ws
217.182.194.171 cs4a0d.4pda.ws
141.94.143.110 cs3b2e.4pda.ws
54.36.104.75 cs2c9f.4pda.ws
# Другое:
204.12.192.222 claude.ai
204.12.192.220 console.anthropic.com
204.12.192.222 www.notion.so
50.7.85.222 www.canva.com
204.12.192.222 www.intel.com
204.12.192.219 www.dell.com
50.7.85.219 www.tiktok.com # Только на сайте. Приложение определяет регион по оператору, а не по IP. Поэтому есть моды.
142.54.189.106 web.archive.org # Блокирует от российских IP некоторые сайты
204.12.192.220 developer.nvidia.com
107.150.34.99 builds.parsec.app
204.12.192.220 tria.ge
204.12.192.220 api.imgur.com
45.95.233.23 www.dyson.com
45.95.233.23 www.dyson.fr
45.95.233.23 usher.ttvnw.net
64.188.98.242 api.manus.im
# Блокировка реально плохих сайтов
# Скримеры:
0.0.0.0 only-fans.uk
0.0.0.0 only-fans.me
0.0.0.0 onlyfans.wtf
# IP Logger'ы:
0.0.0.0 iplogger.org
0.0.0.0 wl.gl
0.0.0.0 ed.tc
0.0.0.0 bc.ax
0.0.0.0 maper.info
0.0.0.0 2no.co
0.0.0.0 yip.su
0.0.0.0 iplis.ru
0.0.0.0 ezstat.ru
0.0.0.0 iplog.co
0.0.0.0 grabify.org
# Мусор/реклама:
0.0.0.0 log16-platform-ycru.tiktokv.com
0.0.0.0 adfox.yandex.ru
0.0.0.0 adfstat.yandex.ru
0.0.0.0 ads-api.tiktok.com
0.0.0.0 ads-api.twitter.com
0.0.0.0 ads-dev.pinterest.com
0.0.0.0 ads-sg.tiktok.com
0.0.0.0 an.yandex.ru
0.0.0.0 appmetrica.yandex.ru
0.0.0.0 mc.yandex.ru
0.0.0.0 amc.yandex.ru

1219
rust/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

26
rust/Cargo.toml Normal file
View File

@@ -0,0 +1,26 @@
[workspace.package]
version = "0.0.1"
edition = "2024"
repository = "https://github.com/egor-white/zaprett"
[workspace]
members = ["crates/*"]
resolver = "3"
[workspace.dependencies]
anyhow = "1.0.100"
clap = { version = "4.5.50", features = ["derive"] }
iptables = "0.6.0"
libc = "0.2.177"
procfs = "0.18.0"
regex = "1.12.2"
rust-ini = "0.21.3"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.145"
sysctl = "0.7.1"
tokio = { version = "1.48.0", features = ["full"] }
once_cell = "1.21.3"
daemonize = "0.5.0"
log = "0.4.28"
pretty_env_logger = "0.5.0"
nix = { version = "0.30.1", features = ["signal"] }

View File

@@ -0,0 +1,11 @@
[package]
name = "libnfqws"
version.workspace = true
edition.workspace = true
repository.workspace = true
[build-dependencies]
cc = "1.2.43"
once_cell = "1.21.3"
glob = "0.3.3"
bindgen = "0.72.1"

View File

@@ -0,0 +1,60 @@
use once_cell::sync::Lazy;
use std::env;
use std::path::{Path, PathBuf};
macro_rules! rel_manifest_path {
($name:ident, $path:expr) => {
static $name: Lazy<PathBuf> = Lazy::new(|| {
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
Path::new(&manifest_dir).join($path)
});
};
}
rel_manifest_path!(NFQ, "zapret/nfq");
rel_manifest_path!(NFQ_CRYPTO, "zapret/nfq/crypto");
fn main() {
cc::Build::new()
.files(glob::glob(&format!("{}/*.c", NFQ.display()))
.unwrap()
.filter_map(Result::ok))
.files(glob::glob(&format!("{}/*.c", NFQ_CRYPTO.display()))
.unwrap()
.filter_map(Result::ok))
.include(&*NFQ)
.include(&*NFQ_CRYPTO)
.flag("-w")
.define("main", "nfqws_main")
.compile("libnfqws.a");
println!("cargo:rustc-link-lib=z");
println!("cargo:rustc-link-lib=netfilter_queue");
println!("cargo:rustc-link-lib=nfnetlink");
println!("cargo:rustc-link-lib=mnl");
println!("cargo:rustc-link-lib=static=nfqws");
println!("cargo:rerun-if-changed={}", NFQ.display());
println!("cargo:rerun-if-changed={}", NFQ_CRYPTO.display());
let mut builder = bindgen::Builder::default();
for header in glob::glob(&format!("{}/*.h", NFQ.display()))
.unwrap()
.filter_map(Result::ok)
{
builder = builder.header(header.to_string_lossy());
}
builder = builder.clang_arg("-Dmain=nfqws_main");
let bindings = builder
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate()
.expect("Unable to generate libnfqws");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("libnfqws.rs"))
.expect("Couldn't write libnfqws");
}

View File

@@ -0,0 +1,2 @@
#![allow(warnings)]
include!(concat!(env!("OUT_DIR"), "/libnfqws.rs"));

View File

@@ -0,0 +1,24 @@
[package]
name = "zaprett"
version.workspace = true
edition.workspace = true
repository.workspace = true
[dependencies]
anyhow = { workspace = true }
clap = { workspace = true }
iptables = { workspace = true }
libc = { workspace = true }
procfs = { workspace = true }
regex = { workspace = true }
rust-ini = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
sysctl ={ workspace = true }
tokio = { workspace = true }
once_cell = { workspace = true }
libnfqws = { path = "../libnfqws" }
daemonize = { workspace = true }
pretty_env_logger = { workspace = true }
log = { workspace = true }
nix = { workspace = true, features = ["user"] }

View File

@@ -0,0 +1,5 @@
use std::env;
fn main() {
let zapret_version = env::var("ZAPRET_VERSION").unwrap_or("unknown".to_string());
println!("cargo:rustc-env=ZAPRET_VERSION={}", zapret_version);
}

View File

@@ -0,0 +1,433 @@
use anyhow::bail;
use clap::{ArgAction, Parser, Subcommand, builder::BoolishValueParser};
use daemonize::Daemonize;
use ini::Ini;
use libnfqws::nfqws_main;
use log::{error, info};
use nix::sys::signal::{Signal, kill};
use nix::unistd::{Pid, Uid};
use procfs::process::all_processes;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::ffi::CString;
use std::fs::File;
use std::io::BufReader;
use std::io::{Read, Write};
use std::os::raw::c_char;
use std::sync::LazyLock;
use std::{fs, path::Path};
use sysctl::Sysctl;
use tokio::task;
#[derive(Parser)]
#[command(version)]
struct Cli {
#[command(subcommand)]
cmd: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
#[clap(about = "Start service")]
Start,
#[clap(about = "Stop service")]
Stop,
#[clap(about = "Restart service")]
Restart,
#[clap(about = "Show service status")]
Status,
#[clap(about = "Enable/disable autorestart")]
SetAutostart {
#[arg(
value_name = "boolean",
action = ArgAction::Set,
value_parser = BoolishValueParser::new()
)]
autostart: bool,
},
#[clap(about = "Get autorestart state")]
GetAutostart,
#[clap(about = "Get module version")]
ModuleVer,
#[clap(about = "Get nfqws binary version")]
BinVer,
}
#[derive(Serialize, Deserialize)]
struct Config {
active_lists: Vec<String>,
active_ipsets: Vec<String>,
active_exclude_lists: Vec<String>,
active_exclude_ipsets: Vec<String>,
list_type: String,
strategy: String,
app_list: String,
whitelist: Vec<String>,
blacklist: Vec<String>,
}
pub static MODULE_PATH: LazyLock<&Path> = LazyLock::new(|| Path::new("/data/adb/modules/zaprett"));
pub static ZAPRETT_DIR_PATH: LazyLock<&Path> =
LazyLock::new(|| Path::new("/storage/emulated/0/zaprett"));
#[tokio::main]
async fn main() -> anyhow::Result<()> {
pretty_env_logger::init();
let cli = Cli::parse();
match &cli.cmd {
Some(Commands::Start) => start_service().await,
Some(Commands::Stop) => {
let _ = stop_service().await;
Ok(())
}
Some(Commands::Restart) => {
restart_service().await;
Ok(())
}
Some(Commands::Status) => {
println!(
"zaprett is {}",
if service_status() {
"working"
} else {
"stopped"
}
);
Ok(())
}
Some(Commands::SetAutostart { autostart }) => {
set_autostart(autostart);
Ok(())
}
Some(Commands::GetAutostart) => {
get_autostart();
Ok(())
}
Some(Commands::ModuleVer) => {
module_version();
Ok(())
}
Some(Commands::BinVer) => {
bin_version();
Ok(())
}
None => {
println!("zaprett installed. Join us: t.me/zaprett_module");
Ok(())
}
}
}
async fn daemonize_nfqws(args: &String) {
info!("Starting nfqws as a daemon");
let daemonize = Daemonize::new()
.pid_file(MODULE_PATH.join("tmp/pid.lock").as_path())
.working_directory("/tmp")
.group("daemon")
.privileged_action(|| "Executed before drop privileges");
match daemonize.start() {
Ok(_) => {
info!("Success, daemonized");
run_nfqws(args).await.unwrap()
}
Err(e) => error!("Error while starting nfqws daemon: {e}"),
}
}
async fn start_service() -> anyhow::Result<()> {
if !Uid::effective().is_root() {
bail!("Running not from root, exiting");
};
println!("Starting zaprett service...");
let tmp_dir = MODULE_PATH.join("/tmp");
if tmp_dir.exists() {
fs::remove_dir_all(&tmp_dir).unwrap();
fs::create_dir_all(&tmp_dir).unwrap();
}
let reader = BufReader::new(
File::open(ZAPRETT_DIR_PATH.join("config.json")).expect("cannot open config.json"),
);
let config: Config = serde_json::from_reader(reader).expect("invalid json");
let list_type: &String = &config.list_type;
let def_strat: String = String::from("
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig,badsum $hostlist --new
--filter-tcp=443 $hostlist --dpi-desync=fake,split2 --dpi-desync-repeats=6 --dpi-desync-fooling=md5sig,badsum --dpi-desync-fake-tls=${zaprettdir}/bin/tls_clienthello_www_google_com.bin --new
--filter-tcp=80,443 --dpi-desync=fake,disorder2 --dpi-desync-repeats=6 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig,badsum $hostlist --new
--filter-udp=50000-50100 --dpi-desync=fake --dpi-desync-any-protocol --dpi-desync-fake-quic=0xC30000000108 --new
--filter-udp=443 $hostlist --dpi-desync=fake --dpi-desync-repeats=6 --dpi-desync-fake-quic=${zaprettdir}/bin/quic_initial_www_google_com.bin --new
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 $hostlist
");
let strat = if Path::new(&config.strategy).exists() {
fs::read_to_string(&config.strategy).unwrap_or_else(|_| def_strat)
} else {
def_strat
};
let regex_hostlist = Regex::new(r"\$hostlist").unwrap();
let regex_ipsets = Regex::new(r"\$ipset").unwrap();
let regex_zaprettdir = Regex::new(r"\$\{?zaprettdir\}?").unwrap();
let mut strat_modified;
if list_type.eq("whitelist") {
merge_files(
config.active_lists,
MODULE_PATH.join("tmp/hostlist").as_path(),
)
.unwrap();
merge_files(
config.active_ipsets,
MODULE_PATH.join("tmp/ipset").as_path(),
)
.unwrap();
let hosts = String::from(format!(
"--hostlist={}/tmp/hostlist",
MODULE_PATH.to_str().unwrap()
));
let ipsets = String::from(format!(
"--ipset={}tmp/ipset",
MODULE_PATH.to_str().unwrap()
));
strat_modified = regex_hostlist.replace_all(&strat, &hosts).into_owned();
strat_modified = regex_ipsets
.replace_all(&strat_modified, &ipsets)
.into_owned();
strat_modified = regex_zaprettdir
.replace_all(&strat_modified, &*ZAPRETT_DIR_PATH.to_str().unwrap())
.into_owned();
} else if list_type.eq("blacklist") {
merge_files(
config.active_exclude_lists,
MODULE_PATH.join("tmp/hostlist-exclude").as_path(),
)
.unwrap();
merge_files(
config.active_exclude_ipsets,
MODULE_PATH.join("tmp/ipset-exclude").as_path(),
)
.unwrap();
let hosts = String::from(format!(
"--hostlist-exclude={}/tmp/hostlist-exclude",
MODULE_PATH.to_str().unwrap()
));
let ipsets = String::from(format!(
"--ipset-exclude={}/tmp/ipset-exclude",
MODULE_PATH.to_str().unwrap()
));
strat_modified = regex_hostlist.replace_all(&strat, &hosts).into_owned();
strat_modified = regex_ipsets
.replace_all(&strat_modified, &ipsets)
.into_owned();
strat_modified = regex_zaprettdir
.replace_all(&strat_modified, &*ZAPRETT_DIR_PATH.to_str().unwrap())
.into_owned();
} else {
panic!("no list-type called {}", &list_type)
}
let ctl = sysctl::Ctl::new("net.netfilter.nf_conntrack_tcp_be_liberal").unwrap();
ctl.set_value(sysctl::CtlValue::String("1".into())).unwrap();
setup_iptables_rules();
daemonize_nfqws(&strat_modified).await;
println!("zaprett service started!");
Ok(())
}
async fn stop_service() -> anyhow::Result<()> {
if !Uid::effective().is_root() {
bail!("Running not from root, exiting");
};
clear_iptables_rules();
let pid_str = fs::read_to_string(MODULE_PATH.join("tmp/pid.lock").as_path())?;
let pid = pid_str.trim().parse::<i32>()?;
kill(Pid::from_raw(pid), Signal::SIGKILL).unwrap();
/*for proc in all_processes().unwrap() {
if let Ok(p) = proc {
if let Ok(stat) = p.stat() {
if stat.comm == "zaprett" {
let pid = Pid::from_raw(p.pid as i32);
if let Err(_) = kill(pid, Signal::SIGTERM) {
println!("failed to stop zaprett service")
} else {
println!("zaprett service stopped!")
}
}
}
}
}*/
Ok(())
}
async fn restart_service() {
stop_service().await.unwrap();
start_service().await.unwrap();
println!("zaprett service restarted!")
}
fn set_autostart(autostart: &bool) {
if *autostart {
if let Err(e) = std::fs::File::create(MODULE_PATH.join("autostart")) {
eprintln!("autostart: cannot create flag file: {e}");
}
} else {
fs::remove_file(MODULE_PATH.join("autostart")).unwrap()
}
}
fn get_autostart() {
let file = MODULE_PATH.join("autostart");
println!("{}", file.exists());
}
fn service_status() -> bool {
let pid_str = match fs::read_to_string(MODULE_PATH.join("tmp/pid.lock")) {
Ok(s) => s,
Err(_) => return false,
};
let pid = match pid_str.trim().parse::<i32>() {
Ok(p) => p,
Err(_) => return false,
};
match all_processes() {
Ok(iter) => iter
.filter_map(|rp| rp.ok())
.filter_map(|p| p.stat().ok())
.any(|st| st.pid == pid),
Err(_) => false,
}
}
fn module_version() {
if let Ok(prop) = Ini::load_from_file(MODULE_PATH.join("module.prop")) {
if let Some(props) = prop.section::<String>(None) {
if let Some(v) = props.get("version") {
println!("{}", v);
}
}
}
}
fn bin_version() {
println!("{}", env!("ZAPRET_VERSION"));
}
fn merge_files(
input_paths: Vec<String>,
output_path: &Path,
) -> Result<(), Box<dyn std::error::Error>> {
let mut combined_content = String::new();
for path_str in input_paths {
let path = Path::new(&path_str);
let mut file = File::open(path)?;
let mut content = String::new();
file.read_to_string(&mut content)?;
combined_content.push_str(&content);
}
let mut output_file = File::create(output_path)?;
output_file.write_all(combined_content.as_bytes())?;
Ok(())
}
fn setup_iptables_rules() {
let ipt = iptables::new(false).unwrap();
ipt.insert(
"mangle",
"POSTROUTING",
"-j NFQUEUE --queue-num 200 --queue-bypass",
1,
)
.unwrap();
ipt.insert(
"mangle",
"PREROUTING",
"-j NFQUEUE --queue-num 200 --queue-bypass",
1,
)
.unwrap();
ipt.append(
"filter",
"FORWARD",
"-j NFQUEUE --queue-num 200 --queue-bypass",
)
.unwrap();
}
fn clear_iptables_rules() {
let ipt = iptables::new(false).unwrap();
ipt.delete(
"mangle",
"POSTROUTING",
"-j NFQUEUE --queue-num 200 --queue-bypass",
)
.unwrap();
ipt.delete(
"mangle",
"PREROUTING",
"-j NFQUEUE --queue-num 200 --queue-bypass",
)
.unwrap();
ipt.delete(
"filter",
"FORWARD",
"-j NFQUEUE --queue-num 200 --queue-bypass",
)
.unwrap();
}
async fn run_nfqws(args_str: &String) -> anyhow::Result<()> {
if service_status() {
bail!("nfqws already started!");
}
let mut args = vec!["nfqws".to_string()];
if args_str.trim().is_empty() {
args.push("-v".to_string());
} else {
args.extend(args_str.trim().split_whitespace().map(String::from));
}
// fire-and-forget
let _ = task::spawn_blocking(move || {
let c_args: Vec<CString> = args
.into_iter()
.map(|arg| CString::new(arg).unwrap())
.collect();
let mut ptrs: Vec<*const c_char> = c_args.iter().map(|arg| arg.as_ptr()).collect();
unsafe {
nfqws_main(c_args.len() as libc::c_int, ptrs.as_mut_ptr() as *mut _);
}
})
.await?;
Ok(())
}

View File

@@ -6,9 +6,9 @@ ui_print " / / (_| | |_) | | | __/ |_| |_ "
ui_print " /___\__,_| .__/|_| \\___|\__|\__|"
ui_print " | | "
ui_print " |_| "
ui_print "(!) To download app, use Telegram chat"
ui_print "Module by: egorwhite, Cherret, Huananzhi X99"
ui_print "Apps by: egorwhite, Cherret"
ui_print "(!) To download app, use Telegram channel"
ui_print "Module by: egor-white, Cherret, Huananzhi X99"
ui_print "App by: egor-white, Cherret"
ui_print "####################"
ui_print "Unpacking archive..."
@@ -17,12 +17,8 @@ unzip -o "$ZIPFILE" -x 'META-INF/*' -d $MODPATH >&2
ui_print "Creating zaprett directory..."
mkdir /sdcard/zaprett; mkdir /sdcard/zaprett/lists; mkdir /sdcard/zaprett/bin; mkdir /sdcard/zaprett/strategies;
ui_print "Removing old config (config structure changed)..."
rm -f /sdcard/zaprett/config
ui_print "Filling configuration file if not exist..."
if [ ! -f "/sdcard/zaprett/config" ]; then
echo start_on_boot=true > /sdcard/zaprett/config
echo active_lists=/storage/emulated/0/zaprett/lists/list-youtube.txt >> /sdcard/zaprett/config
echo active_exclude_lists= >> /sdcard/zaprett/config
echo list_type=whitelist
@@ -69,4 +65,4 @@ chmod 777 /sdcard/zaprett; chmod 777 $MODPATH/service.sh
ui_print "Cleaning temp files..."
rm -rf $MODPATH/system/etc/zaprett
ui_print "Installation done. Telegram chat: https://t.me/zaprett_module"
ui_print "Installation done. Telegram channel: https://t.me/zaprett_module"

View File

@@ -1,11 +1,9 @@
#!/system/bin/sh
while [ -z "$(getprop sys.boot_completed)" ]; do sleep 2; done
sleep 15
source /storage/emulated/0/zaprett/config
if [ "$autorestart" = "true" ]; then
su -c "zaprett start"
while true; do
sleep 3600
su -c "zaprett restart"
done
fi
su -c "zaprett start"
while true; do
sleep 3600
if [ -f "/data/adb/modules/zaprett/autostart" ]; then
su -c "zaprett restart"
fi
done

View File

@@ -10,24 +10,33 @@ clear_iptables_rules() {
start_service() {
rm -f /data/adb/modules/zaprett/tmp/*
echo "Starting zaprett..."
hostlist=""
ipset=""
case "$list_type" in
whitelist)
lists="$active_lists"
ipsets="$active_ipsets"
opt="--hostlist"
ipopt="--ipset"
;;
blacklist)
lists="$active_exclude_lists"
ipsets="$active_exclude_ipsets"
opt="--hostlist-exclude"
ipopt="--ipset-exclude"
;;
*)
echo "Unknown list-type: $list_type" >&2
lists=""
ipsets=""
opt=""
ipopt=""
;;
esac
if [ -n "$lists" ] && [ -n "$opt" ]; then
for itm in $(echo "$lists" | tr ',' ' ' | sort -u); do
if [ -f "$itm" ]; then
@@ -41,6 +50,19 @@ start_service() {
done
fi
if [ -n "$ipsets" ] && [ -n "$ipopt" ]; then
for ipt in $(echo "$ipsets" | tr ',' ' ' | sort -u); do
if [ -f "$ipt" ]; then
dst="/data/adb/modules/zaprett/tmp/$(basename "$ipt")"
cp "$ipt" "$dst"
case "$ipset" in
*"$ipopt=$dst"*) ;;
*) ipset="$ipset $ipopt=$dst" ;;
esac
fi
done
fi
config=""
if [[ -n "$strategy" && -f "$strategy" ]]; then
config="$(eval "echo \"$(<"$strategy")\"")"
@@ -54,9 +76,9 @@ start_service() {
config="$config --filter-udp=443 $hostlist --dpi-desync=fake --dpi-desync-repeats=6 --dpi-desync-fake-quic=${zaprettdir}/bin/quic_initial_www_google_com.bin --new"
config="$config --filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 $hostlist"
fi
sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1 > /dev/null
iptables -t mangle -I POSTROUTING -j NFQUEUE --queue-num 200 --queue-bypass
iptables -t mangle -I PREROUTING -j NFQUEUE --queue-num 200 --queue-bypass
iptables -t filter -A FORWARD -j NFQUEUE --queue-num 200 --queue-bypass
@@ -92,7 +114,7 @@ if [ "$1" == "restart" ]; then
fi
if [ "$1" == "help" ]; then
echo -e "Помощь по модулю zaprett:\nzaprett start - запуск сервиса\nzaprett stop - остановка сервиса\nzaprett restart - перезапуск сервиса\nzaprett status - статус сервиса\nzaprett module-ver - версия модуля\nzaprett bin-ver - версия бинарных файлов"
echo -e "Помощь по модулю zaprett:\nzaprett start - запуск сервиса\nzaprett stop - остановка сервиса\nzaprett restart - перезапуск сервиса\nzaprett status - статус сервиса\nzaprett module-ver - версия модуля\nzaprett bin-ver - версия бинарных файлов\nzaprett autostart - переключение автозапуска модуля\nzaprett get-autostart - получить активен ли автозапуск"
fi
if [ "$1" == "module-ver" ]; then
@@ -103,6 +125,26 @@ if [ "$1" == "bin-ver" ]; then
nfqws --version | grep -o 'version v[0-9.]*' | head -n1 | cut -d' ' -f2
fi
if [ "$1" == "autostart" ]; then
FILE="/data/adb/modules/zaprett/autostart"
if [ -f "$FILE" ]; then
rm "$FILE"
echo "false"
else
touch "$FILE"
echo "true"
fi
fi
if [ "$1" == "get-autostart" ]; then
FILE="/data/adb/modules/zaprett/autostart"
if [ -f "$FILE" ]; then
echo "true"
else
echo "false"
fi
fi
if [[ -z $1 ]]; then
echo "zaprett installed. Telegram: t.me/zaprett_module"
fi

View File

@@ -1,6 +1,6 @@
{
"version": "4.9",
"versionCode": 49,
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/4.9.0/zaprett.zip",
"version": "5.1",
"versionCode": 51,
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/5.1.0/zaprett.zip",
"changelog": "https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/changelog.md"
}

View File

@@ -1,6 +1,6 @@
{
"version": "4.9",
"versionCode": 49,
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/4.9.0/zaprett-hosts.zip",
"version": "5.1",
"versionCode": 51,
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/5.1.0/zaprett-hosts.zip",
"changelog": "https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/changelog.md"
}

View File

@@ -1,6 +1,6 @@
{
"version": "4.9",
"versionCode": 49,
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/4.9.0/zaprett-tv.zip",
"version": "5.1",
"versionCode": 51,
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/5.1.0/zaprett-tv.zip",
"changelog": "https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/changelog.md"
}