diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index c2d1264..499bb8e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -5,7 +5,7 @@
version: 2
updates:
- - package-ecosystem: "cargo"
+ - package-ecosystem: "gomod"
directories:
- "*"
schedule:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 1ef943a..0f8906e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -9,24 +9,21 @@ on:
paths-ignore:
- "**.md"
-env:
- CARGO_TERM_COLOR: always
-
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- - name: Build
- run: cargo build --verbose
- - name: Make release
+ - uses: actions/setup-go@v5
+ with:
+ go-version: '^1.13.1'
+ - name: Build and make release
run: |
- cd target/debug/
- ./make_release.exe
+ scripts/build.bat
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: zapret-discord-youtube-ankddev-debug
path: |
- target/debug/zapret-discord-youtube-ankddev.zip
+ build/zapret-discord-youtube-ankddev.zip
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
deleted file mode 100644
index a588b93..0000000
--- a/.github/workflows/lint.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: Lint with Clippy
-permissions:
- checks: write
-on:
- push:
- branches: ["main"]
- pull_request:
- branches: ["main"]
-
-env:
- CARGO_TERM_COLOR: always
-
-jobs:
- lint:
- runs-on: windows-latest
-
- steps:
- - uses: actions/checkout@v4
- - uses: dtolnay/rust-toolchain@stable
- with:
- components: clippy
- - uses: auguwu/clippy-action@1.4.0
- with:
- token: ${{secrets.GITHUB_TOKEN}}
diff --git a/.gitignore b/.gitignore
index ea8c4bf..826bca8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
-/target
+/build
+/build
diff --git a/.idea/discord.xml b/.idea/discord.xml
new file mode 100644
index 0000000..30bab2a
--- /dev/null
+++ b/.idea/discord.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/zapret-discord-youtube.iml b/.idea/zapret-discord-youtube.iml
index 1a1f2f3..5486a16 100644
--- a/.idea/zapret-discord-youtube.iml
+++ b/.idea/zapret-discord-youtube.iml
@@ -1,5 +1,6 @@
+
diff --git a/Cargo.lock b/Cargo.lock
deleted file mode 100644
index ea04a74..0000000
--- a/Cargo.lock
+++ /dev/null
@@ -1,1885 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "add_to_autorun"
-version = "1.1.0"
-dependencies = [
- "crossterm",
- "ctrlc",
- "regex",
- "shared",
- "winresource",
-]
-
-[[package]]
-name = "adler2"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
-
-[[package]]
-name = "aes"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
-dependencies = [
- "cfg-if",
- "cipher",
- "cpufeatures",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
-
-[[package]]
-name = "arbitrary"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
-dependencies = [
- "derive_arbitrary",
-]
-
-[[package]]
-name = "autocfg"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
-
-[[package]]
-name = "base64"
-version = "0.22.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
-
-[[package]]
-name = "bitflags"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
-
-[[package]]
-name = "block-buffer"
-version = "0.10.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
-
-[[package]]
-name = "byteorder"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
-
-[[package]]
-name = "bzip2"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
-dependencies = [
- "bzip2-sys",
- "libc",
-]
-
-[[package]]
-name = "bzip2-sys"
-version = "0.1.11+1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
-dependencies = [
- "cc",
- "libc",
- "pkg-config",
-]
-
-[[package]]
-name = "cc"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
-dependencies = [
- "jobserver",
- "libc",
- "shlex",
-]
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "cfg_aliases"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
-
-[[package]]
-name = "cipher"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
-dependencies = [
- "crypto-common",
- "inout",
-]
-
-[[package]]
-name = "constant_time_eq"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
-
-[[package]]
-name = "core-foundation"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
-dependencies = [
- "core-foundation-sys",
- "libc",
-]
-
-[[package]]
-name = "core-foundation-sys"
-version = "0.8.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
-
-[[package]]
-name = "cpufeatures"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "crc"
-version = "3.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636"
-dependencies = [
- "crc-catalog",
-]
-
-[[package]]
-name = "crc-catalog"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
-
-[[package]]
-name = "crc32fast"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "crossbeam-deque"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
-dependencies = [
- "crossbeam-epoch",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-epoch"
-version = "0.9.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
-dependencies = [
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
-
-[[package]]
-name = "crossterm"
-version = "0.28.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
-dependencies = [
- "bitflags",
- "crossterm_winapi",
- "mio",
- "parking_lot",
- "rustix",
- "signal-hook",
- "signal-hook-mio",
- "winapi",
-]
-
-[[package]]
-name = "crossterm_winapi"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "crypto-common"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
-dependencies = [
- "generic-array",
- "typenum",
-]
-
-[[package]]
-name = "ctrlc"
-version = "3.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3"
-dependencies = [
- "nix",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "deflate64"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b"
-
-[[package]]
-name = "deranged"
-version = "0.3.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
-dependencies = [
- "powerfmt",
-]
-
-[[package]]
-name = "derive_arbitrary"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "digest"
-version = "0.10.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
-dependencies = [
- "block-buffer",
- "crypto-common",
- "subtle",
-]
-
-[[package]]
-name = "displaydoc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "dunce"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
-
-[[package]]
-name = "either"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
-
-[[package]]
-name = "equivalent"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
-
-[[package]]
-name = "errno"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
-dependencies = [
- "libc",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "fastrand"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4"
-
-[[package]]
-name = "flate2"
-version = "1.0.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
-dependencies = [
- "crc32fast",
- "miniz_oxide",
-]
-
-[[package]]
-name = "foreign-types"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
-dependencies = [
- "foreign-types-shared",
-]
-
-[[package]]
-name = "foreign-types-shared"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
-
-[[package]]
-name = "form_urlencoded"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
-dependencies = [
- "percent-encoding",
-]
-
-[[package]]
-name = "fs_extra"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
-
-[[package]]
-name = "generic-array"
-version = "0.14.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
-dependencies = [
- "typenum",
- "version_check",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.15.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
-
-[[package]]
-name = "heck"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
-
-[[package]]
-name = "hermit-abi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
-
-[[package]]
-name = "hmac"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
-dependencies = [
- "digest",
-]
-
-[[package]]
-name = "icu_collections"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locid"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
-dependencies = [
- "displaydoc",
- "litemap",
- "tinystr",
- "writeable",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locid_transform"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
-dependencies = [
- "displaydoc",
- "icu_locid",
- "icu_locid_transform_data",
- "icu_provider",
- "tinystr",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locid_transform_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
-
-[[package]]
-name = "icu_normalizer"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "utf16_iter",
- "utf8_iter",
- "write16",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
-
-[[package]]
-name = "icu_properties"
-version = "1.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_locid_transform",
- "icu_properties_data",
- "icu_provider",
- "tinystr",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
-
-[[package]]
-name = "icu_provider"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
-dependencies = [
- "displaydoc",
- "icu_locid",
- "icu_provider_macros",
- "stable_deref_trait",
- "tinystr",
- "writeable",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_provider_macros"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "idna"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
-dependencies = [
- "idna_adapter",
- "smallvec",
- "utf8_iter",
-]
-
-[[package]]
-name = "idna_adapter"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
-dependencies = [
- "icu_normalizer",
- "icu_properties",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
-dependencies = [
- "equivalent",
- "hashbrown",
-]
-
-[[package]]
-name = "inout"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "jobserver"
-version = "0.1.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
-
-[[package]]
-name = "libc"
-version = "0.2.166"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
-
-[[package]]
-name = "litemap"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
-
-[[package]]
-name = "lock_api"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
-dependencies = [
- "autocfg",
- "scopeguard",
-]
-
-[[package]]
-name = "lockfree-object-pool"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e"
-
-[[package]]
-name = "log"
-version = "0.4.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
-
-[[package]]
-name = "lzma-rs"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
-dependencies = [
- "byteorder",
- "crc",
-]
-
-[[package]]
-name = "make_release"
-version = "1.1.0"
-dependencies = [
- "anyhow",
- "dunce",
- "fs_extra",
- "spinners",
- "walkdir",
- "winresource",
- "zip",
-]
-
-[[package]]
-name = "maplit"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
-
-[[package]]
-name = "memchr"
-version = "2.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
-dependencies = [
- "adler2",
-]
-
-[[package]]
-name = "mio"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
-dependencies = [
- "hermit-abi",
- "libc",
- "log",
- "wasi",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "native-tls"
-version = "0.2.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
-dependencies = [
- "libc",
- "log",
- "openssl",
- "openssl-probe",
- "openssl-sys",
- "schannel",
- "security-framework",
- "security-framework-sys",
- "tempfile",
-]
-
-[[package]]
-name = "nix"
-version = "0.29.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
-dependencies = [
- "bitflags",
- "cfg-if",
- "cfg_aliases",
- "libc",
-]
-
-[[package]]
-name = "ntapi"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "num-conv"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
-
-[[package]]
-name = "once_cell"
-version = "1.20.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
-
-[[package]]
-name = "openssl"
-version = "0.10.68"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5"
-dependencies = [
- "bitflags",
- "cfg-if",
- "foreign-types",
- "libc",
- "once_cell",
- "openssl-macros",
- "openssl-sys",
-]
-
-[[package]]
-name = "openssl-macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "openssl-probe"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
-
-[[package]]
-name = "openssl-sys"
-version = "0.9.104"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741"
-dependencies = [
- "cc",
- "libc",
- "pkg-config",
- "vcpkg",
-]
-
-[[package]]
-name = "parking_lot"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
-dependencies = [
- "lock_api",
- "parking_lot_core",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.9.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
-dependencies = [
- "cfg-if",
- "libc",
- "redox_syscall",
- "smallvec",
- "windows-targets",
-]
-
-[[package]]
-name = "pbkdf2"
-version = "0.12.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
-dependencies = [
- "digest",
- "hmac",
-]
-
-[[package]]
-name = "percent-encoding"
-version = "2.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
-
-[[package]]
-name = "pkg-config"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
-
-[[package]]
-name = "powerfmt"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
-dependencies = [
- "zerocopy",
-]
-
-[[package]]
-name = "preconfig_tester"
-version = "1.1.0"
-dependencies = [
- "native-tls",
- "sysinfo",
- "termcolor",
- "ureq",
- "winapi",
- "winresource",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "rayon"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
-dependencies = [
- "either",
- "rayon-core",
-]
-
-[[package]]
-name = "rayon-core"
-version = "1.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
-dependencies = [
- "crossbeam-deque",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "regex"
-version = "1.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
-
-[[package]]
-name = "ring"
-version = "0.17.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
-dependencies = [
- "cc",
- "cfg-if",
- "getrandom",
- "libc",
- "spin",
- "untrusted",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "run_preconfig"
-version = "1.1.0"
-dependencies = [
- "crossterm",
- "ctrlc",
- "shared",
- "winresource",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.41"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
-dependencies = [
- "bitflags",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "rustls"
-version = "0.23.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1"
-dependencies = [
- "log",
- "once_cell",
- "ring",
- "rustls-pki-types",
- "rustls-webpki",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "rustls-pki-types"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
-
-[[package]]
-name = "rustls-webpki"
-version = "0.102.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
-dependencies = [
- "ring",
- "rustls-pki-types",
- "untrusted",
-]
-
-[[package]]
-name = "rustversion"
-version = "1.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
-
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "schannel"
-version = "0.1.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
-dependencies = [
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "scopeguard"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-
-[[package]]
-name = "security-framework"
-version = "2.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
-dependencies = [
- "bitflags",
- "core-foundation",
- "core-foundation-sys",
- "libc",
- "security-framework-sys",
-]
-
-[[package]]
-name = "security-framework-sys"
-version = "2.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2"
-dependencies = [
- "core-foundation-sys",
- "libc",
-]
-
-[[package]]
-name = "select_domains"
-version = "1.1.0"
-dependencies = [
- "crossterm",
- "winresource",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.215"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.215"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "serde_spanned"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "sha1"
-version = "0.10.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
-[[package]]
-name = "shared"
-version = "1.1.0"
-dependencies = [
- "crossterm",
- "ctrlc",
-]
-
-[[package]]
-name = "shlex"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
-
-[[package]]
-name = "signal-hook"
-version = "0.3.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
-dependencies = [
- "libc",
- "signal-hook-registry",
-]
-
-[[package]]
-name = "signal-hook-mio"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
-dependencies = [
- "libc",
- "mio",
- "signal-hook",
-]
-
-[[package]]
-name = "signal-hook-registry"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "simd-adler32"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
-
-[[package]]
-name = "smallvec"
-version = "1.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
-
-[[package]]
-name = "spin"
-version = "0.9.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
-
-[[package]]
-name = "spinners"
-version = "4.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0ef947f358b9c238923f764c72a4a9d42f2d637c46e059dbd319d6e7cfb4f82"
-dependencies = [
- "lazy_static",
- "maplit",
- "strum",
-]
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
-
-[[package]]
-name = "strum"
-version = "0.24.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
-dependencies = [
- "strum_macros",
-]
-
-[[package]]
-name = "strum_macros"
-version = "0.24.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "rustversion",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "subtle"
-version = "2.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.89"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "sysinfo"
-version = "0.32.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af"
-dependencies = [
- "core-foundation-sys",
- "libc",
- "memchr",
- "ntapi",
- "rayon",
- "windows",
-]
-
-[[package]]
-name = "tempfile"
-version = "3.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
-dependencies = [
- "cfg-if",
- "fastrand",
- "once_cell",
- "rustix",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "thiserror"
-version = "2.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "2.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "time"
-version = "0.3.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
-dependencies = [
- "deranged",
- "num-conv",
- "powerfmt",
- "serde",
- "time-core",
-]
-
-[[package]]
-name = "time-core"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
-
-[[package]]
-name = "tinystr"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
-dependencies = [
- "displaydoc",
- "zerovec",
-]
-
-[[package]]
-name = "toml"
-version = "0.8.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
-dependencies = [
- "serde",
- "serde_spanned",
- "toml_datetime",
- "toml_edit",
-]
-
-[[package]]
-name = "toml_datetime"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "toml_edit"
-version = "0.22.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
-dependencies = [
- "indexmap",
- "serde",
- "serde_spanned",
- "toml_datetime",
- "winnow",
-]
-
-[[package]]
-name = "typenum"
-version = "1.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
-
-[[package]]
-name = "untrusted"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
-
-[[package]]
-name = "ureq"
-version = "2.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
-dependencies = [
- "base64",
- "flate2",
- "log",
- "once_cell",
- "rustls",
- "rustls-pki-types",
- "url",
- "webpki-roots",
-]
-
-[[package]]
-name = "url"
-version = "2.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
-dependencies = [
- "form_urlencoded",
- "idna",
- "percent-encoding",
-]
-
-[[package]]
-name = "utf16_iter"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
-
-[[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
-[[package]]
-name = "vcpkg"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
-
-[[package]]
-name = "version_check"
-version = "0.9.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
-
-[[package]]
-name = "walkdir"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
-dependencies = [
- "same-file",
- "winapi-util",
-]
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-
-[[package]]
-name = "webpki-roots"
-version = "0.26.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
-dependencies = [
- "rustls-pki-types",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
-dependencies = [
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
-dependencies = [
- "windows-core",
- "windows-targets",
-]
-
-[[package]]
-name = "windows-core"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
-dependencies = [
- "windows-implement",
- "windows-interface",
- "windows-result",
- "windows-targets",
-]
-
-[[package]]
-name = "windows-implement"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "windows-interface"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "windows-result"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
-
-[[package]]
-name = "winnow"
-version = "0.6.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "winresource"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7276691b353ad4547af8c3268488d1311f4be791ffdc0c65b8cfa8f41eed693b"
-dependencies = [
- "toml",
- "version_check",
-]
-
-[[package]]
-name = "write16"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
-
-[[package]]
-name = "writeable"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
-
-[[package]]
-name = "yoke"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
-dependencies = [
- "serde",
- "stable_deref_trait",
- "yoke-derive",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
- "synstructure",
-]
-
-[[package]]
-name = "zerocopy"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
-dependencies = [
- "byteorder",
- "zerocopy-derive",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "zerofrom"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
- "synstructure",
-]
-
-[[package]]
-name = "zeroize"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
-dependencies = [
- "zeroize_derive",
-]
-
-[[package]]
-name = "zeroize_derive"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "zerovec"
-version = "0.10.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
-dependencies = [
- "yoke",
- "zerofrom",
- "zerovec-derive",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.89",
-]
-
-[[package]]
-name = "zip"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99d52293fc86ea7cf13971b3bb81eb21683636e7ae24c729cdaf1b7c4157a352"
-dependencies = [
- "aes",
- "arbitrary",
- "bzip2",
- "constant_time_eq",
- "crc32fast",
- "crossbeam-utils",
- "deflate64",
- "displaydoc",
- "flate2",
- "hmac",
- "indexmap",
- "lzma-rs",
- "memchr",
- "pbkdf2",
- "rand",
- "sha1",
- "thiserror",
- "time",
- "zeroize",
- "zopfli",
- "zstd",
-]
-
-[[package]]
-name = "zopfli"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946"
-dependencies = [
- "bumpalo",
- "crc32fast",
- "lockfree-object-pool",
- "log",
- "once_cell",
- "simd-adler32",
-]
-
-[[package]]
-name = "zstd"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
-dependencies = [
- "zstd-safe",
-]
-
-[[package]]
-name = "zstd-safe"
-version = "7.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
-dependencies = [
- "zstd-sys",
-]
-
-[[package]]
-name = "zstd-sys"
-version = "2.0.13+zstd.1.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa"
-dependencies = [
- "cc",
- "pkg-config",
-]
diff --git a/Cargo.toml b/Cargo.toml
deleted file mode 100644
index f0a1524..0000000
--- a/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[workspace]
-resolver = "2"
-members = [
- "add_to_autorun",
- "make_release",
- "preconfig_tester",
- "run_preconfig",
- "select_domains", "shared",
-]
-
-[workspace.package]
-version = "1.1.1"
-
-[workspace.dependencies]
-# Used for embedding resources in the executable
-winresource = "0.1.19"
-# Used for tui
-crossterm = "0.28.1"
diff --git a/README.RU.md b/README.RU.md
index cbecee0..a3752ef 100644
--- a/README.RU.md
+++ b/README.RU.md
@@ -6,7 +6,7 @@
-Эта сбока включает в себя файлы из [оригинального репозитория](https://github.com/bol-van/zapret-win-bundle), кастомные прре-конфиги для исправления работы YouTube, Discord oили других сервисов в России и некоторые полезные утилиты, написанные на Rust.
+Эта сбока включает в себя файлы из [оригинального репозитория](https://github.com/bol-van/zapret-win-bundle), кастомные прре-конфиги для исправления работы YouTube, Discord oили других сервисов в России и некоторые полезные утилиты, написанные на Go.
# Настройка
## Скачать
Вы можете загрузить эту сборку из [релизов](https://github.com/ankddev/zapret-discord-youtube/releases) или [GitHub Actions](https://github.com/ankddev/zapret-discord-youtube/actions).
@@ -92,26 +92,28 @@ Check [this](https://github.com/bol-van/zapret/blob/master/docs/quick_start.txt)
* Внесите изменения
* Запустите линтер и отформатируйте код:
```bash
-cargo clippy --fix
-cargo fmt
+go fmt .\...
```
* Создайте PR
## Сборка
-Чтобы собрать этот проект, запустите `cargo build --release`. Дальше, перейдите в папку `target/release` и запустите файл `make_release.exe`, чтобы сделать ZIP архив со всеми файлами.
+Чтобы собрать этот проект, запустите:
+```bash
+scripts\build.bat
+```
+Это скомпилиррует все бинарные файлы и создаст zip архив в папке `build`.
## Структура проекта
Этот проект разделён на нескольео папок:
* `bin` содержит готовые бинарники из оригинального репозитория
* `pre-configs` содержит пре-конфиги (батники)
* `lists` содержит списки доменов
* `resources` содержит файлы `README.txt` и `blockcheck.cmd`
-Следующие папки содержат код на `Rust` или утилиты, содержащиеся в фиксе, все они объединены в `cargo workspace` поэтому вам следует запускать все команды Cargo из корневой директории проекта:
-* `make_release` содержит код для утилиты make-release, которая не включена в итоговый архив. Она помогает создать архив со сборкой фикса. Сейчас вы должны запускать его из директории сборки, поэтому, если вы запускаете её из терминала, вы должны перейти в директории `target/release` или `target/debug`
-* `add_to_autorun` включает код для утилиты, котроая позволяет добавить фикс в автозапуск
-* `select_domains` включает код для утилиты, которая позволяет выбрать домены для DPI
-* `preconfig_tester` помогает тестировать пре-конфиги
-* `run_preconfig`помогает запускать пре-конфиги
-* `shared` включает некоторые полезные функции, используемые другими модулями
+* `scripts` содержит скрипты для сборки проекта
+* `cmd` содержит исходный код для утилит
+ * `add_to_autorun` содержит код для утилиты, которая помогает добавить фикс в автозапуск
+ * `select_domains` содержит код для утилиты, которая помогает выбрать домены для DPI
+ * `preconfig_tester` помогает тестировать пре-конфиги
+ * `run_preconfig` помогает запускать пре-конфиги
# Кредиты
* [Zapret](https://github.com/bol-van/zapret)
* [Zapret Win Bundle](https://github.com/bol-van/zapret-win-bundle)
diff --git a/README.md b/README.md
index 59ee9cd..188e5b5 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
[README на русском языке](./README.RU.md)
-This build includes files from [original repository](https://github.com/bol-van/zapret-win-bundle), custom pre-configs for fixing YouTube, Discord or other services in Russia and some useful utilities, written in Rust.
+This build includes files from [original repository](https://github.com/bol-van/zapret-win-bundle), custom pre-configs for fixing YouTube, Discord or other services in Russia and some useful utilities, written in Go.
# Getting started
## Download
You can download this build from [releases](https://github.com/ankddev/zapret-discord-youtube/releases) or [GitHub Actions](https://github.com/ankddev/zapret-discord-youtube/actions).
@@ -94,26 +94,28 @@ Check [this](https://github.com/bol-van/zapret/blob/master/docs/quick_start.txt)
* Make changes
* Lint and format code
```bash
-cargo clippy --fix
-cargo fmt
+go fmt .\...
```
* Create pull request
## Building
-To build this run `cargo build --release`. Then go to `target/release` folder and run `make_release.exe` to make ZIP archive with all files.
+To build this run this:
+```bash
+scripts\build.bat
+```
+This will generate binaries and zip archive in `build` folder.
## Structure of project
This project is separated in few folders:
* `bin` contains pre-built binaries from original repository
* `pre-configs` contains pre-configs (BAT files)
* `lists` contains lists of domains to work with
* `resources` contains `README.txt` and `blockcheck.cmd` files
-Following directories contain `Rust` code or utilities, packaged in build, all of them united to `cargo workspace` so you should run all Cargo commands from root directory of project:
-* `make_release` contains source code for make-release util, which isn't pacakged with build. It helps to create archive with build of projects. Currentlyx you must open it from target directory, so if you running it from terminal tou should firstly go to `target/release` or `target/debug` directories
-* `add_to_autorun` contains code for utility that helps you to add fix to autorun
-* `select_domains` contains source code for util that helps you to select domains for DPI
-* `preconfig_tester` helps you to test pre-configs
-* `run_preconfig` helps to run pre-configs
-* `shared` contains useful function, used by other modules in project
+* `scripts` contains scripts for building and creating release archive
+* `cmd` contains source code for utilities
+ * `add_to_autorun` contains code for utility that helps you to add fix to autorun
+ * `select_domains` contains source code for util that helps you to select domains for DPI
+ * `preconfig_tester` helps you to test pre-configs
+ * `run_preconfig` helps to run pre-configs
# Credits
* [Zapret](https://github.com/bol-van/zapret)
* [Zapret Win Bundle](https://github.com/bol-van/zapret-win-bundle)
diff --git a/add_to_autorun/Cargo.toml b/add_to_autorun/Cargo.toml
deleted file mode 100644
index 702d4c1..0000000
--- a/add_to_autorun/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-name = "add_to_autorun"
-version.workspace = true
-edition = "2021"
-build = "build.rs"
-
-[package.metadata.winresource]
-LegalCopyright = "2024 by ANKDDEV"
-OriginalFilename = "zapret_autorunner.exe"
-
-[dependencies]
-crossterm.workspace = true
-ctrlc = "3.4.1"
-regex = "1.11.1"
-shared = { path = "../shared" }
-
-[build-dependencies]
-winresource.workspace = true
diff --git a/add_to_autorun/build.rs b/add_to_autorun/build.rs
deleted file mode 100644
index 438af54..0000000
--- a/add_to_autorun/build.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-use {std::io, winresource::WindowsResource};
-
-fn main() -> io::Result<()> {
- if cfg!(target_os = "windows") {
- let mut res = WindowsResource::new();
- res.set_icon("icon.ico")
- .set("InternalName", "Autorun BAT as Service by ANKDDEV");
-
- res.compile()?;
- }
-
- Ok(())
-}
diff --git a/add_to_autorun/icon.ico b/add_to_autorun/icon.ico
deleted file mode 100644
index fe579ae..0000000
Binary files a/add_to_autorun/icon.ico and /dev/null differ
diff --git a/add_to_autorun/src/main.rs b/add_to_autorun/src/main.rs
deleted file mode 100644
index 8972ef1..0000000
--- a/add_to_autorun/src/main.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-mod service;
-mod ui;
-mod utils;
-
-use std::io::{self, stdout};
-use shared::terminal::{self, cleanup_terminal, setup_terminal_cleanup};
-use ui::print_welcome_message;
-use utils::get_options;
-
-fn main() -> io::Result<()> {
- setup_terminal_cleanup();
- let mut stdout = stdout();
-
- // Initialize terminal
- terminal::init(&mut stdout)?;
-
- // Get terminal size early
- let (_, term_height) = terminal::get_size()?;
-
- // Print welcome messages and get the starting line
- let current_line = print_welcome_message();
-
- // Get the list of .bat files and add options
- let options = get_options();
- if options.is_empty() {
- println!("Can't find any BAT files in current directory.");
- cleanup_terminal()?;
- return Ok(());
- }
-
- ui::run_main_loop(&mut stdout, &options, current_line, term_height)?;
-
- terminal::cleanup_and_exit(&mut stdout)?;
- Ok(())
-}
diff --git a/add_to_autorun/src/service.rs b/add_to_autorun/src/service.rs
deleted file mode 100644
index 04190d5..0000000
--- a/add_to_autorun/src/service.rs
+++ /dev/null
@@ -1,360 +0,0 @@
-use crate::utils::run_powershell_command_with_output;
-use crossterm::{
- cursor, execute,
- style::{Color, Print, ResetColor, SetForegroundColor},
-};
-use regex::Regex;
-use std::io::{self, Write};
-
-pub struct ServiceManager {
- service_name: String,
-}
-
-impl ServiceManager {
- pub fn new(service_name: &str) -> Self {
- Self {
- service_name: service_name.to_string(),
- }
- }
-
- pub fn remove_service(
- &self,
- stdout: &mut impl Write,
- mut message_row: usize,
- ) -> io::Result {
- // Section header
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- Print("\n=== Deleting existing service ===\n\n")
- )?;
- message_row += 3; // Account for the header and two newlines
- stdout.flush()?;
-
- // Process each operation
- message_row = self.stop_service(stdout, message_row)?;
- message_row = self.terminate_process(stdout, message_row)?;
- message_row = self.delete_service(stdout, message_row)?;
-
- Ok(message_row)
- }
-
- pub fn install_service(
- &self,
- stdout: &mut impl Write,
- bat_file_path: &str,
- mut message_row: usize,
- ) -> io::Result {
- // First remove existing service
- message_row = self.remove_service(stdout, message_row)?;
-
- // Add spacing and section header for installation
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- Print("\n=== Installing new service ===\n\n")
- )?;
- message_row += 3;
-
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- Print(format!("► Installing file as service: {}\n", bat_file_path))
- )?;
- message_row += 1;
- stdout.flush()?;
-
- // Create and start service
- message_row = self.create_service(stdout, bat_file_path, message_row)?;
- message_row = self.start_service(stdout, message_row)?;
-
- Ok(message_row)
- }
-
- fn stop_service(&self, stdout: &mut impl Write, mut message_row: usize) -> io::Result {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- Print(format!("► Stopping service '{}'...\n", self.service_name))
- )?;
- message_row += 1;
- stdout.flush()?;
-
- let command = format!(
- "Start-Process 'sc.exe' -ArgumentList 'stop {}' -Verb RunAs",
- self.service_name
- );
-
- match run_powershell_command_with_output(&command) {
- Ok(_) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Green),
- Print(format!(
- "✓ Service '{}' stopped successfully.\n",
- self.service_name
- )),
- ResetColor
- )?;
- message_row += 2; // Add extra line for spacing
- }
- Err(e) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Red),
- Print(format!("⚠ Error while stopping service: {}\n", e)),
- ResetColor
- )?;
- message_row += 2; // Add extra line for spacing
- }
- }
-
- Ok(message_row)
- }
-
- fn terminate_process(
- &self,
- stdout: &mut impl Write,
- mut message_row: usize,
- ) -> io::Result {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- Print("► Shutting down process 'winws.exe'...\n")
- )?;
- message_row += 1;
- stdout.flush()?;
-
- let command = "Start-Process 'powershell' -ArgumentList 'Stop-Process -Name \"winws\" -Force' -Verb RunAs";
-
- match run_powershell_command_with_output(command) {
- Ok(_) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Green),
- Print("✓ Process 'winws.exe' shut down successfully.\n"),
- ResetColor
- )?;
- message_row += 2; // Add extra line for spacing
- }
- Err(e) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Red),
- Print(format!(
- "⚠ Error occurred while shutting down process 'winws.exe': {}\n",
- e
- )),
- ResetColor
- )?;
- message_row += 2; // Add extra line for spacing
- }
- }
-
- Ok(message_row)
- }
-
- fn delete_service(&self, stdout: &mut impl Write, mut message_row: usize) -> io::Result {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- Print(format!("► Deleting service '{}'...\n", self.service_name))
- )?;
- message_row += 1;
- stdout.flush()?;
-
- let command = format!(
- "Start-Process 'sc.exe' -ArgumentList 'delete {}' -Verb RunAs",
- self.service_name
- );
-
- match run_powershell_command_with_output(&command) {
- Ok(_) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Green),
- Print(format!(
- "✓ Service '{}' deleted successfully.\n",
- self.service_name
- )),
- ResetColor
- )?;
- message_row += 2; // Add extra line for spacing
- }
- Err(e) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Red),
- Print(format!("⚠ Error while deleting service: {}\n", e)),
- ResetColor
- )?;
- message_row += 2; // Add extra line for spacing
- }
- }
-
- Ok(message_row)
- }
-
- fn create_service(
- &self,
- stdout: &mut impl Write,
- bat_file_path: &str,
- mut message_row: usize,
- ) -> io::Result {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- Print("► Creating service...\n")
- )?;
- message_row += 1;
- stdout.flush()?;
-
- // First, check if service exists
- let check_command = format!(
- "$service = Get-Service -Name '{}' -ErrorAction SilentlyContinue; if ($service) {{ Write-Output 'exists' }}",
- self.service_name
- );
-
- if let Ok(output) = run_powershell_command_with_output(&check_command) {
- if output.contains("exists") {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Yellow),
- Print("⚠ Service already installed. Trying to delete...\n"),
- ResetColor
- )?;
- message_row += 1;
-
- // Try to remove existing service
- let _ = self.remove_service(stdout, message_row)?;
- }
- }
-
- // Create service with proper path escaping and validation
- let create_command = format!(
- r#"$process = Start-Process 'sc.exe' -ArgumentList 'create {} binPath= "cmd.exe /c \"{}\"" start= auto' -Verb RunAs -PassThru; $process.WaitForExit(); Write-Output $process.ExitCode"#,
- format!("{}", self.service_name),
- bat_file_path
- );
-
- match run_powershell_command_with_output(&create_command) {
- Ok(output) => {
- let re = Regex::new(r"\d+").unwrap();
- let numbers: Vec = re
- .find_iter(&output)
- .filter_map(|digits| digits.as_str().parse::().ok())
- .collect();
- let output_code: i32 = numbers[0];
-
- if output_code == 0 {
- // success
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Green),
- Print("✓ Service installed successfully.\n"),
- ResetColor
- )?;
- } else if output_code == 5 {
- // access denied
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Yellow),
- Print("⚠ Permission denied, failed to install service.\n"),
- ResetColor
- )?;
- } else if output_code == 740 {
- // elevation required
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Yellow),
- Print("⚠ Need administrative privileges, failed to install service.\n"),
- ResetColor
- )?;
- } else if output_code == 1073 {
- // service already installed
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Yellow),
- Print("⚠ Service already installed.\n"),
- ResetColor
- )?;
- } else {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Red),
- Print(format!(
- "⚠ Error occured while installing service: {}\n",
- output_code
- )),
- ResetColor
- )?;
- }
- message_row += 2;
- }
- Err(e) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Red),
- Print(format!("⚠ Error occured while installing service: {}\n", e)),
- ResetColor
- )?;
- message_row += 2;
- }
- }
-
- Ok(message_row)
- }
-
- fn start_service(&self, stdout: &mut impl Write, mut message_row: usize) -> io::Result {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- Print("► Starting service...\n")
- )?;
- message_row += 1;
- stdout.flush()?;
-
- let command = format!(
- "Start-Process 'sc.exe' -ArgumentList 'start {}' -Verb RunAs",
- self.service_name
- );
-
- match run_powershell_command_with_output(&command) {
- Ok(_) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Green),
- Print("✓ Service started successfully.\n"),
- ResetColor
- )?;
- message_row += 2; // Add extra line for spacing
- }
- Err(e) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- SetForegroundColor(Color::Red),
- Print(format!("⚠ Error occured while starting service: {}\n", e)),
- ResetColor
- )?;
- message_row += 2; // Add extra line for spacing
- }
- }
-
- Ok(message_row)
- }
-}
diff --git a/add_to_autorun/src/ui.rs b/add_to_autorun/src/ui.rs
deleted file mode 100644
index a500874..0000000
--- a/add_to_autorun/src/ui.rs
+++ /dev/null
@@ -1,309 +0,0 @@
-use crate::service::ServiceManager;
-use crate::utils::run_powershell_command_with_output;
-use crossterm::{
- cursor,
- event::{self, Event, KeyCode},
- execute,
- style::{Color, Print, ResetColor, SetForegroundColor},
- terminal::{Clear, ClearType},
-};
-use std::io::{self, Write};
-use std::time::{Duration, Instant};
-
-#[derive(Debug)]
-pub enum KeyAction {
- Exit,
- Select,
- None,
-}
-
-pub fn print_welcome_message() -> usize {
- let mut current_line = 0;
- println!("Welcome!");
- current_line += 1;
- println!("This program can install BAT file as service with autorun.");
- current_line += 1;
- println!("Author: ANKDDEV https://github.com/ankddev");
- current_line += 1;
- println!("Version: {}", env!("CARGO_PKG_VERSION"));
- current_line += 1;
- println!("===");
- current_line += 2;
- println!(
- "Using ARROWS on your keyboard, select BAT file from list \
- for installing service 'discordfix_zapret' or select \
- 'Delete service from autorun' or 'Run BLOCKCHECK (Auto-setting BAT parameters)'.\n"
- );
- println!("For selection press ENTER.");
- current_line += 2;
- current_line
-}
-
-pub fn render_options(
- stdout: &mut impl Write,
- options: &[String],
- current_selection: usize,
- start_row: usize,
- scroll_offset: usize,
- max_visible_options: usize,
-) -> io::Result<()> {
- const MARKER: &str = "►";
- const EMPTY_MARKER: &str = " ";
- const SPACING: &str = " ";
-
- let visible_options = max_visible_options.saturating_sub(2);
- let total_options = options.len();
-
- let end_index = (scroll_offset + visible_options).min(total_options);
- let visible_range = scroll_offset..end_index;
-
- // Clear the options area only once
- execute!(
- stdout,
- cursor::MoveTo(0, start_row as u16),
- Clear(ClearType::FromCursorDown)
- )?;
-
- let mut current_row = start_row;
-
- // Build output buffer to minimize writes
- let mut output_buffer = Vec::new();
-
- // Up scroll indicator
- if scroll_offset > 0 {
- execute!(
- output_buffer,
- cursor::MoveTo(0, current_row as u16),
- SetForegroundColor(Color::DarkGrey),
- Print("↑ More options above"),
- ResetColor
- )?;
- current_row += 1;
- }
-
- // Display visible options
- for (index, option) in options.iter().enumerate() {
- if visible_range.contains(&index) {
- execute!(output_buffer, cursor::MoveTo(0, current_row as u16))?;
-
- if index == current_selection {
- execute!(
- output_buffer,
- SetForegroundColor(Color::Cyan),
- Print(MARKER),
- Print(SPACING),
- Print(option),
- ResetColor
- )?;
- } else {
- execute!(
- output_buffer,
- Print(EMPTY_MARKER),
- Print(SPACING),
- Print(option)
- )?;
- }
-
- current_row += 1;
- }
- }
-
- // Down scroll indicator
- if end_index < total_options {
- execute!(
- output_buffer,
- cursor::MoveTo(0, current_row as u16),
- SetForegroundColor(Color::DarkGrey),
- Print("↓ More options below"),
- ResetColor
- )?;
- }
-
- // Write the entire buffer at once
- stdout.write_all(&output_buffer)?;
- stdout.flush()?;
-
- Ok(())
-}
-
-pub fn handle_key_event(
- key: KeyCode,
- current_selection: &mut usize,
- scroll_offset: &mut usize,
- total_options: usize,
- max_visible_options: usize,
-) -> Option {
- let visible_options = max_visible_options.saturating_sub(2);
-
- match key {
- KeyCode::Up if *current_selection > 0 => {
- *current_selection -= 1;
- if *current_selection < *scroll_offset {
- *scroll_offset = *current_selection;
- }
- Some(KeyAction::None)
- }
- KeyCode::Down if *current_selection < total_options - 1 => {
- *current_selection += 1;
- if *current_selection >= *scroll_offset + visible_options {
- *scroll_offset = current_selection.saturating_sub(visible_options - 1);
- }
- Some(KeyAction::None)
- }
- KeyCode::PageUp => {
- *current_selection = current_selection.saturating_sub(visible_options);
- *scroll_offset = scroll_offset.saturating_sub(visible_options);
- Some(KeyAction::None)
- }
- KeyCode::PageDown => {
- *current_selection = (*current_selection + visible_options).min(total_options - 1);
- *scroll_offset = (*scroll_offset + visible_options)
- .min(total_options.saturating_sub(visible_options));
- Some(KeyAction::None)
- }
- KeyCode::Enter => Some(KeyAction::Select),
- KeyCode::Esc => Some(KeyAction::Exit),
- _ => None,
- }
-}
-
-pub fn handle_selection(
- stdout: &mut impl Write,
- options: &[String],
- current_selection: usize,
- service_manager: &ServiceManager,
- message_row: usize,
-) -> io::Result<()> {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- Clear(ClearType::FromCursorDown)
- )?;
- stdout.flush()?;
-
- match &options[current_selection][..] {
- "Delete service from autorun" => {
- service_manager.remove_service(stdout, message_row)?;
- }
- "Run BLOCKCHECK (Auto-setting BAT parameters)" => {
- match run_powershell_command_with_output("Start-Process 'blockcheck.cmd'") {
- Ok(_) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16 + 1),
- Print("Blockcheck started successfully.")
- )?;
- std::process::exit(0);
- }
- Err(e) => {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16 + 1),
- Print(format!("Error occured while running Blockcheck: {}", e))
- )?;
- }
- }
- }
- selected_file => {
- let current_dir = std::env::current_dir()?;
- let sub_dir = current_dir.join("pre-configs");
- let bat_file_path = sub_dir.join(selected_file);
- service_manager.install_service(
- stdout,
- bat_file_path.to_str().unwrap(),
- message_row,
- )?;
- }
- }
-
- Ok(())
-}
-
-pub fn run_main_loop(
- stdout: &mut impl Write,
- options: &[String],
- start_row: usize,
- term_height: u16,
-) -> io::Result<()> {
- let mut current_selection = 0;
- let mut scroll_offset = 0;
- let max_visible_options = std::cmp::min(15, term_height as usize - start_row - 3);
-
- let mut last_event_time = Instant::now();
- let mut last_render_time = Instant::now();
- let service_manager = ServiceManager::new("discordfix_zapret");
-
- // Define frame timing constants
- const FRAME_TIME: Duration = Duration::from_millis(33); // ~30 FPS
- const KEY_REPEAT_DELAY: Duration = Duration::from_millis(150);
- const EVENT_POLL_TIMEOUT: Duration = Duration::from_millis(16); // ~60 FPS polling
-
- // Initial render
- render_options(
- stdout,
- options,
- current_selection,
- start_row,
- scroll_offset,
- max_visible_options,
- )?;
-
- let mut needs_render = false;
-
- loop {
- let now = Instant::now();
-
- // Only poll for events if enough time has passed
- if event::poll(EVENT_POLL_TIMEOUT)? {
- if let Event::Key(event) = event::read()? {
- if now.duration_since(last_event_time) >= KEY_REPEAT_DELAY {
- match handle_key_event(
- event.code,
- &mut current_selection,
- &mut scroll_offset,
- options.len(),
- max_visible_options,
- ) {
- Some(KeyAction::Exit) => break,
- Some(KeyAction::Select) => {
- handle_selection(
- stdout,
- options,
- current_selection,
- &service_manager,
- start_row + max_visible_options + 1,
- )?;
- break;
- }
- Some(KeyAction::None) => {
- needs_render = true;
- }
- None => {}
- }
- last_event_time = now;
- }
- }
- }
-
- // Only render if needed and enough time has passed since last render
- if needs_render && now.duration_since(last_render_time) >= FRAME_TIME {
- render_options(
- stdout,
- options,
- current_selection,
- start_row,
- scroll_offset,
- max_visible_options,
- )?;
- last_render_time = now;
- needs_render = false;
- }
-
- // Sleep for a small duration to prevent busy waiting
- if !needs_render {
- std::thread::sleep(Duration::from_millis(1));
- }
- }
-
- Ok(())
-}
diff --git a/add_to_autorun/src/utils.rs b/add_to_autorun/src/utils.rs
deleted file mode 100644
index 66b250c..0000000
--- a/add_to_autorun/src/utils.rs
+++ /dev/null
@@ -1,114 +0,0 @@
-use std::{env, fs, io, process::Command};
-
-pub fn get_options() -> Vec {
- let current_dir = env::current_dir().expect("Failed to get current directory");
- let sub_dir = current_dir.join("pre-configs");
- let mut options = vec![
- "Delete service from autorun".to_string(),
- "Run BLOCKCHECK (Auto-setting BAT parameters)".to_string(),
- ];
-
- if let Ok(read_dir) = fs::read_dir(&sub_dir) {
- let mut bat_files: Vec = read_dir
- .filter_map(|entry| {
- entry.ok().and_then(|e| {
- let path = e.path();
- if path.extension().and_then(|ext| ext.to_str()) == Some("bat") {
- path.file_name().and_then(|n| n.to_str()).map(String::from)
- } else {
- None
- }
- })
- })
- .collect();
-
- bat_files.sort_by(|a, b| custom_sort(a, b));
- options.extend(bat_files);
- }
-
- options
-}
-
-fn custom_sort(a: &str, b: &str) -> std::cmp::Ordering {
- // Split filenames into components for hierarchical sorting
- let (a_base, a_variant, a_provider, a_has_provider) = split_filename(a);
- let (b_base, b_variant, b_provider, b_has_provider) = split_filename(b);
-
- // First compare by base name
- match a_base.cmp(&b_base) {
- std::cmp::Ordering::Equal => {
- // Same base name, compare variants
- match a_variant.cmp(&b_variant) {
- std::cmp::Ordering::Equal => {
- // Same variant, non-provider version comes first
- match (a_has_provider, b_has_provider) {
- (false, true) => std::cmp::Ordering::Less,
- (true, false) => std::cmp::Ordering::Greater,
- // Both have or don't have providers, sort by provider name
- _ => a_provider.cmp(&b_provider),
- }
- }
- // Different variants
- other => other,
- }
- }
- // Different base names
- other => other,
- }
-}
-
-fn split_filename(name: &str) -> (String, String, String, bool) {
- let without_ext = name.trim_end_matches(".bat");
-
- // Split into base name and parentheses part
- let (main_part, parentheses) = match without_ext.find('(') {
- Some(idx) => (&without_ext[..idx - 1], &without_ext[idx..]),
- None => (without_ext, ""),
- };
-
- // Split main part into components by underscore
- let parts: Vec<&str> = main_part.split('_').collect();
- let base = parts[0].to_string();
-
- // Get variant part (ALT, v2, etc)
- let variant = parts.get(1..).map_or(String::new(), |p| p.join("_"));
-
- // Check if it's a provider variant
- let has_provider = !parentheses.is_empty();
-
- (base, variant, parentheses.to_string(), has_provider)
-}
-
-pub fn run_powershell_command_with_output(command: &str) -> io::Result {
- println!("{}", command);
- let output = Command::new("powershell")
- .args(["-NoProfile", "-NonInteractive", "-Command", command])
- .output()
- .map_err(|e| {
- io::Error::new(
- io::ErrorKind::Other,
- format!("Failed to execute command: {}", e),
- )
- })?;
-
- let stdout = String::from_utf8_lossy(&output.stdout).to_string();
- let stderr = String::from_utf8_lossy(&output.stderr).to_string();
-
- if output.status.success() {
- if !stderr.is_empty() {
- Err(io::Error::new(io::ErrorKind::Other, stderr))
- } else {
- Ok(stdout)
- }
- } else {
- let error_message = if !stderr.is_empty() {
- stderr
- } else if !stdout.is_empty() {
- stdout
- } else {
- "Unknown error occurred while executing PowerShell command".to_string()
- };
-
- Err(io::Error::new(io::ErrorKind::Other, error_message))
- }
-}
diff --git a/cmd/add_to_autorun/add_to_autorun.go b/cmd/add_to_autorun/add_to_autorun.go
new file mode 100644
index 0000000..5d50352
--- /dev/null
+++ b/cmd/add_to_autorun/add_to_autorun.go
@@ -0,0 +1,330 @@
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "os/signal"
+ "path/filepath"
+ "sort"
+ "strings"
+ "syscall"
+ "time"
+
+ "github.com/eiannone/keyboard"
+)
+
+const (
+ serviceName = "discordfix_zapret"
+ clearScreenSequence = "\033[2J\033[H\033[3J"
+ defaultTermHeight = 24
+ enterAltScreen = "\033[?1049h"
+ exitAltScreen = "\033[?1049l"
+ hideCursor = "\033[?25l"
+ showCursor = "\033[?25h"
+ fps = 144
+ frameTime = time.Second / time.Duration(fps)
+)
+
+var version string
+
+// ServiceManager handles Windows service operations
+type ServiceManager struct {
+ serviceName string
+}
+
+// UI constants
+const (
+ colorReset = "\033[0m"
+ colorRed = "\033[31m"
+ colorGreen = "\033[32m"
+ colorYellow = "\033[33m"
+ colorCyan = "\033[36m"
+ colorGrey = "\033[90m"
+)
+
+func NewServiceManager(name string) *ServiceManager {
+ return &ServiceManager{serviceName: name}
+}
+
+func (sm *ServiceManager) runPowershellCommand(command string) (string, error) {
+ cmd := exec.Command("powershell", "-NoProfile", "-NonInteractive", "-Command", command)
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ return "", fmt.Errorf("PowerShell error: %v - %s", err, string(output))
+ }
+ return string(output), nil
+}
+
+func (sm *ServiceManager) removeService() error {
+ fmt.Println("\n=== Deleting existing service ===\n")
+
+ // Stop service
+ fmt.Printf("► Stopping service '%s'...\n", sm.serviceName)
+ _, err := sm.runPowershellCommand(fmt.Sprintf("Start-Process 'sc.exe' -ArgumentList 'stop %s' -Verb RunAs", sm.serviceName))
+ if err != nil {
+ fmt.Printf("%s⚠ Error while stopping service: %v%s\n", colorRed, err, colorReset)
+ } else {
+ fmt.Printf("%s✓ Service stopped successfully.%s\n", colorGreen, colorReset)
+ }
+
+ // Terminate process
+ fmt.Println("► Shutting down process 'winws.exe'...")
+ _, err = sm.runPowershellCommand("Start-Process 'powershell' -ArgumentList 'Stop-Process -Name \"winws\" -Force' -Verb RunAs")
+ if err != nil {
+ fmt.Printf("%s⚠ Error while terminating process: %v%s\n", colorRed, err, colorReset)
+ } else {
+ fmt.Printf("%s✓ Process terminated successfully.%s\n", colorGreen, colorReset)
+ }
+
+ // Delete service
+ fmt.Printf("► Deleting service '%s'...\n", sm.serviceName)
+ _, err = sm.runPowershellCommand(fmt.Sprintf("Start-Process 'sc.exe' -ArgumentList 'delete %s' -Verb RunAs", sm.serviceName))
+ if err != nil {
+ fmt.Printf("%s⚠ Error while deleting service: %v%s\n", colorRed, err, colorReset)
+ } else {
+ fmt.Printf("%s✓ Service deleted successfully.%s\n", colorGreen, colorReset)
+ }
+
+ return nil
+}
+
+func (sm *ServiceManager) installService(batFilePath string) error {
+ // First remove existing service
+ err := sm.removeService()
+ if err != nil {
+ return err
+ }
+
+ fmt.Println("\n=== Installing new service ===\n")
+ fmt.Printf("► Installing file as service: %s\n", batFilePath)
+
+ // Create service
+ createCmd := fmt.Sprintf(
+ `$process = Start-Process 'sc.exe' -ArgumentList 'create %s binPath= "cmd.exe /c \"%s\"" start= auto' -Verb RunAs -PassThru; $process.WaitForExit(); Write-Output $process.ExitCode`,
+ sm.serviceName,
+ batFilePath,
+ )
+
+ _, err = sm.runPowershellCommand(createCmd)
+ if err != nil {
+ fmt.Printf("%s⚠ Error while creating service: %v%s\n", colorRed, err, colorReset)
+ return err
+ }
+
+ // Start service
+ fmt.Println("► Starting service...")
+ _, err = sm.runPowershellCommand(fmt.Sprintf("Start-Process 'sc.exe' -ArgumentList 'start %s' -Verb RunAs", sm.serviceName))
+ if err != nil {
+ fmt.Printf("%s⚠ Error while starting service: %v%s\n", colorRed, err, colorReset)
+ return err
+ }
+
+ fmt.Printf("%s✓ Service started successfully.%s\n", colorGreen, colorReset)
+ return nil
+}
+
+func getOptions() []string {
+ options := []string{
+ "Delete service from autorun",
+ "Run BLOCKCHECK (Auto-setting BAT parameters)",
+ }
+
+ currentDir, err := os.Getwd()
+ if err != nil {
+ return options
+ }
+
+ files, err := ioutil.ReadDir(filepath.Join(currentDir, "pre-configs"))
+ if err != nil {
+ return options
+ }
+
+ var batFiles []string
+ for _, f := range files {
+ if !f.IsDir() && strings.HasSuffix(f.Name(), ".bat") {
+ batFiles = append(batFiles, f.Name())
+ }
+ }
+
+ sort.Strings(batFiles)
+ options = append(options, batFiles...)
+
+ return options
+}
+
+func clearScreen(buf *bytes.Buffer) {
+ buf.WriteString(clearScreenSequence)
+}
+
+func printWelcomeMessage(buf *bytes.Buffer) {
+ messages := []string{
+ "Welcome!",
+ "This program can install BAT file as service with autorun.",
+ "Author: ANKDDEV https://github.com/ankddev",
+ fmt.Sprintf("Version: %s", version),
+ "===",
+ "\nUsing ARROWS on your keyboard, select BAT file from list for installing service 'discordfix_zapret' or select 'Delete service from autorun' or 'Run BLOCKCHECK (Auto-setting BAT parameters)'.\n",
+ "For selection press ENTER.",
+ }
+
+ for _, msg := range messages {
+ buf.WriteString(msg + "\n")
+ }
+}
+
+// Add new functions for terminal handling
+func getTerminalSize() (int, int) {
+ cmd := exec.Command("stty", "size")
+ cmd.Stdin = os.Stdin
+ out, err := cmd.Output()
+ if err != nil {
+ return 80, defaultTermHeight
+ }
+
+ var rows, cols int
+ fmt.Sscanf(string(out), "%d %d", &rows, &cols)
+ return cols, rows
+}
+
+func main() {
+ // Setup cleanup on exit
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+ go func() {
+ <-c
+ fmt.Print(showCursor + exitAltScreen)
+ keyboard.Close()
+ os.Exit(1)
+ }()
+
+ fmt.Print(enterAltScreen + hideCursor)
+ defer fmt.Print(showCursor + exitAltScreen)
+
+ var buf bytes.Buffer
+
+ // First fill the buffer
+ printWelcomeMessage(&buf)
+ // Then clear screen and output content
+ fmt.Print(clearScreenSequence)
+ fmt.Print(buf.String())
+
+ options := getOptions()
+ if len(options) == 0 {
+ fmt.Println("Can't find any BAT files in current directory.")
+ return
+ }
+
+ currentSelection := 0
+ serviceManager := NewServiceManager(serviceName)
+
+ // Initialize keyboard
+ if err := keyboard.Open(); err != nil {
+ fmt.Println("Error initializing keyboard:", err)
+ return
+ }
+ defer keyboard.Close()
+
+ _, termHeight := getTerminalSize()
+ visibleItems := termHeight - 12 // 12 lines for welcome message and padding
+ startIdx := 0
+
+ // Main loop
+ for {
+ start := time.Now()
+
+ buf.Reset()
+ // Move cursor to start and clear screen to the end
+ buf.WriteString("\033[H\033[J")
+
+ printWelcomeMessage(&buf)
+
+ // Calculate range of visible elements
+ if currentSelection >= startIdx+visibleItems {
+ startIdx = currentSelection - visibleItems + 1
+ } else if currentSelection < startIdx {
+ startIdx = currentSelection
+ }
+
+ endIdx := startIdx + visibleItems
+ if endIdx > len(options) {
+ endIdx = len(options)
+ }
+
+ // Show up arrow if there are hidden elements above
+ if startIdx > 0 {
+ buf.WriteString(fmt.Sprintf("%s↑ more items above%s\n", colorGrey, colorReset))
+ }
+
+ // Output visible options
+ for i := startIdx; i < endIdx; i++ {
+ prefix := " "
+ if i == currentSelection {
+ prefix = "► "
+ buf.WriteString(fmt.Sprintf("%s%s%s%s\n", colorCyan, prefix, options[i], colorReset))
+ } else {
+ buf.WriteString(fmt.Sprintf("%s%s\n", prefix, options[i]))
+ }
+ }
+
+ // Show down arrow if there are hidden elements below
+ if endIdx < len(options) {
+ buf.WriteString(fmt.Sprintf("%s↓ more items below%s\n", colorGrey, colorReset))
+ }
+
+ // Output buffer in one operation
+ os.Stdout.Write(buf.Bytes())
+
+ // Precise timing for next frame
+ elapsed := time.Since(start)
+ if elapsed < frameTime {
+ time.Sleep(frameTime - elapsed)
+ }
+
+ // Handle keyboard input
+ _, key, err := keyboard.GetKey()
+ if err != nil {
+ fmt.Println("Error reading keyboard:", err)
+ return
+ }
+
+ switch key {
+ case keyboard.KeyArrowUp:
+ if currentSelection > 0 {
+ currentSelection--
+ }
+ case keyboard.KeyArrowDown:
+ if currentSelection < len(options)-1 {
+ currentSelection++
+ }
+ case keyboard.KeyEnter:
+ clearScreen(&buf)
+ switch options[currentSelection] {
+ case "Delete service from autorun":
+ serviceManager.removeService()
+ case "Run BLOCKCHECK (Auto-setting BAT parameters)":
+ // Restore normal terminal state before launch
+ fmt.Print(showCursor + exitAltScreen)
+ keyboard.Close()
+
+ _, err := serviceManager.runPowershellCommand("Start-Process 'blockcheck.cmd'")
+ if err != nil {
+ fmt.Printf("%s⚠ Error running BLOCKCHECK: %v%s\n", colorRed, err, colorReset)
+ }
+ return
+ default:
+ batPath := filepath.Join("pre-configs", options[currentSelection])
+ serviceManager.installService(batPath)
+ }
+
+ fmt.Println("\nReady! You can close this window")
+ bufio.NewReader(os.Stdin).ReadBytes('\n')
+ return
+ case keyboard.KeyEsc:
+ return
+ }
+ }
+}
diff --git a/cmd/preconfig_tester/preconfig_tester.go b/cmd/preconfig_tester/preconfig_tester.go
new file mode 100644
index 0000000..c5cdf40
--- /dev/null
+++ b/cmd/preconfig_tester/preconfig_tester.go
@@ -0,0 +1,367 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "time"
+)
+
+const (
+ colorReset = "\033[0m"
+ colorGreen = "\033[38;2;126;176;0m" // RGB(126,176,0)
+ colorRed = "\033[38;2;214;77;91m" // RGB(214,77,91)
+ colorMagenta = "\033[38;2;196;124;186m" // RGB(196,124,186)
+
+ // Terminal control
+ enterAltScreen = "\033[?1049h"
+ exitAltScreen = "\033[?1049l"
+ hideCursor = "\033[?25l"
+ showCursor = "\033[?25h"
+ clearScreen = "\033[2J\033[H"
+)
+
+var domainList = []struct {
+ number string
+ domain string
+}{
+ {"1", "discord.com"},
+ {"2", "youtube.com"},
+ {"3", "spotify.com"},
+ {"4", "speedtest.net"},
+ {"5", "steampowered.com"},
+ {"6", "custom"},
+ {"0", "exit"},
+}
+
+type Config struct {
+ batchDir string
+ targetDomain string
+ processName string
+ processWaitTime time.Duration
+ connectionTimeout time.Duration
+}
+
+type DPITestResult int
+
+const (
+ NoDPI DPITestResult = iota
+ HasDPI
+ NoConnection
+)
+
+func (r DPITestResult) String() string {
+ switch r {
+ case NoDPI:
+ return "No DPI detected"
+ case HasDPI:
+ return "DPI blocks detected"
+ case NoConnection:
+ return "No connection"
+ default:
+ return "Unknown"
+ }
+}
+
+func (c *Config) getBatchFiles() ([]string, error) {
+ var batFiles []string
+ files, err := os.ReadDir(c.batchDir)
+ if err != nil {
+ return nil, fmt.Errorf("error reading batch directory: %v", err)
+ }
+
+ for _, f := range files {
+ if !f.IsDir() && strings.HasSuffix(f.Name(), ".bat") {
+ batFiles = append(batFiles, filepath.Join(c.batchDir, f.Name()))
+ }
+ }
+ return batFiles, nil
+}
+
+func isElevated() bool {
+ cmd := exec.Command("net", "session")
+ err := cmd.Run()
+ return err == nil
+}
+
+func requestElevation() error {
+ executable, err := os.Executable()
+ if err != nil {
+ return fmt.Errorf("failed to get executable path: %v", err)
+ }
+
+ cmd := exec.Command("powershell", "Start-Process", executable, "-Verb", "RunAs", "-ArgumentList", "--elevated")
+ return cmd.Run()
+}
+
+func ensureProcessTerminated(processName string) {
+ cmd := exec.Command("taskkill", "/F", "/IM", processName)
+ cmd.Run() // Игнорируем ошибки, так как процесс может не существовать
+}
+
+func waitForProcess(processName string, timeout time.Duration) bool {
+ deadline := time.Now().Add(timeout)
+ for time.Now().Before(deadline) {
+ cmd := exec.Command("tasklist", "/FI", fmt.Sprintf("IMAGENAME eq %s", processName))
+ output, _ := cmd.Output()
+ if strings.Contains(string(output), processName) {
+ return true
+ }
+ time.Sleep(100 * time.Millisecond)
+ }
+ return false
+}
+
+func testConnection(domain string, timeout time.Duration) bool {
+ cmd := exec.Command("powershell", "-Command", fmt.Sprintf(`
+ $webRequest = [System.Net.WebRequest]::Create("https://%s")
+ $webRequest.Timeout = %d
+ try {
+ $response = $webRequest.GetResponse()
+ $response.Close()
+ return $true
+ } catch {
+ return $false
+ }
+ `, domain, int(timeout.Milliseconds())))
+
+ err := cmd.Run()
+ return err == nil
+}
+
+func getDomainChoice() (string, error) {
+ fmt.Println("\nSelect domain for checking:")
+ for _, item := range domainList {
+ if item.domain == "exit" {
+ fmt.Printf("%s. Exit\n", item.number)
+ } else if item.domain == "custom" {
+ fmt.Printf("%s. Enter your own domain\n", item.number)
+ } else {
+ fmt.Printf("%s. %s\n", item.number, item.domain)
+ }
+ }
+
+ reader := bufio.NewReader(os.Stdin)
+ for {
+ fmt.Print("\nEnter number of variant: ")
+ choice, err := reader.ReadString('\n')
+ if err != nil {
+ return "", fmt.Errorf("error reading input: %v", err)
+ }
+ choice = strings.TrimSpace(choice)
+
+ for _, item := range domainList {
+ if item.number == choice {
+ if item.domain == "exit" {
+ fmt.Print("Exiting..")
+ fmt.Print(showCursor + exitAltScreen)
+ os.Exit(0)
+ }
+ if item.domain == "custom" {
+ fmt.Print("Enter domain (for example, example.com): ")
+
+ domain, err := reader.ReadString('\n')
+ if err != nil {
+ return "", err
+ }
+ domain = strings.TrimSpace(domain)
+ if isValidDomain(domain) {
+ return formatDomainWithPort(domain), nil
+ }
+ fmt.Println("Invalid domain format. Use format domain.com")
+ continue
+ }
+ return formatDomainWithPort(item.domain), nil
+ }
+ }
+ fmt.Printf("Invalid selection. Please select number from 0 to %d\n", len(domainList)-1)
+ }
+}
+
+const DEFAULT_PORT = 443
+
+func isValidDomain(domain string) bool {
+ if len(domain) == 0 || len(domain) > 255 {
+ return false
+ }
+
+ if strings.Contains(domain, ":") {
+ return false
+ }
+
+ // Check if domain contains only allowed characters
+ for _, c := range domain {
+ if !isAsciiAlphanumeric(c) && c != '.' && c != '-' {
+ return false
+ }
+ }
+
+ // Check that domain doesn't start or end with hyphen
+ return !strings.HasPrefix(domain, "-") && !strings.HasSuffix(domain, "-")
+}
+
+func isAsciiAlphanumeric(c rune) bool {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
+}
+
+func formatDomainWithPort(domain string) string {
+ return fmt.Sprintf("%s:%d", strings.TrimSpace(domain), DEFAULT_PORT)
+}
+
+func checkDPIFingerprint(domain string) (DPITestResult, error) {
+ cmd := exec.Command("powershell", "-Command", fmt.Sprintf(`
+ try {
+ $webRequest = [System.Net.WebRequest]::Create("https://%s")
+ $webRequest.Timeout = 5000
+ $response = $webRequest.GetResponse()
+ $response.Close()
+ return 0 # NoDPI
+ } catch [System.Net.WebException] {
+ if ($_.Exception.Message -like "*actively refused*") {
+ return 1 # HasDPI
+ }
+ return 2 # NoConnection
+ }
+ `, domain))
+
+ output, err := cmd.Output()
+ if err != nil {
+ return NoConnection, err
+ }
+
+ result, err := strconv.Atoi(strings.TrimSpace(string(output)))
+ if err != nil {
+ return NoConnection, err
+ }
+
+ return DPITestResult(result), nil
+}
+
+func runBypassCheck(config Config) error {
+ domainWithoutPort := strings.Split(config.targetDomain, ":")[0]
+
+ fmt.Printf("\nStarting testing domain: %s\n", config.targetDomain)
+ fmt.Println("------------------------------------------------")
+
+ fmt.Println("Checking DPI blocks...")
+ result, err := checkDPIFingerprint(domainWithoutPort)
+ if err != nil {
+ fmt.Printf("Error occurred while checking: %v\n", err)
+ } else {
+ fmt.Printf("Checking result: %s\n", result)
+
+ if result == NoDPI {
+ fmt.Println("Using DPI spoofer not required.")
+ return nil
+ }
+
+ if result == NoConnection {
+ fmt.Println("Check internet connection and if domain is correct.")
+ return nil
+ }
+ }
+
+ fmt.Println("------------------------------------------------")
+ fmt.Println("Testing pre-configs...")
+
+ batFiles, err := config.getBatchFiles()
+ if err != nil {
+ return err
+ }
+
+ success := false
+ for _, batFile := range batFiles {
+ fmt.Printf("\n%sRunning pre-config: %s%s\n", colorMagenta, batFile, colorReset)
+
+ // Ensure no previous process is running
+ ensureProcessTerminated(config.processName)
+
+ cmd := exec.Command("cmd", "/c", batFile)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+
+ if err := cmd.Start(); err != nil {
+ fmt.Printf("%sFailed to run pre-config %s: %v%s\n", colorRed, batFile, err, colorReset)
+ continue
+ }
+
+ if !waitForProcess(config.processName, config.processWaitTime) {
+ fmt.Printf("%s%s not started for pre-config %s%s\n", colorRed, config.processName, batFile, colorReset)
+ cmd.Process.Kill()
+ continue
+ }
+
+ if testConnection(config.targetDomain, config.connectionTimeout) {
+ filename := filepath.Base(batFile)
+ fmt.Printf("\n%s!!!!!!!!!!!!!\n[SUCCESS] It seems, this pre-config is suitable for you - %s\n!!!!!!!!!!!!!\n%s\n",
+ colorGreen, filename, colorReset)
+ cmd.Process.Kill()
+ success = true
+ break
+ } else {
+ fmt.Printf("%s[FAIL] Failed to establish connection using pre-config: %s%s\n",
+ colorRed, batFile, colorReset)
+ cmd.Process.Kill()
+ }
+ }
+
+ // Final cleanup
+ ensureProcessTerminated(config.processName)
+ time.Sleep(500 * time.Millisecond)
+ ensureProcessTerminated(config.processName)
+
+ if !success {
+ fmt.Println("\n------------------------------------------------")
+ fmt.Println("Unfortunately, not found pre-config we can establish connection with :(")
+ fmt.Println("Try to run BLOCKCHECK, to find necessary parameters for BAT file.")
+ }
+
+ return nil
+}
+
+func main() {
+ // Terminal initialization
+ fmt.Print(enterAltScreen + hideCursor)
+ // Clear screen before switching
+ fmt.Print(clearScreen)
+ // Restore normal terminal state on exit
+ defer fmt.Print(showCursor + exitAltScreen)
+
+ // Check for administrator privileges
+ if !isElevated() {
+ fmt.Print("Administrative privileges required for correct work of program.\n" +
+ "Please, confirm prompt for administrative privileges.")
+ if err := requestElevation(); err != nil {
+ fmt.Printf("\nError occurred while requesting administrative privileges: %v", err)
+ time.Sleep(3 * time.Second)
+ return
+ }
+ fmt.Print(showCursor + exitAltScreen)
+ os.Exit(0)
+ }
+
+ targetDomain, err := getDomainChoice()
+ if err != nil {
+ fmt.Printf("Error: %v\n", err)
+ return
+ }
+
+ config := Config{
+ batchDir: "pre-configs",
+ targetDomain: targetDomain,
+ processName: "winws.exe",
+ processWaitTime: 10 * time.Second,
+ connectionTimeout: 5 * time.Second,
+ }
+
+ if err := runBypassCheck(config); err != nil {
+ fmt.Printf("Error: %v\n", err)
+ }
+
+ fmt.Println("\nPress Enter to exit...")
+ bufio.NewReader(os.Stdin).ReadBytes('\n')
+}
diff --git a/cmd/run_preconfig/run_preconfig.go b/cmd/run_preconfig/run_preconfig.go
new file mode 100644
index 0000000..4916863
--- /dev/null
+++ b/cmd/run_preconfig/run_preconfig.go
@@ -0,0 +1,260 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "os/exec"
+ "os/signal"
+ "path/filepath"
+ "sort"
+ "strings"
+ "syscall"
+
+ "github.com/eiannone/keyboard"
+)
+
+const (
+ enterAltScreen = "\033[?1049h"
+ exitAltScreen = "\033[?1049l"
+ hideCursor = "\033[?25l"
+ showCursor = "\033[?25h"
+ clearScreenSequence = "\033[2J\033[H\033[3J"
+ defaultTermHeight = 24
+ colorReset = "\033[0m"
+ colorRed = "\033[31m"
+ colorGreen = "\033[32m"
+ colorCyan = "\033[36m"
+ colorGrey = "\033[90m"
+)
+
+func setupTerminalCleanup() {
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+ go func() {
+ <-c
+ fmt.Print(showCursor + exitAltScreen)
+ keyboard.Close()
+ os.Exit(1)
+ }()
+}
+
+func initTerminal() {
+ fmt.Print(enterAltScreen + hideCursor)
+}
+
+func getTerminalSize() (int, int) {
+ cmd := exec.Command("stty", "size")
+ cmd.Stdin = os.Stdin
+ out, err := cmd.Output()
+ if err != nil {
+ return 80, defaultTermHeight
+ }
+
+ var rows, cols int
+ fmt.Sscanf(string(out), "%d %d", &rows, &cols)
+ return cols, rows
+}
+
+func printWelcomeMessage(buf *bytes.Buffer) int {
+ messages := []string{
+ "Welcome!",
+ "This program can install BAT file as service with autorun.",
+ "Author: ANKDDEV https://github.com/ankddev",
+ fmt.Sprintf("Version: %s", version),
+ "===",
+ "\nUsing ARROWS on your keyboard, select BAT file from list for installing service 'discordfix_zapret' or select 'Delete service from autorun' or 'Run BLOCKCHECK (Auto-setting BAT parameters)'.\n",
+ "For selection press ENTER.",
+ }
+
+ for _, msg := range messages {
+ buf.WriteString(msg + "\n")
+ }
+ return len(messages)
+}
+
+var version string
+
+func getOptions() []string {
+ options := []string{
+ "Run BLOCKCHECK (Auto-setting BAT parameters)",
+ }
+
+ currentDir, err := os.Getwd()
+ if err != nil {
+ return options
+ }
+
+ files, err := os.ReadDir(filepath.Join(currentDir, "pre-configs"))
+ if err != nil {
+ return options
+ }
+
+ var batFiles []string
+ for _, f := range files {
+ if !f.IsDir() && strings.HasSuffix(f.Name(), ".bat") {
+ batFiles = append(batFiles, f.Name())
+ }
+ }
+
+ sort.Strings(batFiles)
+ options = append(options, batFiles...)
+
+ return options
+}
+
+func Run() error {
+ setupTerminalCleanup()
+ defer fmt.Print(showCursor + exitAltScreen)
+
+ // Initialize terminal
+ initTerminal()
+
+ // Get terminal size
+ _, termHeight := getTerminalSize()
+
+ var buf bytes.Buffer
+
+ // Print welcome message
+ currentLine := printWelcomeMessage(&buf)
+ fmt.Print(buf.String())
+
+ // Get options list
+ options := getOptions()
+ if len(options) == 0 {
+ fmt.Println("Can't find any BAT files in current directory.")
+ return nil
+ }
+
+ // Start main UI loop
+ if err := runMainLoop(&buf, options, currentLine, termHeight); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func main() {
+ if err := Run(); err != nil {
+ fmt.Printf("Error: %v\n", err)
+ os.Exit(1)
+ }
+}
+
+func runMainLoop(buf *bytes.Buffer, options []string, startRow, termHeight int) error {
+ currentSelection := 0
+ scrollOffset := 0
+ maxVisibleOptions := min(15, termHeight-startRow-3)
+
+ if err := keyboard.Open(); err != nil {
+ return fmt.Errorf("error initializing keyboard: %v", err)
+ }
+ defer keyboard.Close()
+
+ for {
+ buf.Reset()
+ buf.WriteString("\033[H\033[J")
+
+ // Always print welcome message
+ printWelcomeMessage(buf)
+
+ // Show up arrow if there are hidden elements
+ if scrollOffset > 0 {
+ buf.WriteString(fmt.Sprintf("%s↑ more items above%s\n", colorGrey, colorReset))
+ }
+
+ // Show visible options
+ endIdx := min(scrollOffset+maxVisibleOptions, len(options))
+ for i := scrollOffset; i < endIdx; i++ {
+ prefix := " "
+ if i == currentSelection {
+ prefix = "► "
+ buf.WriteString(fmt.Sprintf("%s%s%s%s\n", colorCyan, prefix, options[i], colorReset))
+ } else {
+ buf.WriteString(fmt.Sprintf("%s%s\n", prefix, options[i]))
+ }
+ }
+
+ // Show down arrow if there are hidden elements
+ if endIdx < len(options) {
+ buf.WriteString(fmt.Sprintf("%s↓ more items below%s\n", colorGrey, colorReset))
+ }
+
+ os.Stdout.Write(buf.Bytes())
+
+ _, key, err := keyboard.GetKey()
+ if err != nil {
+ return fmt.Errorf("error reading keyboard: %v", err)
+ }
+
+ switch key {
+ case keyboard.KeyArrowUp:
+ if currentSelection > 0 {
+ currentSelection--
+ if currentSelection < scrollOffset {
+ scrollOffset = currentSelection
+ }
+ }
+ case keyboard.KeyArrowDown:
+ if currentSelection < len(options)-1 {
+ currentSelection++
+ if currentSelection >= scrollOffset+maxVisibleOptions {
+ scrollOffset = currentSelection - maxVisibleOptions + 1
+ }
+ }
+ case keyboard.KeyEnter:
+ return handleSelection(options[currentSelection])
+ case keyboard.KeyEsc:
+ return nil
+ }
+ }
+}
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func handleSelection(selected string) error {
+ switch selected {
+ case "Run BLOCKCHECK (Auto-setting BAT parameters)":
+ fmt.Print(showCursor + exitAltScreen)
+ keyboard.Close()
+
+ _, err := runPowershellCommand("Start-Process 'blockcheck.cmd'")
+ if err != nil {
+ return fmt.Errorf("%s⚠ Error running BLOCKCHECK: %v%s", colorRed, err, colorReset)
+ }
+ return nil
+ default:
+ fmt.Print(showCursor + exitAltScreen)
+ keyboard.Close()
+
+ currentDir, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+ batPath := filepath.Join(currentDir, "pre-configs", selected)
+
+ cmd := exec.Command("cmd", "/c", batPath)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ cmd.Stdin = os.Stdin
+
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("%s⚠ Error running BAT file: %v%s", colorRed, err, colorReset)
+ }
+ return nil
+ }
+}
+
+func runPowershellCommand(command string) (string, error) {
+ cmd := exec.Command("powershell", "-NoProfile", "-NonInteractive", "-Command", command)
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ return "", fmt.Errorf("PowerShell error: %v - %s", err, string(output))
+ }
+ return string(output), nil
+}
diff --git a/cmd/select_domains/select_domains.go b/cmd/select_domains/select_domains.go
new file mode 100644
index 0000000..ee8710a
--- /dev/null
+++ b/cmd/select_domains/select_domains.go
@@ -0,0 +1,305 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "os/signal"
+ "path/filepath"
+ "strings"
+ "syscall"
+ "time"
+
+ "github.com/eiannone/keyboard"
+)
+
+const (
+ // Terminal control
+ enterAltScreen = "\033[?1049h"
+ exitAltScreen = "\033[?1049l"
+ hideCursor = "\033[?25l"
+ showCursor = "\033[?25h"
+ clearScreen = "\033[2J\033[H"
+
+ // Colors
+ colorReset = "\033[0m"
+ colorCyan = "\033[36m"
+ colorRed = "\033[31m"
+ colorGreen = "\033[32m"
+ colorGrey = "\033[90m"
+
+ // UI constants
+ visibleItems = 15
+ headerLines = 5
+ scrollAreaHeight = visibleItems + 2
+)
+
+type FileEntry struct {
+ name string
+ selected bool
+ isControl bool
+}
+
+func setupTerminalCleanup() {
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+ go func() {
+ <-c
+ fmt.Print(showCursor + exitAltScreen)
+ keyboard.Close()
+ os.Exit(1)
+ }()
+}
+
+func drawScreen(buf *bytes.Buffer, entries []FileEntry, currentIndex, scrollOffset int, clearScreen bool) {
+ if clearScreen {
+ buf.WriteString("\033[2J")
+ }
+ buf.WriteString("\033[H")
+
+ // Header section
+ buf.WriteString("Use ↑↓ (arrows) for navigation, SPACE or ↵ (ENTER) to select\n\n")
+
+ // Draw control options first
+ for i, entry := range entries {
+ if !entry.isControl {
+ continue
+ }
+
+ prefix := " "
+ if i == currentIndex {
+ prefix = ">"
+ buf.WriteString(fmt.Sprintf("%s%s %s%s\n", colorCyan, prefix, entry.name, colorReset))
+ } else {
+ buf.WriteString(fmt.Sprintf("%s %s\n", prefix, entry.name))
+ }
+ }
+
+ buf.WriteString("\n\n") // Extra empty line and separator
+
+ // Get file entries
+ var fileEntries []FileEntry
+ for _, entry := range entries {
+ if !entry.isControl {
+ fileEntries = append(fileEntries, entry)
+ }
+ }
+
+ totalFiles := len(fileEntries)
+ visibleEnd := min(scrollOffset+visibleItems, totalFiles)
+
+ // Clear scroll area
+ for i := 0; i < scrollAreaHeight; i++ {
+ buf.WriteString(strings.Repeat(" ", 80) + "\n")
+ }
+
+ // Move back to start of scroll area
+ buf.WriteString("\033[" + fmt.Sprint(scrollAreaHeight) + "A")
+
+ // Show scroll indicator
+ if scrollOffset > 0 {
+ buf.WriteString(fmt.Sprintf("%s↑ Scroll up for more files%s\n", colorGrey, colorReset))
+ } else {
+ buf.WriteString("\n")
+ }
+
+ // Draw visible file entries
+ for i := scrollOffset; i < visibleEnd; i++ {
+ entry := fileEntries[i]
+ realIndex := getRealIndex(entries, entry.name)
+ prefix := " "
+ if realIndex == currentIndex {
+ prefix = ">"
+ }
+ selected := "[ ]"
+ if entry.selected {
+ selected = "[+]"
+ }
+
+ line := fmt.Sprintf("%s %s %s", prefix, selected, entry.name)
+ if realIndex == currentIndex {
+ buf.WriteString(fmt.Sprintf("%s%s%s\n", colorCyan, line, colorReset))
+ } else {
+ buf.WriteString(fmt.Sprintf("%s\n", line))
+ }
+ }
+
+ // Fill remaining lines with empty space
+ for i := visibleEnd - scrollOffset; i < visibleItems; i++ {
+ buf.WriteString("\n")
+ }
+
+ // Show bottom scroll indicator
+ if visibleEnd < totalFiles {
+ buf.WriteString(fmt.Sprintf("%s↓ Scroll down for more files%s\n", colorGrey, colorReset))
+ }
+}
+
+func getRealIndex(entries []FileEntry, name string) int {
+ for i, entry := range entries {
+ if entry.name == name {
+ return i
+ }
+ }
+ return 0
+}
+
+func joinSelectedFiles(listsDir string, selectedEntries []FileEntry) error {
+ ultimatePath := filepath.Join(listsDir, "list-ultimate.txt")
+ ultimateFile, err := os.Create(ultimatePath)
+ if err != nil {
+ return err
+ }
+ defer ultimateFile.Close()
+
+ for _, entry := range selectedEntries {
+ if !entry.isControl {
+ filePath := filepath.Join(listsDir, entry.name)
+ content, err := os.ReadFile(filePath)
+ if err != nil {
+ continue
+ }
+ fmt.Fprintln(ultimateFile, strings.TrimSpace(string(content)))
+ }
+ }
+
+ return nil
+}
+
+func main() {
+ // Terminal initialization
+ fmt.Print(clearScreen)
+ fmt.Print(enterAltScreen + hideCursor)
+ defer fmt.Print(showCursor + exitAltScreen)
+
+ setupTerminalCleanup()
+
+ listsDir := "lists"
+ if err := os.MkdirAll(listsDir, 0755); err != nil {
+ fmt.Printf("Error creating lists directory: %v\n", err)
+ return
+ }
+
+ // Load saved selections
+ var selectedFiles []string
+ if content, err := os.ReadFile(filepath.Join(listsDir, "selected.txt")); err == nil {
+ selectedFiles = strings.Split(strings.TrimSpace(string(content)), "\n")
+ }
+
+ // Create file list
+ entries := []FileEntry{
+ {name: "SAVE LIST", isControl: true},
+ {name: "CANCEL", isControl: true},
+ }
+
+ files, err := os.ReadDir(listsDir)
+ if err != nil {
+ fmt.Printf("Error reading directory: %v\n", err)
+ return
+ }
+
+ for _, file := range files {
+ name := file.Name()
+ if strings.HasPrefix(name, "list-") && strings.HasSuffix(name, ".txt") && name != "list-ultimate.txt" {
+ entries = append(entries, FileEntry{
+ name: name,
+ selected: contains(selectedFiles, name),
+ })
+ }
+ }
+
+ if err := keyboard.Open(); err != nil {
+ fmt.Printf("Error initializing keyboard: %v\n", err)
+ return
+ }
+ defer keyboard.Close()
+
+ var buf bytes.Buffer
+ currentIndex := 0
+ scrollOffset := 0
+
+ for {
+ buf.Reset()
+ drawScreen(&buf, entries, currentIndex, scrollOffset, false)
+ os.Stdout.Write(buf.Bytes())
+
+ _, key, err := keyboard.GetKey()
+ if err != nil {
+ fmt.Printf("Error reading keyboard: %v\n", err)
+ return
+ }
+
+ switch key {
+ case keyboard.KeyArrowUp:
+ if currentIndex > 0 {
+ currentIndex--
+ if currentIndex >= 2 && currentIndex-2 < scrollOffset {
+ scrollOffset = currentIndex - 2
+ }
+ }
+ case keyboard.KeyArrowDown:
+ if currentIndex < len(entries)-1 {
+ currentIndex++
+ if currentIndex >= 2 && currentIndex-2 >= scrollOffset+visibleItems {
+ scrollOffset = currentIndex - visibleItems + 1 - 2
+ }
+ }
+ case keyboard.KeySpace, keyboard.KeyEnter:
+ if entries[currentIndex].isControl {
+ switch entries[currentIndex].name {
+ case "SAVE LIST":
+ // Save selected files
+ selectedFile, err := os.Create(filepath.Join(listsDir, "selected.txt"))
+ if err == nil {
+ for _, entry := range entries {
+ if entry.selected {
+ fmt.Fprintln(selectedFile, entry.name)
+ }
+ }
+ selectedFile.Close()
+
+ // Merge selected files
+ var selectedEntries []FileEntry
+ for _, entry := range entries {
+ if entry.selected {
+ selectedEntries = append(selectedEntries, entry)
+ }
+ }
+
+ if err := joinSelectedFiles(listsDir, selectedEntries); err != nil {
+ fmt.Printf("\n%sError occurred while merging files: %v. Exiting in 5 seconds...%s\n",
+ colorRed, err, colorReset)
+ } else {
+ fmt.Printf("\n%sSuccessful! List saved and files merged. Exiting in 5 seconds...%s\n",
+ colorGreen, colorReset)
+ }
+ time.Sleep(5 * time.Second)
+ return
+ }
+ case "CANCEL":
+ return
+ }
+ } else {
+ entries[currentIndex].selected = !entries[currentIndex].selected
+ }
+ case keyboard.KeyEsc:
+ return
+ }
+ }
+}
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func contains(slice []string, item string) bool {
+ for _, s := range slice {
+ if s == item {
+ return true
+ }
+ }
+ return false
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..7435604
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,10 @@
+module github.com/ankddev/zapret-discord-youtube
+
+go 1.23.1
+
+require (
+ github.com/cli/safeexec v1.0.1
+ github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203
+)
+
+require golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..3d8dfed
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,6 @@
+github.com/cli/safeexec v1.0.1 h1:e/C79PbXF4yYTN/wauC4tviMxEV13BwljGj0N9j+N00=
+github.com/cli/safeexec v1.0.1/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q=
+github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 h1:XBBHcIb256gUJtLmY22n99HaZTz+r2Z51xUPi01m3wg=
+github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203/go.mod h1:E1jcSv8FaEny+OP/5k9UxZVw9YFWGj7eI4KR/iOBqCg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/make_release/Cargo.toml b/make_release/Cargo.toml
deleted file mode 100644
index e031a21..0000000
--- a/make_release/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-name = "make_release"
-version.workspace = true
-edition = "2021"
-build = "build.rs"
-
-[package.metadata.winresource]
-LegalCopyright = "2024 by ANKDDEV"
-OriginalFilename = "zapret_make_release.exe"
-
-[dependencies]
-dunce = "1.0.5"
-fs_extra = "1.3.0"
-spinners = "4.1.1"
-zip = "2.2.1"
-walkdir = "2.5.0"
-anyhow = "1.0.94"
-
-[build-dependencies]
-winresource.workspace = true
diff --git a/make_release/build.rs b/make_release/build.rs
deleted file mode 100644
index a6352ac..0000000
--- a/make_release/build.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use std::io;
-use winresource::WindowsResource;
-
-fn main() -> io::Result<()> {
- if cfg!(target_os = "windows") {
- let mut res = WindowsResource::new();
- res.set_icon("icon.ico")
- .set("InternalName", "Make release of Zapret DPI by ANKDDEV");
-
- res.compile()?;
- }
-
- Ok(())
-}
diff --git a/make_release/icon.ico b/make_release/icon.ico
deleted file mode 100644
index 299933d..0000000
Binary files a/make_release/icon.ico and /dev/null differ
diff --git a/make_release/src/main.rs b/make_release/src/main.rs
deleted file mode 100644
index 99fb197..0000000
--- a/make_release/src/main.rs
+++ /dev/null
@@ -1,157 +0,0 @@
-mod utils;
-
-use spinners::{Spinner, Spinners};
-use std::io::stdin;
-use std::path::Path;
-use std::{fs, io};
-use walkdir::WalkDir;
-use zip::write::ZipWriter;
-
-fn main() -> io::Result<()> {
- print!("\x1b]9;4;3;\x1b\\");
- println!("[1/4] Preparing");
-
- let temp_dir = std::env::temp_dir();
-
- let current_directory = std::env::current_dir().expect("Failed to get current directory");
- assert!(current_directory.exists());
-
- let project_path = dunce::canonicalize(Path::new(env!("CARGO_MANIFEST_DIR")).join(".."))?;
- assert!(project_path.exists());
-
- let bin_path = project_path.join("bin");
- assert!(bin_path.exists());
-
- let lists_path = project_path.join("lists");
- assert!(lists_path.exists());
-
- let pre_configs_path = project_path.join("pre-configs");
- assert!(pre_configs_path.exists());
-
- let resources_path = project_path.join("resources");
- assert!(resources_path.exists());
-
- let add_to_autorun_path = current_directory.join("add_to_autorun.exe");
- assert!(add_to_autorun_path.exists());
-
- let run_preconfig_path = current_directory.join("run_preconfig.exe");
- assert!(run_preconfig_path.exists());
-
- let select_domains_path = current_directory.join("select_domains.exe");
- assert!(select_domains_path.exists());
-
- let pre_config_tester_path = current_directory.join("preconfig_tester.exe");
- assert!(pre_config_tester_path.exists());
-
- let mut spinner = Spinner::new(Spinners::Dots, "[2/4] Copying files".into());
- let copy_options = fs_extra::file::CopyOptions::new().overwrite(true);
-
- let new_select_domains_path = temp_dir.join("Set domain list.exe");
- let new_pre_config_tester_path = temp_dir.join("Automatically search pre-config.exe");
- let new_add_to_autorun_path = temp_dir.join("Add to autorun.exe");
- let new_run_preconfig_path = temp_dir.join("Run pre-config.exe");
- let new_readme_path = temp_dir.join("___README.TXT");
- let new_blockcheck_path = temp_dir.join("blockcheck.cmd");
-
- fs_extra::file::copy(
- &select_domains_path,
- &new_select_domains_path,
- ©_options,
- )
- .expect("Failed to copy `select_domains.exe`");
- fs_extra::file::copy(
- &pre_config_tester_path,
- &new_pre_config_tester_path,
- ©_options,
- )
- .expect("Failed to copy `preconfig_tester.exe`");
- fs_extra::file::copy(
- &run_preconfig_path,
- &new_run_preconfig_path,
- ©_options,
- )
- .expect("Failed to copy `run_preconfig.exe`");
- fs_extra::file::copy(
- &add_to_autorun_path,
- &new_add_to_autorun_path,
- ©_options,
- )
- .expect("Failed to copy `add_to_autorun.exe`");
- fs_extra::file::copy(
- resources_path.join("___README.TXT"),
- &new_readme_path,
- ©_options,
- )
- .expect("Failed to copy `___readme.txt`");
- fs_extra::file::copy(
- resources_path.join("blockcheck.cmd"),
- &new_blockcheck_path,
- ©_options,
- )
- .expect("Failed to copy `blockcheck.cmd`");
-
- spinner.stop_and_persist("[2/4]", "Files copied".into());
-
- let mut spinner = Spinner::new(Spinners::Dots, "[3/4] Archiving files".into());
-
- let zip_path = current_directory.join("zapret-discord-youtube-ankddev.zip");
- let zip_file = fs::File::create(&zip_path).expect("Failed to create archive");
- let mut zip = ZipWriter::new(zip_file);
-
- // Bin folder
- let walkdir = WalkDir::new(&bin_path);
- let mut iterator = walkdir.into_iter().filter_map(|e| e.ok());
- utils::add_dir_to_zip(&mut iterator, &bin_path, &mut zip)
- .expect("Failed to add directory to zip");
-
- // Lists folder
- let walkdir = WalkDir::new(&lists_path);
- let mut iterator = walkdir.into_iter().filter_map(|e| e.ok());
- utils::add_dir_to_zip(&mut iterator, &lists_path, &mut zip)
- .expect("Failed to add directory to zip");
-
- // Pre-configs folder
- let walkdir = WalkDir::new(&pre_configs_path);
- let mut iterator = walkdir.into_iter().filter_map(|e| e.ok());
- utils::add_dir_to_zip(&mut iterator, &pre_configs_path, &mut zip)
- .expect("Failed to add directory to zip");
-
- utils::add_file_to_zip(&new_add_to_autorun_path, &temp_dir, &mut zip)
- .expect("Failed to add file to zip");
- utils::add_file_to_zip(&new_readme_path, &temp_dir, &mut zip)
- .expect("Failed to add file to zip");
- utils::add_file_to_zip(&new_select_domains_path, &temp_dir, &mut zip)
- .expect("Failed to add file to zip");
- utils::add_file_to_zip(&new_blockcheck_path, &temp_dir, &mut zip)
- .expect("Failed to add file to zip");
- utils::add_file_to_zip(&new_pre_config_tester_path, &temp_dir, &mut zip)
- .expect("Failed to add file to zip");
- utils::add_file_to_zip(&new_run_preconfig_path, &temp_dir, &mut zip)
- .expect("Failed to add file to zip");
-
- zip.finish()?;
-
- spinner.stop_and_persist("[3/4]", "Files archived".into());
-
- let mut spinner = Spinner::new(Spinners::Dots, "[4/4] Cleaning cache".into());
-
- fs_extra::file::remove(&new_add_to_autorun_path).expect("Failed to delete file");
- fs_extra::file::remove(&new_readme_path).expect("Failed to delete file");
- fs_extra::file::remove(&new_select_domains_path).expect("Failed to delete file");
- fs_extra::file::remove(&new_blockcheck_path).expect("Failed to delete file");
- fs_extra::file::remove(&new_pre_config_tester_path).expect("Failed to delete file");
- fs_extra::file::remove(&new_run_preconfig_path).expect("Failed to delete file");
-
- spinner.stop_and_persist("[4/4]", "Cache cleaned".into());
- print!("\x1b]9;4;0;\x1b\\");
-
- println!(
- "Release build ready! Check `{}`.\nPress ENTER to continue.",
- &zip_path.display()
- );
-
- let mut input = String::new();
- stdin().read_line(&mut input).expect("Failed to read input");
-
- Ok(())
-}
diff --git a/make_release/src/utils.rs b/make_release/src/utils.rs
deleted file mode 100644
index c3bf168..0000000
--- a/make_release/src/utils.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-use anyhow::Context;
-use std::fs::File;
-use std::io::{Read, Write};
-use std::path::Path;
-use walkdir::DirEntry;
-use zip::write::SimpleFileOptions;
-use zip::ZipWriter;
-
-pub fn add_dir_to_zip(
- it: &mut dyn Iterator- ,
- prefix: &Path,
- writer: &mut ZipWriter,
-) -> anyhow::Result<()> {
- let prefix =
- dunce::canonicalize(Path::new(prefix).join("..")).expect("Failed to canonicalize folder");
- let options = SimpleFileOptions::default().unix_permissions(0o755);
- let mut buffer = Vec::new();
- for entry in it {
- let path = entry.path();
- let name = path.strip_prefix(&prefix)?;
- let path_as_string = name
- .to_str()
- .map(str::to_owned)
- .with_context(|| format!("{name:?} Is a Non UTF-8 Path"))?;
-
- if path.is_file() {
- writer.start_file(path_as_string, options)?;
- let mut f = File::open(path)?;
-
- f.read_to_end(&mut buffer)?;
- writer.write_all(&buffer)?;
- buffer.clear();
- } else if !name.as_os_str().is_empty() {
- // Only if not root! Avoids path spec / warning
- // and mapname conversion failed error on unzip
- writer.add_directory(path_as_string, options)?;
- }
- }
- Ok(())
-}
-
-pub fn add_file_to_zip(
- path: &Path,
- prefix: &Path,
- writer: &mut ZipWriter,
-) -> anyhow::Result<()> {
- let prefix = Path::new(prefix);
- let name = path.strip_prefix(prefix)?;
- let mut buffer = Vec::new();
- let options = SimpleFileOptions::default().unix_permissions(0o755);
- let path_as_string = name
- .to_str()
- .map(str::to_owned)
- .with_context(|| format!("{name:?} Is a Non UTF-8 Path"))?;
- writer.start_file(path_as_string, options)?;
- let mut f = File::open(path)?;
-
- f.read_to_end(&mut buffer)?;
- writer.write_all(&buffer)?;
- buffer.clear();
- Ok(())
-}
diff --git a/preconfig_tester/Cargo.toml b/preconfig_tester/Cargo.toml
deleted file mode 100644
index 0f1ec5f..0000000
--- a/preconfig_tester/Cargo.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-[package]
-name = "preconfig_tester"
-version.workspace = true
-edition = "2021"
-build = "build.rs"
-
-[package.metadata.winresource]
-LegalCopyright = "2024 by ANKDDEV"
-OriginalFilename = "zapret_preconfig_tester.exe"
-
-[dependencies]
-sysinfo = "0.32.0"
-native-tls = "0.2.12"
-ureq = { version = "2.12.1", features = ["tls"] }
-winapi = { version = "0.3.9", features = [
- "processthreadsapi",
- "securitybaseapi",
- "winnt",
- "minwindef",
-] }
-termcolor = "1.4.1"
-
-[build-dependencies]
-winresource.workspace = true
diff --git a/preconfig_tester/build.rs b/preconfig_tester/build.rs
deleted file mode 100644
index 032e0d5..0000000
--- a/preconfig_tester/build.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use std::io;
-
-fn main() -> io::Result<()> {
- if cfg!(target_os = "windows") {
- let mut res = winresource::WindowsResource::new();
- res
- // This path can be absolute, or relative to your crate root.
- .set_icon("icon.ico")
- .set("InternalName", "Testing Zapret pre-configs by ANKDDEV");
-
- res.compile()?;
- }
-
- Ok(())
-}
diff --git a/preconfig_tester/icon.ico b/preconfig_tester/icon.ico
deleted file mode 100644
index f9c5e73..0000000
Binary files a/preconfig_tester/icon.ico and /dev/null differ
diff --git a/preconfig_tester/src/config.rs b/preconfig_tester/src/config.rs
deleted file mode 100644
index b716f3c..0000000
--- a/preconfig_tester/src/config.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-use crate::error::{AppError, AppResult};
-use std::fs;
-use std::path::PathBuf;
-use std::time::Duration;
-
-pub struct Config {
- pub batch_dir: PathBuf,
- pub target_domain: String,
- pub process_name: String,
- pub process_wait_timeout: Duration,
- pub connection_timeout: Duration,
-}
-
-impl Config {
- pub fn get_batch_files(&self) -> AppResult> {
- let entries = fs::read_dir(&self.batch_dir)
- .map_err(|e| AppError::IoError(format!("Failed to read directory: {}", e)))?;
-
- let batch_files: Vec = entries
- .filter_map(Result::ok)
- .filter(|entry| {
- entry.path().is_file() && entry.path().extension().map_or(false, |ext| ext == "bat")
- })
- .map(|entry| entry.path())
- .collect();
-
- if batch_files.is_empty() {
- return Err(AppError::NoBatchFiles);
- }
-
- Ok(batch_files)
- }
-}
diff --git a/preconfig_tester/src/domains.rs b/preconfig_tester/src/domains.rs
deleted file mode 100644
index 3fe4497..0000000
--- a/preconfig_tester/src/domains.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-const DEFAULT_PORT: u16 = 443;
-
-pub fn is_valid_domain(domain: &str) -> bool {
- if domain.is_empty() || domain.len() > 255 {
- return false;
- }
-
- !domain.contains(':')
- && domain
- .chars()
- .all(|c| c.is_ascii_alphanumeric() || c == '.' || c == '-')
- && !domain.starts_with('-')
- && !domain.ends_with('-')
-}
-
-pub fn format_domain_with_port(domain: &str) -> String {
- format!("{}:{}", domain.trim(), DEFAULT_PORT)
-}
diff --git a/preconfig_tester/src/error.rs b/preconfig_tester/src/error.rs
deleted file mode 100644
index ab066c5..0000000
--- a/preconfig_tester/src/error.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-use std::error::Error;
-use std::fmt;
-use std::io; // Import the native_tls crate
-
-#[allow(unused)]
-#[derive(Debug)]
-pub enum AppError {
- IoError(String),
- NetworkError(String),
- NoBatchFiles,
- InputError(String),
-}
-
-impl fmt::Display for AppError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- AppError::IoError(msg) => write!(f, "IO error: {}", msg),
- AppError::NetworkError(msg) => write!(f, "Network error: {}", msg),
- AppError::NoBatchFiles => write!(f, "Pre-configs not found in directory"),
- AppError::InputError(msg) => write!(f, "Input error: {}", msg),
- }
- }
-}
-
-impl Error for AppError {}
-
-// Implement conversion from io::Error to AppError
-impl From for AppError {
- fn from(error: io::Error) -> Self {
- AppError::IoError(error.to_string())
- }
-}
-
-// Implement conversion from native_tls::Error to AppError
-impl From for AppError {
- fn from(error: native_tls::Error) -> Self {
- AppError::NetworkError(error.to_string())
- }
-}
-
-pub type AppResult = Result;
diff --git a/preconfig_tester/src/main.rs b/preconfig_tester/src/main.rs
deleted file mode 100644
index dd52dea..0000000
--- a/preconfig_tester/src/main.rs
+++ /dev/null
@@ -1,266 +0,0 @@
-use std::io::{self, stdin, stdout, Write};
-use std::path::PathBuf;
-use std::thread::sleep;
-use std::time::Duration;
-
-mod config;
-mod domains;
-mod error;
-mod network;
-mod process;
-mod utils;
-
-use crate::network::DPITestResult;
-use config::Config;
-use error::{AppError, AppResult};
-use network::NetworkChecker;
-use process::ProcessManager;
-
-use winapi::um::handleapi::CloseHandle;
-
-use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
-
-struct TokenHandle(*mut winapi::ctypes::c_void);
-
-impl Drop for TokenHandle {
- fn drop(&mut self) {
- if !self.0.is_null() {
- unsafe { CloseHandle(self.0) };
- }
- }
-}
-
-const DOMAIN_LIST: &[(&str, &str)] = &[
- ("1", "discord.com"),
- ("2", "youtube.com"),
- ("3", "spotify.com"),
- ("4", "speedtest.net"),
- ("5", "steampowered.com"),
- ("6", "custom"),
- ("0", "exit"),
-];
-
-const GREEN: Color = Color::Rgb(126, 176, 0);
-const MAGENTA: Color = Color::Rgb(196, 124, 186);
-const RED: Color = Color::Rgb(214, 77, 91);
-
-fn get_domain_choice() -> io::Result {
- println!("\nSelect domain for checking:");
- for (number, domain) in DOMAIN_LIST {
- if *domain == "exit" {
- println!("{}. Exit", number);
- } else if *domain == "custom" {
- println!("{}. Enter your own domain", number);
- } else {
- println!("{}. {}", number, domain);
- }
- }
-
- loop {
- print!("\nEnter number of variant: ");
- stdout().flush()?;
-
- let mut choice = String::new();
- stdin().read_line(&mut choice)?;
- let choice = choice.trim();
-
- if let Some((_, domain)) = DOMAIN_LIST.iter().find(|(num, _)| *num == choice) {
- if *domain == "exit" {
- print!("Exiting..");
- stdout().flush()?;
- std::process::exit(0);
- } else if *domain == "custom" {
- print!("Enter domain (for example, example.com): ");
- stdout().flush()?;
-
- let mut custom_domain = String::new();
- stdin().read_line(&mut custom_domain)?;
- let custom_domain = custom_domain.trim().to_string();
-
- if domains::is_valid_domain(&custom_domain) {
- return Ok(domains::format_domain_with_port(&custom_domain));
- } else {
- println!("Invalid domain format. Use format domain.com");
- continue;
- }
- } else {
- return Ok(domains::format_domain_with_port(domain));
- }
- } else {
- println!(
- "Invalid selection. Please select number from 0 to {}",
- DOMAIN_LIST.len() - 1
- );
- }
- }
-}
-
-fn main() -> AppResult<()> {
- let args: Vec = std::env::args().collect();
- let is_elevated_instance = args.contains(&"--elevated".to_string());
-
- if is_elevated_instance {
- let marker_path = std::env::temp_dir().join("bypass_checker_elevated.tmp");
- if marker_path.exists() {
- let _ = std::fs::remove_file(marker_path);
- }
- }
-
- if !utils::is_elevated() {
- println!("Administrative privileges required for correct work of program.");
- println!("Please, confirm prompt for administrative privileges.");
- match utils::request_elevation() {
- Ok(_) => {
- // Exit immediately to close the non-elevated console window
- std::process::exit(0);
- }
- Err(e) => {
- eprintln!(
- "Error occurred while requesting administrative privileges: {}",
- e
- );
- let marker_path = std::env::temp_dir().join("bypass_checker_elevated.tmp");
- if marker_path.exists() {
- let _ = std::fs::remove_file(marker_path);
- }
- // Give user time to read the error message
- sleep(Duration::from_secs(3));
- return Ok(());
- }
- }
- }
-
- let target_domain = get_domain_choice()
- .map_err(|e| AppError::IoError(format!("Error occurred while reading input: {}", e)))?;
-
- let config = Config {
- batch_dir: PathBuf::from("pre-configs"),
- target_domain,
- process_name: String::from("winws.exe"),
- process_wait_timeout: Duration::from_secs(10),
- connection_timeout: Duration::from_secs(5),
- };
-
- let process_manager = ProcessManager::new();
- let network_checker = NetworkChecker::new(config.connection_timeout);
-
- let result = run_bypass_check(config, process_manager, &network_checker);
-
- println!("\nPress Enter to exit...");
- stdout().flush().expect("Failed to flush buffer of output");
- let mut input = String::new();
- stdin().read_line(&mut input).expect("Failed to read input");
-
- result
-}
-
-fn run_bypass_check(
- config: Config,
- mut process_manager: ProcessManager,
- network_checker: &NetworkChecker,
-) -> AppResult<()> {
- let mut stdout = StandardStream::stdout(ColorChoice::Always);
-
- let batch_files = config.get_batch_files()?;
- let mut success = false;
-
- let domain_without_port = config.target_domain.split(':').next().unwrap_or_default();
-
- println!("\nStarting testing domain: {}", config.target_domain);
- println!("------------------------------------------------");
-
- println!("Checking DPI blocks...");
- match network_checker.check_dpi_fingerprint(domain_without_port) {
- Ok(result) => {
- println!("Checking result: {}", result.to_english_string());
-
- if result == DPITestResult::NoDPI {
- println!("Using DPI spoofer not required.");
- return Ok(());
- }
-
- if result == DPITestResult::NoConnection {
- println!("Check internet connection and if domain is correct.");
- return Ok(());
- }
-
- println!("------------------------------------------------");
- println!("Testing pre-configs...");
- }
- Err(e) => {
- println!("Error occurred while checking: {}", e);
- println!("Testing pre-configs...");
- }
- }
-
- for batch_file in batch_files {
- stdout.set_color(ColorSpec::new().set_fg(Some(MAGENTA)))?;
- println!("\nRunning pre-config: {}", batch_file.display());
- stdout.set_color(ColorSpec::new().set_fg(Some(Color::White)))?;
-
- // before testing new batch file, ensure there's no winws.exe running in background
- process_manager.ensure_process_terminated(&config.process_name);
-
- let mut child = match process_manager.run_batch_file(&batch_file) {
- Ok(child) => child,
- Err(e) => {
- eprintln!("Failed to run pre-config {}: {}", batch_file.display(), e);
- continue;
- }
- };
-
- let process_result =
- process_manager.wait_for_process(&config.process_name, config.process_wait_timeout);
-
- if !process_result {
- eprintln!(
- "{} not started for pre-config {}",
- config.process_name,
- batch_file.display()
- );
- process_manager.cleanup_process(&mut child, &config.process_name)?;
- continue;
- }
-
- if network_checker.test_connection(&config.target_domain)? {
- let filename = batch_file
- .file_name()
- .and_then(|name| name.to_str())
- .unwrap_or("unknown");
-
- stdout.set_color(ColorSpec::new().set_fg(Some(GREEN)))?;
- println!("{}", format!("\n!!!!!!!!!!!!!\n[SUCCESS] It seems, this pre-config is suitable for you - {}\n!!!!!!!!!!!!!\n", filename));
- process_manager.cleanup_process(&mut child, &config.process_name)?;
- stdout.set_color(ColorSpec::new().set_fg(Some(Color::White)))?;
- success = true;
- } else {
- stdout.set_color(ColorSpec::new().set_fg(Some(RED)))?;
- println!(
- "{}",
- format!(
- "[FAIL] Failed to establish connection using pre-config: {}",
- batch_file.display()
- )
- );
- process_manager.cleanup_process(&mut child, &config.process_name)?;
- stdout.set_color(ColorSpec::new().set_fg(Some(Color::White)))?;
- continue;
- }
- }
-
- // Always try to clean up the process at the end
- process_manager.ensure_process_terminated(&config.process_name);
-
- // Double-check after a short delay
- sleep(Duration::from_millis(500));
- process_manager.ensure_process_terminated(&config.process_name);
-
- // If none of the pre-configs worked
- if !success {
- println!("\n------------------------------------------------");
- println!("Unfortunately, not found pre-config we can establish connection with :(");
- println!("Try to run BLOCKCHECK, to find necessary parameters for BAT file.");
- }
-
- Ok(())
-}
diff --git a/preconfig_tester/src/network.rs b/preconfig_tester/src/network.rs
deleted file mode 100644
index 164a4ae..0000000
--- a/preconfig_tester/src/network.rs
+++ /dev/null
@@ -1,218 +0,0 @@
-use crate::error::AppResult;
-use std::time::Duration;
-use ureq::{AgentBuilder, Error as UreqError, ErrorKind as UreqErrorKind, Transport};
-
-pub struct NetworkChecker {
- timeout: Duration,
-}
-
-impl NetworkChecker {
- pub fn new(timeout: Duration) -> Self {
- Self { timeout }
- }
-
- pub fn test_connection(&self, target: &str) -> AppResult {
- // Add a small delay before testing to ensure previous connection is fully closed
- std::thread::sleep(Duration::from_millis(1000));
-
- let domain = target.split(':').next().unwrap_or(target);
- let result = self.try_connect(domain)?;
-
- // Add another delay after testing to ensure connection cleanup
- std::thread::sleep(Duration::from_millis(500));
-
- Ok(result == ConnectionResult::Success)
- }
-
- pub fn check_dpi_fingerprint(&self, domain: &str) -> AppResult {
- println!("Checking connection with {}...", domain);
-
- match self.try_connect(domain)? {
- ConnectionResult::Success => Ok(DPITestResult::NoDPI),
- ConnectionResult::ConnectionReset => Ok(DPITestResult::DPIDetected),
- ConnectionResult::NoConnection => Ok(DPITestResult::NoConnection),
- ConnectionResult::Timeout => Ok(DPITestResult::DPIDetected),
- ConnectionResult::ISPBlock => Ok(DPITestResult::ISPBlocked),
- }
- }
-
- fn try_connect(&self, domain: &str) -> AppResult {
- let url = format!("https://{}", domain);
- println!("DEBUG: Trying to connect to {}...", url);
-
- // Create a new agent for each connection attempt to avoid connection reuse
- let agent = AgentBuilder::new()
- .timeout_read(self.timeout)
- .timeout_write(self.timeout)
- .user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36")
- .try_proxy_from_env(false)
- .redirects(4)
- .build();
-
- // Build a request with browser-like headers
- let request = agent.get(&url)
- // Common headers
- .set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8")
- .set("Accept-Language", "en-US,en;q=0.9")
- .set("Accept-Encoding", "gzip, deflate, br")
- .set("Cache-Control", "max-age=0")
- .set("Connection", "keep-alive")
- .set("Upgrade-Insecure-Requests", "1")
- .set("DNT", "1")
- // Security headers
- .set("Sec-Fetch-Dest", "document")
- .set("Sec-Fetch-Mode", "navigate")
- .set("Sec-Fetch-Site", "none")
- .set("Sec-Fetch-User", "?1")
- // Chrome-specific headers
- .set("Sec-Ch-Ua", "\"Chromium\";v=\"122\", \"Not(A:Brand\";v=\"24\", \"Google Chrome\";v=\"122\"")
- .set("Sec-Ch-Ua-Mobile", "?0")
- .set("Sec-Ch-Ua-Platform", "\"Windows\"");
-
- match request.call() {
- Ok(response) => {
- // Check redirect
- let initial_url = url.to_lowercase();
- let final_url = response.get_url().to_lowercase();
-
- if initial_url != final_url {
- println!("DEBUG: Redirected from {} to {}", initial_url, final_url);
-
- let initial_domain = extract_domain(&initial_url);
- let final_domain = extract_domain(&final_url);
-
- if initial_domain != final_domain && is_block_page_url(&final_url) {
- println!(
- "DEBUG: Detected redirect to potential block page: {}",
- final_url
- );
- return Ok(ConnectionResult::ISPBlock);
- }
- }
-
- // Check response content
- match response.into_string() {
- Ok(body) => {
- if is_block_page_content(&body) {
- println!("DEBUG: Detected block page content");
- Ok(ConnectionResult::ISPBlock)
- } else {
- Ok(ConnectionResult::Success)
- }
- }
- Err(e) => {
- println!("DEBUG: Error reading response body: {}", e);
- Ok(ConnectionResult::ConnectionReset)
- }
- }
- }
- Err(UreqError::Status(code, response)) => {
- println!("DEBUG: HTTP error status: {}", code);
-
- if (300..400).contains(&code) {
- if let Some(location) = response.header("location") {
- if is_block_page_url(location) {
- println!("DEBUG: Detected redirect to block page: {}", location);
- return Ok(ConnectionResult::ISPBlock);
- }
- }
- }
- Ok(ConnectionResult::ConnectionReset)
- }
- Err(UreqError::Transport(transport)) => {
- println!("DEBUG: Transport error: {}", transport);
- handle_transport_error(&transport)
- }
- }
- }
-}
-
-fn handle_transport_error(transport: &Transport) -> AppResult {
- match transport.kind() {
- UreqErrorKind::Io => {
- let err_string = transport.to_string().to_lowercase();
- if err_string.contains("timed out") || err_string.contains("timeout") {
- return Ok(ConnectionResult::Timeout);
- } else if err_string.contains("connection refused")
- || err_string.contains("connection reset")
- || err_string.contains("connection aborted")
- {
- return Ok(ConnectionResult::ConnectionReset);
- } else if err_string.contains("not found")
- || err_string.contains("name resolution failed")
- || err_string.contains("no such host")
- {
- return Ok(ConnectionResult::NoConnection);
- }
- println!("DEBUG: Other IO error: {}", transport);
- Ok(ConnectionResult::ConnectionReset)
- }
- UreqErrorKind::UnknownScheme | UreqErrorKind::InvalidUrl => {
- println!("DEBUG: Network error: {:?}", transport.kind());
- Ok(ConnectionResult::NoConnection)
- }
- _ => {
- println!("DEBUG: Other transport error: {:?}", transport.kind());
- Ok(ConnectionResult::ConnectionReset)
- }
- }
-}
-
-fn is_block_page_url(url: &str) -> bool {
- let url_lower = url.to_lowercase();
- url_lower.contains("block")
- || url_lower.contains("warning")
- || url_lower.contains("blocked")
- || url_lower.contains("rkn")
- || url_lower.contains("restriction")
-}
-
-fn is_block_page_content(body: &str) -> bool {
- let body_lower = body.to_lowercase();
- body_lower.contains("заблокирован")
- || body_lower.contains("доступ ограничен")
- || body_lower.contains("access denied")
- || body_lower.contains("blocked by")
- || body_lower.contains("webmaster@rkn.gov.ru")
-}
-
-fn extract_domain(url: &str) -> String {
- let without_protocol = url.split("://").nth(1).unwrap_or(url);
- without_protocol
- .split('/')
- .next()
- .unwrap_or(without_protocol)
- .to_string()
-}
-
-#[derive(Debug, PartialEq)]
-enum ConnectionResult {
- Success,
- ConnectionReset,
- Timeout,
- NoConnection,
- ISPBlock,
-}
-#[allow(unused)]
-#[derive(Debug, PartialEq)]
-pub enum DPITestResult {
- NoDPI,
- DPIDetected,
- ISPBlocked,
- NoConnection,
- Unclear,
-}
-
-impl DPITestResult {
- pub fn to_english_string(&self) -> String {
- match self {
- DPITestResult::NoDPI => "DPI not found, site available directly".to_string(),
- DPITestResult::DPIDetected => "DPI locking found".to_string().to_uppercase(),
- DPITestResult::ISPBlocked => "Site locked by your internet provider"
- .to_string()
- .to_uppercase(),
- DPITestResult::NoConnection => "No connection with site".to_string(),
- DPITestResult::Unclear => "Check result is unclear".to_string(),
- }
- }
-}
diff --git a/preconfig_tester/src/process.rs b/preconfig_tester/src/process.rs
deleted file mode 100644
index 59c5ad8..0000000
--- a/preconfig_tester/src/process.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-use crate::error::AppResult;
-use std::path::Path;
-use std::process::{Child, Command, Stdio};
-use std::thread::sleep;
-use std::time::{Duration, Instant};
-use sysinfo::{ProcessRefreshKind, ProcessesToUpdate, RefreshKind, System};
-
-pub struct ProcessManager {
- sys: System,
-}
-
-impl ProcessManager {
- pub fn new() -> Self {
- Self {
- sys: System::new_with_specifics(
- RefreshKind::new().with_processes(ProcessRefreshKind::everything()),
- ),
- }
- }
-
- pub fn run_batch_file(&self, batch_file: &Path) -> std::io::Result {
- Command::new("cmd")
- .args(["/C", &batch_file.to_string_lossy()])
- .stdout(Stdio::null())
- .stderr(Stdio::null())
- .spawn()
- }
-
- pub fn wait_for_process(&mut self, process_name: &str, timeout: Duration) -> bool {
- let start = Instant::now();
-
- while start.elapsed() < timeout {
- self.sys.refresh_processes(ProcessesToUpdate::All, true);
-
- if self
- .sys
- .processes()
- .values()
- .any(|process| process.name() == process_name)
- {
- return true;
- }
-
- sleep(Duration::from_millis(500));
- }
-
- false
- }
-
- pub fn cleanup_process(&mut self, child: &mut Child, process_name: &str) -> AppResult<()> {
- // First try to kill the child process
- let _ = child.kill();
- sleep(Duration::from_millis(500));
-
- // Then ensure the named process is terminated
- self.ensure_process_terminated(process_name);
- Ok(())
- }
-
- pub fn ensure_process_terminated(&mut self, process_name: &str) {
- for _ in 0..3 {
- // Try up to 3 times
- self.sys.refresh_processes(ProcessesToUpdate::All, true);
- let processes = self
- .sys
- .processes()
- .values()
- .filter(|process| process.name() == process_name)
- .collect::>();
-
- if processes.is_empty() {
- return; // Process is gone, we're done
- }
-
- // Kill all instances of the process
- for process in processes {
- let _ = process.kill();
- }
-
- sleep(Duration::from_millis(200)); // Wait a bit before checking again
- }
- }
-}
diff --git a/preconfig_tester/src/utils.rs b/preconfig_tester/src/utils.rs
deleted file mode 100644
index 15b52f5..0000000
--- a/preconfig_tester/src/utils.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-use std::{io, mem};
-use std::mem::MaybeUninit;
-use std::process::Command;
-use std::thread::sleep;
-use std::time::Duration;
-use winapi::shared::minwindef::DWORD;
-use winapi::um::processthreadsapi::{GetCurrentProcess, OpenProcessToken};
-use winapi::um::securitybaseapi::GetTokenInformation;
-use winapi::um::winnt::{TokenElevation, TOKEN_ELEVATION, TOKEN_QUERY};
-use crate::TokenHandle;
-
-pub fn is_elevated() -> bool {
- if !cfg!(target_os = "windows") {
- return false;
- }
-
- unsafe {
- let mut token = MaybeUninit::uninit();
- let status = OpenProcessToken(
- GetCurrentProcess(),
- TOKEN_QUERY,
- token.as_mut_ptr()
- );
-
- if status == 0 {
- return false;
- }
-
- let token = TokenHandle(token.assume_init());
- let mut elevation = TOKEN_ELEVATION { TokenIsElevated: 0 };
- let mut size: DWORD = 0;
- let elevation_ptr: *mut TOKEN_ELEVATION = &mut elevation;
-
- let status = GetTokenInformation(
- token.0,
- TokenElevation,
- elevation_ptr as *mut _,
- mem::size_of::() as DWORD,
- &mut size,
- );
-
- if status != 0 {
- elevation.TokenIsElevated != 0
- } else {
- false
- }
- }
-}
-
-pub fn request_elevation() -> io::Result<()> {
- let executable = std::env::current_exe()?;
- if let Some(executable) = executable.to_str() {
- let marker_path = std::env::temp_dir().join("bypass_checker_elevated.tmp");
-
- if marker_path.exists() {
- std::fs::remove_file(marker_path)?;
- return Err(io::Error::new(
- io::ErrorKind::PermissionDenied,
- "Failed to obtain admin privileges",
- ));
- }
-
- std::fs::write(&marker_path, "")?;
-
- let quoted_executable = format!("\"{}\"", executable);
- // Use start /b to prevent new console window creation and run PowerShell hidden
- let spawn_result = Command::new("cmd")
- .args([
- "/C",
- "start",
- "/b",
- "powershell",
- "-WindowStyle",
- "Hidden",
- "-Command",
- &format!(
- "Start-Process -FilePath {} -ArgumentList '--elevated' -Verb RunAs",
- quoted_executable
- ),
- ])
- .spawn();
-
- match &spawn_result {
- Ok(_) => {
- // Small delay to ensure the new process has started
- sleep(Duration::from_millis(300));
- Ok(())
- }
- Err(e) => {
- let _ = std::fs::remove_file(marker_path);
- Err(io::Error::new(e.kind(), e.to_string()))
- }
- }
- } else {
- Err(io::Error::new(
- io::ErrorKind::InvalidInput,
- "Invalid executable path",
- ))
- }
-}
diff --git a/run_preconfig/Cargo.toml b/run_preconfig/Cargo.toml
deleted file mode 100644
index f0c5356..0000000
--- a/run_preconfig/Cargo.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-[package]
-name = "run_preconfig"
-edition = "2021"
-version.workspace = true
-
-[package.metadata.winresource]
-LegalCopyright = "2024 by ANKDDEV"
-OriginalFilename = "zapret_run_preconfig.exe"
-
-[dependencies]
-crossterm.workspace = true
-ctrlc = "3.4.1"
-shared = { path = "../shared" }
-
-[build-dependencies]
-winresource.workspace = true
diff --git a/run_preconfig/build.rs b/run_preconfig/build.rs
deleted file mode 100644
index 3f8aace..0000000
--- a/run_preconfig/build.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use std::io;
-use winresource::WindowsResource;
-
-fn main() -> io::Result<()> {
- if cfg!(target_os = "windows") {
- let mut res = WindowsResource::new();
- res.set_icon("icon.ico")
- .set("InternalName", "Run pre-config for Zapret DPI by ANKDDEV");
-
- res.compile()?;
- }
-
- Ok(())
-}
diff --git a/run_preconfig/icon.ico b/run_preconfig/icon.ico
deleted file mode 100644
index a69b289..0000000
Binary files a/run_preconfig/icon.ico and /dev/null differ
diff --git a/run_preconfig/src/main.rs b/run_preconfig/src/main.rs
deleted file mode 100644
index 2a36d75..0000000
--- a/run_preconfig/src/main.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-mod ui;
-mod utils;
-
-use std::io::{self, stdout};
-use shared::terminal::{self, cleanup_terminal, setup_terminal_cleanup};
-use ui::print_welcome_message;
-use utils::get_options;
-
-fn main() -> io::Result<()> {
- setup_terminal_cleanup();
- let mut stdout = stdout();
-
- // Initialize terminal
- terminal::init(&mut stdout)?;
-
- // Get terminal size early
- let (_, term_height) = terminal::get_size()?;
-
- // Print welcome messages and get the starting line
- let current_line = print_welcome_message();
-
- // Get the list of .bat files and add options
- let options = get_options();
- if options.is_empty() {
- println!("Can't find any BAT files in current directory.");
- cleanup_terminal()?;
- return Ok(());
- }
-
- ui::run_main_loop(&mut stdout, &options, current_line, term_height)?;
-
- terminal::cleanup_and_exit(&mut stdout)?;
- Ok(())
-}
diff --git a/run_preconfig/src/ui.rs b/run_preconfig/src/ui.rs
deleted file mode 100644
index f2588ca..0000000
--- a/run_preconfig/src/ui.rs
+++ /dev/null
@@ -1,297 +0,0 @@
-use crossterm::{
- cursor,
- event::{self, Event, KeyCode},
- execute,
- style::{Color, Print, ResetColor, SetForegroundColor},
- terminal::{Clear, ClearType},
-};
-use std::io::{self, Write};
-use std::process::Command;
-use std::time::{Duration, Instant};
-
-#[derive(Debug)]
-pub enum KeyAction {
- Exit,
- Select,
- None,
-}
-
-pub fn print_welcome_message() -> usize {
- let mut current_line = 0;
- println!("Welcome!");
- current_line += 1;
- println!("This program can run any pre-config (BAT file).");
- current_line += 1;
- println!("Author: ANKDDEV https://github.com/ankddev");
- current_line += 1;
- println!("Version: {}", env!("CARGO_PKG_VERSION"));
- current_line += 1;
- println!("===");
- current_line += 2;
- println!("Using ARROWS on your keyboard, select BAT file from list for running it.\n");
- println!("For selection press ENTER.");
- current_line += 2;
- current_line
-}
-
-pub fn render_options(
- stdout: &mut impl Write,
- options: &[String],
- current_selection: usize,
- start_row: usize,
- scroll_offset: usize,
- max_visible_options: usize,
-) -> io::Result<()> {
- const MARKER: &str = "►";
- const EMPTY_MARKER: &str = " ";
- const SPACING: &str = " ";
-
- let visible_options = max_visible_options.saturating_sub(2);
- let total_options = options.len();
-
- let end_index = (scroll_offset + visible_options).min(total_options);
- let visible_range = scroll_offset..end_index;
-
- // Clear the options area only once
- execute!(
- stdout,
- cursor::MoveTo(0, start_row as u16),
- Clear(ClearType::FromCursorDown)
- )?;
-
- let mut current_row = start_row;
-
- // Build output buffer to minimize writes
- let mut output_buffer = Vec::new();
-
- // Up scroll indicator
- if scroll_offset > 0 {
- execute!(
- output_buffer,
- cursor::MoveTo(0, current_row as u16),
- SetForegroundColor(Color::DarkGrey),
- Print("↑ More options above"),
- ResetColor
- )?;
- current_row += 1;
- }
-
- // Display visible options
- for (index, option) in options.iter().enumerate() {
- if visible_range.contains(&index) {
- execute!(output_buffer, cursor::MoveTo(0, current_row as u16))?;
-
- if index == current_selection {
- execute!(
- output_buffer,
- SetForegroundColor(Color::Cyan),
- Print(MARKER),
- Print(SPACING),
- Print(option),
- ResetColor
- )?;
- } else {
- execute!(
- output_buffer,
- Print(EMPTY_MARKER),
- Print(SPACING),
- Print(option)
- )?;
- }
-
- current_row += 1;
- }
- }
-
- // Down scroll indicator
- if end_index < total_options {
- execute!(
- output_buffer,
- cursor::MoveTo(0, current_row as u16),
- SetForegroundColor(Color::DarkGrey),
- Print("↓ More options below"),
- ResetColor
- )?;
- }
-
- // Write the entire buffer at once
- stdout.write_all(&output_buffer)?;
- stdout.flush()?;
-
- Ok(())
-}
-
-pub fn handle_key_event(
- key: KeyCode,
- current_selection: &mut usize,
- scroll_offset: &mut usize,
- total_options: usize,
- max_visible_options: usize,
-) -> Option {
- let visible_options = max_visible_options.saturating_sub(2);
-
- match key {
- KeyCode::Up if *current_selection > 0 => {
- *current_selection -= 1;
- if *current_selection < *scroll_offset {
- *scroll_offset = *current_selection;
- }
- Some(KeyAction::None)
- }
- KeyCode::Down if *current_selection < total_options - 1 => {
- *current_selection += 1;
- if *current_selection >= *scroll_offset + visible_options {
- *scroll_offset = current_selection.saturating_sub(visible_options - 1);
- }
- Some(KeyAction::None)
- }
- KeyCode::PageUp => {
- *current_selection = current_selection.saturating_sub(visible_options);
- *scroll_offset = scroll_offset.saturating_sub(visible_options);
- Some(KeyAction::None)
- }
- KeyCode::PageDown => {
- *current_selection = (*current_selection + visible_options).min(total_options - 1);
- *scroll_offset = (*scroll_offset + visible_options)
- .min(total_options.saturating_sub(visible_options));
- Some(KeyAction::None)
- }
- KeyCode::Enter => Some(KeyAction::Select),
- KeyCode::Esc => Some(KeyAction::Exit),
- _ => None,
- }
-}
-
-pub fn handle_selection(
- stdout: &mut impl Write,
- options: &[String],
- current_selection: usize,
- message_row: usize,
-) -> io::Result<()> {
- execute!(
- stdout,
- cursor::MoveTo(0, message_row as u16),
- Clear(ClearType::FromCursorDown)
- )?;
- stdout.flush()?;
-
- let selected_file = &options[current_selection][..];
- let current_dir = std::env::current_dir()?;
- let sub_dir = current_dir.join("pre-configs");
- let bat_file_path = sub_dir.join(selected_file);
- let output = Command::new(bat_file_path)
- .output()
- .map_err(|e| {
- io::Error::new(
- io::ErrorKind::Other,
- format!("Failed to execute command: {}", e),
- )
- })
- .expect("Failed to execute command");
- return if output.status.success() {
- Ok(())
- } else {
- let error_message = String::from_utf8_lossy(&output.stderr).into_owned();
-
- let error_message = if error_message.is_empty() {
- String::from_utf8_lossy(&output.stdout).into_owned()
- } else {
- error_message
- };
-
- let error_message = if error_message.is_empty() {
- "Unknown error occured while executing command".to_string()
- } else {
- error_message
- };
-
- Err(io::Error::new(io::ErrorKind::Other, error_message))
- };
-}
-
-pub fn run_main_loop(
- stdout: &mut impl Write,
- options: &[String],
- start_row: usize,
- term_height: u16,
-) -> io::Result<()> {
- let mut current_selection = 0;
- let mut scroll_offset = 0;
- let max_visible_options = std::cmp::min(15, term_height as usize - start_row - 3);
-
- let mut last_event_time = Instant::now();
- let mut last_render_time = Instant::now();
-
- // Define frame timing constants
- const FRAME_TIME: Duration = Duration::from_millis(33); // ~30 FPS
- const KEY_REPEAT_DELAY: Duration = Duration::from_millis(150);
- const EVENT_POLL_TIMEOUT: Duration = Duration::from_millis(16); // ~60 FPS polling
-
- // Initial render
- render_options(
- stdout,
- options,
- current_selection,
- start_row,
- scroll_offset,
- max_visible_options,
- )?;
-
- let mut needs_render = false;
-
- loop {
- let now = Instant::now();
-
- // Only poll for events if enough time has passed
- if event::poll(EVENT_POLL_TIMEOUT)? {
- if let Event::Key(event) = event::read()? {
- if now.duration_since(last_event_time) >= KEY_REPEAT_DELAY {
- match handle_key_event(
- event.code,
- &mut current_selection,
- &mut scroll_offset,
- options.len(),
- max_visible_options,
- ) {
- Some(KeyAction::Exit) => break,
- Some(KeyAction::Select) => {
- handle_selection(
- stdout,
- options,
- current_selection,
- start_row + max_visible_options + 1,
- )?;
- break;
- }
- Some(KeyAction::None) => {
- needs_render = true;
- }
- None => {}
- }
- last_event_time = now;
- }
- }
- }
-
- // Only render if needed and enough time has passed since last render
- if needs_render && now.duration_since(last_render_time) >= FRAME_TIME {
- render_options(
- stdout,
- options,
- current_selection,
- start_row,
- scroll_offset,
- max_visible_options,
- )?;
- last_render_time = now;
- needs_render = false;
- }
-
- // Sleep for a small duration to prevent busy waiting
- if !needs_render {
- std::thread::sleep(Duration::from_millis(1));
- }
- }
-
- Ok(())
-}
diff --git a/run_preconfig/src/utils.rs b/run_preconfig/src/utils.rs
deleted file mode 100644
index dcf626d..0000000
--- a/run_preconfig/src/utils.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-use std::{env, fs};
-
-pub fn get_options() -> Vec {
- let current_dir = env::current_dir().expect("Failed to get current directory");
- let sub_dir = current_dir.join("pre-configs");
- let mut options = vec![];
-
- if let Ok(read_dir) = fs::read_dir(&sub_dir) {
- let mut bat_files: Vec = read_dir
- .filter_map(|entry| {
- entry.ok().and_then(|e| {
- let path = e.path();
- if path.extension().and_then(|ext| ext.to_str()) == Some("bat") {
- path.file_name().and_then(|n| n.to_str()).map(String::from)
- } else {
- None
- }
- })
- })
- .collect();
-
- bat_files.sort_by(|a, b| custom_sort(a, b));
- options.extend(bat_files);
- }
-
- options
-}
-
-fn custom_sort(a: &str, b: &str) -> std::cmp::Ordering {
- // Split filenames into components for hierarchical sorting
- let (a_base, a_variant, a_provider, a_has_provider) = split_filename(a);
- let (b_base, b_variant, b_provider, b_has_provider) = split_filename(b);
-
- // First compare by base name
- match a_base.cmp(&b_base) {
- std::cmp::Ordering::Equal => {
- // Same base name, compare variants
- match a_variant.cmp(&b_variant) {
- std::cmp::Ordering::Equal => {
- // Same variant, non-provider version comes first
- match (a_has_provider, b_has_provider) {
- (false, true) => std::cmp::Ordering::Less,
- (true, false) => std::cmp::Ordering::Greater,
- // Both have or don't have providers, sort by provider name
- _ => a_provider.cmp(&b_provider),
- }
- }
- // Different variants
- other => other,
- }
- }
- // Different base names
- other => other,
- }
-}
-
-fn split_filename(name: &str) -> (String, String, String, bool) {
- let without_ext = name.trim_end_matches(".bat");
-
- // Split into base name and parentheses part
- let (main_part, parentheses) = match without_ext.find('(') {
- Some(idx) => (&without_ext[..idx - 1], &without_ext[idx..]),
- None => (without_ext, ""),
- };
-
- // Split main part into components by underscore
- let parts: Vec<&str> = main_part.split('_').collect();
- let base = parts[0].to_string();
-
- // Get variant part (ALT, v2, etc)
- let variant = parts.get(1..).map_or(String::new(), |p| p.join("_"));
-
- // Check if it's a provider variant
- let has_provider = !parentheses.is_empty();
-
- (base, variant, parentheses.to_string(), has_provider)
-}
diff --git a/scripts/build.bat b/scripts/build.bat
new file mode 100644
index 0000000..97d97e5
--- /dev/null
+++ b/scripts/build.bat
@@ -0,0 +1 @@
+go run scripts\build.go
diff --git a/scripts/build.go b/scripts/build.go
new file mode 100644
index 0000000..d0aab29
--- /dev/null
+++ b/scripts/build.go
@@ -0,0 +1,211 @@
+package main
+
+import (
+ "archive/zip"
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+
+ "github.com/cli/safeexec"
+)
+
+func main() {
+ if !isWindows() {
+ os.Exit(1)
+ }
+
+ fmt.Println("Building...")
+ ldflags := os.Getenv("GO_LDFLAGS")
+ ldflags = fmt.Sprintf("-X main.version=%s %s", version(), ldflags)
+ _ = os.Mkdir("build", os.ModePerm)
+ err := run("go", "build", "-ldflags", ldflags, "-o", "build", "./cmd/...")
+ if err != nil {
+ fmt.Println("Build failed:", err)
+ os.Exit(1)
+ }
+
+ // Get current directory
+ currentDir, err := os.Getwd()
+ if err != nil {
+ fmt.Printf("Error getting current directory: %v\n", err)
+ os.Exit(1)
+ }
+
+ // Define paths
+ buildDir := filepath.Join(currentDir, "build")
+ // projectDir := filepath.Dir(currentDir)
+ projectDir := currentDir
+ binDir := filepath.Join(projectDir, "bin")
+ listsDir := filepath.Join(projectDir, "lists")
+ preConfigsDir := filepath.Join(projectDir, "pre-configs")
+ resourcesDir := filepath.Join(projectDir, "resources")
+
+ // Check required paths exist
+ requiredPaths := []string{
+ buildDir,
+ listsDir,
+ preConfigsDir,
+ resourcesDir,
+ }
+
+ for _, path := range requiredPaths {
+ if _, err := os.Stat(path); os.IsNotExist(err) {
+ fmt.Printf("Required directory not found: %s\n", path)
+ os.Exit(1)
+ }
+ }
+
+ // Create zip file
+ zipPath := filepath.Join(buildDir, "zapret-discord-youtube-ankddev.zip")
+ zipFile, err := os.Create(zipPath)
+ if err != nil {
+ fmt.Printf("Error creating zip file: %v\n", err)
+ os.Exit(1)
+ }
+ defer zipFile.Close()
+
+ zipWriter := zip.NewWriter(zipFile)
+ defer zipWriter.Close()
+
+ // Add directories to zip
+ dirsToAdd := map[string]string{
+ "lists": listsDir,
+ "pre-configs": preConfigsDir,
+ "bin": binDir,
+ }
+
+ fmt.Println("[1/3] Adding directories...")
+ for zipPath, fsPath := range dirsToAdd {
+ err = addDirToZip(zipWriter, zipPath, fsPath)
+ if err != nil {
+ fmt.Printf("Error adding directory %s to zip: %v\n", fsPath, err)
+ os.Exit(1)
+ }
+ }
+
+ // Add individual files
+ fmt.Println("[2/3] Adding files...")
+ filesToAdd := map[string]string{
+ "___README.TXT": filepath.Join(resourcesDir, "___README.TXT"),
+ "blockcheck.cmd": filepath.Join(resourcesDir, "blockcheck.cmd"),
+ "Add to autorun.exe": filepath.Join(buildDir, "add_to_autorun.exe"),
+ "Automatically search pre-config.exe": filepath.Join(buildDir, "preconfig_tester.exe"),
+ "Run pre-config.exe": filepath.Join(buildDir, "run_preconfig.exe"),
+ "Set domain list.exe": filepath.Join(buildDir, "select_domains.exe"),
+ }
+
+ for zipPath, fsPath := range filesToAdd {
+ err = addFileToZip(zipWriter, zipPath, fsPath)
+ if err != nil {
+ fmt.Printf("Error adding file %s to zip: %v\n", fsPath, err)
+ os.Exit(1)
+ }
+ }
+
+ fmt.Println("[3/3] Release archive created successfully!")
+ fmt.Printf("\nRelease build ready! Check '%s'\n", zipPath)
+ fmt.Println("Press Enter to continue...")
+ fmt.Scanln()
+}
+
+func addDirToZip(zipWriter *zip.Writer, zipPath string, fsPath string) error {
+ return filepath.Walk(fsPath, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ // Get zip path for file
+ relativePath, err := filepath.Rel(fsPath, path)
+ if err != nil {
+ return err
+ }
+ zipEntryPath := filepath.Join(zipPath, relativePath)
+
+ if info.IsDir() {
+ return nil
+ }
+
+ return addFileToZip(zipWriter, zipEntryPath, path)
+ })
+}
+
+func addFileToZip(zipWriter *zip.Writer, zipPath string, fsPath string) error {
+ file, err := os.Open(fsPath)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ writer, err := zipWriter.Create(zipPath)
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(writer, file)
+ return err
+}
+
+// version returns version from environment variable or git describe
+func version() string {
+ if versionEnv := os.Getenv("VERSION"); versionEnv != "" {
+ return versionEnv
+ }
+ if desc, err := cmdOutput("git", "describe", "--tags"); err == nil {
+ return desc
+ }
+ rev, _ := cmdOutput("git", "rev-parse", "--short", "HEAD")
+ return rev
+}
+
+func cmdOutput(args ...string) (string, error) {
+ exe, err := safeexec.LookPath(args[0])
+ if err != nil {
+ return "", err
+ }
+ cmd := exec.Command(exe, args[1:]...)
+ cmd.Stderr = io.Discard
+ out, err := cmd.Output()
+ return strings.TrimSuffix(string(out), "\n"), err
+}
+
+func isWindows() bool {
+ if os.Getenv("GOOS") == "windows" {
+ return true
+ }
+ if runtime.GOOS == "windows" {
+ return true
+ }
+ return false
+}
+
+func run(args ...string) error {
+ exe, err := safeexec.LookPath(args[0])
+ if err != nil {
+ return err
+ }
+ announce(args...)
+ cmd := exec.Command(exe, args[1:]...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ return cmd.Run()
+}
+
+func announce(args ...string) {
+ fmt.Println(shellInspect(args))
+}
+
+func shellInspect(args []string) string {
+ fmtArgs := make([]string, len(args))
+ for i, arg := range args {
+ if strings.ContainsAny(arg, " \t'\"") {
+ fmtArgs[i] = fmt.Sprintf("%q", arg)
+ } else {
+ fmtArgs[i] = arg
+ }
+ }
+ return strings.Join(fmtArgs, " ")
+}
diff --git a/select_domains/Cargo.toml b/select_domains/Cargo.toml
deleted file mode 100644
index f25790a..0000000
--- a/select_domains/Cargo.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-name = "select_domains"
-version.workspace = true
-edition = "2021"
-build = "build.rs"
-
-[package.metadata.winresource]
-LegalCopyright = "2024 by ANKDDEV"
-OriginalFilename = "zapret_select_domains.exe"
-
-[dependencies]
-crossterm.workspace = true
-
-[build-dependencies]
-winresource.workspace = true
diff --git a/select_domains/build.rs b/select_domains/build.rs
deleted file mode 100644
index 4687ba6..0000000
--- a/select_domains/build.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use std::io;
-use winresource::WindowsResource;
-
-fn main() -> io::Result<()> {
- if cfg!(target_os = "windows") {
- let mut res = WindowsResource::new();
- res.set_icon("icon.ico")
- .set("InternalName", "Select domains for Zapret DPI by ANKDDEV");
-
- res.compile()?;
- }
-
- Ok(())
-}
diff --git a/select_domains/icon.ico b/select_domains/icon.ico
deleted file mode 100644
index 24ae303..0000000
Binary files a/select_domains/icon.ico and /dev/null differ
diff --git a/select_domains/src/main.rs b/select_domains/src/main.rs
deleted file mode 100644
index dee8763..0000000
--- a/select_domains/src/main.rs
+++ /dev/null
@@ -1,320 +0,0 @@
-use crossterm::{
- cursor::{self, Hide, Show},
- event::{self, Event, KeyCode, KeyEvent, KeyModifiers},
- execute, queue,
- style::Stylize,
- terminal::{self, ClearType, EnterAlternateScreen, LeaveAlternateScreen},
-};
-use std::fs::{self, File};
-use std::io::{self, Read, Write};
-use std::path::Path;
-use std::thread;
-use std::time::Duration;
-
-#[derive(Debug)]
-struct FileEntry {
- name: String,
- selected: bool,
- is_control: bool,
-}
-
-const VISIBLE_ITEMS: usize = 15;
-const HEADER_LINES: usize = 5; // Header text + empty line + control buttons + empty line + separator
-const SCROLL_AREA_HEIGHT: usize = VISIBLE_ITEMS + 2; // +2 for scroll indicators
-
-fn main() -> io::Result<()> {
- terminal::enable_raw_mode()?;
- let mut stdout = io::stdout();
- execute!(stdout, EnterAlternateScreen, Hide)?;
-
- let result = run_app(&mut stdout);
-
- execute!(stdout, Show, LeaveAlternateScreen)?;
- terminal::disable_raw_mode()?;
-
- result
-}
-
-fn draw_screen(
- stdout: &mut io::Stdout,
- entries: &[FileEntry],
- current_index: usize,
- scroll_offset: usize,
- clear_screen: bool,
-) -> io::Result<()> {
- if clear_screen {
- queue!(stdout, terminal::Clear(ClearType::All))?;
- }
-
- queue!(stdout, cursor::MoveTo(0, 0))?;
-
- // Header section
- writeln!(
- stdout,
- "Use ↑↓ (arrows) for navigation, SPACE or ↵ (ENTER) to select\n"
- )?;
-
- // Draw control options first
- let control_entries: Vec<_> = entries
- .iter()
- .enumerate()
- .filter(|(_, entry)| entry.is_control)
- .collect();
-
- for (index, entry) in &control_entries {
- let name = if entry.name == "SAVE LIST" {
- "SAVE LIST"
- } else {
- "CANCEL"
- };
-
- let line = format!(
- "{} {}",
- if *index == current_index { ">" } else { " " },
- name
- );
-
- if *index == current_index {
- writeln!(stdout, "{}", line.reverse().cyan())?;
- } else {
- writeln!(stdout, "{}", line)?;
- }
- }
-
- writeln!(stdout)?; // Extra empty line after control options
- writeln!(stdout)?; // Separator line
-
- // Clear the scroll area
- for _ in 0..SCROLL_AREA_HEIGHT {
- writeln!(stdout, "{}", " ".repeat(50))?; // Clear line with spaces
- }
-
- // Move back to start of scroll area
- queue!(stdout, cursor::MoveTo(0, HEADER_LINES as u16))?;
-
- // Get file entries (non-control entries)
- let file_entries: Vec<_> = entries
- .iter()
- .enumerate()
- .filter(|(_, entry)| !entry.is_control)
- .collect();
-
- let total_files = file_entries.len();
- let visible_end = scroll_offset.saturating_add(VISIBLE_ITEMS).min(total_files);
-
- // Show scroll indicator if needed
- if scroll_offset > 0 {
- writeln!(stdout, " ↑ Scroll up for more files")?;
- } else {
- writeln!(stdout)?; // Keep spacing consistent
- }
-
- // Draw visible file entries
- let visible_entries = &file_entries[scroll_offset..visible_end];
- for entry in visible_entries {
- let real_index = entries.iter().position(|e| e.name == entry.1.name).unwrap();
- let line = format!(
- "{} {} {}",
- if real_index == current_index {
- ">"
- } else {
- " "
- },
- if entry.1.selected { "[+]" } else { "[ ]" },
- entry.1.name
- );
-
- if real_index == current_index {
- writeln!(stdout, "{}", line.reverse())?;
- } else {
- writeln!(stdout, "{}", line)?;
- }
- }
-
- // Move to the bottom scroll indicator position
- queue!(
- stdout,
- cursor::MoveTo(0, (HEADER_LINES + VISIBLE_ITEMS + 1) as u16)
- )?;
-
- // Show scroll indicator if needed
- if visible_end < total_files {
- writeln!(stdout, " ↓ Scroll down for more files")?;
- }
-
- stdout.flush()
-}
-
-fn join_selected_files(lists_dir: &Path, selected_entries: &[&FileEntry]) -> io::Result<()> {
- let ultimate_path = lists_dir.join("list-ultimate.txt");
- let mut ultimate_file = File::create(ultimate_path)?;
-
- for entry in selected_entries {
- let file_path = lists_dir.join(&entry.name);
- if file_path.exists() {
- let mut content = String::new();
- File::open(&file_path)?.read_to_string(&mut content)?;
-
- // Write the content
- writeln!(ultimate_file, "{}", content.trim())?;
- }
- }
-
- Ok(())
-}
-
-fn run_app(stdout: &mut io::Stdout) -> io::Result<()> {
- let lists_dir = Path::new("lists");
- if !lists_dir.exists() {
- fs::create_dir(lists_dir)?;
- }
-
- let config_path = lists_dir.join("selected.txt");
- let mut selected_files = Vec::new();
- if config_path.exists() {
- let mut content = String::new();
- File::open(&config_path)?.read_to_string(&mut content)?;
- selected_files = content.lines().map(String::from).collect();
- }
-
- // Create control entries first
- let mut entries = vec![
- FileEntry {
- name: String::from("SAVE LIST"),
- selected: false,
- is_control: true,
- },
- FileEntry {
- name: String::from("CANCEL"),
- selected: false,
- is_control: true,
- },
- ];
-
- // Add file entries
- let mut file_entries: Vec = fs::read_dir(lists_dir)?
- .filter_map(|entry| {
- let entry = entry.ok()?;
- let name = entry.file_name().into_string().ok()?;
- if name.starts_with("list-") && name.ends_with(".txt") && name != "list-ultimate.txt" {
- Some(FileEntry {
- name: name.clone(),
- selected: selected_files.contains(&name),
- is_control: false,
- })
- } else {
- None
- }
- })
- .collect();
-
- file_entries.sort_by(|a, b| a.name.cmp(&b.name));
- entries.extend(file_entries);
-
- let mut current_index = 0;
- let mut scroll_offset = 0;
- let num_control_entries = entries.iter().filter(|e| e.is_control).count();
-
- draw_screen(stdout, &entries, current_index, scroll_offset, true)?;
-
- 'main: loop {
- if let Ok(true) = event::poll(Duration::from_millis(16)) {
- if let Ok(Event::Key(key)) = event::read() {
- let mut redraw = true;
-
- match key {
- KeyEvent {
- code: KeyCode::Up,
- kind: event::KeyEventKind::Press,
- ..
- } => {
- if current_index > 0 {
- current_index -= 1;
- if current_index >= num_control_entries {
- let file_index = current_index - num_control_entries;
- if scroll_offset > file_index {
- scroll_offset = file_index;
- }
- }
- }
- }
- KeyEvent {
- code: KeyCode::Down,
- kind: event::KeyEventKind::Press,
- ..
- } => {
- if current_index < entries.len() - 1 {
- current_index += 1;
- if current_index >= num_control_entries {
- let file_index = current_index - num_control_entries;
- if file_index >= scroll_offset + VISIBLE_ITEMS {
- scroll_offset = file_index - VISIBLE_ITEMS + 1;
- }
- }
- }
- }
- KeyEvent {
- code: KeyCode::Char(' ') | KeyCode::Enter,
- kind: event::KeyEventKind::Press,
- ..
- } => {
- match entries[current_index].name.as_str() {
- "SAVE LIST" => {
- // Save selected files to config
- let mut file = File::create(&config_path)?;
- let selected_entries: Vec<_> = entries
- .iter()
- .filter(|e| e.selected && !e.is_control)
- .collect();
-
- for entry in &selected_entries {
- writeln!(file, "{}", entry.name)?;
- }
-
- // Join selected files into list-ultimate.txt
- if let Err(e) = join_selected_files(lists_dir, &selected_entries) {
- execute!(
- stdout,
- cursor::MoveToNextLine(1),
- terminal::Clear(ClearType::FromCursorDown)
- )?;
- println!("{}", format!("Error occurred while merging files: {}. Exiting in 5 seconds...", e).red());
- } else {
- execute!(
- stdout,
- cursor::MoveToNextLine(1),
- terminal::Clear(ClearType::FromCursorDown)
- )?;
- println!("{}", "Successful! List saved and files merged. Exiting in 5 seconds...".green());
- }
-
- stdout.flush()?;
- thread::sleep(Duration::from_secs(5));
- break 'main Ok(());
- }
- "CANCEL" => break 'main Ok(()),
- _ => {
- entries[current_index].selected = !entries[current_index].selected;
- }
- }
- }
- KeyEvent {
- code: KeyCode::Char('c'),
- modifiers: KeyModifiers::CONTROL,
- kind: event::KeyEventKind::Press,
- ..
- } => {
- break 'main Ok(());
- }
- _ => {
- redraw = false;
- }
- }
-
- if redraw {
- draw_screen(stdout, &entries, current_index, scroll_offset, false)?;
- }
- }
- }
- }
-}
diff --git a/shared/Cargo.toml b/shared/Cargo.toml
deleted file mode 100644
index 1e61c04..0000000
--- a/shared/Cargo.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-[package]
-name = "shared"
-edition = "2021"
-version.workspace = true
-
-[dependencies]
-crossterm.workspace = true
-ctrlc = "3.4.1"
diff --git a/shared/src/lib.rs b/shared/src/lib.rs
deleted file mode 100644
index a566381..0000000
--- a/shared/src/lib.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod terminal;
diff --git a/shared/src/terminal.rs b/shared/src/terminal.rs
deleted file mode 100644
index 57b7e8d..0000000
--- a/shared/src/terminal.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use crossterm::{
- cursor, execute,
- terminal::{self, Clear, ClearType},
-};
-use std::io::{self, Write};
-
-
-/// Go to alternate screen, hide cursor and clear screen
-pub fn init(stdout: &mut impl Write) -> io::Result<()> {
- terminal::enable_raw_mode()?;
- execute!(
- stdout,
- terminal::EnterAlternateScreen,
- cursor::Hide,
- Clear(ClearType::All),
- cursor::MoveTo(0, 0)
- )?;
- Ok(())
-}
-
-
-/// Get size of current terminal window
-pub fn get_size() -> io::Result<(u16, u16)> {
- terminal::size()
-}
-
-/// Clean terminal screen
-pub fn cleanup_terminal() -> io::Result<()> {
- let mut stdout = std::io::stdout();
- terminal::disable_raw_mode()?;
- execute!(
- stdout,
- Clear(ClearType::All),
- cursor::Show,
- terminal::LeaveAlternateScreen
- )?;
- stdout.flush()?;
- Ok(())
-}
-
-/// Setup clearing terminal screen on Ctrl-C
-pub fn setup_terminal_cleanup() {
- let original_hook = std::panic::take_hook();
- std::panic::set_hook(Box::new(move |panic_info| {
- let _ = cleanup_terminal();
- original_hook(panic_info);
- }));
-
- ctrlc::set_handler(move || {
- let _ = cleanup_terminal();
- std::process::exit(0);
- })
- .expect("Error setting Ctrl-C handler");
-}
-
-/// Clean screen and exit
-pub fn cleanup_and_exit(mut stdout: &mut impl Write) -> io::Result<()> {
- writeln!(&mut stdout, "\nReady!\nYou can close this window")
- .expect("Failed to print line to stdout");
- let mut input = String::new();
- io::stdin().read_line(&mut input)?;
- Ok(())
-}