🎉 Sync 2026-10-13 04:18:45

This commit is contained in:
github-actions[bot] committed 2026-10-13 04:18:45 +08:00
1 parent 20088f50c1
commit de5c7f129c
11 files changed
+1458 -8

No files matched your search

@@ -71,6 +71,12 @@ list)
printf '"cut_status":{},'
printf '"cut_set":{"active":"bool","duration":"int","persist":"bool"},'
printf '"activity_log":{"lines":"int"},'
printf '"history_status":{},'
printf '"history_read":{"period":"str","to":"str"},'
printf '"history_periods":{},'
printf '"history_config_get":{},'
printf '"history_config_set":{"enabled":"bool","dir":"str","period":"str","interval":"int","sample_interval":"int","keep":"int"},'
printf '"history_flush":{},'
printf '"version":{}'
printf '}'
;;
@@ -596,6 +602,99 @@ call)
echo '{"ok":true,"lines":[]}'
fi
;;
history_status)
printf '{"result":'
$SCRIPTS/trafficctl-history.sh status
printf '}'
;;
history_periods)
printf '{"result":'
$SCRIPTS/trafficctl-history.sh periods
printf '}'
;;
history_read)
read -r input
# Period ids are compared as strings inside the script and never
# interpolated into a path, but they still come from the network, so
# the shape is pinned here: a value that is not a period id is
# rejected rather than passed through and silently matching nothing.
hp=$(echo "$input" | jsonfilter -e '@.period' 2>/dev/null)
ht=$(echo "$input" | jsonfilter -e '@.to' 2>/dev/null)
for v in "$hp" "$ht"; do
[ -z "$v" ] && continue
case "$v" in
[0-9][0-9][0-9][0-9]-[0-9][0-9]) ;;
[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]) ;;
[0-9][0-9][0-9][0-9]-W[0-9][0-9]) ;;
*) echo '{"result":[]}'; exit 0 ;;
esac
done
printf '{"result":'
$SCRIPTS/trafficctl-history.sh read "$hp" "$ht"
printf '}'
;;
history_config_get)
printf '{"result":'
$SCRIPTS/trafficctl-history.sh status
printf '}'
;;
history_config_set)
read -r input
uci -q get trafficctl.history >/dev/null 2>&1 || uci set trafficctl.history=history
val=$(echo "$input" | jsonfilter -e '@.dir' 2>/dev/null)
if [ -n "$val" ]; then
# Validated by the script that owns the rule, not by a second copy
# of it here. The directory is both a mkdir -p and a delete target
# (prune removes *.tsv inside it), so an unconstrained value would
# hand this write method arbitrary directory creation and the
# removal of any .tsv on the filesystem.
if ! $SCRIPTS/trafficctl-history.sh validate-dir "$val" 2>/dev/null; then
echo '{"ok":false,"msg":"dir must be under /etc/trafficctl, /mnt, /media, /srv or /tmp"}'
exit 0
fi
uci set trafficctl.history.dir="$val"
fi
val=$(echo "$input" | jsonfilter -e '@.period' 2>/dev/null)
if [ -n "$val" ]; then
case "$val" in
day|week|month) uci set trafficctl.history.period="$val" ;;
*) echo '{"ok":false,"msg":"period must be day, week or month"}'; exit 0 ;;
esac
fi
for k in interval sample_interval keep; do
val=$(echo "$input" | jsonfilter -e "@.$k" 2>/dev/null)
[ -z "$val" ] && continue
case "$val" in
''|*[!0-9]*) echo "{\"ok\":false,\"msg\":\"$k must be a number\"}"; exit 0 ;;
esac
uci set "trafficctl.history.$k=$val"
done
val=$(echo "$input" | jsonfilter -e '@.enabled' 2>/dev/null)
if [ -n "$val" ]; then
uci set "trafficctl.history.enabled=$([ "$val" = "true" ] && echo 1 || echo 0)"
fi
tctl_commit
# The keeper re-reads the intervals and the directory on every tick,
# but it has to be RUNNING to do that — switching history on for the
# first time must not wait for a reboot.
if [ -x /etc/init.d/trafficctl-history ]; then
if [ "$(uci -q get trafficctl.history.enabled)" = "1" ]; then
/etc/init.d/trafficctl-history enable 2>/dev/null
/etc/init.d/trafficctl-history start 2>/dev/null
else
/etc/init.d/trafficctl-history stop 2>/dev/null
fi
fi
tctl_log "config_change" "history" "" "luci" "${TCTL_SRC:-local}"
echo '{"ok":true}'
;;
history_flush)
# A "flush now" button. Writes to durable storage, so it is a write
# method even though it only persists numbers that already exist.
printf '{"result":'
$SCRIPTS/trafficctl-history.sh flush
printf '}'
;;
version)
ver=$(opkg info luci-app-trafficctl 2>/dev/null | awk '/^Version:/{print $2}')
[ -z "$ver" ] && ver="dev"