mirror of
https://github.com/egor-white/zaprett.git
synced 2025-12-10 13:30:23 +05:00
Compare commits
321 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf98c42995 | ||
|
|
942578b5c5 | ||
|
|
6215a36eb6 | ||
|
|
5e64628d7f | ||
|
|
8b0945352a | ||
|
|
ca65e0c6f1 | ||
|
|
234e9e5824 | ||
|
|
aedf249712 | ||
|
|
526bf7ded2 | ||
|
|
2c8721e42b | ||
|
|
d59340a5c9 | ||
|
|
fc5cc814d6 | ||
|
|
924b6d20e8 | ||
|
|
dedab3386a | ||
|
|
44deef4aef | ||
|
|
eaf0e6c756 | ||
|
|
d1e56df7fc | ||
|
|
574bbbd8cc | ||
|
|
b5e37044e2 | ||
|
|
aa1788386a | ||
|
|
8a1d336e4b | ||
|
|
16ba9bedfc | ||
|
|
6343e67cd9 | ||
|
|
2d9463e507 | ||
|
|
91d08d3df4 | ||
|
|
3e4f7bad3a | ||
|
|
2c1594b13c | ||
|
|
ab7c49864c | ||
|
|
9dfb0b6d67 | ||
|
|
46bff39782 | ||
|
|
0c932ff69c | ||
|
|
689488ba3f | ||
|
|
d63cb7c6e6 | ||
|
|
90c7a55ab2 | ||
|
|
dd80ffcd5f | ||
|
|
a581e02ccd | ||
|
|
2e7b943712 | ||
|
|
4f6a80a8ee | ||
|
|
8caa7ff696 | ||
|
|
ef58166767 | ||
|
|
89ecb5e7fe | ||
|
|
26cb5ca046 | ||
|
|
4370ff8867 | ||
|
|
eafb226036 | ||
|
|
0316a4b004 | ||
|
|
3d78a3d0a4 | ||
|
|
d11eb93be6 | ||
|
|
490c8fa685 | ||
|
|
1128168924 | ||
|
|
1b7448afa3 | ||
|
|
636cd47ffa | ||
|
|
ceb27e1ee8 | ||
|
|
fc431f8e88 | ||
|
|
8a3df7b253 | ||
|
|
bb1fe1bc32 | ||
|
|
f5cee6df60 | ||
|
|
930eaf48d2 | ||
|
|
515c946f13 | ||
|
|
bf76e162ee | ||
|
|
2790c8ed62 | ||
|
|
2e9e08fb96 | ||
|
|
8542d33af2 | ||
|
|
1d9a8a641f | ||
|
|
17d5e7a8f0 | ||
|
|
aecde98d0d | ||
|
|
d5267997a3 | ||
|
|
57382991ad | ||
|
|
12ceb7a7d1 | ||
|
|
f37c14ef0a | ||
|
|
bfdd7a0a76 | ||
|
|
47f314cd19 | ||
|
|
10fdf4c227 | ||
|
|
784a248c11 | ||
|
|
192d846a12 | ||
|
|
87a6b72aee | ||
|
|
7ea4a516be | ||
|
|
4b9e60336b | ||
|
|
51af644b5f | ||
|
|
0f5492a29a | ||
|
|
a16796a699 | ||
|
|
19a8ccd384 | ||
|
|
58d0fdbab3 | ||
|
|
3c0488f629 | ||
|
|
3e009479c8 | ||
|
|
3b66cc8136 | ||
|
|
db724d8667 | ||
|
|
a1a2961628 | ||
|
|
e91cb00eec | ||
|
|
227db9b7fd | ||
|
|
c9b4a722c1 | ||
|
|
021fc6f53e | ||
|
|
5f6663a067 | ||
|
|
0e51fb14fd | ||
|
|
31c2c08cf0 | ||
|
|
bb389dff34 | ||
|
|
3882924d60 | ||
|
|
2f47b3c63d | ||
|
|
2e4c484ffb | ||
|
|
55fd437762 | ||
|
|
d6bc7f17d7 | ||
|
|
5136f3901b | ||
|
|
ec072d4ae8 | ||
|
|
e7b2075d1e | ||
|
|
c7271b2825 | ||
|
|
71e918bd13 | ||
|
|
d3dbf4ddc5 | ||
|
|
0213c239fc | ||
|
|
2d90aea5ca | ||
|
|
e62336e253 | ||
|
|
dd78b59a68 | ||
|
|
0a0c3fd80b | ||
|
|
3a7c40f167 | ||
|
|
9ef7c70f78 | ||
|
|
534f3a733a | ||
|
|
ccaac37b52 | ||
|
|
c2db7fbdac | ||
|
|
ea92b6cf6f | ||
|
|
0fbcd24088 | ||
|
|
45017d35b2 | ||
|
|
718ed43ef8 | ||
|
|
6318977857 | ||
|
|
e3effc3292 | ||
|
|
c92b3a1b19 | ||
|
|
afed7b1122 | ||
|
|
1fa0e306ac | ||
|
|
fece7149e3 | ||
|
|
751788feb8 | ||
|
|
cc3500635f | ||
|
|
b01c5dc95f | ||
|
|
bf69249e12 | ||
|
|
63c45d8a2a | ||
|
|
26325b79f1 | ||
|
|
2cee0712c3 | ||
|
|
79b63ec5e9 | ||
|
|
c230f4876c | ||
|
|
531c403ce2 | ||
|
|
70d3b3e28d | ||
|
|
cf507f059b | ||
|
|
bf81100acb | ||
|
|
5ac9234ca2 | ||
|
|
156cedb080 | ||
|
|
f59ec45e9f | ||
|
|
45b25dd1ee | ||
|
|
e967dc12d7 | ||
|
|
6e1b3f12d9 | ||
|
|
6f395b1df9 | ||
|
|
638c45b243 | ||
|
|
78af1977fd | ||
|
|
97f495a56a | ||
|
|
63b279114e | ||
|
|
f1d3ec0b5e | ||
|
|
ffb296744b | ||
|
|
7966bbaebf | ||
|
|
f162004b56 | ||
|
|
71a5df5356 | ||
|
|
bcf0aa2b50 | ||
|
|
8248d43f67 | ||
|
|
f3d26d5677 | ||
|
|
2ef9ac91be | ||
|
|
b16b9e4d7a | ||
|
|
aa3dd6cce5 | ||
|
|
092cc65bbe | ||
|
|
6679a9c71a | ||
|
|
ac815f62a0 | ||
|
|
a71baaa98b | ||
|
|
db69426185 | ||
|
|
6f7eb991a7 | ||
|
|
65ff8f0661 | ||
|
|
c843494c8a | ||
|
|
1acb992344 | ||
|
|
ca10ed0a7a | ||
|
|
c4d1724ace | ||
|
|
89a457da84 | ||
|
|
8069ae43fc | ||
|
|
02d3d2fb1c | ||
|
|
0ad93a2c94 | ||
|
|
a1a3db7a94 | ||
|
|
80bea7d472 | ||
|
|
27192c15a3 | ||
|
|
2ccf9e909b | ||
|
|
428392033d | ||
|
|
baf209317d | ||
|
|
114dc16ffd | ||
|
|
57b0b820f7 | ||
|
|
c3117c24e1 | ||
|
|
3ba0b39464 | ||
|
|
08e6f1a588 | ||
|
|
cb4d956929 | ||
|
|
94ae3dfa5c | ||
|
|
044bc08601 | ||
|
|
a9b6beb58b | ||
|
|
df43ad221a | ||
|
|
e547dcb01f | ||
|
|
66e1243c87 | ||
|
|
2dabb61c27 | ||
|
|
43e8da1a6f | ||
|
|
7a31d2d71c | ||
|
|
ba03ad017f | ||
|
|
230241eccc | ||
|
|
b9e2915c11 | ||
|
|
a9433ab7eb | ||
|
|
c98eef39a5 | ||
|
|
b102a95b06 | ||
|
|
1992f0a0d7 | ||
|
|
af95cc36b2 | ||
|
|
703137c3dd | ||
|
|
7788a61a2b | ||
|
|
e2231dafba | ||
|
|
ac9b39c95c | ||
|
|
93ad791dc6 | ||
|
|
7ef462f6e9 | ||
|
|
9d968fcea5 | ||
|
|
046afedd65 | ||
|
|
d2dcdebe5b | ||
|
|
2f9658f7c0 | ||
|
|
f452f250ed | ||
|
|
063db1c312 | ||
|
|
e06921d4e2 | ||
|
|
d44922fa5c | ||
|
|
54371df71d | ||
|
|
f18842fd05 | ||
|
|
f7291945b3 | ||
|
|
218d5a835d | ||
|
|
b08109d91a | ||
|
|
7279be91c3 | ||
|
|
f757c20d63 | ||
|
|
1312bd04d6 | ||
|
|
93f1975629 | ||
|
|
0558b4b619 | ||
|
|
8b137cd210 | ||
|
|
84b2817842 | ||
|
|
79f9c8ab43 | ||
|
|
1116899c74 | ||
|
|
895412e6dd | ||
|
|
152002bb34 | ||
|
|
ed0197ce43 | ||
|
|
9a416e7ba5 | ||
|
|
98f96103bd | ||
|
|
755a5c3862 | ||
|
|
27e57c0b8f | ||
|
|
66f36d7c56 | ||
|
|
5f18c82a93 | ||
|
|
b696e93d19 | ||
|
|
4451d78913 | ||
|
|
0d8148d781 | ||
|
|
1f3fd3b2f6 | ||
|
|
1d59e6ae9a | ||
|
|
aed27e80d0 | ||
|
|
ab4f590358 | ||
|
|
7b80a5881b | ||
|
|
7b87215460 | ||
|
|
bd41635291 | ||
|
|
8931550f83 | ||
|
|
a138572257 | ||
|
|
f27049ec55 | ||
|
|
e6be2ea05e | ||
|
|
426269a66a | ||
|
|
20c01d55f8 | ||
|
|
8244d750a8 | ||
|
|
beb1be3b13 | ||
|
|
d9fe9a25b4 | ||
|
|
f3fd0477cd | ||
|
|
f61679a20e | ||
|
|
1068fa8d98 | ||
|
|
6535922576 | ||
|
|
3fc4e388bc | ||
|
|
64f3ec397c | ||
|
|
ea1b82a483 | ||
|
|
24731284f4 | ||
|
|
52a2287c00 | ||
|
|
fa8b798943 | ||
|
|
f3c918de80 | ||
|
|
e55df9bf31 | ||
|
|
885aa16736 | ||
|
|
c7fda1faba | ||
|
|
f69ce002c3 | ||
|
|
157d05d21e | ||
|
|
907f6db57f | ||
|
|
80941e4b8c | ||
|
|
c2d3ea25a0 | ||
|
|
6057c726d7 | ||
|
|
e44d04033e | ||
|
|
4403b8d57a | ||
|
|
e304e8c79b | ||
|
|
dee3311289 | ||
|
|
499b75f391 | ||
|
|
2b4683f8f9 | ||
|
|
2cf05e8600 | ||
|
|
4e631f638d | ||
|
|
e6755c0e68 | ||
|
|
b34b223261 | ||
|
|
5c04b16408 | ||
|
|
9bd3a7e93d | ||
|
|
64646885d6 | ||
|
|
228871c7d3 | ||
|
|
34d79a9f4b | ||
|
|
c37cca684d | ||
|
|
7654294c18 | ||
|
|
59bea9f644 | ||
|
|
8fce9f4a6d | ||
|
|
5a0068fad6 | ||
|
|
db83adb442 | ||
|
|
3bde37684a | ||
|
|
856711543b | ||
|
|
97402d9eb6 | ||
|
|
cb9055f001 | ||
|
|
c94661dc81 | ||
|
|
9e5fb19adf | ||
|
|
6aeab9558e | ||
|
|
d97d6a109d | ||
|
|
220f0ad0f2 | ||
|
|
cc35b7bfb9 | ||
|
|
c818d58c0a | ||
|
|
68938e4df3 | ||
|
|
88814c2b73 | ||
|
|
1b7f3149fe | ||
|
|
cd21a9f5ba | ||
|
|
04cf4e7692 | ||
|
|
5a6a455c0f | ||
|
|
0063cb4066 | ||
|
|
7ef7c02c97 |
169
.github/workflows/workflow.yml
vendored
Normal file
169
.github/workflows/workflow.yml
vendored
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
name: Build module
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
create_release:
|
||||||
|
description: 'Create GitHub release?'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
tag:
|
||||||
|
description: "Tag for the release (x.x.x)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
zapret-version:
|
||||||
|
description: "Zapret version (x.x)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
version:
|
||||||
|
description: "Module version (x.x)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
version_code:
|
||||||
|
description: "Module version code (xx)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_name:
|
||||||
|
description: "Release Name"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_changes:
|
||||||
|
description: "Release Changes"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
ZAPRET_VERSION: ${{ inputs.zapret-version }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Git submodules
|
||||||
|
run: git submodule update --init --recursive
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: sudo apt install build-essential pkg-config just unzip
|
||||||
|
|
||||||
|
- name: Build zaprett
|
||||||
|
run: just -f rust/justfile build-android --release
|
||||||
|
|
||||||
|
- name: Make build dirs
|
||||||
|
run: mkdir -p zaprett/system/bin zaprett-hosts/system/bin zaprett/system/etc/zaprett/lists out lists zapret-hosts/system/etc/zaprett/lists
|
||||||
|
|
||||||
|
- name: Copy files to dirs
|
||||||
|
run: |
|
||||||
|
cp rust/target/armv7-linux-androideabi/release/zaprett zaprett/system/bin/zaprett-armv7
|
||||||
|
cp rust/target/aarch64-linux-android/release/zaprett zaprett/system/bin/zaprett-aarch64
|
||||||
|
cp rust/target/x86_64-linux-android/release/zaprett zaprett/system/bin/zaprett-x86_64
|
||||||
|
|
||||||
|
cp -a src/* zaprett/
|
||||||
|
cp -r zaprett/* zaprett-hosts/
|
||||||
|
|
||||||
|
- name: Download and copy actual lists
|
||||||
|
run: |
|
||||||
|
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/
|
||||||
|
|
||||||
|
cp lists/list-discord.txt zaprett/system/etc/zaprett/lists/
|
||||||
|
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
|
||||||
|
id=zaprett
|
||||||
|
name=zaprett
|
||||||
|
version=${{ inputs.version }}
|
||||||
|
versionCode=${{ inputs.version_code }}
|
||||||
|
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, Cherret
|
||||||
|
description=Ускорение CDN серверов Google. ТГК: https://t.me/zaprett_module
|
||||||
|
updateJson=https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/update-hosts.json
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Create archives
|
||||||
|
run: |
|
||||||
|
cd zaprett && zip -r ../zaprett.zip ./* && cd ..
|
||||||
|
cd zaprett-hosts && zip -r ../zaprett-hosts.zip ./* && cd ..
|
||||||
|
|
||||||
|
mv zaprett.zip out/
|
||||||
|
mv zaprett-hosts.zip out/
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
if: ${{ inputs.create_release == 'true' }}
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
tag_name: ${{ inputs.tag }}
|
||||||
|
name: ${{ inputs.release_name }}
|
||||||
|
body: ${{ inputs.release_changes }}
|
||||||
|
files: out/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
if: ${{ inputs.create_release != 'true' }}
|
||||||
|
uses: actions/upload-artifact@v5.0.0
|
||||||
|
with:
|
||||||
|
name: zaprett
|
||||||
|
path: out/*
|
||||||
|
|
||||||
|
- name: Update changelog
|
||||||
|
if: ${{ inputs.create_release == 'true' }}
|
||||||
|
run: echo "${{ inputs.release_changes }}" > changelog.md
|
||||||
|
|
||||||
|
- name: Update update.json
|
||||||
|
if: ${{ inputs.create_release == 'true' }}
|
||||||
|
run: |
|
||||||
|
cat > update.json <<EOF
|
||||||
|
{
|
||||||
|
"version": "${{ inputs.version }}",
|
||||||
|
"versionCode": ${{ inputs.version_code }},
|
||||||
|
"zipUrl": "https://github.com/${{ github.repository }}/releases/download/${{ inputs.tag }}/zaprett.zip",
|
||||||
|
"changelog": "https://raw.githubusercontent.com/${{ github.repository }}/refs/heads/main/changelog.md"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cat > update-hosts.json <<EOF
|
||||||
|
{
|
||||||
|
"version": "${{ inputs.version }}",
|
||||||
|
"versionCode": ${{ inputs.version_code }},
|
||||||
|
"zipUrl": "https://github.com/${{ github.repository }}/releases/download/${{ inputs.tag }}/zaprett-hosts.zip",
|
||||||
|
"changelog": "https://raw.githubusercontent.com/${{ github.repository }}/refs/heads/main/changelog.md"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
- name: Commit jsons and changelog
|
||||||
|
if: ${{ inputs.create_release == 'true' }}
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v5
|
||||||
|
with:
|
||||||
|
commit_message: "Update update's.json and changelog"
|
||||||
|
file_pattern: "update.json update-hosts.json changelog.md"
|
||||||
|
- name: Send bot post
|
||||||
|
env:
|
||||||
|
MESSAGE_TEXT: |
|
||||||
|
🔄 <b>Обновление модуля</b> ${{ inputs.version }}
|
||||||
|
|
||||||
|
📋 Изменения: ${{ inputs.release_changes }}
|
||||||
|
|
||||||
|
⬇️ <a href='https://github.com/egor-white/zaprett/releases/tag/${{ inputs.tag }}'>Скачать</a>
|
||||||
|
|
||||||
|
ℹ️ @zaprett_module <a href='mailru.pro'>[web]</a>
|
||||||
|
run: |
|
||||||
|
curl -X POST "https://api.telegram.org/bot${{ secrets.BOT_TOKEN }}/sendMessage" \
|
||||||
|
-d chat_id=-1002531270265 \
|
||||||
|
-d parse_mode=HTML \
|
||||||
|
-d disable_web_page_preview=true \
|
||||||
|
--data-urlencode "text=$MESSAGE_TEXT"
|
||||||
156
.github/workflows/workflow_without_post.yml
vendored
Normal file
156
.github/workflows/workflow_without_post.yml
vendored
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
name: Build module (without post)
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
create_release:
|
||||||
|
description: 'Create GitHub release?'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
tag:
|
||||||
|
description: "Tag for the release (x.x.x)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
zapret-version:
|
||||||
|
description: "Zapret version (x.x)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
version:
|
||||||
|
description: "Module version (x.x)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
version_code:
|
||||||
|
description: "Module version code (xx)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_name:
|
||||||
|
description: "Release Name"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_changes:
|
||||||
|
description: "Release Changes"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
ZAPRET_VERSION: ${{ inputs.zapret-version }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Git submodules
|
||||||
|
run: git submodule update --init --recursive
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: sudo apt install build-essential pkg-config just unzip
|
||||||
|
|
||||||
|
- name: Build zaprett
|
||||||
|
run: just -f rust/justfile build-android --release
|
||||||
|
|
||||||
|
- name: Make build dirs
|
||||||
|
run: mkdir -p zaprett/system/bin zaprett-hosts/system/bin zaprett/system/etc/zaprett/lists out lists zapret-hosts/system/etc/zaprett/lists
|
||||||
|
|
||||||
|
- name: Copy files to dirs
|
||||||
|
run: |
|
||||||
|
#copy nfqws and zaprett
|
||||||
|
cp rust/target/armv7-linux-androideabi/release/zaprett zaprett/system/bin/zaprett-armv7
|
||||||
|
cp rust/target/aarch64-linux-android/release/zaprett zaprett/system/bin/zaprett-aarch64
|
||||||
|
cp rust/target/x86_64-linux-android/release/zaprett zaprett/system/bin/zaprett-x86_64
|
||||||
|
|
||||||
|
cp -a src/* zaprett/
|
||||||
|
cp -r zaprett/* zaprett-hosts/
|
||||||
|
|
||||||
|
- name: Download and copy actual lists
|
||||||
|
run: |
|
||||||
|
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/
|
||||||
|
|
||||||
|
cp lists/list-discord.txt zaprett/system/etc/zaprett/lists/
|
||||||
|
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
|
||||||
|
id=zaprett
|
||||||
|
name=zaprett
|
||||||
|
version=${{ inputs.version }}
|
||||||
|
versionCode=${{ inputs.version_code }}
|
||||||
|
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, Cherret
|
||||||
|
description=Ускорение CDN серверов Google. ТГК: https://t.me/zaprett_module
|
||||||
|
updateJson=https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/update-hosts.json
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Create archives
|
||||||
|
run: |
|
||||||
|
cd zaprett && zip -r ../zaprett.zip ./* && cd ..
|
||||||
|
cd zaprett-hosts && zip -r ../zaprett-hosts.zip ./* && cd ..
|
||||||
|
|
||||||
|
mv zaprett.zip out/
|
||||||
|
mv zaprett-hosts.zip out/
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
if: ${{ inputs.create_release == 'true' }}
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
tag_name: ${{ inputs.tag }}
|
||||||
|
name: ${{ inputs.release_name }}
|
||||||
|
body: ${{ inputs.release_changes }}
|
||||||
|
files: out/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
if: ${{ inputs.create_release != 'true' }}
|
||||||
|
uses: actions/upload-artifact@v5.0.0
|
||||||
|
with:
|
||||||
|
name: zaprett
|
||||||
|
path: out/*
|
||||||
|
|
||||||
|
- name: Update changelog
|
||||||
|
if: ${{ inputs.create_release == 'true' }}
|
||||||
|
run: echo "${{ inputs.release_changes }}" > changelog.md
|
||||||
|
|
||||||
|
- name: Update update.json
|
||||||
|
if: ${{ inputs.create_release == 'true' }}
|
||||||
|
run: |
|
||||||
|
cat > update.json <<EOF
|
||||||
|
{
|
||||||
|
"version": "${{ inputs.version }}",
|
||||||
|
"versionCode": ${{ inputs.version_code }},
|
||||||
|
"zipUrl": "https://github.com/${{ github.repository }}/releases/download/${{ inputs.tag }}/zaprett.zip",
|
||||||
|
"changelog": "https://raw.githubusercontent.com/${{ github.repository }}/refs/heads/main/changelog.md"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cat > update_hosts.json <<EOF
|
||||||
|
{
|
||||||
|
"version": "${{ inputs.version }}",
|
||||||
|
"versionCode": ${{ inputs.version_code }},
|
||||||
|
"zipUrl": "https://github.com/${{ github.repository }}/releases/download/${{ inputs.tag }}/zaprett-hosts.zip",
|
||||||
|
"changelog": "https://raw.githubusercontent.com/${{ github.repository }}/refs/heads/main/changelog.md"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Commit jsons and changelog
|
||||||
|
if: ${{ inputs.create_release == 'true' }}
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v5
|
||||||
|
with:
|
||||||
|
commit_message: "Update update's.json and changelog"
|
||||||
|
file_pattern: "update.json update_hosts.json changelog.md"
|
||||||
|
|
||||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
target
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "rust/crates/libnfqws/zapret"]
|
||||||
|
path = rust/crates/libnfqws/zapret
|
||||||
|
url = https://github.com/bol-van/zapret.git
|
||||||
36
README.md
36
README.md
@@ -1,17 +1,43 @@
|
|||||||
# zaprett
|
# zaprett
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
### [📣 Официальный Telegram-канал модуля](https://t.me/zaprett_module)
|
||||||
|
|
||||||
## О модуле
|
## О модуле
|
||||||
Представляет собой портированную версию [zapret](https://github.com/bol-van/zapret/) от [bol-van](https://github.com/bol-van/) для Android устройств.
|
Представляет собой портированную версию [zapret](https://github.com/bol-van/zapret/) от [bol-van](https://github.com/bol-van/) для Android устройств.
|
||||||
|
|
||||||
Требования:
|
Требования:
|
||||||
* Magisk 24.1+
|
* Magisk 24.1+
|
||||||
* Прямые руки
|
* Прямые руки
|
||||||
* Termux или другой эмулятор терминала **И/ИЛИ** [приложение zaprett](https://github.com/egor-white/zaprett-app)
|
* Termux или другой эмулятор терминала **И/ИЛИ** [ремейк приложения zaprett от cherret](https://github.com/CherretGit/zaprett-app) ("оригинал" устарел и не обновляется, вместо этого мы вдвоём занимаемся версией на Kotlin!)
|
||||||
|
|
||||||
На данный момент модуль умеет:
|
На данный момент модуль умеет:
|
||||||
+ Включать, выключать и перезапускать nfqws
|
+ Включать, выключать и перезапускать nfqws
|
||||||
|
+ Работать с листами, айписетами, стратегиями
|
||||||
|
+ Предлагать обновления через Magisk/KSU/KSU Next/APatch
|
||||||
|
|
||||||
Планируемый функционал:
|
## Какую версию модуля выбрать?
|
||||||
+ Автообновление модуля
|
|
||||||
|
|
||||||
Модуль разрабатывается при поддержке **Telegram чата** [Usb.mineralka #нахуйРКН](https://t.me/mineral_usb)
|
В актуальных релизах есть 3 версии модуля, а именно:
|
||||||
|
- zaprett.zip
|
||||||
|
- zaprett-hosts.zip
|
||||||
|
- zaprett-tv.zip
|
||||||
|
|
||||||
Оригинальный автор - [notmalware](https://t.me/notmalware). Отредактировано - [egor-white](https://t.me/cheesedroid), [MT6833](https://t.me/MT6833), [Mineralka](https://t.me/Program_dayn), [Cherret](https://t.me/Cherret).
|
Основные их отличия представленны в таблице ниже.
|
||||||
|
Для устройств на 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>, иначе модули будут конфликтовать друг с другом.
|
||||||
|
|
||||||
|
⚠️ Сервера, используемые в качестве прокси и указанные в файле hosts нам неподконтрольны, мы не несём за них отвественность, используйте с осторожностью
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
Обвнолены бинарники zapret до версии 70.3
|
Обновление бинарников zapret до версии 72.2
|
||||||
|
Обновление hosts файла в zaprett hosts
|
||||||
|
|
||||||
|
|||||||
246
hosts/hosts
Normal file
246
hosts/hosts
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
### dns.malw.link: hosts file
|
||||||
|
# Последнее обновление: 17 октября 2025
|
||||||
|
# Дополнение к 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
|
||||||
|
64.233.164.132 yt4.ggpht.com
|
||||||
|
52.223.13.41 tracker.openbittorrent.com
|
||||||
|
130.255.77.28 ntc.party
|
||||||
|
172.64.33.155 rutor.info
|
||||||
|
173.245.59.155 rutor.is
|
||||||
|
185.87.51.182 controlplane.tailscale.com
|
||||||
|
|
||||||
|
# ChatGPT, OpenAI:
|
||||||
|
185.246.223.127 chatgpt.com
|
||||||
|
185.246.223.127 ab.chatgpt.com
|
||||||
|
185.246.223.127 auth.openai.com
|
||||||
|
185.246.223.127 auth0.openai.com
|
||||||
|
185.246.223.127 platform.openai.com
|
||||||
|
185.246.223.127 cdn.oaistatic.com
|
||||||
|
185.246.223.127 files.oaiusercontent.com
|
||||||
|
185.246.223.127 cdn.auth0.com
|
||||||
|
185.246.223.127 tcr9i.chat.openai.com
|
||||||
|
185.246.223.127 webrtc.chatgpt.com
|
||||||
|
185.246.223.127 android.chat.openai.com
|
||||||
|
185.246.223.127 api.openai.com
|
||||||
|
45.95.233.23 operator.chatgpt.com
|
||||||
|
185.246.223.127 sora.chatgpt.com
|
||||||
|
185.246.223.127 sora.com
|
||||||
|
185.246.223.127 videos.openai.com
|
||||||
|
|
||||||
|
# Сервисы Google:
|
||||||
|
185.246.223.127 gemini.google.com
|
||||||
|
134.0.118.88 aistudio.google.com
|
||||||
|
134.0.118.88 generativelanguage.googleapis.com
|
||||||
|
185.246.223.127 aitestkitchen.withgoogle.com
|
||||||
|
134.0.118.88 aisandbox-pa.googleapis.com
|
||||||
|
134.0.118.88 webchannel-alkalimakersuite-pa.clients6.google.com
|
||||||
|
134.0.118.88 alkalimakersuite-pa.clients6.google.com
|
||||||
|
134.0.118.88 assistant-s3-pa.googleapis.com
|
||||||
|
134.0.118.88 proactivebackend-pa.googleapis.com
|
||||||
|
185.246.223.127 o.pki.goog
|
||||||
|
185.246.223.127 labs.google
|
||||||
|
185.246.223.127 notebooklm.google
|
||||||
|
185.246.223.127 notebooklm.google.com
|
||||||
|
185.246.223.127 jules.google.com
|
||||||
|
185.246.223.127 stitch.withgoogle.com
|
||||||
|
|
||||||
|
# Microsoft Copilot, Microsoft Rewards, Xbox, Xbox Cloud Gaming:
|
||||||
|
185.246.223.127 copilot.microsoft.com
|
||||||
|
185.246.223.127 sydney.bing.com
|
||||||
|
185.246.223.127 edgeservices.bing.com
|
||||||
|
45.95.233.23 rewards.bing.com
|
||||||
|
185.246.223.127 xsts.auth.xboxlive.com
|
||||||
|
185.246.223.127 xgpuwebf2p.gssv-play-prod.xboxlive.com
|
||||||
|
185.246.223.127 xgpuweb.gssv-play-prod.xboxlive.com
|
||||||
|
|
||||||
|
# Spotify:
|
||||||
|
185.246.223.127 api.spotify.com
|
||||||
|
185.246.223.127 xpui.app.spotify.com
|
||||||
|
185.246.223.127 appresolve.spotify.com
|
||||||
|
185.246.223.127 login5.spotify.com
|
||||||
|
185.246.223.127 login.app.spotify.com
|
||||||
|
185.246.223.127 encore.scdn.co
|
||||||
|
185.246.223.127 ap-gew1.spotify.com
|
||||||
|
185.246.223.127 gew1-spclient.spotify.com
|
||||||
|
185.246.223.127 spclient.wg.spotify.com
|
||||||
|
185.246.223.127 api-partner.spotify.com
|
||||||
|
185.246.223.127 aet.spotify.com
|
||||||
|
185.246.223.127 www.spotify.com
|
||||||
|
185.246.223.127 accounts.spotify.com
|
||||||
|
45.95.233.23 open.spotify.com
|
||||||
|
|
||||||
|
# GitHub Copilot:
|
||||||
|
50.7.87.84 api.github.com
|
||||||
|
185.246.223.127 api.individual.githubcopilot.com
|
||||||
|
185.246.223.127 proxy.individual.githubcopilot.com
|
||||||
|
|
||||||
|
# JetBrains:
|
||||||
|
50.7.85.221 datalore.jetbrains.com
|
||||||
|
107.150.34.100 plugins.jetbrains.com
|
||||||
|
185.246.223.127 download.jetbrains.com
|
||||||
|
185.246.223.127 api.jetbrains.ai
|
||||||
|
185.246.223.127 account.jetbrains.com
|
||||||
|
|
||||||
|
# ElevenLabs:
|
||||||
|
185.246.223.127 elevenlabs.io
|
||||||
|
185.246.223.127 api.us.elevenlabs.io
|
||||||
|
185.246.223.127 elevenreader.io
|
||||||
|
185.246.223.127 api.elevenlabs.io
|
||||||
|
185.246.223.127 help.elevenlabs.io
|
||||||
|
|
||||||
|
# Truth Social
|
||||||
|
204.12.192.219 truthsocial.com
|
||||||
|
204.12.192.219 static-assets-1.truthsocial.com
|
||||||
|
|
||||||
|
# Grok
|
||||||
|
185.246.223.127 grok.com
|
||||||
|
185.246.223.127 accounts.x.ai
|
||||||
|
185.246.223.127 assets.grok.com
|
||||||
|
|
||||||
|
# Tidal
|
||||||
|
185.246.223.127 api.tidal.com
|
||||||
|
185.246.223.127 listen.tidal.com
|
||||||
|
185.246.223.127 login.tidal.com
|
||||||
|
185.246.223.127 auth.tidal.com
|
||||||
|
185.246.223.127 link.tidal.com
|
||||||
|
185.246.223.127 dd.tidal.com
|
||||||
|
185.246.223.127 resources.tidal.com
|
||||||
|
45.95.233.23 images.tidal.com
|
||||||
|
185.246.223.127 fsu.fa.tidal.com
|
||||||
|
185.246.223.127 geolocation.onetrust.com
|
||||||
|
185.246.223.127 api.squareup.com
|
||||||
|
185.246.223.127 api-global.squareup.com
|
||||||
|
|
||||||
|
# Supercell
|
||||||
|
185.246.223.127 cdn.id.supercell.com
|
||||||
|
185.246.223.127 security.id.supercell.com
|
||||||
|
45.95.233.23 accounts.supercell.com
|
||||||
|
185.246.223.127 game-assets.clashroyaleapp.com
|
||||||
|
185.246.223.127 game-assets.clashofclans.com
|
||||||
|
185.246.223.127 clashofclans.inbox.supercell.com
|
||||||
|
185.246.223.127 game-assets.brawlstarsgame.com
|
||||||
|
185.246.223.127 store.supercell.com
|
||||||
|
45.95.233.23 game.clashroyaleapp.com
|
||||||
|
64.188.98.242 gamea.clashofclans.com
|
||||||
|
185.246.223.127 game.brawlstarsgame.com
|
||||||
|
108.61.167.26 game.squadbustersgame.com
|
||||||
|
45.95.233.23 game.mocogame.com
|
||||||
|
|
||||||
|
# DeepL
|
||||||
|
185.246.223.127 deepl.com
|
||||||
|
185.246.223.127 www.deepl.com
|
||||||
|
185.246.223.127 www2.deepl.com
|
||||||
|
185.246.223.127 login-wall.deepl.com
|
||||||
|
185.246.223.127 w.deepl.com
|
||||||
|
185.246.223.127 s.deepl.com
|
||||||
|
185.246.223.127 dict.deepl.com
|
||||||
|
185.246.223.127 ita-free.www.deepl.com
|
||||||
|
185.246.223.127 write-free.www.deepl.com
|
||||||
|
185.246.223.127 experimentation.deepl.com
|
||||||
|
185.246.223.127 experimentation-grpc.deepl.com
|
||||||
|
185.246.223.127 ita-free.app.deepl.com
|
||||||
|
185.246.223.127 shield.deepl.com
|
||||||
|
185.246.223.127 ott.deepl.com
|
||||||
|
185.246.223.127 api-free.deepl.com
|
||||||
|
185.246.223.127 backend.deepl.com
|
||||||
|
185.246.223.127 clearance.deepl.com
|
||||||
|
185.246.223.127 errortracking.deepl.com
|
||||||
|
185.246.223.127 auth.deepl.com
|
||||||
|
185.246.223.127 oneshot-free.www.deepl.com
|
||||||
|
|
||||||
|
# Deezer
|
||||||
|
185.246.223.127 deezer.com
|
||||||
|
185.246.223.127 www.deezer.com
|
||||||
|
185.246.223.127 dzcdn.net
|
||||||
|
185.246.223.127 payment.deezer.com
|
||||||
|
|
||||||
|
# Weather.com
|
||||||
|
185.246.223.127 weather.com
|
||||||
|
185.246.223.127 upsx.weather.com
|
||||||
|
|
||||||
|
# Guilded
|
||||||
|
204.12.192.219 guilded.gg
|
||||||
|
204.12.192.219 www.guilded.gg
|
||||||
|
|
||||||
|
# Fitbit
|
||||||
|
185.246.223.127 api.fitbit.com
|
||||||
|
185.246.223.127 fitbit-pa.googleapis.com
|
||||||
|
185.246.223.127 fitbitvestibuleshim-pa.googleapis.com
|
||||||
|
185.246.223.127 fitbit.google.com
|
||||||
|
|
||||||
|
# Claude
|
||||||
|
185.246.223.127 claude.ai
|
||||||
|
185.246.223.127 console.anthropic.com
|
||||||
|
185.246.223.127 auth.anthropic.com
|
||||||
|
185.246.223.127 api.anthropic.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
|
||||||
|
|
||||||
|
# Trae.ai
|
||||||
|
185.246.223.127 trae-api-sg.mchost.guru
|
||||||
|
185.246.223.127 api.trae.ai
|
||||||
|
185.246.223.127 api-sg-central.trae.ai
|
||||||
|
185.246.223.127 api16-normal-alisg.mchost.guru
|
||||||
|
|
||||||
|
# Другое:
|
||||||
|
185.246.223.127 www.notion.so
|
||||||
|
50.7.85.222 www.canva.com
|
||||||
|
185.246.223.127 www.intel.com
|
||||||
|
185.246.223.127 www.dell.com
|
||||||
|
50.7.85.219 www.tiktok.com # Только на сайте. Приложение определяет регион по оператору, а не по IP. Поэтому есть моды.
|
||||||
|
142.54.189.106 web.archive.org # Блокирует от российских IP некоторые сайты
|
||||||
|
185.246.223.127 developer.nvidia.com
|
||||||
|
107.150.34.99 builds.parsec.app
|
||||||
|
185.246.223.127 tria.ge
|
||||||
|
185.246.223.127 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
|
||||||
|
185.246.223.127 profile.broadcom.com
|
||||||
|
45.95.233.23 test.dns.malw.link
|
||||||
|
45.95.233.23 eu.posthog.com
|
||||||
|
185.246.223.127 www.qwant.com
|
||||||
|
185.246.223.127 guidedhacking.com
|
||||||
|
|
||||||
|
# Блокировка реально плохих сайтов
|
||||||
|
# Скримеры:
|
||||||
|
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
|
||||||
|
### dns.malw.link: end hosts file
|
||||||
1126
rust/Cargo.lock
generated
Normal file
1126
rust/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
32
rust/Cargo.toml
Normal file
32
rust/Cargo.toml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
[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"] }
|
||||||
|
libc = "0.2.177"
|
||||||
|
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"] }
|
||||||
|
getset = "0.1.6"
|
||||||
|
sysinfo = "0.37.2"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
opt-level = "z"
|
||||||
|
lto = true
|
||||||
|
strip = true
|
||||||
11
rust/crates/libnfqws/Cargo.toml
Normal file
11
rust/crates/libnfqws/Cargo.toml
Normal 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"
|
||||||
68
rust/crates/libnfqws/build.rs
Normal file
68
rust/crates/libnfqws/build.rs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
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");
|
||||||
|
|
||||||
|
let _ = env::var("NETFILTER_LIBS")
|
||||||
|
.map(|libs| println!("cargo:rustc-link-search=native={libs}/lib"));
|
||||||
|
|
||||||
|
println!("cargo:rustc-link-lib=static=nfqws");
|
||||||
|
println!("cargo:rerun-if-changed={}", NFQ.display());
|
||||||
|
println!("cargo:rerun-if-changed={}", NFQ_CRYPTO.display());
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
2
rust/crates/libnfqws/src/lib.rs
Normal file
2
rust/crates/libnfqws/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#![allow(warnings)]
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/libnfqws.rs"));
|
||||||
1
rust/crates/libnfqws/zapret
Submodule
1
rust/crates/libnfqws/zapret
Submodule
Submodule rust/crates/libnfqws/zapret added at 1408c38522
23
rust/crates/zaprett/Cargo.toml
Normal file
23
rust/crates/zaprett/Cargo.toml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[package]
|
||||||
|
name = "zaprett"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = { workspace = true }
|
||||||
|
clap = { workspace = true }
|
||||||
|
libc = { workspace = true }
|
||||||
|
regex = { workspace = true }
|
||||||
|
rust-ini = { workspace = true }
|
||||||
|
serde = { workspace = true }
|
||||||
|
serde_json = { workspace = true }
|
||||||
|
sysctl ={ workspace = true }
|
||||||
|
tokio = { workspace = true }
|
||||||
|
libnfqws = { path = "../libnfqws" }
|
||||||
|
daemonize = { workspace = true }
|
||||||
|
pretty_env_logger = { workspace = true }
|
||||||
|
log = { workspace = true }
|
||||||
|
nix = { workspace = true, features = ["user"] }
|
||||||
|
getset = { workspace = true }
|
||||||
|
sysinfo = { workspace = true }
|
||||||
5
rust/crates/zaprett/build.rs
Normal file
5
rust/crates/zaprett/build.rs
Normal 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);
|
||||||
|
}
|
||||||
20
rust/crates/zaprett/src/autostart.rs
Normal file
20
rust/crates/zaprett/src/autostart.rs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
use crate::MODULE_PATH;
|
||||||
|
use tokio::fs;
|
||||||
|
use tokio::fs::File;
|
||||||
|
|
||||||
|
pub async fn set_autostart(autostart: bool) -> Result<(), anyhow::Error> {
|
||||||
|
let autostart_path = MODULE_PATH.join("autostart");
|
||||||
|
|
||||||
|
if autostart {
|
||||||
|
File::create(autostart_path).await?;
|
||||||
|
} else {
|
||||||
|
fs::remove_file(autostart_path).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_autostart() {
|
||||||
|
let file = MODULE_PATH.join("autostart");
|
||||||
|
println!("{}", file.exists());
|
||||||
|
}
|
||||||
13
rust/crates/zaprett/src/cli.rs
Normal file
13
rust/crates/zaprett/src/cli.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
pub mod commands;
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
use commands::Command;
|
||||||
|
use getset::Getters;
|
||||||
|
|
||||||
|
#[derive(Parser, Getters)]
|
||||||
|
#[command(version)]
|
||||||
|
#[getset(get = "pub")]
|
||||||
|
pub struct CliApp {
|
||||||
|
#[command(subcommand)]
|
||||||
|
cmd: Option<Command>,
|
||||||
|
}
|
||||||
68
rust/crates/zaprett/src/cli/commands.rs
Normal file
68
rust/crates/zaprett/src/cli/commands.rs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
use crate::service::{restart_service, service_status, start_service, stop_service};
|
||||||
|
use crate::{bin_version, module_version};
|
||||||
|
use clap::Subcommand;
|
||||||
|
use log::error;
|
||||||
|
use crate::autostart::{get_autostart, set_autostart};
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
pub enum Command {
|
||||||
|
/// Start the service
|
||||||
|
Start,
|
||||||
|
|
||||||
|
/// Stop the service
|
||||||
|
Stop,
|
||||||
|
|
||||||
|
/// Restart the service
|
||||||
|
Restart,
|
||||||
|
|
||||||
|
/// Show the current service status
|
||||||
|
Status,
|
||||||
|
|
||||||
|
/// Enable or disable automatic restart
|
||||||
|
SetAutostart {
|
||||||
|
/// Whether to enable (true) or disable (false) autostart
|
||||||
|
#[arg(value_parser = clap::value_parser!(bool))]
|
||||||
|
autostart: bool,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Show whether autostart is enabled
|
||||||
|
GetAutostart,
|
||||||
|
|
||||||
|
/// Show the module version
|
||||||
|
ModuleVersion,
|
||||||
|
|
||||||
|
/// Show the nfqws binary version
|
||||||
|
BinaryVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command {
|
||||||
|
pub async fn exec(&self) -> anyhow::Result<()> {
|
||||||
|
match self {
|
||||||
|
Command::Start => return start_service().await,
|
||||||
|
Command::Stop => {
|
||||||
|
let _ = stop_service().await;
|
||||||
|
}
|
||||||
|
Command::Restart => return restart_service().await,
|
||||||
|
Command::Status => {
|
||||||
|
println!(
|
||||||
|
"zaprett is {}",
|
||||||
|
if service_status().await? {
|
||||||
|
"working"
|
||||||
|
} else {
|
||||||
|
"stopped"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Command::SetAutostart { autostart } => {
|
||||||
|
if let Err(err) = set_autostart(*autostart).await {
|
||||||
|
error!("Failed to set auto start: {err}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command::GetAutostart => get_autostart(),
|
||||||
|
Command::ModuleVersion => println!("{}", module_version().await?),
|
||||||
|
Command::BinaryVersion => println!("{}", bin_version()),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
63
rust/crates/zaprett/src/config.rs
Normal file
63
rust/crates/zaprett/src/config.rs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
use crate::{MODULE_PATH, merge_files};
|
||||||
|
use getset::Getters;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Default, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum ListType {
|
||||||
|
#[default]
|
||||||
|
Whitelist,
|
||||||
|
Blacklist,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Serialize, Deserialize, Getters)]
|
||||||
|
#[getset(get = "pub")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct Config {
|
||||||
|
active_lists: Vec<String>,
|
||||||
|
active_ipsets: Vec<String>,
|
||||||
|
active_exclude_lists: Vec<String>,
|
||||||
|
active_exclude_ipsets: Vec<String>,
|
||||||
|
list_type: ListType,
|
||||||
|
strategy: String,
|
||||||
|
app_list: String,
|
||||||
|
whitelist: Vec<String>,
|
||||||
|
blacklist: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListType {
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// (hostlist arg, ipset arg)
|
||||||
|
pub async fn merge(&self, config: &Config) -> (String, String) {
|
||||||
|
let module_path_str = MODULE_PATH.to_str().unwrap();
|
||||||
|
|
||||||
|
let (host_files, ipset_files, host_suffix, ipset_suffix, exclude_flag) = match self {
|
||||||
|
ListType::Whitelist => (
|
||||||
|
&config.active_lists,
|
||||||
|
&config.active_ipsets,
|
||||||
|
"hostlist",
|
||||||
|
"ipset",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
ListType::Blacklist => (
|
||||||
|
&config.active_exclude_lists,
|
||||||
|
&config.active_exclude_ipsets,
|
||||||
|
"hostlist-exclude",
|
||||||
|
"ipset-exclude",
|
||||||
|
"-exclude",
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let host_path = MODULE_PATH.join(format!("tmp/{host_suffix}"));
|
||||||
|
let ipset_path = MODULE_PATH.join(format!("tmp/{ipset_suffix}"));
|
||||||
|
|
||||||
|
merge_files(host_files, host_path).await.unwrap();
|
||||||
|
merge_files(ipset_files, ipset_path).await.unwrap();
|
||||||
|
|
||||||
|
(
|
||||||
|
format!("--hostlist{exclude_flag}={module_path_str}/tmp/{host_suffix}"),
|
||||||
|
format!("--ipset{exclude_flag}={module_path_str}/tmp/{ipset_suffix}"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
26
rust/crates/zaprett/src/daemon.rs
Normal file
26
rust/crates/zaprett/src/daemon.rs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
use crate::{MODULE_PATH, run_nfqws};
|
||||||
|
use daemonize::Daemonize;
|
||||||
|
use log::{error, info};
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
pub async fn daemonize_nfqws(args: &str) {
|
||||||
|
info!("Starting nfqws as a daemon");
|
||||||
|
|
||||||
|
let stdout = File::create(MODULE_PATH.join("tmp/nfqws.out")).unwrap();
|
||||||
|
let stderr = File::create(MODULE_PATH.join("tmp/nfqws.err")).unwrap();
|
||||||
|
|
||||||
|
let daemonize = Daemonize::new()
|
||||||
|
.pid_file(MODULE_PATH.join("tmp/pid.lock").as_path())
|
||||||
|
.working_directory(MODULE_PATH.join("tmp"))
|
||||||
|
.stdout(stdout)
|
||||||
|
.stderr(stderr)
|
||||||
|
.privileged_action(|| "Executed before drop privileges");
|
||||||
|
|
||||||
|
match daemonize.start() {
|
||||||
|
Ok(_) => {
|
||||||
|
info!("Success, daemonized");
|
||||||
|
run_nfqws(args).unwrap()
|
||||||
|
}
|
||||||
|
Err(e) => error!("Error while starting nfqws daemon: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
88
rust/crates/zaprett/src/iptables_rust.rs
Normal file
88
rust/crates/zaprett/src/iptables_rust.rs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
use std::error;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
pub fn setup_iptables_rules() -> Result<(), Box<dyn error::Error>> {
|
||||||
|
Command::new("iptables")
|
||||||
|
.arg("-t")
|
||||||
|
.arg("mangle")
|
||||||
|
.arg("-I")
|
||||||
|
.arg("POSTROUTING")
|
||||||
|
.arg("-j")
|
||||||
|
.arg("NFQUEUE")
|
||||||
|
.arg("--queue-num")
|
||||||
|
.arg("200")
|
||||||
|
.arg("--queue-bypass")
|
||||||
|
.status()
|
||||||
|
.expect("failed to add iptables rules");
|
||||||
|
|
||||||
|
Command::new("iptables")
|
||||||
|
.arg("-t")
|
||||||
|
.arg("mangle")
|
||||||
|
.arg("-I")
|
||||||
|
.arg("PREROUTING")
|
||||||
|
.arg("-j")
|
||||||
|
.arg("NFQUEUE")
|
||||||
|
.arg("--queue-num")
|
||||||
|
.arg("200")
|
||||||
|
.arg("--queue-bypass")
|
||||||
|
.status()
|
||||||
|
.expect("failed to add iptables rules");
|
||||||
|
|
||||||
|
Command::new("iptables")
|
||||||
|
.arg("-t")
|
||||||
|
.arg("filter")
|
||||||
|
.arg("-A")
|
||||||
|
.arg("FORWARD")
|
||||||
|
.arg("-j")
|
||||||
|
.arg("NFQUEUE")
|
||||||
|
.arg("--queue-num")
|
||||||
|
.arg("200")
|
||||||
|
.arg("--queue-bypass")
|
||||||
|
.status()
|
||||||
|
.expect("failed to add iptables rules");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_iptables_rules() -> Result<(), Box<dyn error::Error>> {
|
||||||
|
Command::new("iptables")
|
||||||
|
.arg("-t")
|
||||||
|
.arg("mangle")
|
||||||
|
.arg("-D")
|
||||||
|
.arg("POSTROUTING")
|
||||||
|
.arg("-j")
|
||||||
|
.arg("NFQUEUE")
|
||||||
|
.arg("--queue-num")
|
||||||
|
.arg("200")
|
||||||
|
.arg("--queue-bypass")
|
||||||
|
.status()
|
||||||
|
.expect("failed to remove iptables rules");
|
||||||
|
|
||||||
|
Command::new("iptables")
|
||||||
|
.arg("-t")
|
||||||
|
.arg("mangle")
|
||||||
|
.arg("-D")
|
||||||
|
.arg("PREROUTING")
|
||||||
|
.arg("-j")
|
||||||
|
.arg("NFQUEUE")
|
||||||
|
.arg("--queue-num")
|
||||||
|
.arg("200")
|
||||||
|
.arg("--queue-bypass")
|
||||||
|
.status()
|
||||||
|
.expect("failed to remove iptables rules");
|
||||||
|
|
||||||
|
Command::new("iptables")
|
||||||
|
.arg("-t")
|
||||||
|
.arg("filter")
|
||||||
|
.arg("-D")
|
||||||
|
.arg("FORWARD")
|
||||||
|
.arg("-j")
|
||||||
|
.arg("NFQUEUE")
|
||||||
|
.arg("--queue-num")
|
||||||
|
.arg("200")
|
||||||
|
.arg("--queue-bypass")
|
||||||
|
.status()
|
||||||
|
.expect("failed to remove iptables rules");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
103
rust/crates/zaprett/src/lib.rs
Normal file
103
rust/crates/zaprett/src/lib.rs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
pub mod cli;
|
||||||
|
pub mod config;
|
||||||
|
mod daemon;
|
||||||
|
pub mod iptables_rust;
|
||||||
|
mod service;
|
||||||
|
mod autostart;
|
||||||
|
|
||||||
|
use ini::Ini;
|
||||||
|
use libnfqws::nfqws_main;
|
||||||
|
use std::error;
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::os::raw::c_char;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
use anyhow::bail;
|
||||||
|
use tokio::fs::File;
|
||||||
|
use tokio::io::{copy, AsyncWriteExt};
|
||||||
|
use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
|
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"));
|
||||||
|
|
||||||
|
pub static DEFAULT_START: &str = "
|
||||||
|
--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
|
||||||
|
";
|
||||||
|
|
||||||
|
async fn module_version() -> anyhow::Result<String> {
|
||||||
|
let prop = spawn_blocking(|| Ini::load_from_file(MODULE_PATH.join("module.prop")))
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
if let Some(props) = prop.section::<String>(None)
|
||||||
|
&& let Some(version) = props.get("version")
|
||||||
|
{
|
||||||
|
return Ok(version.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
bail!("Failed to get version, prop not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bin_version() -> &'static str {
|
||||||
|
env!("ZAPRET_VERSION")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn merge_files(
|
||||||
|
input_paths: &[impl AsRef<Path>],
|
||||||
|
output_path: impl AsRef<Path>,
|
||||||
|
) -> Result<(), Box<dyn error::Error>> {
|
||||||
|
let output_path = output_path.as_ref();
|
||||||
|
let mut output_file = File::create(output_path).await?;
|
||||||
|
|
||||||
|
for input in input_paths {
|
||||||
|
let input = input.as_ref();
|
||||||
|
|
||||||
|
let mut input_file = File::open(input)
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("Failed to open {}: {e}", input.display()))?;
|
||||||
|
|
||||||
|
copy(&mut input_file, &mut output_file).await.map_err(|e| {
|
||||||
|
format!(
|
||||||
|
"Failed to write contents of {}: {e}",
|
||||||
|
input.display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
output_file.flush().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_nfqws(args_str: &str) -> anyhow::Result<()> {
|
||||||
|
let mut args = vec![
|
||||||
|
"nfqws".to_string(),
|
||||||
|
"--uid=0:0".to_string(),
|
||||||
|
"--qnum=200".to_string(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if args_str.trim().is_empty() {
|
||||||
|
args.push("-v".to_string());
|
||||||
|
} else {
|
||||||
|
args.extend(args_str.split_whitespace().map(String::from));
|
||||||
|
}
|
||||||
|
|
||||||
|
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 _);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
15
rust/crates/zaprett/src/main.rs
Normal file
15
rust/crates/zaprett/src/main.rs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
use clap::Parser;
|
||||||
|
use zaprett::cli::CliApp;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
pretty_env_logger::init();
|
||||||
|
|
||||||
|
let cli = CliApp::parse();
|
||||||
|
match cli.cmd() {
|
||||||
|
Some(cmd) => cmd.exec().await?,
|
||||||
|
None => println!("zaprett installed. Join us: t.me/zaprett_module"),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
125
rust/crates/zaprett/src/service.rs
Normal file
125
rust/crates/zaprett/src/service.rs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
use crate::config::Config;
|
||||||
|
use crate::daemon::daemonize_nfqws;
|
||||||
|
use crate::iptables_rust::{clear_iptables_rules, setup_iptables_rules};
|
||||||
|
use crate::{DEFAULT_START, MODULE_PATH, ZAPRETT_DIR_PATH};
|
||||||
|
use anyhow::bail;
|
||||||
|
use log::info;
|
||||||
|
use nix::sys::signal::{Signal, kill};
|
||||||
|
use nix::unistd::{Pid, Uid};
|
||||||
|
use regex::Regex;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use sysctl::{Ctl, CtlValue, Sysctl};
|
||||||
|
use sysinfo::{Pid as SysPid, System};
|
||||||
|
use tokio::fs;
|
||||||
|
use tokio::fs::File;
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub async fn start_service() -> anyhow::Result<()> {
|
||||||
|
if !Uid::effective().is_root() {
|
||||||
|
bail!("Running not from root, exiting");
|
||||||
|
};
|
||||||
|
|
||||||
|
if service_status().await? {
|
||||||
|
bail!("zaprett already started")
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Starting zaprett service...");
|
||||||
|
|
||||||
|
let tmp_dir = MODULE_PATH.join("tmp");
|
||||||
|
if tmp_dir.exists() {
|
||||||
|
fs::remove_dir_all(&tmp_dir).await?;
|
||||||
|
fs::create_dir_all(&tmp_dir).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut config_contents = String::new();
|
||||||
|
File::open(ZAPRETT_DIR_PATH.join("config.json"))
|
||||||
|
.await
|
||||||
|
.expect("cannot open config.json")
|
||||||
|
.read_to_string(&mut config_contents)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let config: Config = serde_json::from_str(&config_contents).expect("invalid json");
|
||||||
|
|
||||||
|
let start = fs::read_to_string(config.strategy())
|
||||||
|
.await
|
||||||
|
.map(Cow::Owned)
|
||||||
|
.unwrap_or(Cow::Borrowed(DEFAULT_START));
|
||||||
|
|
||||||
|
let regex_hostlist = Regex::new(r"\$hostlist")?;
|
||||||
|
let regex_ipsets = Regex::new(r"\$ipset")?;
|
||||||
|
let regex_zaprettdir = Regex::new(r"\$\{?zaprettdir}?")?;
|
||||||
|
|
||||||
|
let mut strat_modified;
|
||||||
|
let (hosts, ipsets) = config.list_type().merge(&config).await;
|
||||||
|
|
||||||
|
strat_modified = regex_hostlist.replace_all(&start, &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();
|
||||||
|
|
||||||
|
let ctl = Ctl::new("net.netfilter.nf_conntrack_tcp_be_liberal")?;
|
||||||
|
ctl.set_value(CtlValue::String("1".into()))?;
|
||||||
|
|
||||||
|
setup_iptables_rules().expect("setup iptables rules");
|
||||||
|
|
||||||
|
daemonize_nfqws(&strat_modified).await;
|
||||||
|
println!("zaprett service started!");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn stop_service() -> anyhow::Result<()> {
|
||||||
|
if !Uid::effective().is_root() {
|
||||||
|
bail!("Running not from root, exiting");
|
||||||
|
};
|
||||||
|
|
||||||
|
if !service_status().await? {
|
||||||
|
bail!("zaprett service already stopped")
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_iptables_rules().expect("clear iptables rules");
|
||||||
|
|
||||||
|
let pid_str = fs::read_to_string(MODULE_PATH.join("tmp/pid.lock")).await?;
|
||||||
|
let pid = pid_str.trim().parse::<i32>()?;
|
||||||
|
|
||||||
|
kill(Pid::from_raw(pid), Signal::SIGKILL)?;
|
||||||
|
|
||||||
|
println!("zaprett service stopped");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn restart_service() -> anyhow::Result<()> {
|
||||||
|
if !Uid::effective().is_root() {
|
||||||
|
bail!("Running not from root, exiting");
|
||||||
|
};
|
||||||
|
stop_service().await?;
|
||||||
|
start_service().await?;
|
||||||
|
info!("zaprett service restarted!");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn service_status() -> anyhow::Result<bool> {
|
||||||
|
if !Uid::effective().is_root() {
|
||||||
|
bail!("Running not from root, exiting");
|
||||||
|
};
|
||||||
|
|
||||||
|
let pid_i32 = match fs::read_to_string(Path::new(*MODULE_PATH).join("tmp/pid.lock")).await {
|
||||||
|
Ok(s) => match s.trim().parse::<i32>() {
|
||||||
|
Ok(pid) => pid,
|
||||||
|
Err(_) => return Ok(false),
|
||||||
|
},
|
||||||
|
Err(_) => return Ok(false),
|
||||||
|
};
|
||||||
|
let pid = SysPid::from(pid_i32 as usize);
|
||||||
|
let system = System::new_all();
|
||||||
|
if let Some(process) = system.process(pid) {
|
||||||
|
if process.name() == "zaprett" {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
109
rust/justfile
Normal file
109
rust/justfile
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
set shell := ["bash", "-eu", "-c"]
|
||||||
|
|
||||||
|
export ANDROID_API := "21"
|
||||||
|
export ANDROID_NDK_VERSION := "r27d-linux"
|
||||||
|
|
||||||
|
TARGET := `pwd` + "/target"
|
||||||
|
|
||||||
|
export NETFILTER_LIBS := TARGET + "/netfilter"
|
||||||
|
|
||||||
|
export NDK_HOME := TARGET + "/android-ndk-" + ANDROID_NDK_VERSION
|
||||||
|
|
||||||
|
_download_android_ndk:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
if [ ! -d "{{NDK_HOME}}" ]; then
|
||||||
|
echo "Downloading ndk {{ANDROID_NDK_VERSION}} to {{NDK_HOME}}"
|
||||||
|
TMPFILE="{{NDK_HOME}}.tmp"
|
||||||
|
TMPDIR="{{NDK_HOME}}.extracted.tmp"
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$TMPFILE")"
|
||||||
|
|
||||||
|
curl -L -C - -o "$TMPFILE" "https://dl.google.com/android/repository/android-ndk-{{ANDROID_NDK_VERSION}}.zip"
|
||||||
|
|
||||||
|
unzip "$TMPFILE" -d "$TMPDIR"
|
||||||
|
|
||||||
|
inner_folder=$(find "$TMPDIR" -mindepth 1 -maxdepth 1 -type d | head -n 1)
|
||||||
|
mv -T "$inner_folder" "$NDK_HOME"
|
||||||
|
|
||||||
|
rm -rf "$TMPFILE" "$TMPDIR"
|
||||||
|
|
||||||
|
echo "Android ndk {{ANDROID_NDK_VERSION}} successfully installed in {{NDK_HOME}}"
|
||||||
|
else
|
||||||
|
echo "Android ndk {{ANDROID_NDK_VERSION}} already installed in {{NDK_HOME}}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_build_netfilter_libs target_arch:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [ ! -d "{{NETFILTER_LIBS}}-{{target_arch}}" ]; then
|
||||||
|
export PATCH="$(pwd)/libnetfilter_queue-android.patch"
|
||||||
|
cd "{{TARGET}}"
|
||||||
|
|
||||||
|
export TOOLCHAIN=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
|
||||||
|
export CC="$TOOLCHAIN/bin/clang --target={{target_arch}}$ANDROID_API"
|
||||||
|
export AR=$TOOLCHAIN/bin/llvm-ar
|
||||||
|
export AS=$CC
|
||||||
|
export LD=$TOOLCHAIN/bin/ld
|
||||||
|
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
|
||||||
|
export STRIP=$TOOLCHAIN/bin/llvm-strip
|
||||||
|
export PKG_CONFIG_PATH=$NETFILTER_LIBS-{{target_arch}}/lib/pkgconfig
|
||||||
|
|
||||||
|
if [ ! -d "libnfnetlink-1.0.2" ]; then
|
||||||
|
wget -O- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "libmnl-1.0.5" ]; then
|
||||||
|
wget -O- https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "libnetfilter_queue-1.0.5" ]; then
|
||||||
|
wget -O- https://www.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2 | tar -xj
|
||||||
|
patch -p1 -d libnetfilter_queue-* -i $PATCH
|
||||||
|
fi
|
||||||
|
|
||||||
|
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||||
|
(
|
||||||
|
cd $i-*
|
||||||
|
make clean
|
||||||
|
CFLAGS="-Os -flto=auto -Wno-implicit-function-declaration" \
|
||||||
|
./configure --prefix= --host={{target_arch}} --enable-static --disable-shared --disable-dependency-tracking
|
||||||
|
make -j$(nproc)
|
||||||
|
make install DESTDIR=$NETFILTER_LIBS-{{target_arch}}
|
||||||
|
)
|
||||||
|
sed -i "s|^prefix=.*|prefix=$NETFILTER_LIBS-{{target_arch}}|g" $NETFILTER_LIBS-{{target_arch}}/lib/pkgconfig/$i.pc
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "Netfilter libs for {{target_arch}} already built"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_instal_rust_target target:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
if ! rustup target list --installed | grep -q "{{target}}"; then
|
||||||
|
echo "Installing missing target: {{target}}"
|
||||||
|
rustup target add "{{target}}"
|
||||||
|
else
|
||||||
|
echo "Target already installed: {{target}}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
prepare-android: _download_android_ndk
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
cargo install cargo-ndk
|
||||||
|
|
||||||
|
build-android *args: prepare-android
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
targets=("armv7-linux-androideabi" "aarch64-linux-android" "x86_64-linux-android")
|
||||||
|
|
||||||
|
for i in "${!targets[@]}"; do
|
||||||
|
t=${targets[$i]}
|
||||||
|
(
|
||||||
|
echo "Building target $t"
|
||||||
|
export CFLAGS="-I$NETFILTER_LIBS-$t/include"
|
||||||
|
export LDFLAGS="-L$NETFILTER_LIBS-$t/lib"
|
||||||
|
export CXXFLAGS="$CFLAGS"
|
||||||
|
|
||||||
|
just _build_netfilter_libs $t
|
||||||
|
just _instal_rust_target $t
|
||||||
|
NETFILTER_LIBS=$NETFILTER_LIBS-$t cargo ndk -t $t --platform $ANDROID_API build {{args}}
|
||||||
|
)
|
||||||
|
done
|
||||||
41
rust/libnetfilter_queue-android.patch
Normal file
41
rust/libnetfilter_queue-android.patch
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
--- a/src/extra/pktbuff.c
|
||||||
|
+++ b/src/extra/pktbuff.c
|
||||||
|
@@ -14,7 +14,7 @@
|
||||||
|
#include <string.h> /* for memcpy */
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
-#include <netinet/if_ether.h>
|
||||||
|
+#include <linux/if_ether.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
|
--- a/src/nlmsg.c
|
||||||
|
+++ b/src/nlmsg.c
|
||||||
|
@@ -21,7 +21,7 @@
|
||||||
|
|
||||||
|
#include <linux/netfilter/nfnetlink_queue.h>
|
||||||
|
|
||||||
|
-#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||||
|
+// #include <libnetfilter_queue/libnetfilter_queue.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
--- a/src/extra/tcp.c
|
||||||
|
+++ b/src/extra/tcp.c
|
||||||
|
@@ -139,12 +139,16 @@ void nfq_tcp_compute_checksum_ipv6(struc
|
||||||
|
* (union is compatible to any of its members)
|
||||||
|
* This means this part of the code is -fstrict-aliasing safe now.
|
||||||
|
*/
|
||||||
|
+#ifndef __ANDROID__
|
||||||
|
union tcp_word_hdr {
|
||||||
|
struct tcphdr hdr;
|
||||||
|
uint32_t words[5];
|
||||||
|
};
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
+#ifndef tcp_flag_word
|
||||||
|
#define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words[3])
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_pkt_snprintf_tcp_hdr - print tcp header into one buffer in a humnan
|
||||||
33
src/com/META-INF/google/android/update-binary
Normal file
33
src/com/META-INF/google/android/update-binary
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/sbin/sh
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Initialization
|
||||||
|
#################
|
||||||
|
|
||||||
|
umask 022
|
||||||
|
|
||||||
|
# echo before loading util_functions
|
||||||
|
ui_print() { echo "$1"; }
|
||||||
|
|
||||||
|
require_new_magisk() {
|
||||||
|
ui_print "*******************************"
|
||||||
|
ui_print " Please install Magisk v20.4+! "
|
||||||
|
ui_print "*******************************"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#########################
|
||||||
|
# Load util_functions.sh
|
||||||
|
#########################
|
||||||
|
|
||||||
|
OUTFD=$2
|
||||||
|
ZIPFILE=$3
|
||||||
|
|
||||||
|
mount /data 2>/dev/null
|
||||||
|
|
||||||
|
[ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk
|
||||||
|
. /data/adb/magisk/util_functions.sh
|
||||||
|
[ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk
|
||||||
|
|
||||||
|
install_module
|
||||||
|
exit 0
|
||||||
1
src/com/META-INF/google/android/updater-script
Normal file
1
src/com/META-INF/google/android/updater-script
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#MAGISK
|
||||||
67
src/customize.sh
Normal file
67
src/customize.sh
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
ui_print " _ _ "
|
||||||
|
ui_print " | | | | "
|
||||||
|
ui_print " ______ _ _ __ _ __ ___| |_| |_ "
|
||||||
|
ui_print " |_ / _' | '_ \| '__/ _ \ __| __|"
|
||||||
|
ui_print " / / (_| | |_) | | | __/ |_| |_ "
|
||||||
|
ui_print " /___\__,_| .__/|_| \\___|\__|\__|"
|
||||||
|
ui_print " | | "
|
||||||
|
ui_print " |_| "
|
||||||
|
ui_print "(!) To download app, use Telegram channel"
|
||||||
|
ui_print "Module by: egor-white, Cherret"
|
||||||
|
ui_print "App by: egor-white, Cherret"
|
||||||
|
ui_print "####################"
|
||||||
|
|
||||||
|
ui_print "Unpacking archive..."
|
||||||
|
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 "Filling configuration file if not exist..."
|
||||||
|
if [ ! -f "/sdcard/zaprett/config.json" ]; then
|
||||||
|
cat > /sdcard/zaprett/config.json << EOL
|
||||||
|
{
|
||||||
|
"active_lists": ["/sdcard/zaprett/lists/include/list-youtube.txt", "/sdcard/zaprett/lists/include/list-discord.txt"],
|
||||||
|
"active_ipsets": [],
|
||||||
|
"active_exclude_lists": [],
|
||||||
|
"active_exclude_ipsets": [],
|
||||||
|
"list_type": "whitelist",
|
||||||
|
"strategy": "",
|
||||||
|
"app_list": "whitelist",
|
||||||
|
"whitelist": [],
|
||||||
|
"blacklist": []
|
||||||
|
}
|
||||||
|
EOL
|
||||||
|
fi
|
||||||
|
|
||||||
|
ui_print "Copying lists and binaries to /sdcard/zaprett..."
|
||||||
|
cp -r $MODPATH/system/etc/zaprett/. /sdcard/zaprett/
|
||||||
|
|
||||||
|
ui_print "Copying files to /bin"
|
||||||
|
arch=$(uname -m)
|
||||||
|
case "$arch" in
|
||||||
|
"x86_64")
|
||||||
|
zaprett_bin="zaprett-x86_64"
|
||||||
|
;;
|
||||||
|
"armv7l"|"arm")
|
||||||
|
zaprett_bin="zaprett-armv7"
|
||||||
|
;;
|
||||||
|
"aarch64"|"armv8l")
|
||||||
|
zaprett_bin="zaprett-aarch64"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ui_print "Unknown arch: $arch"
|
||||||
|
abort
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
mv $MODPATH/system/bin/$zaprett_bin $MODPATH/system/bin/zaprett
|
||||||
|
rm $MODPATH/system/bin/zaprett-*
|
||||||
|
mkdir $MODPATH/tmp
|
||||||
|
|
||||||
|
ui_print "Setting permissions..."
|
||||||
|
chmod 777 /sdcard/zaprett; chmod 777 $MODPATH/service.sh
|
||||||
|
|
||||||
|
ui_print "Cleaning temp files..."
|
||||||
|
rm -rf $MODPATH/system/etc/zaprett
|
||||||
|
|
||||||
|
ui_print "Installation done. Join us in Telegram: https://t.me/zaprett_module"
|
||||||
9
src/service.sh
Normal file
9
src/service.sh
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/system/bin/sh
|
||||||
|
while [ -z "$(getprop sys.boot_completed)" ]; do sleep 2; done
|
||||||
|
if [ -f "/data/adb/modules/zaprett/autostart" ]; then
|
||||||
|
su -c "zaprett start"
|
||||||
|
while true; do
|
||||||
|
sleep 3600
|
||||||
|
su -c "zaprett restart"
|
||||||
|
done
|
||||||
|
fi
|
||||||
BIN
src/system/etc/zaprett/bin/quic_initial_www_google_com.bin
Normal file
BIN
src/system/etc/zaprett/bin/quic_initial_www_google_com.bin
Normal file
Binary file not shown.
BIN
src/system/etc/zaprett/bin/tls_clienthello_www_google_com.bin
Normal file
BIN
src/system/etc/zaprett/bin/tls_clienthello_www_google_com.bin
Normal file
Binary file not shown.
6
update-hosts.json
Normal file
6
update-hosts.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"version": "5.2",
|
||||||
|
"versionCode": 52,
|
||||||
|
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/5.2.0/zaprett-hosts.zip",
|
||||||
|
"changelog": "https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/changelog.md"
|
||||||
|
}
|
||||||
6
update-tv.json
Normal file
6
update-tv.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"version": "5.2",
|
||||||
|
"versionCode": 52,
|
||||||
|
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/5.2.0/zaprett-tv.zip",
|
||||||
|
"changelog": "https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/changelog.md"
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "2.5",
|
"version": "5.2",
|
||||||
"versionCode": 25,
|
"versionCode": 52,
|
||||||
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/Zapret_2_5_0/zapret.zip",
|
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/5.2.0/zaprett.zip",
|
||||||
"changelog": "https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/changelog.md"
|
"changelog": "https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/changelog.md"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "2.5",
|
"version": "100",
|
||||||
"versionCode": 25,
|
"versionCode": 100,
|
||||||
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/Zapret_2_5_0/zapret-extended.zip",
|
"zipUrl": "https://github.com/egor-white/zaprett/releases/download/4.7.0/zaprett-hosts.zip",
|
||||||
"changelog": "https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/changelog.md"
|
"changelog": "https://raw.githubusercontent.com/egor-white/zaprett/refs/heads/main/changelog.md"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user