mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 01:26:11 -08:00
Better version handling #458 + docs
This commit is contained in:
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -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">
|
||||||
|
|||||||
@@ -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)",
|
||||||
|
|||||||
@@ -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/) |
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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])
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user