Better version handling #458 + docs

This commit is contained in:
Jokob-sk
2023-09-30 09:53:15 +10:00
parent 07367a2ca3
commit ebeeb6c3a5
10 changed files with 115 additions and 132 deletions

View File

@@ -545,24 +545,24 @@ function getDevicesList (status) {
}; };
function handleLoadingDialog() function handleLoadingDialog()
{ {
$.get('api/app_state.json?nocache=' + Date.now(), function(appState) { $.get('api/app_state.json?nocache=' + Date.now(), function(appState) {
console.log(appState["showSpinner"]) console.log(appState["showSpinner"])
if(appState["showSpinner"]) if(appState["showSpinner"])
{ {
showSpinner("settings_old") showSpinner("settings_old")
setTimeout("handleLoadingDialog()", 1000); setTimeout("handleLoadingDialog()", 1000);
} else } else
{ {
hideSpinner() hideSpinner()
} }
}) })
} }
</script> </script>

View File

@@ -1,80 +1,51 @@
function handleVersion(){ //--------------------------------------------------------------
// Handle the UI changes to show or hide notifications about a new version
function versionUpdateUI(){
release_timestamp = getCookie("release_timestamp") isNewVersion = getCookie("isNewVersion")
if(release_timestamp != "") console.log(isNewVersion)
{
build_timestamp = parseInt($('#version').attr("data-build-time").match( /\d+/g ).join('')) // if the release_timestamp is older by 10 min or more as the build timestamp then there is a new release available
if(isNewVersion != "false")
// if the release_timestamp is older by 10 min or more as the build timestamp then there is a new release available
if(release_timestamp > build_timestamp + 600 )
{
console.log("New release!")
// handling the navigation menu icon
$('#version').attr("class", $('#version').attr("class").replace("myhidden", ""))
maintenanceDiv = $('#new-version-text')
}
else{
console.log("All up-to-date!")
maintenanceDiv = $('#current-version-text')
}
// handling the maintenance section message
if(emptyArr.includes(maintenanceDiv) == false && $(maintenanceDiv).length != 0)
{
$(maintenanceDiv).attr("class", $(maintenanceDiv).attr("class").replace("myhidden", ""))
}
}
}
//--------------------------------------------------------------
function getVersion()
{ {
release_timestamp = getCookie("release_timestamp") console.log("New release!")
// handling the navigation menu icon
$('#version').attr("class", $('#version').attr("class").replace("myhidden", ""))
release_timestampNum = Number(release_timestamp) maintenanceDiv = $('#new-version-text')
}
else{
console.log("All up-to-date!")
// logging maintenanceDiv = $('#current-version-text')
console.log(`Latest release in cookie: ${new Date(release_timestampNum*1000)}`)
// no cached value available
if(release_timestamp == "")
{
$.get('https://api.github.com/repos/jokob-sk/Pi.Alert/releases').done(function(response) {
// Handle successful response
var releases = response;
console.log(response)
if(releases.length > 0)
{
release_datetime = releases[0].published_at; // get latest release
release_timestamp = new Date(release_datetime).getTime() / 1000;
// cache value
setCookie("release_timestamp", release_timestamp, 30);
handleVersion();
}
}).fail(function(jqXHR, textStatus, errorThrown) {
$('.version').append(`<p>Github API: ${errorThrown} (${jqXHR.status}), ${jqXHR.responseJSON.message}</p>`)
});
} else
{
// cache is available, just call the handler
handleVersion()
}
} }
// handling the maintenance section message
if(emptyArr.includes(maintenanceDiv) == false && $(maintenanceDiv).length != 0)
{
$(maintenanceDiv).attr("class", $(maintenanceDiv).attr("class").replace("myhidden", ""))
}
}
//--------------------------------------------------------------
// Checks if a new version is available via the global app_state.json
function checkIfNewVersionAvailable()
{
$.get('api/app_state.json?nocache=' + Date.now(), function(appState) {
console.log(appState["isNewVersionChecked"])
console.log(appState["isNewVersion"])
// cache value
setCookie("isNewVersion", appState["isNewVersion"], 30);
setCookie("isNewVersionChecked", appState["isNewVersionChecked"], 30);
versionUpdateUI();
})
}
// handle the dispaly of the NEW icon // handle the dispaly of the NEW icon
getVersion() checkIfNewVersionAvailable()

