From e5d57360706e3b5798ab4fdd3b88aa15d7c334f3 Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Wed, 18 Jun 2025 06:32:20 -0700 Subject: [PATCH 1/7] Update Create-NewReleases.yml Linefeed to --- .github/workflows/Create-NewReleases.yml | 212 +++++++++++------------ 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/.github/workflows/Create-NewReleases.yml b/.github/workflows/Create-NewReleases.yml index 19f7939..19b54ea 100644 --- a/.github/workflows/Create-NewReleases.yml +++ b/.github/workflows/Create-NewReleases.yml @@ -1,106 +1,106 @@ -name: Auto Tag and Release on PR Merge - -on: - pull_request: - branches: - - 'master' - types: - - closed - -permissions: - contents: write - -jobs: - tag-and-release: - # Run only when the PR came from the develop branch and was merged - if: github.event.pull_request.merged == true && github.head_ref == 'develop' - runs-on: ubuntu-latest - - steps: - # 1--- Check out master so we tag the exact merge commit - - name: Checkout source code - uses: actions/checkout@v4.2.2 - with: - fetch-depth: 0 - ref: 'master' - ssh-key: ${{ secrets.DEPLOY_KEY }} - - # 2--- Configure author details for any subsequent commits - - name: Configure Git - run: | - git config --local user.email "github-actions@github.com" - git config --local user.name "GitHub Actions" - - # 3--- Identify the version in Script.sh and expose it as an output - - name: Determine Version Tag from Script.sh - id: nextver - run: | - VERSION=$(grep -E '^readonly[[:space:]]+SCRIPT_VERSION=' ntpmerlin.sh \ - | cut -d '=' -f2 \ - | cut -d '#' -f1 \ - | tr -d '"[:space:]') - - # Fallback to previous logic only if unable to read from script - if [[ -z "$VERSION" ]]; then - CURRENT_TAG=$(git tag --sort=-v:refname | head -n 1) - [[ $CURRENT_TAG == '' ]] && CURRENT_TAG='v0.1.0' - MAJOR=$(echo $CURRENT_TAG | cut -d '.' -f 1 | cut -c 2-) - MINOR=$(echo $CURRENT_TAG | cut -d '.' -f 2) - PATCH=$(echo $CURRENT_TAG | cut -d '.' -f 3) - if [[ $PATCH -eq 9 ]]; then - PATCH=0 - if [[ $MINOR -eq 9 ]]; then - MINOR=0 - MAJOR=$((MAJOR+1)) - else - MINOR=$((MINOR+1)) - fi - else - PATCH=$((PATCH+1)) - fi - VERSION="v$MAJOR.$MINOR.$PATCH" - fi - - # Ensure the tag starts with "v" - [[ $VERSION != v* ]] && VERSION="v$VERSION" - - echo "Using version tag $VERSION" - echo "tag=$VERSION" >> "$GITHUB_OUTPUT" - - # 4--- Update SCRIPT_BRANCH only - - name: Update Script.sh Script Branch - run: | - sed -i '/^SCRIPT_BRANCH=.*$/s/.*/SCRIPT_BRANCH="master"/' ntpmerlin.sh - - # 5--- Commit branch change only if the file was actually modified - - name: Commit branch change - run: | - git add ntpmerlin.sh - if ! git diff --cached --quiet; then - git commit -m 'Set SCRIPT_BRANCH to "master" after merge' - git push origin master - else - echo "No branch change needed" - fi - - # 6--- Create and push the tag taken from Script.sh - - name: Create and Push Tag - run: | - TAG="${{ steps.nextver.outputs.tag }}" - # Skip if the tag already exists (avoids fatal push error) - if git rev-parse "$TAG" >/dev/null 2>&1; then - echo "Tag $TAG already exists – skipping creation" - else - git tag "$TAG" - git push origin "$TAG" - fi - - # 7--- Publish a GitHub Release with auto-generated notes - - name: Create Release with Automated Release Notes - uses: softprops/action-gh-release@v2.2.2 - with: - token: ${{ secrets.GITHUB_TOKEN }} - tag_name: ${{ steps.nextver.outputs.tag }} - name: "Release ${{ steps.nextver.outputs.tag }}" - prerelease: false - generate_release_notes: true +name: Auto Tag and Release on PR Merge + +on: + pull_request: + branches: + - 'master' + types: + - closed + +permissions: + contents: write + +jobs: + tag-and-release: + # Run only when the PR came from the develop branch and was merged + if: github.event.pull_request.merged == true && github.head_ref == 'develop' + runs-on: ubuntu-latest + + steps: + # 1--- Check out master so we tag the exact merge commit + - name: Checkout source code + uses: actions/checkout@v4.2.2 + with: + fetch-depth: 0 + ref: 'master' + ssh-key: ${{ secrets.DEPLOY_KEY }} + + # 2--- Configure author details for any subsequent commits + - name: Configure Git + run: | + git config --local user.email "github-actions@github.com" + git config --local user.name "GitHub Actions" + + # 3--- Identify the version in Script.sh and expose it as an output + - name: Determine Version Tag from Script.sh + id: nextver + run: | + VERSION=$(grep -E '^readonly[[:space:]]+SCRIPT_VERSION=' ntpmerlin.sh \ + | cut -d '=' -f2 \ + | cut -d '#' -f1 \ + | tr -d '"[:space:]') + + # Fallback to previous logic only if unable to read from script + if [[ -z "$VERSION" ]]; then + CURRENT_TAG=$(git tag --sort=-v:refname | head -n 1) + [[ $CURRENT_TAG == '' ]] && CURRENT_TAG='v0.1.0' + MAJOR=$(echo $CURRENT_TAG | cut -d '.' -f 1 | cut -c 2-) + MINOR=$(echo $CURRENT_TAG | cut -d '.' -f 2) + PATCH=$(echo $CURRENT_TAG | cut -d '.' -f 3) + if [[ $PATCH -eq 9 ]]; then + PATCH=0 + if [[ $MINOR -eq 9 ]]; then + MINOR=0 + MAJOR=$((MAJOR+1)) + else + MINOR=$((MINOR+1)) + fi + else + PATCH=$((PATCH+1)) + fi + VERSION="v$MAJOR.$MINOR.$PATCH" + fi + + # Ensure the tag starts with "v" + [[ $VERSION != v* ]] && VERSION="v$VERSION" + + echo "Using version tag $VERSION" + echo "tag=$VERSION" >> "$GITHUB_OUTPUT" + + # 4--- Update SCRIPT_BRANCH only + - name: Update Script.sh Script Branch + run: | + sed -i '/^SCRIPT_BRANCH=.*$/s/.*/SCRIPT_BRANCH="master"/' ntpmerlin.sh + + # 5--- Commit branch change only if the file was actually modified + - name: Commit branch change + run: | + git add ntpmerlin.sh + if ! git diff --cached --quiet; then + git commit -m 'Set SCRIPT_BRANCH to "master" after merge' + git push origin master + else + echo "No branch change needed" + fi + + # 6--- Create and push the tag taken from Script.sh + - name: Create and Push Tag + run: | + TAG="${{ steps.nextver.outputs.tag }}" + # Skip if the tag already exists (avoids fatal push error) + if git rev-parse "$TAG" >/dev/null 2>&1; then + echo "Tag $TAG already exists – skipping creation" + else + git tag "$TAG" + git push origin "$TAG" + fi + + # 7--- Publish a GitHub Release with auto-generated notes + - name: Create Release with Automated Release Notes + uses: softprops/action-gh-release@v2.2.2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag_name: ${{ steps.nextver.outputs.tag }} + name: "Release ${{ steps.nextver.outputs.tag }}" + prerelease: false + generate_release_notes: true From 9d1a5b6d7b9be2d815e21d049d7ed9e8fd516cd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 08:44:44 +0000 Subject: [PATCH 2/7] Bump actions/checkout from 5.0.0 to 6.0.0 in the all-actions group Bumps the all-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 5.0.0 to 6.0.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5.0.0...v6.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: all-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/Create-NewReleases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Create-NewReleases.yml b/.github/workflows/Create-NewReleases.yml index 3e950ee..d249078 100644 --- a/.github/workflows/Create-NewReleases.yml +++ b/.github/workflows/Create-NewReleases.yml @@ -19,7 +19,7 @@ jobs: steps: # 1--- Check out master so we tag the exact merge commit - name: Checkout source code - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v6.0.0 with: fetch-depth: 0 ref: 'master' From 6a86c2a1ec61f0b5f8a70a788030c5177295ada3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 09:59:24 +0000 Subject: [PATCH 3/7] Bump softprops/action-gh-release in the all-actions group Bumps the all-actions group with 1 update: [softprops/action-gh-release](https://github.com/softprops/action-gh-release). Updates `softprops/action-gh-release` from 2.4.2 to 2.5.0 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2.4.2...v2.5.0) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 2.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/Create-NewReleases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Create-NewReleases.yml b/.github/workflows/Create-NewReleases.yml index d249078..3ea75f4 100644 --- a/.github/workflows/Create-NewReleases.yml +++ b/.github/workflows/Create-NewReleases.yml @@ -97,7 +97,7 @@ jobs: # 7--- Publish a GitHub Release with auto-generated notes - name: Create Release with Automated Release Notes - uses: softprops/action-gh-release@v2.4.2 + uses: softprops/action-gh-release@v2.5.0 with: token: ${{ secrets.GITHUB_TOKEN }} tag_name: ${{ steps.nextver.outputs.tag }} From fe90302977448da41cee9f6fb10729e01f19abed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 08:19:35 +0000 Subject: [PATCH 4/7] Bump actions/checkout from 6.0.0 to 6.0.1 in the all-actions group Bumps the all-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 6.0.0 to 6.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6.0.0...v6.0.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/Create-NewReleases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Create-NewReleases.yml b/.github/workflows/Create-NewReleases.yml index 3ea75f4..a253826 100644 --- a/.github/workflows/Create-NewReleases.yml +++ b/.github/workflows/Create-NewReleases.yml @@ -19,7 +19,7 @@ jobs: steps: # 1--- Check out master so we tag the exact merge commit - name: Checkout source code - uses: actions/checkout@v6.0.0 + uses: actions/checkout@v6.0.1 with: fetch-depth: 0 ref: 'master' From c71d8019fee45b65a7e330af8c64aa739f45a6c2 Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 15 Dec 2025 23:34:27 -0800 Subject: [PATCH 5/7] Improvements for the top Main Menu Modified the CLI top Main Menu to separate some groups of options and settings into their own sub-menus. This is an effort to make the top Main Menu shorter, more manageable, more user-friendly, and to improve the user experience. --- README.md | 4 +- ntpmerlin.sh | 450 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 283 insertions(+), 171 deletions(-) diff --git a/README.md b/README.md index ea5b3be..a9ee47b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ntpMerlin -## v3.4.12 -### Updated on 2025-Nov-16 +## v3.4.13 +### Updated on 2025-Dec-15 ## About ntpMerlin implements an NTP time server for AsusWRT Merlin with charts for daily, weekly and monthly summaries of performance. A choice between ntpd and chrony is available. diff --git a/ntpmerlin.sh b/ntpmerlin.sh index 82033ab..1ddcba2 100644 --- a/ntpmerlin.sh +++ b/ntpmerlin.sh @@ -14,7 +14,7 @@ ## Forked from https://github.com/jackyaz/ntpMerlin ## ## ## ############################################################## -# Last Modified: 2025-Nov-16 +# Last Modified: 2025-Dec-15 #------------------------------------------------------------- ############### Shellcheck directives ############# @@ -36,8 +36,8 @@ ### Start of script variables ### readonly SCRIPT_NAME="ntpMerlin" readonly SCRIPT_NAME_LOWER="$(echo "$SCRIPT_NAME" | tr 'A-Z' 'a-z' | sed 's/d//')" -readonly SCRIPT_VERSION="v3.4.12" -readonly SCRIPT_VERSTAG="25111608" +readonly SCRIPT_VERSION="v3.4.13" +readonly SCRIPT_VERSTAG="25121522" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/$SCRIPT_NAME_LOWER.d" @@ -112,6 +112,8 @@ readonly PassBGRNct="\e[30;102m" readonly WarnBYLWct="\e[30;103m" readonly WarnIMGNct="\e[45m" readonly WarnBMGNct="\e[30;105m" +readonly BOLDUNDERLN="\e[1;4m" +readonly menuSepStr="${BOLD}##############################################################${CLRct}" ### End of output format variables ### @@ -1423,8 +1425,9 @@ DaysToKeep() while true do ScriptHeader - printf "${BOLD}Current number of days to keep data: ${GRNct}${daysToKeep}${CLRct}\n\n" - printf "${BOLD}Please enter the maximum number of days\nto keep the data for [${MINvalue}-${MAXvalue}] (e=Exit):${CLEARFORMAT} " + printf " ${BOLD}Current number of days to keep data: ${GRNct}${daysToKeep}${CLRct}\n\n" + printf " ${BOLD}Please enter the maximum number of days\n" + printf " to keep the data for [${MINvalue}-${MAXvalue}] (e=Exit):${CLEARFORMAT} " read -r daystokeep_choice if [ -z "$daystokeep_choice" ] && \ echo "$daysToKeep" | grep -qE "^([1-9][0-9]{1,2})$" && \ @@ -1438,11 +1441,11 @@ DaysToKeep() break elif ! Validate_Number "$daystokeep_choice" then - printf "\n${ERR}Please enter a valid number [${MINvalue}-${MAXvalue}].${CLEARFORMAT}\n" + printf "\n ${ERR}Please enter a valid number [${MINvalue}-${MAXvalue}].${CLEARFORMAT}\n" PressEnter elif [ "$daystokeep_choice" -lt "$MINvalue" ] || [ "$daystokeep_choice" -gt "$MAXvalue" ] then - printf "\n${ERR}Please enter a number between ${MINvalue} and ${MAXvalue}.${CLEARFORMAT}\n" + printf "\n ${ERR}Please enter a number between ${MINvalue} and ${MAXvalue}.${CLEARFORMAT}\n" PressEnter else daysToKeep="$daystokeep_choice" @@ -1479,8 +1482,9 @@ LastXResults() while true do ScriptHeader - printf "${BOLD}Current number of results to display: ${GRNct}${lastXResults}${CLRct}\n\n" - printf "${BOLD}Please enter the maximum number of results\nto display in the WebUI [${MINvalue}-${MAXvalue}] (e=Exit):${CLEARFORMAT} " + printf " ${BOLD}Current number of results to display: ${GRNct}${lastXResults}${CLRct}\n\n" + printf " ${BOLD}Please enter the maximum number of results\n" + printf " to display in the WebUI [${MINvalue}-${MAXvalue}] (e=Exit):${CLEARFORMAT} " read -r lastx_choice if [ -z "$lastx_choice" ] && \ echo "$lastXResults" | grep -qE "^([1-9][0-9]{0,2})$" && \ @@ -1494,11 +1498,11 @@ LastXResults() break elif ! Validate_Number "$lastx_choice" then - printf "\n${ERR}Please enter a valid number [${MINvalue}-${MAXvalue}].${CLEARFORMAT}\n" + printf "\n ${ERR}Please enter a valid number [${MINvalue}-${MAXvalue}].${CLEARFORMAT}\n" PressEnter elif [ "$lastx_choice" -lt "$MINvalue" ] || [ "$lastx_choice" -gt "$MAXvalue" ] then - printf "\n${ERR}Please enter a number between ${MINvalue} and ${MAXvalue}.${CLEARFORMAT}\n" + printf "\n ${ERR}Please enter a number between ${MINvalue} and ${MAXvalue}.${CLEARFORMAT}\n" PressEnter else lastXResults="$lastx_choice" @@ -2517,30 +2521,37 @@ _CenterTextStr_() } ##----------------------------------------## -## Modified by Martinski W. [2025-Oct-25] ## +## Modified by Martinski W. [2025-Dec-15] ## ##----------------------------------------## ScriptHeader() { - clear - local spaceLen=56 colorCT - [ "$SCRIPT_BRANCH" = "master" ] && colorCT="$GRNct" || colorCT="$MGNTct" + local spaceLen=56 colorCT showFullInfo=false - DST_ENABLED="$(nvram get time_zone_dst)" - if ! Validate_Number "$DST_ENABLED"; then DST_ENABLED=0; fi - if [ "$DST_ENABLED" -eq 0 ]; then - DST_ENABLED="Inactive" - else - DST_ENABLED="Active" + if [ $# -gt 0 ] && [ "$1" = "true" ] + then showFullInfo=true fi + [ "$SCRIPT_BRANCH" = "master" ] && colorCT="$GRNct" || colorCT="$MGNTct" - DST_SETTING="$(nvram get time_zone_dstoff)" - DST_SETTING="$(echo "$DST_SETTING" | sed 's/M//g')" - DST_START="$(echo "$DST_SETTING" | cut -f1 -d",")" - DST_START="Month $(echo "$DST_START" | cut -f1 -d".") Week $(echo "$DST_START" | cut -f2 -d".") Weekday $(echo "$DST_START" | cut -f3 -d"." | cut -f1 -d"/") Hour $(echo "$DST_START" | cut -f3 -d"." | cut -f2 -d"/")" - DST_END="$(echo "$DST_SETTING" | cut -f2 -d",")" - DST_END="Month $(echo "$DST_END" | cut -f1 -d".") Week $(echo "$DST_END" | cut -f2 -d".") Weekday $(echo "$DST_END" | cut -f3 -d"." | cut -f1 -d"/") Hour $(echo "$DST_END" | cut -f3 -d"." | cut -f2 -d"/")" + if "$showFullInfo" + then + DST_ENABLED="$(nvram get time_zone_dst)" + if ! Validate_Number "$DST_ENABLED" + then DST_ENABLED=0 + fi + if [ "$DST_ENABLED" -ne 0 ] + then DST_ENABLED="Active" + else DST_ENABLED="Inactive" + fi - echo + DST_SETTING="$(nvram get time_zone_dstoff)" + DST_SETTING="$(echo "$DST_SETTING" | sed 's/M//g')" + DST_START="$(echo "$DST_SETTING" | cut -f1 -d",")" + DST_START="Month $(echo "$DST_START" | cut -f1 -d".") Week $(echo "$DST_START" | cut -f2 -d".") Weekday $(echo "$DST_START" | cut -f3 -d"." | cut -f1 -d"/") Hour $(echo "$DST_START" | cut -f3 -d"." | cut -f2 -d"/")" + DST_END="$(echo "$DST_SETTING" | cut -f2 -d",")" + DST_END="Month $(echo "$DST_END" | cut -f1 -d".") Week $(echo "$DST_END" | cut -f2 -d".") Weekday $(echo "$DST_END" | cut -f3 -d"." | cut -f1 -d"/") Hour $(echo "$DST_END" | cut -f3 -d"." | cut -f2 -d"/")" + fi + + clear ; echo printf "${BOLD}##############################################################${CLRct}\n" printf "${BOLD}## _ __ __ _ _ ##${CLRct}\n" printf "${BOLD}## | | | \/ | | |(_) ##${CLRct}\n" @@ -2557,78 +2568,53 @@ ScriptHeader() printf "${BOLD}## https://github.com/AMTM-OSR/ntpMerlin ##${CLRct}\n" printf "${BOLD}## Forked from https://github.com/jackyaz/ntpMerlin ##${CLRct}\n" printf "${BOLD}## ##${CLRct}\n" + + if "$showFullInfo" + then printf "${BOLD}## DST is currently %-8s ##${CLRct}\n" "$DST_ENABLED" printf "${BOLD}## ##${CLRct}\n" printf "${BOLD}## DST starts on %-33s ##${CLRct}\n" "$DST_START" printf "${BOLD}## DST ends on %-33s ##${CLRct}\n" "$DST_END" printf "${BOLD}## ##${CLRct}\n" + fi printf "${BOLD}##############################################################${CLRct}\n\n" } ##----------------------------------------## -## Modified by Martinski W. [2025-Jul-30] ## +## Modified by Martinski W. [2025-Dec-15] ## ##----------------------------------------## -MainMenu() +_HandleInvalidMenuOption_() { - local menuOption storageLocStr ntpRedirectStatus - local jffsFreeSpace jffsFreeSpaceStr jffsSpaceMsgTag + [ -n "$menuOption" ] && \ + printf "\n${REDct}INVALID input [$menuOption]${CLRct}" + printf "\nPlease choose a valid option.\n\n" +} - if Auto_NAT check - then ntpRedirectStatus="${PassBGRNct} ENABLED ${CLRct}" - else ntpRedirectStatus="${CritIREDct} DISABLED ${CLRct}" - fi +##----------------------------------------## +## Modified by Martinski W. [2025-Dec-15] ## +##----------------------------------------## +_Menu_TimeServerOptions_() +{ + local menuOption exitMenu=false TIMESERVER_NAME configPath - TIMESERVER_NAME_MENU="$(TimeServer check)" - CONFFILE_MENU="" - if [ "$TIMESERVER_NAME_MENU" = "ntpd" ] - then CONFFILE_MENU="$SCRIPT_STORAGE_DIR/ntp.conf" - elif [ "$TIMESERVER_NAME_MENU" = "chronyd" ] - then CONFFILE_MENU="$SCRIPT_STORAGE_DIR/chrony.conf" + TIMESERVER_NAME="$(TimeServer check)" + configPath="UNKNOWN" + if [ "$TIMESERVER_NAME" = "ntpd" ] + then configPath="$SCRIPT_STORAGE_DIR/ntp.conf" + elif [ "$TIMESERVER_NAME" = "chronyd" ] + then configPath="$SCRIPT_STORAGE_DIR/chrony.conf" fi - storageLocStr="$(ScriptStorageLocation check | tr 'a-z' 'A-Z')" - - _UpdateJFFS_FreeSpaceInfo_ - jffsFreeSpace="$(_Get_JFFS_Space_ FREE HRx | sed 's/%/%%/')" - if ! echo "$JFFS_LowFreeSpaceStatus" | grep -E "^WARNING[0-9]$" - then - jffsFreeSpaceStr="${SETTING}$jffsFreeSpace" - else - if [ "$storageLocStr" = "JFFS" ] - then jffsSpaceMsgTag="${CritBREDct} <<< WARNING! " - else jffsSpaceMsgTag="${WarnBMGNct} <<< NOTICE! " - fi - jffsFreeSpaceStr="${WarnBYLWct} $jffsFreeSpace ${CLRct} ${jffsSpaceMsgTag}${CLRct}" - fi + ScriptHeader + printf " ${BOLDUNDERLN}${GRNct}Time Server Options${CLRct}\n\n" - printf "WebUI for %s is available at:\n${SETTING}%s${CLEARFORMAT}\n\n" "$SCRIPT_NAME" "$(Get_WebUI_URL)" - - printf "1. Update timeserver stats now\n" - printf " Database size: ${SETTING}%s${CLEARFORMAT}\n\n" "$(_GetFileSize_ "$NTPDSTATS_DB" HRx)" - printf "2. Toggle redirect of all NTP traffic to %s\n" "$SCRIPT_NAME" - printf " Currently: ${ntpRedirectStatus}${CLEARFORMAT}\n\n" - printf "3. Edit ${SETTING}%s${CLEARFORMAT} configuration file\n\n" "$(TimeServer check)" - printf "4. Toggle time output mode\n" - printf " Currently: ${SETTING}%s${CLEARFORMAT} time values will be used for CSV exports\n\n" "$(OutputTimeMode check)" - printf "5. Set number of timeserver stats to show in WebUI\n" - printf " Currently: ${SETTING}%s results will be shown${CLEARFORMAT}\n\n" "$(LastXResults check)" - printf "6. Set number of days data to keep in database\n" - printf " Currently: ${SETTING}%s days data will be kept${CLEARFORMAT}\n\n" "$(DaysToKeep check)" - printf "s. Toggle storage location for stats and config\n" - printf " Current location: ${SETTING}%s${CLEARFORMAT}\n" "$storageLocStr" - printf " JFFS Available: ${jffsFreeSpaceStr}${CLEARFORMAT}\n\n" - printf "t. Switch timeserver between ${SETTING}ntpd${CLRct} and ${SETTING}chronyd${CLRct}\n" - printf " Currently: ${SETTING}%s${CLEARFORMAT}\n" "$(TimeServer check)" - printf " Config location: ${SETTING}%s${CLEARFORMAT}\n\n" "$CONFFILE_MENU" - printf "r. Restart ${SETTING}%s${CLEARFORMAT}\n\n" "$(TimeServer check)" - printf "u. Check for updates\n" - printf "uf. Update %s with latest version (force update)\n\n" "$SCRIPT_NAME" - printf "rs. Reset %s database / delete all data\n\n" "$SCRIPT_NAME" - printf "e. Exit %s\\n\n" "$SCRIPT_NAME" - printf "z. Uninstall %s\n" "$SCRIPT_NAME" - printf "\n" - printf "${BOLD}##############################################################${CLEARFORMAT}\n" - printf "\n" + printf " ${GRNct}1${CLRct}. Edit ${SETTING}%s${CLRct} time server configuration file\n\n" "$(TimeServer check)" + printf " ${GRNct}ts${CLRct}. Switch time server between ${SETTING}ntpd${CLRct} and ${SETTING}chronyd${CLRct}\n" + printf " Currently: ${SETTING}%s${CLRct}\n" "$(TimeServer check)" + printf " Config location: ${SETTING}%s${CLRct}\n\n" "$configPath" + printf " ${GRNct}rs${CLRct}. Restart ${SETTING}%s${CLRct}\n\n" "$(TimeServer check)" + printf " ${GRNct}e${CLRct}. Return to Main Menu\n" + printf "\n${menuSepStr}\n\n" while true do @@ -2637,53 +2623,113 @@ MainMenu() case "$menuOption" in 1) printf "\n" - TimeServer_ServiceCheck if Check_Lock menu then - Get_TimeServer_Stats - Clear_Lock + Menu_Edit && PressEnter fi - PressEnter break ;; - 2) + ts) printf "\n" - if Auto_NAT check + if Check_Lock menu then - Auto_NAT delete - NTP_Redirect delete - printf "${BOLD}NTP Redirect has been ${REDct}DISABLED${CLEARFORMAT}\n\n" - else - Auto_NAT create - NTP_Redirect create - printf "${BOLD}NTP Redirect has been ${GRNct}ENABLED${CLEARFORMAT}\n\n" + if [ "$(TimeServer check)" = "ntpd" ] + then + TimeServer chronyd + elif [ "$(TimeServer check)" = "chronyd" ] + then + TimeServer ntpd + fi + Clear_Lock fi PressEnter break ;; - 3) + rs) printf "\n" - if Check_Lock menu; then - Menu_Edit - fi + TIMESERVER_NAME="$(TimeServer check)" + Print_Output true "Restarting $TIMESERVER_NAME..." "$PASS" + TimeServer_ServiceCheck + "/opt/etc/init.d/S77$TIMESERVER_NAME" restart >/dev/null 2>&1 PressEnter break ;; - 4) + e) exitMenu=true + break + ;; + *) + _HandleInvalidMenuOption_ + PressEnter + break + ;; + esac + done + + "$exitMenu" && return 0 + _Menu_TimeServerOptions_ +} + +##----------------------------------------## +## Modified by Martinski W. [2025-Dec-15] ## +##----------------------------------------## +_Menu_DatabaseOptions_() +{ + local menuOption exitMenu=false storageLocStr + local jffsFreeSpace jffsFreeSpaceStr jffsSpaceMsgTag + + storageLocStr="$(ScriptStorageLocation check | tr 'a-z' 'A-Z')" + + _UpdateJFFS_FreeSpaceInfo_ + jffsFreeSpace="$(_Get_JFFS_Space_ FREE HRx | sed 's/%/%%/')" + if ! echo "$JFFS_LowFreeSpaceStatus" | grep -E "^WARNING[0-9]$" + then + jffsFreeSpaceStr="${SETTING}$jffsFreeSpace" + else + if [ "$storageLocStr" = "JFFS" ] + then jffsSpaceMsgTag="${CritBREDct} <<< WARNING! " + else jffsSpaceMsgTag="${WarnBMGNct} <<< NOTICE! " + fi + jffsFreeSpaceStr="${WarnBYLWct} $jffsFreeSpace ${CLRct} ${jffsSpaceMsgTag}${CLRct}" + fi + + ScriptHeader + printf " ${BOLDUNDERLN}${GRNct}Database Options${CLRct}\n\n" + + printf " ${GRNct}1${CLRct}. Toggle time output mode\n" + printf " Currently: ${SETTING}%s${CLRct} time values will be used for CSV exports\n\n" "$(OutputTimeMode check)" + printf " ${GRNct}2${CLRct}. Set number of time server database stats to show in WebUI\n" + printf " Currently: ${SETTING}%s results will be shown${CLRct}\n\n" "$(LastXResults check)" + printf " ${GRNct}3${CLRct}. Set maximum number of days data to keep in database\n" + printf " Currently: ${SETTING}%s days data will be kept${CLRct}\n\n" "$(DaysToKeep check)" + printf " ${GRNct}s${CLRct}. Toggle storage location for database stats and config\n" + printf " Current location: ${SETTING}%s${CLRct}\n" "$storageLocStr" + printf " JFFS Available: ${jffsFreeSpaceStr}${CLRct}\n\n" + printf " ${GRNct}rs${CLRct}. Reset %s database / delete all data\n\n" "$SCRIPT_NAME" + printf " ${GRNct}e${CLRct}. Return to Main Menu\n" + printf "\n${menuSepStr}\n\n" + + while true + do + printf "Choose an option: " + read -r menuOption + case "$menuOption" in + 1) printf "\n" - if [ "$(OutputTimeMode check)" = "unix" ]; then + if [ "$(OutputTimeMode check)" = "unix" ] + then OutputTimeMode non-unix - elif [ "$(OutputTimeMode check)" = "non-unix" ]; then + elif [ "$(OutputTimeMode check)" = "non-unix" ] + then OutputTimeMode unix fi break ;; - 5) + 2) printf "\n" LastXResults update && PressEnter break ;; - 6) + 3) printf "\n" DaysToKeep update && PressEnter break @@ -2710,65 +2756,127 @@ MainMenu() fi break ;; - t) + rs) printf "\n" if Check_Lock menu then - if [ "$(TimeServer check)" = "ntpd" ]; then - TimeServer chronyd - elif [ "$(TimeServer check)" = "chronyd" ]; then - TimeServer ntpd - fi + Menu_ResetDB Clear_Lock fi PressEnter break ;; - r) + e) exitMenu=true + break + ;; + *) + _HandleInvalidMenuOption_ + PressEnter + break + ;; + esac + done + + "$exitMenu" && return 0 + _Menu_DatabaseOptions_ +} + +##----------------------------------------## +## Modified by Martinski W. [2025-Dec-15] ## +##----------------------------------------## +MainMenu() +{ + local menuOption ntpRedirectStatus + + if Auto_NAT check + then ntpRedirectStatus="${PassBGRNct} ENABLED ${CLRct}" + else ntpRedirectStatus="${CritIREDct} DISABLED ${CLRct}" + fi + _UpdateJFFS_FreeSpaceInfo_ + + printf " WebUI for %s is available at:\n" "$SCRIPT_NAME" + printf " ${SETTING}%s${CLRct}\n\n" "$(Get_WebUI_URL)" + + printf " ${GRNct}1${CLRct}. Update time server stats now\n" + printf " Database size: ${SETTING}%s${CLRct}\n\n" "$(_GetFileSize_ "$NTPDSTATS_DB" HRx)" + printf " ${GRNct}2${CLRct}. Toggle redirect of all NTP traffic to %s\n" "$SCRIPT_NAME" + printf " Currently: ${ntpRedirectStatus}${CLRct}\n\n" + printf " ${GRNct}3${CLRct}. Configure time server options\n\n" + printf " ${GRNct}4${CLRct}. Configure database options\n\n" + printf " ${GRNct}u${CLRct}. Check for updates\n" + printf " ${GRNct}uf${CLRct}. Update %s with latest version (force update)\n\n" "$SCRIPT_NAME" + printf " ${GRNct}e${CLRct}. Exit %s\n\n" "$SCRIPT_NAME" + printf " ${GRNct}z${CLRct}. Uninstall %s\n" "$SCRIPT_NAME" + printf "\n${menuSepStr}\n\n" + + while true + do + printf "Choose an option: " + read -r menuOption + case "$menuOption" in + 1) printf "\n" - TIMESERVER_ID="$(TimeServer check)" - Print_Output true "Restarting $TIMESERVER_ID..." "$PASS" TimeServer_ServiceCheck - "/opt/etc/init.d/S77$TIMESERVER_ID" restart >/dev/null 2>&1 + if Check_Lock menu + then + Get_TimeServer_Stats + Clear_Lock + fi PressEnter break ;; - u) + 2) printf "\n" - if Check_Lock menu; then - Update_Version - Clear_Lock + if Auto_NAT check + then + Auto_NAT delete + NTP_Redirect delete + printf "${BOLD}NTP Redirect has been ${REDct}DISABLED${CLRct}\n\n" + else + Auto_NAT create + NTP_Redirect create + printf "${BOLD}NTP Redirect has been ${GRNct}ENABLED${CLRct}\n\n" fi PressEnter break ;; - uf) + 3) + _Menu_TimeServerOptions_ + break + ;; + 4) + _Menu_DatabaseOptions_ + break + ;; + u) printf "\n" - if Check_Lock menu; then - Update_Version force + if Check_Lock menu + then + Update_Version Clear_Lock fi PressEnter break ;; - rs) + uf) printf "\n" - if Check_Lock menu; then - Menu_ResetDB + if Check_Lock menu + then + Update_Version force Clear_Lock fi PressEnter break ;; e) - ScriptHeader - printf "\n${BOLD}Thanks for using %s!${CLEARFORMAT}\n\n\n" "$SCRIPT_NAME" + ScriptHeader true + printf "\n${BOLD}Thanks for using %s!${CLRct}\n\n\n" "$SCRIPT_NAME" exit 0 ;; z) while true do - printf "\n${BOLD}Are you sure you want to uninstall %s? (y/n)${CLEARFORMAT} " "$SCRIPT_NAME" + printf "\n${BOLD}Are you sure you want to uninstall %s? (y/n)${CLRct} " "$SCRIPT_NAME" read -r confirm case "$confirm" in y|Y) @@ -2782,16 +2890,14 @@ MainMenu() done ;; *) - [ -n "$menuOption" ] && \ - printf "\n${REDct}INVALID input [$menuOption]${CLEARFORMAT}" - printf "\nPlease choose a valid option.\n\n" + _HandleInvalidMenuOption_ PressEnter break ;; esac done - ScriptHeader + ScriptHeader true MainMenu } @@ -2887,7 +2993,7 @@ Menu_Install() Get_TimeServer_Stats Clear_Lock - ScriptHeader + ScriptHeader true MainMenu } @@ -2949,56 +3055,62 @@ Menu_Startup() Clear_Lock } +##----------------------------------------## +## Modified by Martinski W. [2025-Dec-15] ## +##----------------------------------------## Menu_Edit() { - texteditor="" - exitmenu="false" + local textEditor="" exitMenu=false retCode CONF_FILE - printf "\n${BOLD}A choice of text editors is available:${CLEARFORMAT}\n" - printf "1. nano (recommended for beginners)\n" - printf "2. vi\n" - printf "\ne. Exit to main menu\n" + printf "\n${BOLD}A choice of text editors is available:${CLRct}\n\n" + printf " ${GRNct}1${CLRct}. nano (recommended for beginners)\n" + printf " ${GRNct}2${CLRct}. vi\n\n" + printf " ${GRNct}e${CLRct}. Go back\n" while true do - printf "\n${BOLD}Choose an option:${CLEARFORMAT} " - read -r editor - case "$editor" in - 1) - texteditor="nano -K" - break - ;; - 2) - texteditor="vi" - break - ;; - e) - exitmenu="true" - break - ;; + printf "\n${BOLD}Choose an option:${CLRct} " + read -r editorOption + case "$editorOption" in + 1) textEditor="nano -K" ; break + ;; + 2) textEditor="vi" ; break + ;; + e) exitMenu=true ; break + ;; *) - printf "\nPlease choose a valid option\n\n" + if [ -z "$editorOption" ] + then exitMenu=true ; break + fi + printf "\n Please choose a valid option\n\n" ;; esac done - if [ "$exitmenu" != "true" ] + if "$exitMenu" then + echo ; retCode=1 + else TIMESERVER_NAME="$(TimeServer check)" - CONFFILE="" - if [ "$TIMESERVER_NAME" = "ntpd" ]; then - CONFFILE="$SCRIPT_STORAGE_DIR/ntp.conf" - elif [ "$TIMESERVER_NAME" = "chronyd" ]; then - CONFFILE="$SCRIPT_STORAGE_DIR/chrony.conf" + CONF_FILE="" + if [ "$TIMESERVER_NAME" = "ntpd" ] + then + CONF_FILE="$SCRIPT_STORAGE_DIR/ntp.conf" + elif [ "$TIMESERVER_NAME" = "chronyd" ] + then + CONF_FILE="$SCRIPT_STORAGE_DIR/chrony.conf" fi - oldmd5="$(md5sum "$CONFFILE" | awk '{print $1}')" - $texteditor "$CONFFILE" - newmd5="$(md5sum "$CONFFILE" | awk '{print $1}')" - if [ "$oldmd5" != "$newmd5" ]; then + oldmd5="$(md5sum "$CONF_FILE" | awk '{print $1}')" + $textEditor "$CONF_FILE" + newmd5="$(md5sum "$CONF_FILE" | awk '{print $1}')" + if [ "$oldmd5" != "$newmd5" ] + then "/opt/etc/init.d/S77$TIMESERVER_NAME" restart >/dev/null 2>&1 fi + echo ; retCode=0 fi Clear_Lock + return "$retCode" } Menu_ResetDB() @@ -3316,7 +3428,7 @@ then Shortcut_Script create _CheckFor_WebGUI_Page_ Process_Upgrade - ScriptHeader + ScriptHeader true MainMenu exit 0 fi @@ -3425,12 +3537,12 @@ case "$1" in exit 0 ;; about) - ScriptHeader + ScriptHeader true Show_About exit 0 ;; help) - ScriptHeader + ScriptHeader true Show_Help exit 0 ;; From 57407a708f75f0d9cc1ed1400b72b4fd3dfb48c3 Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Wed, 17 Dec 2025 00:02:53 -0800 Subject: [PATCH 6/7] Fine-Tuning Some more fine-tuning. --- README.md | 2 +- ntpmerlin.sh | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index a9ee47b..ba6057f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ntpMerlin ## v3.4.13 -### Updated on 2025-Dec-15 +### Updated on 2025-Dec-16 ## About ntpMerlin implements an NTP time server for AsusWRT Merlin with charts for daily, weekly and monthly summaries of performance. A choice between ntpd and chrony is available. diff --git a/ntpmerlin.sh b/ntpmerlin.sh index 1ddcba2..6abdc39 100644 --- a/ntpmerlin.sh +++ b/ntpmerlin.sh @@ -14,7 +14,7 @@ ## Forked from https://github.com/jackyaz/ntpMerlin ## ## ## ############################################################## -# Last Modified: 2025-Dec-15 +# Last Modified: 2025-Dec-16 #------------------------------------------------------------- ############### Shellcheck directives ############# @@ -37,7 +37,7 @@ readonly SCRIPT_NAME="ntpMerlin" readonly SCRIPT_NAME_LOWER="$(echo "$SCRIPT_NAME" | tr 'A-Z' 'a-z' | sed 's/d//')" readonly SCRIPT_VERSION="v3.4.13" -readonly SCRIPT_VERSTAG="25121522" +readonly SCRIPT_VERSTAG="25121620" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/$SCRIPT_NAME_LOWER.d" @@ -1427,7 +1427,7 @@ DaysToKeep() ScriptHeader printf " ${BOLD}Current number of days to keep data: ${GRNct}${daysToKeep}${CLRct}\n\n" printf " ${BOLD}Please enter the maximum number of days\n" - printf " to keep the data for [${MINvalue}-${MAXvalue}] (e=Exit):${CLEARFORMAT} " + printf " to keep the data for [${GRNct}${MINvalue}-${MAXvalue}${CLRct}] (e=Exit):${CLRct} " read -r daystokeep_choice if [ -z "$daystokeep_choice" ] && \ echo "$daysToKeep" | grep -qE "^([1-9][0-9]{1,2})$" && \ @@ -1441,11 +1441,11 @@ DaysToKeep() break elif ! Validate_Number "$daystokeep_choice" then - printf "\n ${ERR}Please enter a valid number [${MINvalue}-${MAXvalue}].${CLEARFORMAT}\n" + printf "\n${ERR}Please enter a valid number [${MINvalue}-${MAXvalue}].${CLRct}\n" PressEnter elif [ "$daystokeep_choice" -lt "$MINvalue" ] || [ "$daystokeep_choice" -gt "$MAXvalue" ] then - printf "\n ${ERR}Please enter a number between ${MINvalue} and ${MAXvalue}.${CLEARFORMAT}\n" + printf "\n${ERR}Please enter a number between ${MINvalue} and ${MAXvalue}.${CLRct}\n" PressEnter else daysToKeep="$daystokeep_choice" @@ -1484,7 +1484,7 @@ LastXResults() ScriptHeader printf " ${BOLD}Current number of results to display: ${GRNct}${lastXResults}${CLRct}\n\n" printf " ${BOLD}Please enter the maximum number of results\n" - printf " to display in the WebUI [${MINvalue}-${MAXvalue}] (e=Exit):${CLEARFORMAT} " + printf " to display in the WebUI [${GRNct}${MINvalue}-${MAXvalue}${CLRct}] (e=Exit):${CLRct} " read -r lastx_choice if [ -z "$lastx_choice" ] && \ echo "$lastXResults" | grep -qE "^([1-9][0-9]{0,2})$" && \ @@ -1498,11 +1498,11 @@ LastXResults() break elif ! Validate_Number "$lastx_choice" then - printf "\n ${ERR}Please enter a valid number [${MINvalue}-${MAXvalue}].${CLEARFORMAT}\n" + printf "\n${ERR}Please enter a valid number [${MINvalue}-${MAXvalue}].${CLRct}\n" PressEnter elif [ "$lastx_choice" -lt "$MINvalue" ] || [ "$lastx_choice" -gt "$MAXvalue" ] then - printf "\n ${ERR}Please enter a number between ${MINvalue} and ${MAXvalue}.${CLEARFORMAT}\n" + printf "\n${ERR}Please enter a number between ${MINvalue} and ${MAXvalue}.${CLRct}\n" PressEnter else lastXResults="$lastx_choice" From 6dea73967207c92c6b62ec5e829557a2c302f37c Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Sat, 20 Dec 2025 23:48:50 -0800 Subject: [PATCH 7/7] Update README.md Updated. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ba6057f..aa292d9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ntpMerlin ## v3.4.13 -### Updated on 2025-Dec-16 +### Updated on 2025-Dec-20 ## About ntpMerlin implements an NTP time server for AsusWRT Merlin with charts for daily, weekly and monthly summaries of performance. A choice between ntpd and chrony is available.