Compare commits

...

77 Commits

Author SHA1 Message Date
elseif
6cbdbffbcb Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-09-13 03:43:55 +08:00
elseif
6d27075389 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-13 03:39:43 +08:00
elseif
9b92fc3fa6 Update README.md
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 13:21:58 +08:00
elseif
0c92a04b58 Update README.md
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 13:21:30 +08:00
elseif
296db5b558 Update README.md
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 13:20:35 +08:00
elseif
49bbcb1983 Update mikrotik_patch_6.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 10:04:24 +08:00
elseif
f750442687 Add files via upload
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 09:45:56 +08:00
elseif
06bd69f331 Delete keygen/keygen_aarch64
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 09:45:42 +08:00
elseif
e35cf5f74e Add files via upload
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 09:45:27 +08:00
elseif
e12e1aa67b Delete keygen/keygen_arm
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 09:45:06 +08:00
elseif
6a8aaa89d8 Delete keygen/keygen_x86
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 09:44:53 +08:00
elseif
495927d0de Update mikrotik_patch_6.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 08:57:23 +08:00
elseif
c73c6bacc8 Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-11 08:56:31 +08:00
elseif
8e7134e0a6 Update mikrotik_patch_6.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 17:27:26 +08:00
elseif
f4cc728789 Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 17:26:58 +08:00
elseif
8c3278f477 Update npk.py
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 17:07:20 +08:00
elseif
04a831b463 Update mikrotik_patch_6.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 16:30:01 +08:00
elseif
c75dd48261 Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 15:36:11 +08:00
elseif
6519ab2e12 Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 15:26:20 +08:00
elseif
ec1c0f1719 Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 15:16:03 +08:00
elseif
3de34ef556 Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 15:09:47 +08:00
elseif
8499e4591a Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 12:23:18 +08:00
elseif
f520ff799c Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 12:12:45 +08:00
elseif
ccb4220a61 Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 12:10:02 +08:00
elseif
8159018e3c Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 12:09:07 +08:00
elseif
dc30d89afb Update README.md
Signed-off-by: elseif <elseif@live.cn>
2025-09-10 07:47:39 +08:00
elseif
4472649719 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-08 10:23:13 +08:00
elseif
fc469087be Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-08 10:22:15 +08:00
elseif
477fd66fe0 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-08 10:04:22 +08:00
elseif
cd32348c52 Update README.md
Signed-off-by: elseif <elseif@live.cn>
2025-09-08 08:37:29 +08:00
elseif
37f92c3def Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-01 01:39:38 +08:00
elseif
2bb452b300 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-01 00:16:44 +08:00
elseif
710921ef23 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-01 00:13:21 +08:00
elseif
8bfcdfe5a8 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-01 00:12:51 +08:00
elseif
2baf264aec Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-01 00:11:15 +08:00
elseif
fd6f36d484 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-01 00:08:06 +08:00
elseif
2ab01e5328 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-09-01 00:06:52 +08:00
elseif
16854dadf9 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-08-31 23:56:16 +08:00
elseif
d981a4b137 Delete keygen/tmp
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 21:53:58 +08:00
elseif
378c9009b8 Add files via upload
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 21:53:34 +08:00
elseif
73f9ba0506 Create tmp
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 21:52:28 +08:00
elseif
646f479290 Delete keygen/keygen_x86
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 21:49:53 +08:00
elseif
e3b46ed7c3 Delete keygen/keygen_arm
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 21:49:41 +08:00
elseif
1a66685cc4 Delete keygen/keygen_aarch64
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 21:49:29 +08:00
elseif
cbd6ffa50c Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 19:38:57 +08:00
elseif
73d90b27e0 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 19:31:24 +08:00
elseif
60728d6fe2 Update index.html
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 19:27:34 +08:00
elseif
556cc81474 Add files via upload
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 18:35:01 +08:00
elseif
2286063b65 Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 17:29:36 +08:00
elseif
907b335d3a Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 17:29:10 +08:00
elseif
567819bec4 Update mikrotik_patch_7.yml
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 17:19:41 +08:00
elseif
bbc6b854cd Add files via upload
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 16:53:43 +08:00
elseif
6f4c9b43fc Delete keygen/keygen_arm
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 16:52:57 +08:00
elseif
659de9d659 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 16:34:23 +08:00
elseif
78707050a0 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 16:31:09 +08:00
elseif
cdb378b45d Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 16:25:09 +08:00
elseif
9b40d04e38 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 16:17:43 +08:00
elseif
110cda779c Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 16:12:13 +08:00
elseif
36be15859e Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-27 15:56:02 +08:00
elseif
c40954115b Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-26 17:22:44 +08:00
elseif
2babd89f27 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-26 17:19:46 +08:00
elseif
7a6e538834 Update README.md
Signed-off-by: elseif <elseif@live.cn>
2025-08-26 14:10:29 +08:00
elseif
a2f9af37ad Update README.md
Signed-off-by: elseif <elseif@live.cn>
2025-08-26 14:05:54 +08:00
elseif
6e630b852a Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-26 00:49:44 +08:00
elseif
4987501168 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-26 00:35:49 +08:00
elseif
c2ec6d439c Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-26 00:27:00 +08:00
elseif
c5712825ba Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-26 00:22:40 +08:00
elseif
072417bf1b Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-26 00:17:09 +08:00
elseif
f2d18e32f6 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-26 00:10:04 +08:00
elseif
7758330905 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-25 22:25:45 +08:00
elseif
0ff47ed53e Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-25 22:24:17 +08:00
elseif
90dfb10d32 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-25 22:21:53 +08:00
elseif
a217ae8df0 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-25 22:18:07 +08:00
elseif
fa9c53bef1 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-25 22:07:27 +08:00
elseif
18b6449701 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-25 22:05:07 +08:00
elseif
d7517cb9f4 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-25 21:55:55 +08:00
elseif
3a17176568 Update chr.sh
Signed-off-by: elseif <elseif@live.cn>
2025-08-25 21:54:18 +08:00
9 changed files with 1128 additions and 64 deletions

View File