View File

@@ -174,6 +174,12 @@ $db->close();
<?php echo date("Y-m-d", ((int)file_get_contents( "buildtimestamp.txt")));?> <?php echo date("Y-m-d", ((int)file_get_contents( "buildtimestamp.txt")));?>
</div> </div>
</div> </div>
<div class="db_info_table_row">
<div class="db_info_table_cell" style="min-width: 140px"><?= lang('Maintenance_Running_Version');?></div>
<div class="db_info_table_cell">
<?php include 'php/templates/version.php'; ?>
</div>
</div>
<div class="db_info_table_row"> <div class="db_info_table_row">
<div class="db_info_table_cell" style="min-width: 140px"><?= lang('Maintenance_database_path');?></div> <div class="db_info_table_cell" style="min-width: 140px"><?= lang('Maintenance_database_path');?></div>
<div class="db_info_table_cell"> <div class="db_info_table_cell">

View File

@@ -260,6 +260,7 @@
"Maintenance_new_version" : "🆕 A new version is available. Check out the <a href=\"https://github.com/jokob-sk/Pi.Alert/releases\" target=\"_blank\">release notes</a>.", "Maintenance_new_version" : "🆕 A new version is available. Check out the <a href=\"https://github.com/jokob-sk/Pi.Alert/releases\" target=\"_blank\">release notes</a>.",
"Maintenance_current_version" : "You are up-to-date. Check out what <a href=\"https://github.com/jokob-sk/Pi.Alert/issues/138\" target=\"_blank\">I am working on</a>.", "Maintenance_current_version" : "You are up-to-date. Check out what <a href=\"https://github.com/jokob-sk/Pi.Alert/issues/138\" target=\"_blank\">I am working on</a>.",
"Maintenance_built_on" : "Built on", "Maintenance_built_on" : "Built on",
"Maintenance_Running_Version" : "Installed version",
"Maintenance_database_path" : "Database-Path", "Maintenance_database_path" : "Database-Path",
"Maintenance_database_size" : "Database-Size", "Maintenance_database_size" : "Database-Size",
"Maintenance_database_rows" : "Table (Rows)", "Maintenance_database_rows" : "Table (Rows)",

View File

@@ -19,6 +19,7 @@
| | Yes | ARPSCAN | Script | 📚[arp_scan](/front/plugins/arp_scan/) | | | Yes | ARPSCAN | Script | 📚[arp_scan](/front/plugins/arp_scan/) |
| | | CSVBCKP | Script | 📚[csv_backup](/front/plugins/csv_backup/) | | | | CSVBCKP | Script | 📚[csv_backup](/front/plugins/csv_backup/) |
| Yes* | | DBCLNP | Script | 📚[db_cleanup](/front/plugins/db_cleanup/) | | Yes* | | DBCLNP | Script | 📚[db_cleanup](/front/plugins/db_cleanup/) |
| | | DDNS | Script | 📚[ddns_update](/front/plugins/ddns_update/) |
| | Yes | DHCPLSS | Script | 📚[dhcp_leases](/front/plugins/dhcp_leases/) | | | Yes | DHCPLSS | Script | 📚[dhcp_leases](/front/plugins/dhcp_leases/) |
| | | DHCPSRVS | Script | 📚[dhcp_servers](/front/plugins/dhcp_servers/) | | | | DHCPSRVS | Script | 📚[dhcp_servers](/front/plugins/dhcp_servers/) |
| | Yes | INTRNT | Script | 📚[internet_ip](/front/plugins/internet_ip/) | | | Yes | INTRNT | Script | 📚[internet_ip](/front/plugins/internet_ip/) |

View File

@@ -1,6 +1,6 @@
## Overview ## Overview
Plugin to run regular database cleanup tasks. It is strongly recommended to have an hourly or at least daily schedule running. Plugin to run regular DDNS update tasks.
### Usage ### Usage

View File

