Skip to content

Commit

Permalink
modified: README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
aesclever committed Oct 28, 2022
1 parent 9afade5 commit 13c8e08
Showing 1 changed file with 335 additions and 0 deletions.
335 changes: 335 additions & 0 deletions index.copy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
import * as dotenv from 'dotenv';
let WEATHERBIT_KEY = "";
let WEATHERBIT_URI = "";

dotenv.config();

// dotenv.config()
import request from 'request';
import express from 'express';
import bodyParser from 'body-parser';
import {encryptAES, decryptAES} from './crypto.js';


import awssdk from 'aws-sdk';




if (process.env.NODE_ENV == 'production') {
// Code for AWS Production Mode
getAwsSecrets();
} else if (process.env.NODE_ENV === 'awsdeploy') {
WEATHERBIT_URI="https://api.weatherbit.io/v2.0/";
WEATHERBIT_KEY="U2FsdGVkX18HMV5UUT9rJN76hOtIHDw1bH0beQYWH8a6E7uzKqskdgHvc6Nq2lO6O+GAb2vrcL+X8ZDqcGPuLw==";
console.log("AWSDEPLOY mode!");
} else {
// Code for Development Mode
WEATHERBIT_KEY = process.env.WEATHERBIT_KEY;
WEATHERBIT_URI = process.env.WEATHERBIT_URI;
}


// Create network routing
const app = express();

// EJS is accessed by default in the views directory.
app.set('view engine', 'ejs');

// Allow access to 'public' folder where resources are available to this app
app.use(express.static('public'));

app.use(bodyParser.urlencoded({ extended: true }));

// get the locale from the client-side via the ejs form
app.get('/', (req, res) => {
// console.dir(req.params);
// console.dir(req.body);
let apikey = encryptAES(WEATHERBIT_KEY);
res.render('index', {xkey: apikey});
})



app.get('/weatherbit', (req, res) => {
// console.log('render get weatherbit:');
// console.dir(req.params)
// console.dir(req.body);
res.render('pages/weatherbit');
})

// Posting data to the client-side requires two API calls.
// We implement the Promise.all() below to call and wait for all data to come back.

app.post('/weatherbit', (req, res) => {
let city = req.body.locale;
let coords = [ req.body.lat, req.body.lng ];
let promisedData;
// console.log(coords[0], coords[1]);
if (city.length > 0) {
// get data by address
promisedData = gatherWeatheBits(city);
} else if (typeof(coords[0]) === "string") {
// get data by latitude/longitude
promisedData = gatherWeatheBits(coords);
}

promisedData.then( (data) => {
res.render('pages/weatherbit', data);
})
});


/*
* function get AWS environment variables
*/
function getAwsSecrets() {
var AWS = awssdk,
region = "us-east-1",
secretName = "techrolemi_weather_secret",
secret,
decodedBinarySecret;

// Create a Secrets Manager client
var client = new AWS.SecretsManager({
region: region
});


client.getSecretValue({SecretId: secretName}, function(err, data) {
if (err) {
if (err.code === 'DecryptionFailureException')
// Secrets Manager can't decrypt the protected secret text using the provided KMS key.
// Deal with the exception here, and/or rethrow at your discretion.
throw err;
else if (err.code === 'InternalServiceErrorException')
// An error occurred on the server side.
// Deal with the exception here, and/or rethrow at your discretion.
throw err;
else if (err.code === 'InvalidParameterException')
// You provided an invalid value for a parameter.
// Deal with the exception here, and/or rethrow at your discretion.
throw err;
else if (err.code === 'InvalidRequestException')
// You provided a parameter value that is not valid for the current state of the resource.
// Deal with the exception here, and/or rethrow at your discretion.
throw err;
else if (err.code === 'ResourceNotFoundException')
// We can't find the resource that you asked for.
// Deal with the exception here, and/or rethrow at your discretion.
throw err;
}
else {
// Decrypts secret using the associated KMS key.
// Depending on whether the secret is a string or binary, one of these fields will be populated.
// console.log(data);
if ('SecretString' in data) {
secret = data.SecretString;
var aesParams = JSON.parse(secret);
// console.log(data.Name + " : " + data.SecretString);
Object.entries(aesParams).forEach((entry) => {
var [key, value] = entry;
if (`${key}` === "WEATHERBIT_KEY") {
WEATHERBIT_KEY = `${value}`;
console.log("WEATHERBIT_KEY="+ WEATHERBIT_KEY);
}
else if (`${key}` === "WEATHERBIT_URI") {
WEATHERBIT_URI = `${value}`;
console.log("WEATHERBIT_URI="+WEATHERBIT_URI);
}
});

} else {
let buff = new Buffer(data.SecretBinary, 'base64');
decodedBinarySecret = buff.toString('ascii');
console.log("decodedBinarySecret: " + decodedBinarySecret);
}
}
})
}



