8 Commits
v2.0 ... main

Author SHA1 Message Date
dichgrem
fa3b2954cd add:mirror_workflow 2025-10-31 10:56:57 +08:00
dichgrem
c056ca8a4b style:format 2025-10-20 15:51:17 +08:00
dichgrem
69ff02fdbb style:readme 2025-10-20 12:51:30 +08:00
dichgrem
e4d1f1b108 feat:mips_actions 2025-10-20 12:38:00 +08:00
dichgrem
ef45a9414b fix:save_logic
chore:add_guide
2025-10-20 10:13:15 +08:00
dichgrem
cd7f41d7a7 feat:add_workflow 2025-10-16 21:35:19 +08:00
dichgrem
e1e0f03143 style:readme 2025-10-16 19:54:33 +08:00
dichgrem
9dd9806fd8 fix:username 2025-09-24 10:43:44 +08:00
6 changed files with 317 additions and 100 deletions

138
.github/workflows/build-zzz.yml vendored Normal file
View File

@@ -0,0 +1,138 @@
name: Build luci-app-zzz
on:
workflow_dispatch:
inputs:
sdk:
description: '选择架构'
required: true
type: choice
options:
- ramips
- filogic
- x86_64
default: filogic
env:
RAMIPS_SDK_URL: https://downloads.immortalwrt.org/releases/24.10.3/targets/ramips/mt7621/immortalwrt-sdk-24.10.3-ramips-mt7621_gcc-13.3.0_musl.Linux-x86_64.tar.zst
FILOGIC_SDK_URL: https://downloads.immortalwrt.org/releases/24.10.3/targets/mediatek/filogic/immortalwrt-sdk-24.10.3-mediatek-filogic_gcc-13.3.0_musl.Linux-x86_64.tar.zst
X86_SDK_URL: https://downloads.immortalwrt.org/releases/24.10.3/targets/x86/64/immortalwrt-sdk-24.10.3-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
run: |
echo "👉 正在下载依赖项"
sudo apt-get update
sudo apt-get install -y build-essential git wget python3 rsync zstd g++ make libncurses-dev
echo "✅ 下载完毕"
- name: Resolve SDK choice
id: vars
run: |
set -e
if [ "${{ github.event.inputs.sdk }}" = "x86_64" ]; then
echo "SDK_URL=${X86_SDK_URL}" >> $GITHUB_ENV
echo "PACKAGE_ARCH=x86_64" >> $GITHUB_ENV
echo "👉 选择x86_64架构"
elif [ "${{ github.event.inputs.sdk }}" = "filogic" ]; then
echo "SDK_URL=${FILOGIC_SDK_URL}" >> $GITHUB_ENV
echo "PACKAGE_ARCH=aarch64_cortex-a53" >> $GITHUB_ENV
echo "👉 选择aarch64架构"
else
echo "SDK_URL=${RAMIPS_SDK_URL}" >> $GITHUB_ENV
echo "PACKAGE_ARCH=ramips" >> $GITHUB_ENV
echo "👉 选择ramips架构"
fi
echo "WORK_ROOT=$GITHUB_WORKSPACE/imwrt-sdk" >> $GITHUB_ENV
- name: Download & extract SDK
run: |
set -euo pipefail
mkdir -p "$WORK_ROOT"
cd "$WORK_ROOT"
SDK_TAR="$(basename "$SDK_URL")"
echo "👉 正在下载SDK$SDK_TAR"
wget -q "$SDK_URL" -O "$SDK_TAR"
echo "📦 正在解压SDK..."
tar --use-compress-program="zstd -q -d" -xf "$SDK_TAR" >/dev/null 2>&1
echo "✅ SDK解压完成"
SDK_ROOT="$(find . -maxdepth 1 -type d -name 'immortalwrt-sdk*' | head -n 1)"
if [ -z "$SDK_ROOT" ]; then
echo "❌ 未找到SDK目录" >&2
exit 1
fi
SDK_ROOT="$(cd "$SDK_ROOT" && pwd)"
echo "SDK_ROOT=$SDK_ROOT" >> $GITHUB_ENV
echo "📁 SDK路径: $SDK_ROOT"
- name: Setup feeds & clone source
run: |
set -euo pipefail
cd "$SDK_ROOT"
echo "👉 正在设置feeds"
./scripts/feeds update -a
./scripts/feeds update luci || true
./scripts/feeds install -a -p luci || ./scripts/feeds install luci || true
echo "✅ feeds下载完毕"
cd package
git clone https://github.com/Dichgrem/luci-app-nyn.git
cp -r luci-app-nyn/luci-app-zzz . 2>/dev/null || true
cp -r luci-app-nyn/zzz . 2>/dev/null || true
rm -rf luci-app-nyn
- name: Build luci-app-zzz
run: |
set -euo pipefail
cd "$SDK_ROOT"
make defconfig
echo "👉 正在编译中"
make package/luci-app-zzz/compile V=s
echo "✅ 编译完成"
- name: Collect packages
run: |
set -euo pipefail
SDK_ROOT="$SDK_ROOT"
OUT="$GITHUB_WORKSPACE/output"
mkdir -p "$OUT"
echo "🔍 自动检测 SDK 包架构目录..."
BASE_DIR=$(find "$SDK_ROOT/bin/packages" -type d -path "*/base" | head -n1 || true)
if [ -z "$BASE_DIR" ]; then
echo "❌ 未找到 base 目录" >&2
ls -R "$SDK_ROOT/bin/packages" || true
exit 1
fi
echo "📦 从: $BASE_DIR 收集 luci-app-zzz 与 zzz 包..."
ls -lah "$BASE_DIR" || true
cp -v "$BASE_DIR"/*luci-app-zzz*.ipk "$OUT"/ 2>/dev/null || true
cp -v "$BASE_DIR"/*zzz*.ipk "$OUT"/ 2>/dev/null || true
echo "✅ 收集完成,输出目录内容:"
ls -lah "$OUT"
shell: bash
- name: Upload package one
uses: actions/upload-artifact@v4
with:
name: luci-app-zzz
path: output/*luci-app-zzz*.ipk
if-no-files-found: error
- name: Upload package two
uses: actions/upload-artifact@v4
with:
name: zzz
path: output/*zzz*.ipk
if-no-files-found: error

View File

@@ -0,0 +1,38 @@
name: Mirror to Codeberg
on:
push:
branches:
- main
tags:
- '*'
jobs:
mirror:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Push to Codeberg
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY_CODEBERG }}
REPO_URL_CODEBERG: ${{ secrets.REPO_URL_CODEBERG }}
run: |
set -euxo pipefail
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
cat >> ~/.ssh/config <<EOF
Host codeberg.org
IdentityFile ~/.ssh/id_ed25519
StrictHostKeyChecking no
EOF
git config --global user.name "GitHub Actions"
git config --global user.email "github-actions@github.com"
git remote add codeberg "$REPO_URL_CODEBERG"
git push --tags --force --prune codeberg "refs/remotes/origin/*:refs/heads/*"

View File

@@ -8,6 +8,15 @@
> Attention ! The nyn project is archived and it is recommended to use the c language version of zzz instead of it ! In order to commemorate nyn, the name of this project is not modified.
## How to use
- Step 0: Make sure you have an ``openwrt router``, ``download the ipk`` in Releases in this project, and ``upload and install`` it in the system-package of the Luci background.
- Step 1Fill in the user name: Student ID@operator. For example, ``212306666@cucc``, China Unicom is cucc, mobile is cmcc, and telecom is ctcc.
- Step 2: Fill in the password. The ``initial password`` is the last six digits of the ID card by default. It can be modified in the official client.
- Step 3: Select your network card; generally speaking, you can use ``ip addr`` to view the network card that has been assigned an IP, such as eth1.
- Step 4: ``Start the service`` and observe whether you can access the Internet, and then enable ``scheduled startup``; because the campus network will be closed from 12:00 to 7:00 the next day.
- Finallyenjoy it!
## How to build
- First clone this repository to the package directory of the openwrt you want to compile:
@@ -15,31 +24,35 @@
```
cd ./package
git clone https://github.com/Dichgrem/luci-app-nyn.git
cp -r ./luci-app-nyn/luci-app-zzz ./
cp -r ./luci-app-nyn/zzz ./
rm -rf ./luci-app-nyn
```
- Then select ``Network->nyn`` and ``LuCI->Applications->luci-app-nyn`` in make menuconfig and change them to "M" state;
- Then select ``Network->zzz`` and ``LuCI->Applications->luci-app-zzz`` in make menuconfig and change them to "M" state;
- Finally, run
```
make package/luci-app-nyn/clean V=s
make package/luci-app-nyn/compile V=s
make package/luci-app-zzz/clean V=s
make package/luci-app-zzz/compile V=s
```
and
```
make package/nyn/clean V=s
make package/nyn/compile V=s
make package/zzz/clean V=s
make package/zzz/compile V=s
```
to start build.
- You can use this command to find the compiled ipk:
```
find bin/ -name "nyn*.ipk"
bin/packages/x86_64/base/nyn_1.0.0-r1_x86_64.ipk
find bin/ -name "luci-app-nyn*.ipk"
bin/packages/x86_64/base/luci-app-nyn_0_all.ipk
find bin/ -name "zzz*.ipk"
bin/packages/x86_64/base/zzz_1.0.0-r1_x86_64.ipk
find bin/ -name "luci-app-zzz*.ipk"
bin/packages/x86_64/base/luci-app-zzz_0_all.ipk
```
## Acknowledgements
- [diredocks/zzz](https://github.com/diredocks/zzz)
- [diredocks/nyn](https://github.com/diredocks/nyn)
- [bitdust/njit8021xclient](https://github.com/bitdust/njit8021xclient)

View File

@@ -2,72 +2,71 @@
module("luci.controller.zzz", package.seeall)
function index()
if not nixio.fs.access("/etc/config/zzz") then
return
end
if not nixio.fs.access("/etc/config/zzz") then
return
end
-- Menu
entry({"admin", "network", "zzz"}, cbi("zzz"), "ZZZ", 60).dependent = false
-- Menu
entry({ "admin", "network", "zzz" }, cbi("zzz"), "ZZZ", 60).dependent = false
-- Settings
entry({"admin", "network", "zzz", "service_control"}, call("service_control")).leaf = true
-- Settings
entry({ "admin", "network", "zzz", "service_control" }, call("service_control")).leaf = true
-- Status API
entry({"admin", "network", "zzz", "get_status"}, call("act_status")).leaf = true
-- Status API
entry({ "admin", "network", "zzz", "get_status" }, call("act_status")).leaf = true
end
function service_control()
local sys = require "luci.sys"
local action = luci.http.formvalue("action")
local result = { success = false, message = "" }
local sys = require("luci.sys")
local action = luci.http.formvalue("action")
local result = { success = false, message = "" }
if action then
local cmd = ""
if action == "start" then
cmd = "/etc/rc.d/S99zzz start"
elseif action == "stop" then
cmd = "/etc/rc.d/S99zzz stop"
elseif action == "restart" then
cmd = "/etc/rc.d/S99zzz stop && sleep 2 && /etc/rc.d/S99zzz start"
end
if action then
local cmd = ""
if action == "start" then
cmd = "/etc/rc.d/S99zzz start"
elseif action == "stop" then
cmd = "/etc/rc.d/S99zzz stop"
elseif action == "restart" then
cmd = "/etc/rc.d/S99zzz stop && sleep 2 && /etc/rc.d/S99zzz start"
end
if cmd ~= "" then
local ret = sys.call(cmd)
if ret == 0 then
result.success = true
result.message = action .. " 成功"
else
result.success = false
result.message = action .. " 失败"
end
end
end
if cmd ~= "" then
local ret = sys.call(cmd)
if ret == 0 then
result.success = true
result.message = action .. " 成功"
else
result.success = false
result.message = action .. " 失败"
end
end
end
luci.http.prepare_content("application/json")
luci.http.write_json(result)
luci.http.prepare_content("application/json")
luci.http.write_json(result)
end
function act_status()
local sys = require "luci.sys"
local util = require "luci.util"
local status = {}
local sys = require("luci.sys")
local util = require("luci.util")
local status = {}
-- Get status
status.running = (sys.call("pgrep -f zzz >/dev/null") == 0)
-- Get status
status.running = (sys.call("pgrep -f zzz >/dev/null") == 0)
-- Get process info
if status.running then
status.process_info = util.trim(sys.exec("ps | grep -v grep | grep zzz"))
end
-- Get process info
if status.running then
status.process_info = util.trim(sys.exec("ps | grep -v grep | grep zzz"))
end
-- Get log
local log_file = "/tmp/zzz.log"
if nixio.fs.access(log_file) then
status.log = util.trim(sys.exec("tail -20 " .. log_file))
else
status.log = util.trim(sys.exec("logread | grep zzz | tail -10"))
end
-- Get log
local log_file = "/tmp/zzz.log"
if nixio.fs.access(log_file) then
status.log = util.trim(sys.exec("tail -20 " .. log_file))
else
status.log = util.trim(sys.exec("logread | grep zzz | tail -10"))
end
luci.http.prepare_content("application/json")
luci.http.write_json(status)
luci.http.prepare_content("application/json")
luci.http.write_json(status)
end

View File

@@ -1,6 +1,6 @@
-- /usr/lib/lua/luci/model/cbi/zzz.lua
local m, s, o
local sys = require "luci.sys"
local sys = require("luci.sys")
-- control
local start_action = luci.http.formvalue("cbid.zzz.auth.start_service")
@@ -8,15 +8,14 @@ local stop_action = luci.http.formvalue("cbid.zzz.auth.stop_service")
local restart_action = luci.http.formvalue("cbid.zzz.auth.restart_service")
if start_action then
sys.call("/etc/rc.d/S99zzz start")
sys.call("/etc/rc.d/S99zzz start")
elseif stop_action then
sys.call("/etc/rc.d/S99zzz stop")
sys.call("/etc/rc.d/S99zzz stop")
elseif restart_action then
sys.call("/etc/rc.d/S99zzz stop; sleep 2; /etc/rc.d/S99zzz start")
sys.call("/etc/rc.d/S99zzz stop; sleep 2; /etc/rc.d/S99zzz start")
end
m = Map("zzz", "ZZZ 802.1x 认证客户端",
"配置使用 zzz 客户端进行网络访问的 802.1x 认证")
m = Map("zzz", "ZZZ 802.1x 认证客户端", "配置使用 zzz 客户端进行网络访问的 802.1x 认证")
-- Authentication Settings
s = m:section(TypedSection, "auth", "认证设置")
@@ -27,20 +26,20 @@ s.addremove = false
o = s:option(DummyValue, "_status", "当前状态")
o.rawhtml = true
o.cfgvalue = function()
local sys = require "luci.sys"
local running = sys.call("pgrep zzz >/dev/null") == 0
if running then
return "<span style='color:green;font-weight:bold'>✔ 正在运行中</span>"
else
return "<span style='color:red;font-weight:bold'>✘ 未运行</span>"
end
local sys = require("luci.sys")
local running = sys.call("pgrep zzz >/dev/null") == 0
if running then
return "<span style='color:green;font-weight:bold'>✔ 正在运行中</span>"
else
return "<span style='color:red;font-weight:bold'>✘ 未运行</span>"
end
end
-- control buttons
control_buttons = s:option(DummyValue, "_control", "服务控制")
control_buttons.rawhtml = true
control_buttons.cfgvalue = function()
return [[
return [[
<div style="display: flex; gap: 10px; align-items: center; flex-wrap: wrap;">
<input type="submit" class="cbi-button cbi-button-apply"
name="cbid.zzz.auth.start_service" value="启动服务" />
@@ -53,17 +52,39 @@ control_buttons.cfgvalue = function()
end
-- Username
o = s:option(Value, "user", "用户名", "802.1x 认证用户名")
o = s:option(
Value,
"username",
"用户名",
[[802.1x 认证用户名
<span style="cursor: help; color: #007bff; font-weight: bold;" title="用户名为学号@运营商例如212306666@cucc移动为cmcc联通为cucc电信为ctcc">?</span>]]
)
o.password = true
o.rmempty = false
o.rawhtml = true
-- Password
o = s:option(Value, "password", "密码", "802.1x 认证密码")
o.password = true
o.rmempty = false
o = s:option(
Value,
"password",
"密码",
[[802.1x 认证密码
<span style="cursor: help; color: #007bff; font-weight: bold;" title="密码默认为身份证号后六位可以在官方客户端inode中修改">?</span>]]
)
o.password = true
o.rmempty = false
o.rawhtml = true
-- Network Device
o = s:option(ListValue, "device", "网络接口", "用于认证的网络接口")
o = s:option(
Value,
"device",
"网络接口",
[[用于认证的网络接口
<span style="cursor: help; color: #007bff; font-weight: bold;" title="可以用ip addr命令查看有10.38开头ip的接口">?</span>]]
)
o.rmempty = false
o:value("eth0", "eth0")
o:value("eth1", "eth1")
@@ -72,9 +93,9 @@ o:value("wan", "WAN")
-- Add network interface
local interfaces = sys.net.devices()
for _, iface in ipairs(interfaces) do
if iface ~= "lo" then
o:value(iface, iface)
end
if iface ~= "lo" then
o:value(iface, iface)
end
end
-- Auto start
@@ -84,34 +105,42 @@ auto_start.rmempty = false
-- Get Status
auto_start.cfgvalue = function(self, section)
local has_cron = sys.call("crontab -l 2>/dev/null | grep 'S99zzz' >/dev/null") == 0
return has_cron and "1" or "0"
local has_cron = sys.call("crontab -l 2>/dev/null | grep 'S99zzz' >/dev/null") == 0
return has_cron and "1" or "0"
end
-- Crontab
auto_start.write = function(self, section, value)
if value == "1" then
-- 启用定时任务:每周一至周五 7:00 启动
sys.call("(crontab -l 2>/dev/null | grep -v 'S99zzz' | grep -v '# zzz auto') | crontab - 2>/dev/null")
sys.call("(crontab -l 2>/dev/null; echo '0 7 * * 1,2,3,4,5 /etc/rc.d/S99zzz start # zzz auto start') | crontab -")
sys.call("/etc/init.d/cron enable && /etc/init.d/cron restart")
else
-- 禁用定时任务
sys.call("(crontab -l 2>/dev/null | grep -v 'S99zzz' | grep -v '# zzz auto') | crontab - 2>/dev/null")
sys.call("/etc/init.d/cron restart")
end
if value == "1" then
-- 启用定时任务:每周一至周五 7:00 启动
sys.call("(crontab -l 2>/dev/null | grep -v 'S99zzz' | grep -v '# zzz auto') | crontab - 2>/dev/null")
sys.call(
"(crontab -l 2>/dev/null; echo '0 7 * * 1,2,3,4,5 /etc/rc.d/S99zzz start # zzz auto start') | crontab -"
)
sys.call("/etc/init.d/cron enable && /etc/init.d/cron restart")
else
-- 禁用定时任务
sys.call("(crontab -l 2>/dev/null | grep -v 'S99zzz' | grep -v '# zzz auto') | crontab - 2>/dev/null")
sys.call("/etc/init.d/cron restart")
end
end
-- Crontab Status
timer_status_display = s:option(DummyValue, "_timer_status_display", "定时任务状态")
timer_status_display.rawhtml = true
timer_status_display.cfgvalue = function()
local cron_output = sys.exec("crontab -l 2>/dev/null | grep 'S99zzz' || echo '未设置'")
if cron_output:match("S99zzz") then
return "<span style='color:green;font-weight:bold'>✔ 已启用 (每周一至周五 7:00 自动启动)</span>"
else
return "<span style='color:red;font-weight:bold'>✘ 未启用</span>"
end
local cron_output = sys.exec("crontab -l 2>/dev/null | grep 'S99zzz' || echo '未设置'")
if cron_output:match("S99zzz") then
return "<span style='color:green;font-weight:bold'>✔ 已启用 (每周一至周五 7:00 自动启动)</span>"
else
return "<span style='color:red;font-weight:bold'>✘ 未启用</span>"
end
end
-- 保存后自动重启 zzz 服务
m.on_commit = function(self)
local sys = require("luci.sys")
sys.call("/etc/rc.d/S99zzz restart >/dev/null 2>&1 &")
end
return m

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 155 KiB