/** * @preserve Copyright (c) 2018-2022 NN Solex, www.sublunar.space * License MIT: http://www.opensource.org/licenses/MIT * * SUBLUNAR ALMANAC */ var SL = SL || {}; /** * Offline App Functions */ SL.App = (function() { const fs = require('fs'); const path = require('path'); const http = require('http'); const AutoUpdater = require( "nw-autoupdater" ); const mid = require( "node-machine-id" ); const crypto = require('crypto'); const config = path.normalize(nw.App.dataPath+'/config.json'); var editJson = ''; var waiting = false; function downloadStatus(file, response) { var num = parseInt($(".stoke span").text()); $(".stoke span").html(++num); if ( num == 4 ) { waiting = false; file.hasFiles = true; writeHash(file, response); } } function downloadPreset(file, url, filename, response) { var p = path.normalize(nw.App.dataPath+"/presets/"+filename); waiting = true; http.get(url, function(r) { r.pipe(fs.createWriteStream(p)).on('finish', function () { downloadStatus(file, response); }); }); } function writeHash(file, response) { if ( waiting == false) { file.hash = response.hash; fs.writeFile(config, JSON.stringify(file, null, 2), 'utf8', function(err) { if(err) { return console.log(err); } else { $('#caption .stoke').html('All set. Restarting application...'); console.log(file); window.setTimeout(chrome.runtime.reload,2000); } }); } else { console.log("still waiting for download..."); } } function authorize() { $("#navigation").css({"visibility":"hidden"}); if (!fs.existsSync(config)){ fs.writeFile(config, JSON.stringify({"config" : "Sublunar Almanac"}), 'utf8', function(err) { if(err) { return console.log(err); } else { $('#caption .stoke').html('Created configuration file... Restarting application...'); window.setTimeout(chrome.runtime.reload,2000); } }); } else { editJson = require(config); let file = editJson; if ( !file.hasOwnProperty("userEmail") ) { if ( !navigator.onLine) { $('#caption .stoke').html('You need to be online for activation...'); return; } var email = prompt("Please enter the email address you registered with"); file.userEmail = email; /* fs.writeFile(config, JSON.stringify(file, null, 2), 'utf8', function(err) { if(err) { return console.log(err); } }); */ } if ( !file.hasOwnProperty("hash") ) { if ( !navigator.onLine) { $('#caption .stoke').html('You need to be online for activation...'); return; } $.ajax({ url : "http://release.sublunar.space/index.php", type: "POST", data: { email: file.userEmail, mid: mid.machineIdSync({original: true}) }, success:function(response) { console.log(response); if ( response.status == "authorized") { var dir = path.normalize(nw.App.dataPath+"/presets"); if (!fs.existsSync(dir)){ fs.mkdirSync(dir); } if ( response.hasOwnProperty("files") ) { var url = "http://release.sublunar.space/presets/"; $('#caption .stoke').html('downloaded preset file 0 of 5'); downloadPreset(file, url+response.files.file1, "modals.html", response); downloadPreset(file, url+response.files.file2, "filtermenu.html", response); downloadPreset(file, url+response.files.file3, "grid.html", response); downloadPreset(file, url+response.files.file4, "ephemeris.json", response); downloadPreset(file, url+response.files.file5, "setup.json", response); } else { writeHash(file, response); } } else { $('#caption .stoke').html('Sorry, there is something wrong with your authorization. Reset?'); } }, error:function(){ console.log("error"); } }); } else { const check = crypto.createHash('sha256'); check.update(mid.machineIdSync({original: true})); if ( file.hash == check.digest('hex') ) { $("#navigation").css({"visibility":"visible"}); if ( file.hasOwnProperty("hasFiles") && file.hasFiles == true ) $("#filterreset").closest('li').before('
  • '); if ( !navigator.onLine ) { offlineUse(); } else { updateApp(); } } else { $('#caption .stoke').html('Sorry, there is something wrong with your authorization. Reset?'); } } } } function reset() { file = require(config); if ( file.hasOwnProperty("userEmail") ) delete file.userEmail; if ( file.hasOwnProperty("hash") ) delete file.hash; if ( file.hasOwnProperty("hasFiles") ) delete file.hasFiles; var presetfiles = ['/presets/modals.html', '/presets/filtermenu.html', '/presets/grid.html', '/presets/ephemeris.json', '/config.json']; presetfiles.forEach( function(fn) { var p = path.normalize(nw.App.dataPath+fn); fs.unlink(p, (err) => { if (err) throw err; console.log(p+' was deleted'); }); }); $('#caption .stoke').html('App has been reset. Reload?'); fs.writeFile(config, JSON.stringify(file, null, 2), 'utf8', function(err) { if(err) { return console.log(err); } }); $('#aboutSLC').modal('hide'); } function geoLocate() { $.ajax({ type : 'POST', data: '', url: "https://www.googleapis.com/geolocation/v1/geolocate?key=AIzaSyA7DG6Kz0VawkYVONoq7Yk8igTAQFGxGN4", success: function(data){ var item = { lat: data.location.lat, lon: data.location.lng } SL.Calendar.getGeoCode(item); } }); } /** * loadPreset loads precalculated menubar, modals and hour grid */ function loadPreset() { $('#caption .stoke').html('loading preset...please wait.'); fs.readFile(path.normalize(nw.App.dataPath+"/presets/filtermenu.html"), "utf8", function(err, html) { if (err) throw err; $("#filterList").empty(); $("#filterList").append(html); }); fs.readFile(path.normalize(nw.App.dataPath+"/presets/modals.html"), "utf8", function(err, html) { if (err) throw err; $("#modals").empty(); $("#modals").append(html); SL.Calendar.about(); }); fs.readFile(path.normalize(nw.App.dataPath+"/presets/grid.html"), "utf8", function(err, html) { if (err) throw err; $("#grid").empty(); $("#grid").append(html); $('#caption .stoke').empty(); $('#moduleSelect input:checkbox').prop('checked', true); $(".planetaryhour").each(function() { if ( $(this).attr("ts") < (moment.utc().startOf("day").unix()) ) $(this).remove(); }); $('.planetaryhour').on('click', SL.Calendar.hourInfo); }); fs.readFile(path.normalize(nw.App.dataPath+"/presets/ephemeris.json"), "utf8", function(err, data) { if (err) throw err; var json = JSON.parse(data); SL.Calendar.load(json.query); }); fs.readFile(path.normalize(nw.App.dataPath+"/presets/setup.json"), "utf8", function(err, data) { if (err) throw err; var json = JSON.parse(data); $("#search").val(json.place.name); $("#lat").val(json.place.lat); $("#lon").val(json.place.lon); $("#offset").val(json.place.offset); $('#zodiac').prop('checked', json.sidereal); }); if ( $('#calendar').data('isotope') ) $('#calendar').isotope('destroy'); } /** * updateApp function updates the offline App * from https://github.com/dsheiko/nw-autoupdater/blob/master/example/client-strategy-app/index.html */ async function updateApp() { const updater = new AutoUpdater( require( "./package.json" ) ), output = $("#caption .stoke"); try { // Update copy is running to replace app with the update if ( updater.isSwapRequest() ) { output.html("Swapping..."); await updater.swap(); output.html("Done."); await updater.restart(); return; } // Download/unpack update if any available const rManifest = await updater.readRemoteManifest(); const needsUpdate = await updater.checkNewVersion( rManifest ); if ( !needsUpdate ) { return; } if ( !confirm( "New release is available. Do you want to upgrade?" ) ) { return; } // Subscribe for progress events updater.on( "download", ( downloadSize, totalSize ) => { output.html("Downloading "+Math.floor( downloadSize / totalSize * 100 )+"%" ); }); updater.on( "install", ( installFiles, totalFiles ) => { output.html("Installing "+Math.floor( installFiles / totalFiles * 100 )+"%" ); }); reset(); const updateFile = await updater.download( rManifest ); await updater.unpack( updateFile ); alert( `The application will automatically restart to finish installing the update` ); await updater.restartToSwap(); } catch ( e ) { console.error( e ); } } function offlineUse() { $(".autolocate label").html("Save Coordinates"); $(".autolocate button").attr('id', 'savePlace').html("Save Place"); $(".manuallocate label").html("Last Searched & Saved Places"); $(".manuallocate input").remove(); $(".manuallocate").append("
    "); $('