@@ -143,18 +143,9 @@ jobs:
7z x -p"${{ secrets.LOADER_7Z_PASSWORD }}" loader.7z >> /dev/null
rm loader.7z
- name: Cache Squashfs
if: steps.get_latest.outputs.has_new_version == 'true'
id: cache-squashfs
uses: actions/cache@v4
with:
path: |
python3.sfs
option.sfs
key: busybox-python3-squashfs-${{ matrix.arch }}
- name: Create Squashfs for option and python3
if: steps.get_latest.outputs.has_new_version == 'true' && steps.cache-squashfs.outputs.cache-hit != 'true'
if: steps.get_latest.outputs.has_new_version == 'true'
run: |
sudo mkdir -p ./option-root/bin/
sudo cp busybox/busybox_x86 ./option-root/bin/busybox
@@ -221,8 +212,8 @@ jobs:
fi
sudo cp -f system-$LATEST_VERSION.npk ./new_iso/
sudo -E python3 patch.py kernel ./new_iso/isolinux/initrd.rgz
#sudo -E python3 npk.py create ./new_iso/gps-$LATEST_VERSION.npk ./option-$LATEST_VERSION.npk option ./option.sfs -desc="busybox"
#sudo cp option-$LATEST_VERSION.npk ./new_iso/
# sudo -E python3 npk.py create ./new_iso/gps-$LATEST_VERSION.npk ./option-$LATEST_VERSION.npk option ./option.sfs -desc="busybox"
# sudo cp option-$LATEST_VERSION.npk ./new_iso/
sudo mkisofs -o mikrotik-$LATEST_VERSION.iso \
-V "MikroTik $LATEST_VERSION" \
-sysid "" -preparer "MiKroTiK" \
@@ -300,8 +291,8 @@ jobs:
sudo cp ./all_packages/dude-$LATEST_VERSION.npk ./chr/var/pdb/dude/image
sudo -E python3 patch.py npk ./chr/var/pdb/routeros-x86/image
sudo cp ./chr/var/pdb/routeros-x86/image ./all_packages/routeros-x86-$LATEST_VERSION.npk
#sudo mkdir -p ./chr/var/pdb/option
#sudo cp ./all_packages/option-$LATEST_VERSION.npk ./chr/var/pdb/option/image
# sudo mkdir -p ./chr/var/pdb/option
# sudo cp ./all_packages/option-$LATEST_VERSION.npk ./chr/var/pdb/option/image
sudo umount ./chr
sudo qemu-nbd -d /dev/nbd0
sudo rm -rf ./chr
@@ -328,13 +319,22 @@ jobs:
cd ./all_packages
sudo zip ../all_packages-x86-$LATEST_VERSION.zip *.npk
cd ..
- name: Upload Files
- name: Prepare for Upload
if: steps.get_latest.outputs.has_new_version == 'true' && env.RELEASE == 'true'
run: |
sudo mkdir -p ./publish/$LATEST_VERSION
sudo cp CHANGELOG ./publish/$LATEST_VERSION/
sudo cp ./all_packages/*.npk ./publish/$LATEST_VERSION/
# sudo cp mikrotik-${{ env.LATEST_VERSION }}${{ env.ARCH }}.iso ./publish/$LATEST_VERSION/ 2>/dev/null || true
# sudo cp chr-${{ env.LATEST_VERSION }}*.zip ./publish/$LATEST_VERSION/ 2>/dev/null || true
# sudo cp netinstall-${{ env.LATEST_VERSION }}.* ./publish/$LATEST_VERSION/ 2>/dev/null || true
# sudo cp install-image-${{ env.LATEST_VERSION }}.zip ./publish/$LATEST_VERSION/ 2>/dev/null || true
echo $LATEST_VERSION $BUILD_TIME | sudo tee ./publish/NEWEST6.${{ matrix.channel }}
- name: Upload Files
if: steps.get_latest.outputs.has_new_version == 'true' && env.RELEASE == 'true'
run: |
sudo chown -R root:root ./publish/
LOCAL_PATH=./publish/$LATEST_VERSION
@@ -355,6 +355,20 @@ jobs:
sshpass -p "$PASS" ssh -o StrictHostKeyChecking=no -p $PORT $USER@$SERVER \
"echo $LATEST_VERSION $BUILD_TIME | tee /rw/disk/$REMOTE_PATH/NEWEST6.$CHANNEL; chown -R 32768:32768 /rw/disk/$REMOTE_PATH/"
# - name: Upload to R2 Bucket
# if: steps.get_latest.outputs.has_new_version == 'true' && env.RELEASE == 'true'
# uses: ryand56/r2-upload-action@latest
# with:
# r2-account-id: ${{ secrets.R2_ACCOUNT_ID }}
# r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
# r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
# r2-bucket: routeros
# source-dir: ./publish
# destination-dir: ./routeros
# keep-file-fresh: true
# output-file-url: false
- name: Clear Cloudflare cache
if: steps.get_latest.outputs.has_new_version == 'true' && env.RELEASE == 'true'
@@ -367,6 +381,7 @@ jobs:
- name: Delete Release tag ${{ env.LATEST_VERSION }}
if: steps.get_latest.outputs.has_new_version == 'true' && env.RELEASE == 'true'
run: |
sed -i "1i Build Time:$BUILD_TIME" CHANGELOG
HEADER="Authorization: token ${{ secrets.GITHUB_TOKEN }}"
RELEASE_INFO=$(curl -s -H $HEADER https://api.github.com/repos/${{ github.repository }}/releases/tags/$LATEST_VERSION)
RELEASE_ID=$(echo $RELEASE_INFO | jq -r '.id')

View File

@@ -159,18 +159,8 @@ jobs:
7z x -p"${{ secrets.LOADER_7Z_PASSWORD }}" loader.7z >> /dev/null
rm loader.7z
- name: Cache Squashfs
if: steps.get_latest.outputs.has_new_version == 'true'
id: cache-squashfs
uses: actions/cache@v4
with:
path: |
python3.sfs
option.sfs
key: busybox-python3-squashfs-${{ matrix.arch }}
- name: Create Squashfs for option and python3
if: steps.get_latest.outputs.has_new_version == 'true' && steps.cache-squashfs.outputs.cache-hit != 'true'
if: steps.get_latest.outputs.has_new_version == 'true'
run: |
sudo mkdir -p ./option-root/bin/
if [ "${{ matrix.arch }}" == "x86" ]; then
@@ -221,6 +211,7 @@ jobs:
path: |
mikrotik.iso
key: mikrotik-${{ env.LATEST_VERSION }}${{ env.ARCH }}
restore-keys: mikrotik-${{ env.LATEST_VERSION }}${{ env.ARCH }}
- name: Get mikrotik-${{ env.LATEST_VERSION }}${{ env.ARCH }}.iso
if: steps.get_latest.outputs.has_new_version == 'true' && steps.cache-mikrotik.outputs.cache-hit != 'true' && (matrix.arch == 'x86' || matrix.arch == 'arm64')
@@ -311,6 +302,7 @@ jobs:
path: |
chr.img
key: chr-${{ env.LATEST_VERSION }}${{ env.ARCH }}.img
restore-keys: chr-${{ env.LATEST_VERSION }}${{ env.ARCH }}.img
- name: Get chr-${{ env.LATEST_VERSION }}${{ env.ARCH }}.img
if: steps.get_latest.outputs.has_new_version == 'true' && steps.cache-chr-img.outputs.cache-hit != 'true' && (matrix.arch == 'x86' || matrix.arch == 'arm64')
@@ -565,6 +557,7 @@ jobs:
with:
path: all_packages.zip
key: all_packages${{ env.ARCH }}-${{ env.LATEST_VERSION }}.zip
restore-keys: all_packages${{ env.ARCH }}-${{ env.LATEST_VERSION }}.zip
- name: Get all_packages{{ env.ARCH }}-${{ env.LATEST_VERSION }}.zip
if: steps.get_latest.outputs.has_new_version == 'true' && steps.cache-all-packages.outputs.cache-hit != 'true' && matrix.arch != 'x86' && matrix.arch != 'arm64'
@@ -578,6 +571,7 @@ jobs:
with:
path: routeros.npk
key: routeros-${{ env.LATEST_VERSION }}${{ env.ARCH }}.npk
restore-keys: routeros-${{ env.LATEST_VERSION }}${{ env.ARCH }}.npk
- name: Get Main package routeros-${{ env.LATEST_VERSION }}${{ env.ARCH }}.npk
if: steps.get_latest.outputs.has_new_version == 'true' && steps.cache-main-package.outputs.cache-hit != 'true' && matrix.arch != 'x86' && matrix.arch != 'arm64'
@@ -608,6 +602,7 @@ jobs:
with:
path: refind-bin-0.14.2.zip
key: refind
restore-keys: refind
- name: Get refind
if: steps.get_latest.outputs.has_new_version == 'true' && matrix.arch == 'x86' && steps.cache-refind.outputs.cache-hit != 'true' && env.RELEASE == 'true'
@@ -661,6 +656,7 @@ jobs:
netinstall.zip
netinstall.tar.gz
key: netinstall-${{ env.LATEST_VERSION }}
restore-keys: netinstall-${{ env.LATEST_VERSION }}
- name: Get netinstall ${{ env.LATEST_VERSION }}
if: steps.get_latest.outputs.has_new_version == 'true' && matrix.arch == 'x86' && steps.cache-netinstall.outputs.cache-hit != 'true' && env.RELEASE == 'true'
@@ -678,14 +674,22 @@ jobs:
sudo -E python3 patch.py netinstall netinstall-cli
sudo tar -czvf netinstall-$LATEST_VERSION.tar.gz ./netinstall-cli
- name: Upload Files
- name: Prepare for Upload
if: steps.get_latest.outputs.has_new_version == 'true' && env.RELEASE == 'true'
run: |
sudo mkdir -p ./publish/$LATEST_VERSION
sudo cp CHANGELOG ./publish/$LATEST_VERSION/
sudo cp ./all_packages/*.npk ./publish/$LATEST_VERSION/
# sudo cp mikrotik-${{ env.LATEST_VERSION }}${{ env.ARCH }}.iso ./publish/$LATEST_VERSION/ 2>/dev/null || true
# sudo cp chr-${{ env.LATEST_VERSION }}*.zip ./publish/$LATEST_VERSION/ 2>/dev/null || true
# sudo cp netinstall-${{ env.LATEST_VERSION }}.* ./publish/$LATEST_VERSION/ 2>/dev/null || true
# sudo cp install-image-${{ env.LATEST_VERSION }}.zip ./publish/$LATEST_VERSION/ 2>/dev/null || true
echo $LATEST_VERSION $BUILD_TIME | sudo tee ./publish/NEWESTa7.${{ matrix.channel }}
- name: Upload Files
if: steps.get_latest.outputs.has_new_version == 'true' && env.RELEASE == 'true'
run: |
sudo chown -R root:root ./publish/
LOCAL_PATH=./publish/$LATEST_VERSION
REMOTE_PATH=${{ secrets.SSH_DIRECTORY }}
SERVER=${{ secrets.SSH_SERVER }}
@@ -706,10 +710,22 @@ jobs:
"echo $LATEST_VERSION $BUILD_TIME | tee /rw/disk/$REMOTE_PATH/NEWESTa7.$CHANNEL; bash /rw/disk/$REMOTE_PATH/packages.sh /rw/disk/$REMOTE_PATH/$LATEST_VERSION"
sshpass -p "$PASS" ssh -o StrictHostKeyChecking=no -p $PORT $USER@$SERVER \
"chown -R 32768:32768 /rw/disk/$REMOTE_PATH/"
"chown -R 32768:32768 /rw/disk/$REMOTE_PATH/"
# - name: Upload to R2 Bucket
# if: steps.get_latest.outputs.has_new_version == 'true' && env.RELEASE == 'true'
# uses: ryand56/r2-upload-action@latest
# with:
# r2-account-id: ${{ secrets.R2_ACCOUNT_ID }}
# r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
# r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
# r2-bucket: routeros
# source-dir: ./publish
# destination-dir: ./routeros
# keep-file-fresh: true
# output-file-url: false
- name: Clear Cloudflare cache
if: steps.get_latest.outputs.has_new_version == 'true' && env.RELEASE == 'true'
run: |
@@ -721,6 +737,7 @@ jobs:
- name: Delete Release tag ${{ env.LATEST_VERSION }} ${{ env.ARCH }}
if: steps.get_latest.outputs.has_new_version == 'true' && env.RELEASE == 'true'
run: |
sed -i "1i Build Time:$BUILD_TIME" CHANGELOG
HEADER="Authorization: token ${{ secrets.GITHUB_TOKEN }}"
RELEASE_INFO=$(curl -s -H "$HEADER" https://api.github.com/repos/${{ github.repository }}/releases/tags/$LATEST_VERSION$ARCH)
RELEASE_ID=$(echo $RELEASE_INFO | jq -r '.id')

View File

@@ -9,8 +9,8 @@
支持:在线更新、在线授权、云备份、DDNS
![Cloud Status](https://img.shields.io/endpoint?url=https://upgrade.mikrotik.ltd/status?type=cloud)
![VPS Status](https://img.shields.io/endpoint?url=https://upgrade.mikrotik.ltd/status?type=dartnode)
![Cloud Status](https://img.shields.io/endpoint?url=https://mikrotik.ltd/status/cloud)
![VPS Status](https://img.shields.io/endpoint?url=https://mikrotik.ltd/status/dartnode)
*如果云服务或部署云服务的虚拟主机都不在线那么在线更新、在线授权、云备份、DDNS以及ROS_Keygen_Bot都暂时不能使用*
@@ -22,7 +22,7 @@ graph TD
B -->|否| D[检查 rc.local 文件是否存在]
C --> D
D -->|是| E[fork 执行 /bin/sh rc.local]
D -->|否| F[结束]
D -->|否| F[启动服务]
E --> F
```
![](image/install.png)
@@ -63,7 +63,6 @@ graph TD
### 感谢赞助
[ZMTO](https://console.zmto.com)
[![Powered by DartNode](https://dartnode.com/branding/DN-Open-Source-sm.png)](https://dartnode.com "Powered by DartNode - Free VPS for Open Source")

97
chr.sh
View File

@@ -1,34 +1,68 @@
#!/bin/sh
#!/bin/bash
set -e
if [ -d /sys/firmware/efi ]; then
echo "System boot mode: UEFI"
wget --no-check-certificate -O /tmp/chr.img.zip https://github.com/elseif/MikroTikPatch/releases/download/7.19.4/chr-7.19.4.img.zip
LATEST_VERSION="${1:-7.19.4}"
echo "VERSION: $LATEST_VERSION"
ARCH=$(uname -m)
if [[ $LATEST_VERSION == 7.* ]]; then
case $ARCH in
x86_64|i386|i486|i586|i686)
echo "ARCH: $ARCH"
if [ -d /sys/firmware/efi ]; then
echo "BOOT MODE: UEFI"
IMG_URL="https://github.com/elseif/MikroTikPatch/releases/download/$LATEST_VERSION/chr-$LATEST_VERSION.img.zip"
else
echo "BOOT MODE: BIOS/MBR"
IMG_URL="https://github.com/elseif/MikroTikPatch/releases/download/$LATEST_VERSION/chr-$LATEST_VERSION-legacy-bios.img.zip"
fi
;;
aarch64)
echo "ARCH: $ARCH"
IMG_URL="https://github.com/elseif/MikroTikPatch/releases/download/$LATEST_VERSION-arm64/chr-$LATEST_VERSION-arm64.img.zip"
;;
*)
echo "Unsupported architecture: $ARCH"
exit 1
;;
esac
else
echo "System boot mode: BIOS/MBR"
wget --no-check-certificate -O /tmp/chr.img.zip https://github.com/elseif/MikroTikPatch/releases/download/7.19.4/chr-7.19.4-legacy-bios.img.zip
case $ARCH in
x86_64|i386|i486|i586|i686)
echo "ARCH: $ARCH"
IMG_URL="https://github.com/elseif/MikroTikPatch/releases/download/$LATEST_VERSION/chr-$LATEST_VERSION.img.zip"
;;
*)
echo "Unsupported architecture: $ARCH"
exit 1
;;
esac
fi
STORAGE=$(lsblk -d -n -o NAME,TYPE | awk '$2=="disk"{print $1; exit}')
echo "STORAGE: $STORAGE"
ETH=$(ip route show default | grep '^default' | sed -n 's/.* dev \([^\ ]*\) .*/\1/p')
echo "ETH: $ETH"
ADDRESS=$(ip addr show $ETH | grep global | cut -d' ' -f 6 | head -n 1)
echo "ADDRESS: $ADDRESS"
GATEWAY=$(ip route list | grep default | cut -d' ' -f 3)
echo "GATEWAY: $GATEWAY"
DNS=$(grep '^nameserver' /etc/resolv.conf | awk '{print $2}' | head -n 1)
[ -z "$DNS" ] && DNS="8.8.8.8"
echo "DNS: $DNS"
echo "FILE: $(basename $IMG_URL)"
if command -v wget >/dev/null 2>&1; then
wget --no-check-certificate -O /tmp/chr.img.zip "$IMG_URL" || { echo "Download failed!"; exit 1; }
elif command -v curl >/dev/null 2>&1; then
curl -L --insecure -o /tmp/chr.img.zip "$IMG_URL" || { echo "Download failed!"; exit 1; }
else
echo "Neither wget nor curl is installed. Cannot download $url"
exit 1
fi
cd /tmp
unzip -p chr.img.zip > chr.img
STORAGE=$(for d in /sys/block/*; do
case $(basename $d) in
loop*|ram*|sr*) continue ;;
*) echo $(basename $d); break ;;
esac
done)
echo "STORAGE is $STORAGE"
ETH=$(ip route show default | grep '^default' | sed -n 's/.* dev \([^\ ]*\) .*/\1/p')
echo "ETH is $ETH"
ADDRESS=$(ip addr show $ETH | grep global | cut -d' ' -f 6 | head -n 1)
echo "ADDRESS is $ADDRESS"
GATEWAY=$(ip route list | grep default | cut -d' ' -f 3)
echo "GATEWAY is $GATEWAY"
gunzip -c chr.img.zip > chr.img
RANDOM_PASS=$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 8)
if LOOP=$(losetup -Pf --show chr.img 2>/dev/null); then
echo "LOOP device is $LOOP"
sleep 3
MNT=/tmp/chr
mkdir -p $MNT
@@ -36,8 +70,11 @@ if LOOP=$(losetup -Pf --show chr.img 2>/dev/null); then
cat <<EOF | tee $MNT/rw/autorun.scr
/ip address add address=$ADDRESS interface=ether1
/ip route add gateway=$GATEWAY
/ip dns set servers=$DNS
/user set admin password="$RANDOM_PASS"
EOF
echo "autorun.scr file created."
echo -e "admin password: \e[31m$RANDOM_PASS\e[0m"
umount $MNT
else
echo "Failed to mount partition 2, skipping autorun.scr creation."
@@ -46,8 +83,12 @@ EOF
fi
echo "WARNING: All data on /dev/$STORAGE will be lost!"
read -p "Do you want to continue? [Y/n]: " confirm
[ "$confirm" = "n" ] && echo "Operation aborted." && exit 1
read -p "Do you want to continue? [Y/n]: " confirm < /dev/tty
confirm=${confirm:-Y}
if [[ "$confirm" =~ ^[Nn]$ ]]; then
echo "Operation aborted."
exit 1
fi
dd if=chr.img of=/dev/$STORAGE bs=4M conv=fsync
echo "Ok, rebooting..."

