├── .github └── workflows │ ├── autoupdate.yml │ ├── build.yml │ └── shellcheck.yml ├── .gitignore ├── .shellcheckrc ├── .vscode └── settings.json ├── README.md ├── compile.sh ├── deploy.sh ├── lists.txt ├── magiskmodule └── META-INF │ └── com │ └── google │ └── android │ ├── update-binary │ └── updater-script ├── module.prop ├── shellcheck.sh ├── update.sh └── update_template.json /.github/workflows/autoupdate.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Update 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * 3' 6 | workflow_dispatch: 7 | 8 | env: 9 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 10 | 11 | concurrency: 12 | group: update 13 | cancel-in-progress: false 14 | 15 | jobs: 16 | update: 17 | name: Update Hosts 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | with: 23 | fetch-depth: 0 24 | - name: Setup git 25 | run: | 26 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" 27 | git config --global user.name "github-actions[bot]" 28 | - name: Run update.sh 29 | run: ./update.sh 30 | build: 31 | name: Build 32 | needs: update 33 | runs-on: ubuntu-latest 34 | steps: 35 | - name: Checkout 36 | uses: actions/checkout@v4 37 | with: 38 | fetch-depth: 0 39 | - name: Run compile.sh 40 | run: ./compile.sh 41 | - name: Upload Build Result 42 | uses: actions/upload-artifact@v4 43 | with: 44 | name: MagicalProtection.zip 45 | path: | 46 | MagicalProtection-*.zip 47 | if-no-files-found: error 48 | deploy: 49 | name: Deploy 50 | needs: build 51 | runs-on: ubuntu-latest 52 | steps: 53 | - name: Checkout 54 | uses: actions/checkout@v4 55 | with: 56 | fetch-depth: 0 57 | - name: Setup git 58 | run: | 59 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" 60 | git config --global user.name "github-actions[bot]" 61 | - name: Download Build Result 62 | uses: actions/download-artifact@v4 63 | with: 64 | name: MagicalProtection.zip 65 | - name: Run deploy.sh 66 | run: ./deploy.sh 67 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - '**' 7 | 8 | jobs: 9 | build: 10 | name: Build Magisk Module 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | - name: Compile 18 | run: ./compile.sh 19 | - name: Upload Result 20 | uses: actions/upload-artifact@v4 21 | with: 22 | name: MagicalProtection.zip 23 | path: | 24 | MagicalProtection-*.zip 25 | if-no-files-found: error 26 | -------------------------------------------------------------------------------- /.github/workflows/shellcheck.yml: -------------------------------------------------------------------------------- 1 | name: ShellCheck 2 | 3 | on: 4 | push: 5 | branches: 6 | - '**' 7 | 8 | jobs: 9 | check: 10 | name: ShellCheck 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | - name: Install ShellCheck 16 | run: sudo apt-get install -y shellcheck 17 | - name: Run shellcheck 18 | run: ./shellcheck.sh 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | magiskmodule/module.prop 2 | magiskmodule/system 3 | magiskmodule/README.md 4 | hosts 5 | deploy 6 | *.zip 7 | .gitauth 8 | -------------------------------------------------------------------------------- /.shellcheckrc: -------------------------------------------------------------------------------- 1 | 2 | # enable additional checks 3 | enable=add-default-case 4 | enable=avoid-nullary-conditions 5 | enable=check-set-e-suppressed 6 | enable=check-unassigned-uppercase 7 | enable=deprecate-which 8 | 9 | # cd fail 10 | # this is usually covered by set -e 11 | disable=SC2164 12 | 13 | # dont follow source files info 14 | # we check all shell scripts anyways 15 | disable=SC1091 16 | 17 | # unnecessary arithmetic variables style 18 | # i dont care whether it says $(($TODAY)) or $((TODAY)) 19 | disable=SC2004 20 | 21 | # redundant sed invocation 22 | disable=SC2001 23 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // editor and files config 3 | "editor.tabSize": 2, 4 | "editor.insertSpaces": true, 5 | "editor.formatOnSave": true, 6 | "editor.wordWrap": "off", 7 | "editor.detectIndentation": false, 8 | "editor.trimAutoWhitespace": true, 9 | "editor.autoIndent": "full", 10 | "editor.renderWhitespace": "trailing", 11 | "files.insertFinalNewline": true, 12 | "files.trimFinalNewlines": true, 13 | "files.trimTrailingWhitespace": true, 14 | "[markdown]": { 15 | "files.trimTrailingWhitespace": false, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MagicalProtection 2 | Magisk-only completely systemless adblocking. 3 | 4 | [![GitHub Latest Release (by date)](https://img.shields.io/github/v/release/programminghoch10/MagicalProtection?label=latest&logo=github&display_name=release)](https://github.com/programminghoch10/MagicalProtection/releases/latest) 5 | [![GitHub Automatic Update Workflow Status](https://img.shields.io/github/actions/workflow/status/programminghoch10/MagicalProtection/autoupdate.yml?logo=github%20actions&logoColor=white&label=autoupdate)](https://github.com/programminghoch10/MagicalProtection/actions/workflows/autoupdate.yml) \ 6 | [![GitHub Global Download Counter](https://img.shields.io/github/downloads/programminghoch10/MagicalProtection/total?logo=github)](https://github.com/programminghoch10/MagicalProtection/releases) 7 | [![GitHub Latest Download Counter](https://img.shields.io/github/downloads/programminghoch10/MagicalProtection/latest/total?logo=github)](https://github.com/programminghoch10/MagicalProtection/releases/latest) \ 8 | [![GitHub last commit](https://img.shields.io/github/last-commit/programminghoch10/MagicalProtection?logo=git&logoColor=white)](https://github.com/programminghoch10/MagicalProtection/commits/main) 9 | [![GitHub Latest Release Date](https://img.shields.io/github/release-date/programminghoch10/MagicalProtection?logo=github)](https://github.com/programminghoch10/MagicalProtection/releases/latest) \ 10 | [![GitHub Build Workflow Status](https://img.shields.io/github/actions/workflow/status/programminghoch10/MagicalProtection/build.yml?logo=github%20actions&logoColor=white&label=build)](https://github.com/programminghoch10/MagicalProtection/actions/workflows/build.yml) 11 | [![ShellCheck Status](https://img.shields.io/github/actions/workflow/status/programminghoch10/MagicalProtection/shellcheck.yml?logo=github%20actions&logoColor=white&label=shellcheck)](https://github.com/programminghoch10/MagicalProtection/actions/workflows/shellcheck.yml) \ 12 | [![GitHub Repo stars](https://img.shields.io/github/stars/programminghoch10/MagicalProtection?style=social)](https://github.com/programminghoch10/MagicalProtection/stargazers) \ 13 | [![GitHub followers](https://img.shields.io/github/followers/programminghoch10?style=social)](https://github.com/programminghoch10) 14 | 15 | ## Inspiration 16 | 17 | I've been loving 18 | [`EnergizedProtection`](https://github.com/EnergizedProtection) 19 | and its simplicity of setting it up once 20 | without an app and then forgetting about it. 21 | However, setting up the 22 | [`EnergizedProtection Magisk Module`](https://github.com/Magisk-Modules-Repo/energizedprotection) 23 | includes executing some shell commands 24 | to download and install the preferred pack. 25 | Additionally, 26 | their infrastructure was kinda flaky, 27 | the shellscripts weren't POSIX compliant 28 | and some other minor inconveniences... 29 | 30 | So I've been envisioning a Magisk Module, 31 | which simply can be installed and forgot about. 32 | And with updates simply delivered 33 | via the Magisk inbuilt module updater, 34 | updating is an easy and straight forward process. 35 | 36 | The name `MagicalProtection` is inspired by 37 | Magisk's Magic Mount 38 | and _(obviously)_ by 39 | [`EnergizedProtection`](https://github.com/EnergizedProtection). 40 | 41 | ## Usage / Installation 42 | 43 | To use this Magisk module, install it and reboot. 44 | There is nothing more to do, it will work straightaway. 45 | _Magisk's Systemless Hosts module is not required._ 46 | 47 | ## Automatic Updates 48 | 49 | [![GitHub Automatic Update Workflow Status](https://img.shields.io/github/actions/workflow/status/programminghoch10/MagicalProtection/autoupdate.yml?logo=github%20actions&logoColor=white&label=autoupdate)](https://github.com/programminghoch10/MagicalProtection/actions/workflows/autoupdate.yml) 50 | 51 | Updates for this module and its hosts lists are 52 | [completely automated in GitHub Actions](https://github.com/programminghoch10/MagicalProtection/actions/workflows/autoupdate.yml). 53 | 54 | To differentiate kinds of module updates, 55 | the version info contains two version numbers: 56 | The module version (`mv`) 57 | and the hosts version (`hv`). 58 | Both will tick up individually 59 | as updates for module and hosts are deployed. 60 | 61 | ## Blocklist Issues 62 | 63 | This mod uses blocklists from other sources. 64 | If you have an issue with the blocked domains, 65 | look at [the currently used blocklists](lists.txt) 66 | and report the issue there. 67 | -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -u 4 | set -o pipefail 5 | shopt -s inherit_errexit 6 | IFS=$'\n' 7 | renice -n 19 $$ &>/dev/null 8 | cd "$(dirname "$(readlink -f "$0")")" 9 | 10 | for cmd in git zip base64; do 11 | [ -z "$(command -v "$cmd")" ] && echo "missing $cmd" && exit 1 12 | done 13 | 14 | git clean -fdxq magiskmodule/ 15 | rm -f MagicalProtection-*.zip 16 | 17 | ./update.sh checkOutHosts 18 | 19 | function getCommitCount() { 20 | local folder="${1-.}" 21 | ( 22 | cd "$folder" 23 | git rev-list --count HEAD 24 | ) 25 | } 26 | 27 | git diff --exit-code --quiet && LOCALCHANGES=false || LOCALCHANGES=true 28 | $LOCALCHANGES && CHANGES="+" || CHANGES="-" 29 | MODULE_COMMITS=$(getCommitCount) 30 | HOSTS_COMMITS=$(getCommitCount hosts) 31 | VERSIONCODE=$MODULE_COMMITS$(printf '%05d' "$HOSTS_COMMITS") 32 | COMMITHASH=$(git log -1 --pretty=%h) 33 | COMMITHASHFULL=$(git log -1 --pretty=%H) 34 | VERSIONTAG=mv$MODULE_COMMITS-hv$HOSTS_COMMITS 35 | VERSION=$VERSIONTAG$CHANGES$COMMITHASH 36 | FILENAME=MagicalProtection-$VERSIONTAG 37 | LOCALDIFF=$(git diff --no-color --irreversible-delete | base64 -w 0) 38 | 39 | declare -x VERSION VERSIONCODE VERSIONTAG MODULE_COMMITS HOSTS_COMMITS COMMITHASHFULL LOCALCHANGES LOCALDIFF 40 | envsubst < module.prop > magiskmodule/module.prop 41 | 42 | cp -f README.md magiskmodule/README.md 43 | 44 | mkdir -p magiskmodule/system/etc 45 | cat hosts/* \ 46 | | grep -v '^\s*#' \ 47 | | sed -e '/^$/d' \ 48 | | sort \ 49 | | uniq \ 50 | > magiskmodule/system/etc/hosts 51 | 52 | ./update.sh removeHosts 53 | 54 | ( 55 | cd magiskmodule 56 | zip -r -9 -q ../"$FILENAME" . 57 | ) 58 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -u 4 | set -o pipefail 5 | shopt -s inherit_errexit 6 | IFS=$'\n' 7 | cd "$(dirname "$(readlink -f "$0")")" 8 | 9 | [ -f .gitauth ] && source .gitauth 10 | [ -z "${GITHUB_TOKEN-}" ] && echo "missing GITHUB_TOKEN" && exit 1 11 | 12 | for cmd in git curl jq; do 13 | [ -z "$(command -v "$cmd")" ] && echo "missing $cmd" && exit 1 14 | done 15 | 16 | FILE="${1-}" 17 | # shellcheck disable=SC2012 18 | [ -z "$FILE" ] && FILE=$(ls MagicalProtection-*.zip | tail -n 1) 19 | [ -z "$FILE" ] && echo "require input file" && exit 1 20 | 21 | function getprop() { 22 | local prop="$1" 23 | local content 24 | content=$(cat) 25 | [ -z "$content" ] && echo "missing content in getProp" >&2 && return 1 26 | grep -q "^$prop" <<< "$content" || return 1 27 | grep "^$prop" <<< "$content" | head -n 1 | cut -d'=' -f2 28 | } 29 | 30 | FILE_MODULE_PROP=$(unzip -p "$FILE" module.prop) 31 | 32 | ./update.sh checkOutDeploy 33 | 34 | DEPLOY_VERSION=$(getprop version < deploy/module.prop) 35 | DEPLOY_VERSIONCODE=$(getprop versionCode < deploy/module.prop) 36 | FILE_VERSION=$(getprop version <<< "$FILE_MODULE_PROP") 37 | FILE_VERSIONCODE=$(getprop versionCode <<< "$FILE_MODULE_PROP") 38 | 39 | echo "deploy version = $DEPLOY_VERSION" >&2 40 | echo " file version = $FILE_VERSION" >&2 41 | 42 | [ "$FILE_VERSIONCODE" -le "$DEPLOY_VERSIONCODE" ] && { 43 | echo "versioncode did not increase, no deploy required." 44 | ./update.sh removeDeploy 45 | exit 0 46 | } 47 | 48 | NEW_TAG_NAME=$(getprop versionTag <<< "$FILE_MODULE_PROP") 49 | 50 | export FILENAME="$FILE" 51 | export VERSIONTAG="$NEW_TAG_NAME" 52 | export VERSION="$FILE_VERSION" 53 | VERSIONCODE=$(getprop versionCode <<< "$FILE_MODULE_PROP") 54 | export VERSIONCODE 55 | envsubst < update_template.json > deploy/update.json 56 | echo "$FILE_MODULE_PROP" > deploy/module.prop 57 | 58 | ( 59 | cd deploy 60 | git add module.prop update.json 61 | git commit -m "$VERSIONTAG" || exit 62 | git push -q 63 | ) || exit 1 64 | 65 | GITHUB_OWNER="programminghoch10" 66 | GITHUB_REPO="MagicalProtection" 67 | 68 | COMMITISH=$(getprop versionModuleCommitHash <<< "$FILE_MODULE_PROP") 69 | 70 | CURL_GITHUB_API_ARGS=( 71 | --fail 72 | --location 73 | --show-error 74 | --header "Accept: application/vnd.github+json" 75 | --header "Authorization: Bearer $GITHUB_TOKEN" 76 | --header "X-GitHub-Api-Version: 2022-11-28" 77 | ) 78 | 79 | CREATE_RELEASE_RESPONSE=$(curl \ 80 | --silent \ 81 | "${CURL_GITHUB_API_ARGS[@]}" \ 82 | --request POST \ 83 | "https://api.github.com/repos/$GITHUB_OWNER/$GITHUB_REPO/releases" \ 84 | --data "{ 85 | \"tag_name\":\"$VERSIONTAG\", 86 | \"target_commitish\":\"$COMMITISH\", 87 | \"name\":\"$VERSIONTAG\", 88 | \"body\":\"$(cat deploy/changelog.md)\", 89 | \"draft\":true 90 | }" 91 | ) 92 | 93 | ./update.sh removeDeploy 94 | 95 | RELEASE_ID=$(jq --raw-output .id <<< "$CREATE_RELEASE_RESPONSE") 96 | [ -z "$RELEASE_ID" ] && echo "failed to acquire created release id" && exit 1 97 | 98 | curl \ 99 | "${CURL_GITHUB_API_ARGS[@]}" \ 100 | --request POST \ 101 | --header "Content-Type: application/zip" \ 102 | "https://uploads.github.com/repos/$GITHUB_OWNER/$GITHUB_REPO/releases/$RELEASE_ID/assets?name=$(basename "$FILENAME")" \ 103 | --data-binary "@$FILENAME" \ 104 | --output /dev/null 105 | 106 | curl \ 107 | --silent \ 108 | "${CURL_GITHUB_API_ARGS[@]}" \ 109 | --request PATCH \ 110 | "https://api.github.com/repos/$GITHUB_OWNER/$GITHUB_REPO/releases/$RELEASE_ID" \ 111 | --data '{"draft":false}' \ 112 | --output /dev/null 113 | 114 | ./update.sh pushDeploy 115 | -------------------------------------------------------------------------------- /lists.txt: -------------------------------------------------------------------------------- 1 | # adblocking hosts lists 2 | # format: name,url 3 | badmojr_1hosts,https://raw.githubusercontent.com/badmojr/1Hosts/master/Pro/hosts.txt 4 | -------------------------------------------------------------------------------- /magiskmodule/META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | ################# 4 | # Initialization 5 | ################# 6 | 7 | umask 022 8 | 9 | # echo before loading util_functions 10 | ui_print() { echo "$1"; } 11 | 12 | require_new_magisk() { 13 | ui_print "*******************************" 14 | ui_print " Please install Magisk v20.4+! " 15 | ui_print "*******************************" 16 | exit 1 17 | } 18 | 19 | ######################### 20 | # Load util_functions.sh 21 | ######################### 22 | 23 | OUTFD=$2 24 | ZIPFILE=$3 25 | 26 | mount /data 2>/dev/null 27 | 28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk 29 | . /data/adb/magisk/util_functions.sh 30 | [ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk 31 | 32 | install_module 33 | exit 0 34 | -------------------------------------------------------------------------------- /magiskmodule/META-INF/com/google/android/updater-script: -------------------------------------------------------------------------------- 1 | #MAGISK 2 | -------------------------------------------------------------------------------- /module.prop: -------------------------------------------------------------------------------- 1 | id=MagicalProtection 2 | name=MagicalProtection 3 | version=$VERSION 4 | versionCode=$VERSIONCODE 5 | versionTag=$VERSIONTAG 6 | versionModule=$MODULE_COMMITS 7 | versionHosts=$HOSTS_COMMITS 8 | versionModuleCommitHash=$COMMITHASHFULL 9 | versionModuleLocalChanges=$LOCALCHANGES 10 | versionModuleLocalDiff=$LOCALDIFF 11 | author=programminghoch10 12 | description=Magisk-only completely systemless adblocking. 13 | updateJson=https://raw.githubusercontent.com/programminghoch10/MagicalProtection/deploy/update.json 14 | -------------------------------------------------------------------------------- /shellcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export IFS=$'\n' 3 | [ -z "$(command -v shellcheck)" ] && echo "shellcheck not installed!" && exit 1 4 | shellcheck --version 5 | 6 | SHELLCHECK_ARGS=() 7 | SHELLCHECK_ARGS+=(--wiki-link-count=256) 8 | 9 | declare -a FILES 10 | mapfile -t FILES < <(find . -type f -name '*.sh') 11 | 12 | shellcheck \ 13 | "${SHELLCHECK_ARGS[@]}" \ 14 | "$@" \ 15 | "${FILES[@]}" 16 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -u 4 | set -o pipefail 5 | shopt -s inherit_errexit 6 | IFS=$'\n' 7 | cd "$(dirname "$(readlink -f "$0")")" 8 | 9 | for cmd in git curl; do 10 | [ -z "$(command -v "$cmd")" ] && echo "missing $cmd" && exit 1 11 | done 12 | 13 | function checkOutBranch() { 14 | local branch="$1" 15 | local folder="${2-}" 16 | [ -z "$folder" ] && folder="$branch" 17 | ! git branch | grep -q "$branch" && git fetch origin "$branch":"$branch" 18 | [ -d "$folder" ] && rm -rf "$folder" 19 | mkdir "$folder" 20 | git clone -q "$(pwd)" "$folder" 21 | cd "$folder" 22 | git config --local push.autoSetupRemote true 23 | git fetch -q origin "$branch":"$branch" 24 | git checkout -q "$branch" 25 | cd .. 26 | } 27 | 28 | function removeBranch() { 29 | local branch="$1" 30 | local folder="${2-}" 31 | [ -z "$folder" ] && folder="$branch" 32 | rm -rf "$folder" 33 | } 34 | 35 | function pushBranch() { 36 | local branch="$1" 37 | git push origin "$branch" 38 | } 39 | 40 | case "${1-}" in 41 | checkOutHosts) 42 | checkOutBranch hosts 43 | exit 44 | ;; 45 | removeHosts) 46 | removeBranch hosts 47 | exit 48 | ;; 49 | pushHosts) 50 | pushBranch hosts 51 | exit 52 | ;; 53 | checkOutDeploy) 54 | checkOutBranch deploy 55 | exit 56 | ;; 57 | removeDeploy) 58 | removeBranch deploy 59 | exit 60 | ;; 61 | pushDeploy) 62 | pushBranch deploy 63 | exit 64 | ;; 65 | *) 66 | ;; 67 | esac 68 | 69 | $0 checkOutHosts 70 | 71 | while read -r line; do 72 | grep -q '^\s*#' <<< "$line" && continue 73 | file=$(cut -d',' -f1 <<< "$line") 74 | url=$(cut -d',' -f2 <<< "$line") 75 | curl \ 76 | -o hosts/"$file" \ 77 | --etag-save hosts/"$file".etag \ 78 | --etag-compare hosts/"$file".etag \ 79 | "$url" 80 | done < lists.txt 81 | 82 | ( 83 | cd hosts 84 | for file in *; do 85 | listsfile=$(sed -e 's/\.etag$//' <<< "$file") 86 | grep -q "^$listsfile" < ../lists.txt && continue 87 | rm "$file" 88 | done 89 | ) 90 | 91 | ( 92 | cd hosts 93 | git add . 94 | git commit -m "Update lists" || true 95 | git push -q 96 | ) 97 | 98 | $0 removeHosts 99 | 100 | $0 pushHosts 101 | -------------------------------------------------------------------------------- /update_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "$VERSION", 3 | "versionCode": $VERSIONCODE, 4 | "zipUrl": "https://github.com/programminghoch10/MagicalProtection/releases/download/$VERSIONTAG/$FILENAME", 5 | "changelog": "https://raw.githubusercontent.com/programminghoch10/MagicalProtection/deploy/changelog.md" 6 | } 7 | --------------------------------------------------------------------------------