/*
* Function retrieves weatherbit.io current conditions.
* Used in the Promise call below.
*/
function getWeatherBitCurrentConditions(city){
return new Promise(resolve => {
if (Array.isArray(city) === true && typeof(city[0]) === "string") {
city = "&lat=" + city[0] + "&lon=" + city[1];
} else {
city = "&city=" + city;
}

var Xcode = "";
if (process.env.NODE_ENV === 'awsdeploy') {
Xcode = JSON.parse(decryptAES(WEATHERBIT_KEY)).text;
} else {
Xcode = WEATHERBIT_KEY;
}

setTimeout(() => {

let uriWeatherBitStr = `${WEATHERBIT_URI}current?units=I${city}&key=${Xcode}`;
let retCode;
if (WEATHERBIT_URI.length === 0) {
console.log('Failed to get aws secrets!');
return null;
} else {
console.log(uriWeatherBitStr);
}
try {
request(uriWeatherBitStr, async function (err, response, body) {
console.log(response.statusCode);
if (response.statusCode == 429) {
console.log("WARNING: You have exceeded your API call limit with weatherbit.io!");
resolve(null);
}
if (response.statusCode == 200) {
let weather = await JSON.parse(body).data[0];
resolve(weather);
} else {
resolve(null);
}
})
} catch (err) {
console.log(err);
}
})
}, 300);
}


/*
* Function retrieves weatherbit.io daily forecast.
* Used in the Promise call below.
*/
function getWeatherBitDailyForecast(city){
return new Promise(resolve => {
if (Array.isArray(city) === true && typeof(city[0]) === "string") {
city = "&lat=" + city[0] + "&lon=" + city[1];
} else {
city = "&city=" + city;
}

var Xcode = "";
if (process.env.NODE_ENV === 'awsdeploy') {
Xcode = JSON.parse(decryptAES(WEATHERBIT_KEY)).text;
} else {
Xcode = WEATHERBIT_KEY;
}

setTimeout(() => {
let uriWeatherBitStr = `${WEATHERBIT_URI}forecast/daily?units=I${city}&key=${Xcode}`;
let retCode;
// console.log(uriWeatherBitStr);
try {
request(uriWeatherBitStr, async function (err, response, body) {
console.log(response.statusCode);

if (response.statusCode == 429) {
console.log("WARNING: You have exceeded your API call limit with weatherbit.io!");
resolve(null);
}
if (response.statusCode == 200) {
retCode = await JSON.parse(body);
resolve(retCode);
} else {
resolve(null);
}
})
} catch (err) {
console.log(err);
}
}, 500);
})
}

function getWeatherBitAirQuality(city) {
/* API_URL = https://api.weatherbit.io/v2.0/history/airquality?city=${city}&start_date=2022-10-03&end_date=2022-10-04&tz=local&key=${apikey} */
return new Promise(resolve => {
if (Array.isArray(city) === true && typeof(city[0]) === "string") {
city = "?lat=" + city[0] + "&lon=" + city[1];
} else {
city = "?city=" + city;
}

var Xcode = "";
if (process.env.NODE_ENV === 'awsdeploy') {
Xcode = JSON.parse(decryptAES(WEATHERBIT_KEY)).text;
} else {
Xcode = WEATHERBIT_KEY;
}

setTimeout(() => {
let e = new Date().toISOString().slice(0, 16).replace('T', ' ')
let enddate = e.split(' ')[0];
// add 1 day to enddate
let s = new Date(enddate);
s.setDate(s.getDate() - 1);
s = s.toISOString().slice(0, 16).replace('T', ' ');
let startdate = s.split(' ')[0];

let retCode;
let uriWeatherBitAPIStr = `${WEATHERBIT_URI}history/airquality${city}&start_date=${startdate}&end_date=${enddate}&key=${Xcode}`;

// console.log(uriWeatherBitAPIStr);
try {
request(uriWeatherBitAPIStr, async function (err, response, body) {
console.log(response.statusCode);

if (response.statusCode == 429) {
console.log("WARNING: You have exceeded your API call limit with weatherbit.io!");
resolve(null);
}
if (response.statusCode == 200) {
retCode = await JSON.parse(body);
resolve(retCode);
} else {
resolve(null);
}
})
} catch (err) {
console.log(err);
}
}, 300);

})
}


/*
* Return multiple promises consists of currentConditions and dailyForecast data.
*/
async function gatherWeatheBits(city) {
const [dailyForecast, currentConditions, airQuality,] = await Promise.all([
getWeatherBitDailyForecast(city),
getWeatherBitCurrentConditions(city),
getWeatherBitAirQuality(city)
]);


// Make sure all promisses fulfilled.
if (dailyForecast !== null && airQuality !== null && currentConditions !== null ) {
let currentHour = new Date().getHours();
// combine 3 promises into a huge rendering passing paramters:
let combinedData = { locale: city, curStatus: 200, curData: currentConditions, foreStatus: 200, foreData: dailyForecast, airqStatus: 200, airqData: airQuality.data[currentHour], error: null };
return combinedData;
} else {
return { locale: city, curStatus: 400, curData: null, foreStatus: 400, foreData: null, airqStatus: 400, airqData: null, error: null };
}
}

// about page
app.get('/about', function(req, res) {
res.render('pages/about');
});

let port = process.env.PORT || 3000;

// creating a server that is listening on ${port} for connections.
app.listen(port, () => {
console.log(`TechRolEmi weather report is listening on port ${port}`);
});

0 comments on commit 13c8e08

Please sign in to comment.