990
index.html Normal file
View File

@@ -0,0 +1,990 @@
<!doctype html>
<html lang="en" >
<head>
<meta charset="utf-8" />
<title>MikroTik RouterOS Patched Versions</title>
<link href="https://unpkg.com/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="https://unpkg.com/firacode/distr/fira_code.css" rel="stylesheet">
<style>
body,html {
height: 100%;
font-size: 100%
}
*,:after,:before {box-sizing: border-box}
body {
background: #F7F7F7;
color: #757575;
margin: 0;
font-family: arial,sans-serif;
line-height: 1.5;
}
.wrapper { background:white; }
table { background: #fff; }
table thead, table tfoot { background: #f5f5f5; }
/* --- DARK THEME --- */
body.dark {
background: #1e1e1e;
color: #ddd;
}
body.dark .wrapper {
background: #2a2a2a;
}
body.dark h1,h2,h3,h4,h5,h6 {
color: #f0f0f0;
}
body.dark a { color:#4ea3ff; }
body.dark a:hover { color:#81c8ff; }
body.dark table {
background: #2a2a2a;
border-color: #444;
}
body.dark table thead, body.dark table tfoot {
background: #333;
}
body.dark table tr td,
body.dark table tr th {
color: #ddd;
}
body.dark .downloadTable tbody tr:hover {
background-color: #333 !important;
}
body.dark .downloadTable thead tr {
background-color: #444 !important;
}
body.dark .downloadTable thead th {
color: #eee !important;
}
body.dark #command pre {
background: #111;
color: #eaeaea;
}
/* دکمه تغییر تم */
#theme-toggle {
position: fixed;
top: 60px;
right: 15px;
background: #0992c9;
color: #fff;
border: none;
padding: 8px 14px;
cursor: pointer;
border-radius: 6px;
font-size: 14px;
z-index: 2000;
}
#theme-toggle:hover {
background: #0775a1;
}
body,html {
height: 100%;
font-size: 100%
}
*,:after,:before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box
}
body {
background: #F7F7F7;
color: #757575;
padding-top:80px;
font-family:arial,sans-serif;
padding: 0;
margin: 0;
font-style: normal;
line-height: 1.5;
cursor: auto;
opacity:1;
}
a {-webkit-transition: all 200ms ease-in-out;transition: all 200ms ease-in-out; color:#4984AE;text-decoration: none;}
a:hover{color: #2F5B7B}
h1,h2,h3,h4,h5,h6{font-family:'Open Sans',sans-serif;font-weight:normal;margin-bottom:18px;margin-top:26px;color:#626262;}
h1 {font-weight: 300}
h2{font-size:1.875rem}
h3{font-size:1.5rem}
.text-center{text-align:center}
.button {
border-style: solid;
border-width: 0;
cursor: pointer;
line-height: normal;
margin: 0 0 1.25rem;
position: relative;
text-align: center;
border-radius: 0;
display: inline-block;
font-size: 1rem;
background-color: #0992c9;
border-color: #0775a1;
color: #fff;
transition: background-color .3s ease-out;
padding: 1rem 2rem 1.0625rem
}
.button:focus,.button:hover,button:focus,button:hover {
background-color: #0775a1;
color: #fff
}
.button.secondary,button.secondary {
background-color: #e7e7e7;
border-color: #b9b9b9;
color: #333
}
.button.secondary:focus,.button.secondary:hover,button.secondary:focus,button.secondary:hover {
background-color: #b9b9b9;
color: #333
}
.wrapper{background:white;max-width:1600px;margin:auto;overflow:auto;padding-top:25px; padding-bottom: 35px;position: relative;}
.row {
max-width: 62.5rem;
margin: 0 auto
}
.row.collapse>.column,.row.collapse>.columns {
padding-left: 0;
padding-right: 0
}
.row.collapse .row {
margin-left: 0;
margin-right: 0
}
.row .row {
width: auto;
max-width: none;
margin: 0 -.9375rem
}
.row .row.collapse {
width: auto;
margin: 0;
max-width: none
}
.column,.columns {
padding-left: .9375rem;
padding-right: .9375rem;
width: 100%;
float: left
}
[class*=column]+[class*=column]:last-child {float: right}
[class*=column]+[class*=column].end { float: left}
hr {
border: solid #ddd;
border-width: 1px 0 0;
margin: 1.25rem 0 1.1875rem;
height: 0
}
b,strong { font-weight: 700}
small {font-size: 60%}
table {
background: #fff;
margin-bottom: 1.25rem;
border: 1px solid #ddd;
table-layout: auto
}
table caption {
background: 0 0;
color: #222;
font-size: 1rem;
font-weight: 700
}
table tfoot,table thead {
background: #f5f5f5;
}
table tfoot tr td,table tfoot tr th,table thead tr td,table thead tr th {
padding: .5rem .625rem .625rem;
font-size: .875rem;
font-weight: 700;
color: #222
}
table tr td,table tr th {
padding: .5625rem .625rem;
font-size: .875rem;
color: #222;
text-align: left;
}
table tr.alt,table tr.even,table tr:nth-of-type(even) {
background: #f9f9f9
}
table tbody tr td,table tbody tr th,table tfoot tr td,table tfoot tr th,table thead tr th,table tr td {
display: table-cell;
line-height: 1.125rem;
}
.table{width:100%;border:0;border-collapse:collapse;}
.table tr:nth-of-type(even){background-color:transparent;}
.table td{padding:4px 10px 4px 0;color:#757575}
.table thead {background:transparent;}
.table thead th{padding:4px 10px 4px 0;color:#747474}
.downloadTable, .fullWidth{width:100%;}
.downloadTable tbody tr{border-bottom:1px solid #e3e3e3}
.downloadTable tbody tr:hover{background-color:#f7f7f7}
.downloadTable td{padding:6px 10px}
.downloadTable tbody tr.ht td{background-color:#888;border-bottom:0;}
.downloadTable tbody tr td.boldy{font-weight:bold;color:#ddd}
.downloadTable tbody tr:last-child{border-bottom:0;}
.downloadTable thead tr{background-color:#4caf50;}
.downloadTable thead th{color:white;padding:12px 5px}
.downloadTable tbody tr:first-child td:first-child{font-weight:bold;width:230px;}
.downloadTable tbody tr.hv td:not(:first-child){min-width:150px;}
.downloadTable td {padding: 0 4px; }
.downloadTable tr td:first-child {padding: 6px 10px;}
.download-btn, .changelog-btn, .checksums-btn { padding: 10px; color: grey;font-size: 1.2em;}
.download-btn:hover {color: #007bff;}
.downloadTable tr:hover .checksum-btn {
visibility: visible;
}
.download_version_row:hover{
background: #f0f3f7;
cursor: pointer;
}
.small-1 {
width: 8.33333%
}
.small-11 {
width: 91.66667%
}
.filter-blue {
filter: invert(39%) sepia(88%) saturate(5000%) hue-rotate(190deg) brightness(95%) contrast(90%);
}
.table-wrapper { position: relative; }
thead { position: relative; }
.collapse-btn {
position: absolute;
top: 50%;
right: 8px;
transform: translateY(-50%);
background: #fff;
border: 1px solid #ccc;
border-radius: 2px;
padding: 2px 6px;
cursor: pointer;
font-size: 0.85em;
line-height: 1;
}
.collapse-btn:hover {
background: gray;
}
.github-corner svg {clip-path: polygon(0 0, 100% 0, 100% 100%);}
.github-corner:hover .octo-arm {animation: octocat-wave 560ms ease-in-out;}
@keyframes octocat-wave {
0% { transform: rotate(0deg);}
20% {transform: rotate(-25deg);}
40% {transform: rotate(10deg);}
60% {transform: rotate(-25deg);}
80% {transform: rotate(10deg);}
100% {transform: rotate(0deg);}
}
@media (max-width: 500px) {
.github-corner:hover .octo-arm {animation: none;}
.github-corner .octo-arm {animation: octocat-wave 560ms ease-in-out;}
}
.reveal-modal {
display: none;
position: fixed;
z-index: 1005;
width: 60%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
margin: auto;
background-color: #fff;
padding: 1.875rem;
border: 1px solid #666;
box-shadow: 0 0 10px rgba(0,0,0,.4)
}
.reveal-modal .close-reveal-modal {
font-size: 2.5rem;
line-height: 1;
position: absolute;
top: .625rem;
right: 1.375rem;
color: #aaa;
font-weight: 700;
cursor: pointer
}
#version-buttons {margin-bottom: 12px;}
#version-buttons button {
background-color: #b9b9b9;
color: #fff;
border: none;
padding: 6px 12px;
margin-left: 6px;
border-radius: 1px;
cursor: pointer;
}
#version-buttons button:hover {background-color: #555;}
#version-buttons button.active {background-color: #4caf50;}
#command-container {
position: relative;
margin-top: 12px;
}
#copy-btn {
position: absolute;
top: 10px;
right: 10px;
background-color: #4caf50;
color: white;
border: none;
padding: 4px 8px;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
z-index: 10;
}
#copy-btn i {margin-right: 6px;}
#copy-btn:hover {background-color: #45a049;}
#command pre {
font-family: 'Fira Code', monospace !important;
font-size: 13px;
line-height: 1.5;
background-color: #1e1e1e;
color: #d4d4d4;
padding: 12px;
border-radius: 3px;
overflow-x: auto;
}
#command .bash { color: #c586c0; font-weight: bold; }
#command .url { color: #569cd6; }
#command .version { color: #4ec9b0; font-weight: bold; }
#command pre:hover {background-color: #2c2c2c;}
.loading {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-style: italic;
color: gray;
background: rgba(255,255,255,0.9);
padding: 15px 25px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.2);
z-index: 1000;
}
.loading i {
margin-right: 10px;
animation: fa-spin 1s linear infinite;
}
</style>
</head>
<body>
<script>
async function fetch_latest_versions(url, defaultValue, timeout = 3000) {
try {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
const res = await fetch(url, { signal: controller.signal });
clearTimeout(id);
if(res.ok){
const text = await res.text();
return text.split(" ")[0];
}
} catch(e) {
console.warn("fetch failed or timeout:", e);
}
return defaultValue;
}
async function init() {
const i18n = {
en: {
language: "Language:",
infoLabel1:`If you are already running <b>patched</b> RouterOS, upgrading to the latest version can be done by clicking on <b>"Check For Updates"</b>
in <b>QuickSet or System > Packages</b>
menu in WebFig or WinBox.`,
infoLabel2:`For more information about <b>install and upgrade</b> see the <a href="https://help.mikrotik.com/docs/" target="_blank">Documentation</a><br>
For more information about <b>patch</b> see the <a href="https://github.com/elseif/MikroTikPatch" target="_blank">MikroTikPatch</a>`,
installCmdLabel:"<b>Install Command</b>",
proxyLabel:"Use a proxy service to accelerate access to GitHub files",
clearCache:"Clear Cache",
copyUrlsClearCache:"Copy URLs to Clear Cache",
loading:"Loading...",
},
zh: {
language: "语言:",
infoLabel1:`如果你已经在运行<b>Patch</b>过的RouterOS可以通过WebFig或WinBox中的<b>QuickSet或System > Packages</b>菜单点击<b>"Check For Updates"</b>来升级到最新版本。`,
infoLabel2:`有关<b>安装和升级</b>的更多信息,请参阅<a href="https://help.mikrotik.com/docs/" target="_blank">文档</a><br>有关<b>Patch</b>的更多信息,请参阅<a href="https://github.com/elseif/MikroTikPatch" target="_blank">MikroTikPatch</a>`,
installCmdLabel:"<b>安装命令</b>",
proxyLabel:"使用代理服务加速访问GitHub文件",
clearCache:"清除缓存",
copyUrlsClearCache:"复制链接以清除缓存",
loading:"加载中...",
}
};
function setLanguage(lang) {
document.querySelectorAll("[data-i18n]").forEach(el => {
const key = el.getAttribute("data-i18n");
if (i18n[lang] && i18n[lang][key]) {
el.innerHTML = i18n[lang][key];
}
});
localStorage.setItem("lang", lang);
}
function initLanguage() {
let savedLang = localStorage.getItem("lang");
if (!savedLang) {
savedLang = navigator.language.startsWith("zh") ? "zh" : "en";
}
document.getElementById("lang-switcher").value = savedLang;
setLanguage(savedLang);
}
document.getElementById("lang-switcher").addEventListener("change", e => {
setLanguage(e.target.value);
});
initLanguage();
const loading = document.getElementById("loading");
loading.style.display = "inline";
const routeros7_stable = await fetch_latest_versions("https://upgrade.mikrotik.ltd/routeros/NEWESTa7.stable", "7.19.4");
const routeros7_testing = await fetch_latest_versions("https://upgrade.mikrotik.ltd/routeros/NEWESTa7.testing", "7.20rc1");
const routeros6_longterm = await fetch_latest_versions("https://upgrade.mikrotik.ltd/routeros/NEWEST6.long-term", "6.49.18");
const routeros6_stable = await fetch_latest_versions("https://upgrade.mikrotik.ltd/routeros/NEWEST6.stable", "6.49.19");
loading.style.display = "none";
const downloads =[
{
title:"RouterOS v7",
versions:[
{
title:"Stable",
version:routeros7_stable,
},
{
title:"Testing",
version:routeros7_testing,
}
],
groups: [
{
title:"ARM64 / AMPERE",
arch:"arm64",
downloads:[
{
title:"Main package",
type:"main"
},
{
title:"Extra packages",
type:"extra"
},
{
title:"ISO image for AMPERE",
type:"iso"
}
]
},
{
title:"X86",
arch:"x86",
downloads:[
{
title:"Main package",
type:"main"
},
{
title:"Extra packages",
type:"extra"
},
{
title:"CD Image",
type:"iso"
},
{
title:"Install image",
type:"install"
}
]
},
{
title:"GENERAL",
arch:"general",
downloads:[
{
title:"Netinstall (Windows)",
type:"netinstall_windows"
},
{
title:"Netinstall (CLI Linux)",
type:"netinstall_linux_cli"
},
{
title:"Changelog",
type:"changlog"
},
]
}
]
},
{
title:"RouterOS v6",
versions:[
{
title:"Long-Term",
version:routeros6_longterm,
},
{
title:"Stable",
version:routeros6_stable,
}
],
groups: [
{
title:"X86",
arch:"x86",
downloads:[
{
title:"Extra packages",
type:"extra"
},
{
title:"CD Image",
type:"iso"
},
{
title:"Install image",
type:"install"
},
{
title:"Changelog",
type:"changlog"
}
]
}
]
},
{
title:"Cloud Hosted Router",
versions:[
{
title:"Long-Term",
version:routeros6_longterm,
},
{
title:"Stable",
version:routeros6_stable,
},
{
title:"Stable",
version:routeros7_stable,
},
{
title:"Testing",
version:routeros7_testing,
}
],
groups:[
{
title:"X86",
arch:"x86",
downloads:[
{
title:"Main package",
type:"main"
},
{
title:"Extra packages",
type:"extra"
},
{
title:"VHDX image",
type:"vhdx"
},
{
title:"VMDK image",
type:"vmdk"
},
{
title:"VDI image",
type:"vdi"
},
{
title:"VirtualPC image",
type:"vhd"
},
{
title:"Raw disk image",
type:"img"
},
{
title:"OVA template ",
type:"ova"
}
],
},
{
title:"ARM64 / AMPERE",
arch:"arm64",
downloads:[
{
title:"Main package",
type:"main"
},
{
title:"Extra packages",
type:"extra"
},
{
title:"VHDX image",
type:"vhdx"
},
{
title:"VMDK image",
type:"vmdk"
},
{
title:"VDI image",
type:"vdi"
},
{
title:"VirtualPC image",
type:"vhd"
},
{
title:"Raw disk image",
type:"img"
}
],
}
]
},
]
const fileNames = (version,arch,type) => {
const files = [];
if(version.charAt(0) === "6" && arch != "x86") return files;
if(type === "main" && version.charAt(0) === "7" )
files.push(`routeros-${version}${arch === "x86" ? "" : "-"+arch}.npk`);
if(type === "iso")
files.push(`mikrotik-${version}${arch === "x86" ? "" : "-"+arch}.iso`);
if(type === "extra")
files.push(`all_packages-${arch}-${version}.zip`);
if(type === "install")
files.push(`install-image-${version}${arch === "x86" ? "" : "-"+arch}.zip`);
if(type in {vhdx:1, vmdk:1, vdi:1, vhd:1, img:1}){
files.push(`chr-${version}${arch === "x86" ? "" : "-"+arch}.${type}.zip`);
if(arch === "x86" && version.charAt(0) != "6" ) files.push(`chr-${version}-legacy-bios.${type}.zip`);
}
if(type === "ova" && version.charAt(0) != "6"){
files.push(`chr-${version}${arch === "x86" ? "" : "-"+arch}.${type}.zip`);
if(arch === "x86" ) files.push(`chr-${version}-legacy-bios.${type}.zip`);
}
if(type === "netinstall_windows")
files.push(`netinstall-${version}.zip`);
if(type === "netinstall_linux_cli")
files.push(`netinstall-${version}.tar.gz`);
return files;
};
const baseUrl = (version,arch) => `${localStorage.getItem("gh-proxy-enabled") === "true" ? "https://gh-proxy.com/":""}https://github.com/elseif/MikroTikPatch/releases/download/${version}${arch === "x86" ? "":arch === "general"? "": "-"+arch}/`;
const container = document.getElementById("download-rows");
downloads.forEach((download, index) => {
const wrapper = document.createElement("div");
wrapper.className = "table-wrapper";
const table = document.createElement("table");
table.className = "table tablev downloadTable"
table.innerHTML = `
<thead>
<tr>
<th>${download.title}</th>
${download.versions.map(v => `<th>${v.version} ${v.title}</th>`).join("")}
</tr>
</thead>
<tbody>
${download.groups.map(g => {
return `
<tr class="ht">
<td class="boldy">${g.title}</td>
<td colspan="${download.versions.length}"></td>
</tr>
${g.downloads.map(d => {
return `
<tr class="hv">
<td>${d.title}</td>
${download.versions.map(v => {
if(d.type === "changlog"){
return `<td><a href="https://upgrade.mikrotik.ltd/routeros/${v.version}/CHANGELOG" class="download-btn" title="${d.title}" target="_blank"><i class="fa fa-file-text"></i></a></td>`;
}else{
const files = fileNames(v.version,g.arch,d.type);
if (files && files.length > 0) {
const links = files.map(file => {
const url = `${baseUrl(v.version, g.arch)}${file}`;
if (download.versions.length === 4 && d.type in {vhdx:1,vmdk:1,vdi:1,vhd:1,img:1,ova:1} ){
if (v.version.charAt(0) === "6" ){
return `<a href="${url}" class="download-btn" title="${file}" target="_blank"><i class="fa fa-save"></i> Legacy</a>`;
}else{
if (file.includes("legacy-bios")){
return `<a href="${url}" class="download-btn" title="${file}" target="_blank"><i class="fa fa-save"></i> Legacy</a>`;
}else{
return `<a href="${url}" class="download-btn" title="${file}" target="_blank"><i class="fa fa-save"></i> UEFI</a>`;
}
}
}else{
return `<a href="${url}" class="download-btn" title="${file}" target="_blank"><i class="fa fa-save"></i></a>`;
}
}).join(" ");
return `<td>${links}</td>`;
}else{
return `<td></td>`;
}
}
}).join("")}
</tr>
`;
}).join("")}
`;
}).join("")}
</tbody>
`
const btn = document.createElement("button");
btn.className = "collapse-btn";
btn.innerHTML = `<i class="fa fa-minus"></i>`;
table.querySelector("thead").appendChild(btn);
wrapper.appendChild(table);
container.appendChild(wrapper);
const tbody = table.querySelector("tbody");
if (index === 0) {
tbody.style.display = "";
btn.innerHTML = `<i class="fa fa-minus"></i>`;
} else {
tbody.style.display = "none";
btn.innerHTML = `<i class="fa fa-plus"></i>`;
}
btn.onclick = () => {
if (tbody.style.display === "none") {
tbody.style.display = "";
btn.innerHTML = `<i class="fa fa-minus"></i>`;
} else {
tbody.style.display = "none";
btn.innerHTML = `<i class="fa fa-plus"></i>`;
}
};
});
document.getElementById("clear-cache").onclick = e => {
const links = document.querySelectorAll("a[href^='https://gh-proxy.com/https://github.com/elseif/MikroTikPatch/']");
document.getElementById("urls-list").innerText = Array.from(links).map(a => a.href).filter(href => !href.includes(".yml")).join("\n");
document.getElementById("urls-pannel").style.display = "block";
};
document.getElementById("urls-close").onclick = () => {
document.getElementById("urls-pannel").style.display = "none";
};
document.getElementById("copy-to-clear-cache").onclick = () => {
const el = document.getElementById("urls-list");
const range = document.createRange();
range.selectNodeContents(el);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
document.execCommand("copy");
window.open("https://cache.gh-proxy.com/", "_blank");
document.getElementById("urls-pannel").style.display = "none";
}
const ghProxyCheckbox = document.querySelector('input[name="gh-proxy"]');
ghProxyCheckbox.checked = localStorage.getItem("gh-proxy-enabled") === "true";
document.getElementById("clear-cache").style.display = ghProxyCheckbox.checked ?"inline-block":"none";
ghProxyCheckbox.addEventListener("change", () => {
if (ghProxyCheckbox.checked) {
localStorage.setItem("gh-proxy-enabled", "true");
const links = document.querySelectorAll("a[href^='https://github.com/elseif/MikroTikPatch/']");
links.forEach(link => {
link.href = link.href.replace(/^https:\/\/github\.com\//, "https://gh-proxy.com/https://github.com/");
});
document.getElementById("clear-cache").style.display = "inline-block";
} else {
localStorage.setItem("gh-proxy-enabled", "false");
const links = document.querySelectorAll("a[href^='https://gh-proxy.com/https://github.com/elseif/MikroTikPatch/']");
links.forEach(link => {
link.href = link.href.replace(/^https:\/\/gh-proxy\.com\//, "");
});
document.getElementById("clear-cache").style.display = "none";
}
const activeBtn = document.querySelector("#version-buttons button.active");
if (activeBtn) updateCommand(activeBtn.dataset.version);
});
const versionBtns = document.getElementById("version-buttons");
const commandDiv = document.getElementById("command");
const copyBtn = document.getElementById("copy-btn");
versionBtns.innerHTML = `
<span data-i18n="installCmdLabel"></span>
<label><input type="radio" name="tool" value="curl" checked>curl</label>
<label><input type="radio" name="tool" value="wget">wget</label>
<button data-version="${routeros7_stable}">RouterOS v7 Stable</button>
<button data-version="${routeros7_testing}">RouterOS v7 Testing</button>
<button data-version="${routeros6_longterm}">RouterOS v6 Long-Term</button>
<button data-version="${routeros6_stable}">RouterOS v6 Stable</button>
`
function updateCommand(version) {
const tool = document.querySelector('input[name="tool"]:checked').value;
let cmd;
const proxy = `${localStorage.getItem("gh-proxy-enabled") === "true"?" | sed 's#https://github.com#https://gh-proxy.com/https://github.com#g'":""}`;
if (tool === "curl") {
cmd = `<pre ${proxy === ""?"":"style='font-size:12px'"}><span class="bash">curl</span> <span class="url">https://mikrotik.ltd/chr.sh</span>${proxy} | <span class="bash">bash</span> -s <span class="version">${version}</span></pre>`;
} else {
cmd = `<pre ${proxy === ""?"":"style='font-size:11px'"}><span class="bash">wget</span> -O - <span class="url">https://mikrotik.ltd/chr.sh</span>${proxy} | <span class="bash">bash</span> -s <span class="version">${version}</span></pre>`;
}
commandDiv.innerHTML = cmd;
}
document.querySelectorAll('input[name="tool"]').forEach(radio => {
radio.addEventListener("change", () => {
const activeBtn = document.querySelector("#version-buttons button.active");
if (activeBtn) updateCommand(activeBtn.dataset.version);
});
});
const buttons = document.querySelectorAll("#version-buttons button");
buttons.forEach(btn => {
btn.addEventListener("click", () => {
updateCommand(btn.dataset.version);
buttons.forEach(b => b.classList.remove("active"));
btn.classList.add("active");
});
});
updateCommand(buttons[0].dataset.version);
buttons[0].classList.add("active");
copyBtn.addEventListener("click", () => {
const code = commandDiv.querySelector("pre").innerText;
navigator.clipboard.writeText(code).then(() => {
copyBtn.innerHTML = `<i class="fa fa-copy"></i>Copied!`;
setTimeout(() => { copyBtn.innerHTML = `<i class="fa fa-copy"></i>Copy`; }, 1500);
}).catch(err => {
console.error("Copy failed:", err);
});
});
const themeBtn = document.getElementById("theme-toggle");
const currentTheme = localStorage.getItem("theme");
if(currentTheme === "dark"){
document.body.classList.add("dark");
themeBtn.innerHTML = '<i class="fa fa-sun-o"></i> Light';
}
themeBtn.addEventListener("click", ()=>{
document.body.classList.toggle("dark");
if(document.body.classList.contains("dark")){
themeBtn.innerHTML = '<i class="fa fa-sun-o"></i> Light';
localStorage.setItem("theme","dark");
} else {
themeBtn.innerHTML = '<i class="fa fa-moon-o"></i> Dark';
localStorage.setItem("theme","light");
}
});
}
window.addEventListener("DOMContentLoaded", init);
</script>
<script async defer src="https://buttons.github.io/buttons.js"></script>
<div class="wrapper">
<button id="theme-toggle"><i class="fa fa-moon-o"></i> Dark</button>
<a href="https://github.com/elseif/MikroTikPatch" class="github-corner" aria-label="View source on GitHub" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 250 250" fill="#151513" style="position: absolute; top: 0; right: 0">
<path d="M0 0l115 115h15l12 27 108 108V0z" fill="#151513"/>
<path class="octo-arm" fill="#fff" d="M128 109c-15-9-9-19-9-19 3-7 2-11 2-11-1-7 3-2 3-2 4 5 2 11 2 11-3 10 5 15 9 16" style="-webkit-transform-origin: 130px 106px; transform-origin: 130px 106px"/>
<path class="octo-body" fill="#fff" d="M115 115s4 2 5 0l14-14c3-2 6-3 8-3-8-11-15-24 2-41 5-5 10-7 16-7 1-2 3-7 12-11 0 0 5 3 7 16 4 2 8 5 12 9s7 8 9 12c14 3 17 7 17 7-4 8-9 11-11 11 0 6-2 11-7 16-16 16-30 10-41 2 0 3-1 7-5 11l-12 11c-1 1 1 5 1 5z"/>
</svg>
</a>
<div class="row">
<div class="text-center">
<h1 class="filter-blue" style="margin-top: 20px;"><b>MikroTik RouterOS Patched Versions</b></h1>
</div>
</div>
<div class="row text-center">
<div>
<a href="https://github.com/elseif/MikroTikPatch/actions/workflows/mikrotik_patch_6.yml" target="_blank"><img src="https://mikrotik.ltd/badge/mikrotik_patch_6.yml" alt="Patch Mikrotik RouterOS 6.x"></a>
<a href="https://github.com/elseif/MikroTikPatch/actions/workflows/mikrotik_patch_7.yml" target="_blank"><img src="https://mikrotik.ltd/badge/mikrotik_patch_7.yml" alt="Patch Mikrotik RouterOS 7.x"></a>
</div>
<div>
<img src="https://img.shields.io/endpoint?logo=icloud&url=https://mikrotik.ltd/status/cloud" alt="Cloud Status">
<img src="https://img.shields.io/endpoint?logo=googlecloudstorage&url=https://mikrotik.ltd/status/dartnode" alt="VPS Status">
</div>
<a class="github-button" href="https://github.com/elseif/MikroTikPatch" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star elseif/MikroTikPatch on GitHub">Star</a>
<a class="github-button" href="https://github.com/elseif/MikroTikPatch/fork" data-icon="octicon-repo-forked" data-size="large" data-show-count="true" aria-label="Fork elseif/MikroTikPatch on GitHub">Fork</a>
</div>
<div class="row">
<p data-i18n="infoLabel1"></p>
<p data-i18n="infoLabel2"></p>
<div id="version-buttons"></div >
<div id="command-container">
<button id="copy-btn"><i class="fa fa-copy"></i>Copy</button>
<div id="command"></div>
</div>
<div style="height: 30px;">
<label><input type="checkbox" name="gh-proxy"><span data-i18n="proxyLabel"></span></label>
<a data-i18n="clearCache" id="clear-cache" class="button secondary" style="margin: 0px 10px !important;padding: 6px;font-size: .8125rem;height: 30px;" href="#" title="gh-proxy"></a>
</div>
</div>
<div class="row" style="display: flex; align-items: center; justify-content: center; ">
<div id="urls-pannel" class="reveal-modal" style="display: none;" tabindex="0">
<a id="urls-close" class="close-reveal-modal" aria-label="Close">×</a>
<div id="urls-list" style="margin: 20px; font-size: 16px;overflow:auto;height: 300px;"></div>
<div style="display: flex; align-items: center; justify-content: center; ">
<a data-i18n="copyUrlsClearCache" id="copy-to-clear-cache" class="button" style="margin-bottom: 0;padding: 8px;; width:180px;height:30px;font-size: .8125rem;" href="#" title="gh-proxy"></a>
</div>
</div>
</div>
<div class="row" id="download-rows" style="margin-top: 2vh;">
<div class="loading" id="loading"><i class="fa fa-spinner"></i><span data-i18n="loading"></span></div>
</div>
<div class="row">
<ul style="display: flex; align-items: center; justify-content: center; gap: 20px; list-style: none; padding: 0; margin: 0; ">
<li>
<a href="https://t.me/mikrotikpatch" target="_blank" title="Telegram">
<i class="fa fa-telegram fa-2x"></i>
</a>
</li>
<li>
<a href="https://github.com/elseif/MikroTikPatch" target="_blank" title="GitHub">
<i class="fa fa-github fa-2x"></i>
</a>
</li>
<li style="display: flex; gap: 6px;">
<span data-i18n="language"></span>
<select id="lang-switcher">
<option value="en">English</option>
<option value="zh">中文</option>
</select>
</li>
</ul>
</div>
</div>
</body>
</html>

Binary file not shown.

Binary file not shown.

Binary file not shown.

2
npk.py
View File

@@ -209,6 +209,8 @@ class NovaPackage(Package):
self._parts.append(NpkPartItem(NpkPartID(part_id),part_data))
def set_null_block(self):
def rebuild_squashfs(data):
if len(part.data) < 4 or part.data[:4] != b'hsqs':
return part.data
with open('squashfs.sfs', 'wb') as f:
f.write(data)
os.system('unsquashfs -d squashfs-root squashfs.sfs')