@@ -75,7 +75,7 @@ def ddns_update ( DDNS_UPDATE_URL, DDNS_USER, DDNS_PASSWORD, DDNS_DOMAIN, PREV_I
mylog('none', ['[DDNS] ', dns_IP]) mylog('none', ['[DDNS] ', dns_IP])
# Check DNS Change # Check DNS Change
if dns_IP != internet_IP : if dns_IP != PREV_IP :
mylog('none', ['[DDNS] Updating Dynamic DNS IP']) mylog('none', ['[DDNS] Updating Dynamic DNS IP'])
message = set_dynamic_DNS_IP (DDNS_UPDATE_URL, DDNS_USER, DDNS_PASSWORD, DDNS_DOMAIN) message = set_dynamic_DNS_IP (DDNS_UPDATE_URL, DDNS_USER, DDNS_PASSWORD, DDNS_DOMAIN)
mylog('none', ['[DDNS] ', message]) mylog('none', ['[DDNS] ', message])

View File

@@ -1,6 +1,6 @@
## Overview ## Overview
Plugin to run regular database cleanup tasks. It is strongly recommended to have an hourly or at least daily schedule running. Plugin to run regular Internet connectivity and IP checks.
### Usage ### Usage

View File

@@ -24,7 +24,7 @@ import multiprocessing
import conf import conf
from const import * from const import *
from logger import mylog from logger import mylog
from helper import filePermissions, isNewVersion, timeNowTZ, updateState, get_setting_value from helper import filePermissions, timeNowTZ, updateState, get_setting_value
from api import update_api from api import update_api
from networkscan import process_scan from networkscan import process_scan
from initialise import importConfigs from initialise import importConfigs
@@ -60,10 +60,6 @@ def main ():
mylog('none', ['[MAIN] Setting up ...']) # has to be level 'none' as user config not loaded yet mylog('none', ['[MAIN] Setting up ...']) # has to be level 'none' as user config not loaded yet
mylog('none', [f'[conf.tz] Setting up ...{conf.tz}']) mylog('none', [f'[conf.tz] Setting up ...{conf.tz}'])
# indicates, if a new version is available
conf.newVersionAvailable = False
# check file permissions and fix if required # check file permissions and fix if required
filePermissions() filePermissions()
@@ -83,24 +79,18 @@ def main ():
mylog('debug', '[MAIN] Starting loop') mylog('debug', '[MAIN] Starting loop')
# Header + init app state
updateState("Initializing")
while True: while True:
# re-load user configuration and plugins # re-load user configuration and plugins
importConfigs(db) importConfigs(db)
# update time started # update time started
conf.loop_start_time = timeNowTZ() conf.loop_start_time = timeNowTZ()
# TODO fix these
loop_start_time = conf.loop_start_time # TODO fix loop_start_time = conf.loop_start_time # TODO fix
last_version_check = conf.last_version_check
# check if new version is available / only check once an hour
if conf.last_version_check + datetime.timedelta(hours=1) < conf.loop_start_time :
# if newVersionAvailable is already true the function does nothing and returns true again
mylog('debug', [f"[Version check] Last version check timestamp: {conf.last_version_check}"])
conf.last_version_check = conf.loop_start_time
conf.newVersionAvailable = isNewVersion(conf.newVersionAvailable)
# Handle plugins executed ONCE # Handle plugins executed ONCE
if conf.plugins_once_run == False: if conf.plugins_once_run == False:

View File

@@ -3,12 +3,12 @@
import io import io
import sys import sys
import datetime import datetime
# from datetime import strptime
import os import os
import re import re
import subprocess import subprocess
import pytz import pytz
from pytz import timezone from pytz import timezone
from datetime import timedelta
import json import json
import time import time
from pathlib import Path from pathlib import Path
@@ -43,6 +43,9 @@ class app_state_class:
# json file containing the state to communicate with the frontend # json file containing the state to communicate with the frontend
stateFile = apiPath + '/app_state.json' stateFile = apiPath + '/app_state.json'
# if currentState == 'Initializing':
# checkNewVersion(False)
# Update self # Update self
self.currentState = currentState self.currentState = currentState
self.lastUpdated = str(timeNowTZ()) self.lastUpdated = str(timeNowTZ())
@@ -50,16 +53,20 @@ class app_state_class:
# Check if the file exists and init values # Check if the file exists and init values
if os.path.exists(stateFile): if os.path.exists(stateFile):
with open(stateFile, 'r') as json_file: with open(stateFile, 'r') as json_file:
previousState = json.load(json_file) previousState = json.load(json_file)
self.settingsSaved = previousState.get("settingsSaved", 0) self.settingsSaved = previousState.get("settingsSaved", 0)
self.settingsImported = previousState.get("settingsImported", 0) self.settingsImported = previousState.get("settingsImported", 0)
self.showSpinner = previousState.get("showSpinner", False) self.showSpinner = previousState.get("showSpinner", False)
self.isNewVersion = previousState.get("isNewVersion", False)
self.isNewVersionChecked = previousState.get("isNewVersionChecked", 0)
else: else:
self.settingsSaved = 0 self.settingsSaved = 0
self.settingsImported = 0 self.settingsImported = 0
self.showSpinner = False self.showSpinner = False
self.isNewVersion = checkNewVersion()
self.isNewVersionChecked = int(timeNow().timestamp())
# Overwrite with provided parameters if not None # Overwrite with provided parameters if supplied
if settingsSaved is not None: if settingsSaved is not None:
self.settingsSaved = settingsSaved self.settingsSaved = settingsSaved
if settingsImported is not None: if settingsImported is not None:
@@ -67,6 +74,11 @@ class app_state_class:
if showSpinner is not None: if showSpinner is not None:
self.showSpinner = showSpinner self.showSpinner = showSpinner
# check for new version every hour and if currently not running new version
if self.isNewVersion is False and self.isNewVersionChecked + 3600 < int(timeNow().timestamp()):
self.isNewVersion = checkNewVersion()
self.isNewVersionChecked = int(timeNow().timestamp())
# Update .json file # Update .json file
with open(stateFile, 'w') as json_file: with open(stateFile, 'w') as json_file:
json.dump(self, json_file, cls=AppStateEncoder, indent=4) json.dump(self, json_file, cls=AppStateEncoder, indent=4)
@@ -547,36 +559,38 @@ def collect_lang_strings(json, pref, stringSqlParams):
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def isNewVersion(newVersion: bool): def checkNewVersion():
mylog('debug', [f"[Version check] New version available? {newVersion}"]) mylog('debug', [f"[Version check] Checking if new version available"])
if newVersion == False: newVersion = False
f = open(pialertPath + '/front/buildtimestamp.txt', 'r') f = open(pialertPath + '/front/buildtimestamp.txt', 'r')
buildTimestamp = int(f.read().strip()) buildTimestamp = int(f.read().strip())
f.close() f.close()
data = ""
try:
url = requests.get("https://api.github.com/repos/jokob-sk/Pi.Alert/releases")
text = url.text
data = json.loads(text)
except requests.exceptions.ConnectionError as e:
mylog('minimal', ["[Version check] Error: Couldn't check for new release."])
data = "" data = ""
try: # make sure we received a valid response and not an API rate limit exceeded message
url = requests.get("https://api.github.com/repos/jokob-sk/Pi.Alert/releases") if data != "" and len(data) > 0 and isinstance(data, list) and "published_at" in data[0]:
text = url.text
data = json.loads(text)
except requests.exceptions.ConnectionError as e:
mylog('minimal', [" Couldn't check for new release."])
data = ""
# make sure we received a valid response and not an API rate limit exceeded message dateTimeStr = data[0]["published_at"]
if data != "" and len(data) > 0 and isinstance(data, list) and "published_at" in data[0]:
dateTimeStr = data[0]["published_at"] realeaseTimestamp = int(datetime.datetime.strptime(dateTimeStr, '%Y-%m-%dT%H:%M:%SZ').strftime('%s'))
realeaseTimestamp = int(datetime.datetime.strptime(dateTimeStr, '%Y-%m-%dT%H:%M:%SZ').strftime('%s')) if realeaseTimestamp > buildTimestamp + 600:
mylog('none', ["[Version check] New version of the container available!"])
if realeaseTimestamp > buildTimestamp + 600: newVersion = True
mylog('none', ["[Version check] New version of the container available!"]) else:
newVersion = True mylog('none', ["[Version check] Running the latest version."])
return newVersion return newVersion