Skip to content

Commit

Permalink
Merge pull request #3 from smdthiranjaya/dev
Browse files Browse the repository at this point in the history
Clean the code.
  • Loading branch information
smdthiranjaya authored Apr 4, 2024
2 parents d7922f9 + 84e45e8 commit e027ae3
Show file tree
Hide file tree
Showing 10 changed files with 488 additions and 21 deletions.
315 changes: 311 additions & 4 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"start": "node server.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
Expand All @@ -15,6 +15,9 @@
"dotenv": "^16.4.5",
"express": "^4.19.1",
"node-fetch": "^3.3.2",
"pg": "^8.11.3"
"nodemailer": "^6.9.13",
"pg": "^8.11.3",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.0"
}
}
14 changes: 11 additions & 3 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,35 @@ const cors = require('cors');
const { PORT } = require('./src/config');
const weatherRoutes = require('./src/routes/weatherRoutes');
const { updateWeatherDataManually } = require('./src/controllers/weatherController');
const { sendWeatherUpdates } = require('./src/services/emailService');
const swaggerUi = require('swagger-ui-express');
const swaggerDocs = require('./src/swaggerConfig');

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));
const subscriptionRoutes = require('./src/routes/subscriptionRoutes');

const app = express();
app.use(cors());

app.use(express.json());
app.use(weatherRoutes);

app.get('/', (req, res) => {
res.send('Weather Data Fetching Service is running.');
});

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));
app.use('/api', subscriptionRoutes);

setInterval(() => {
sendWeatherUpdates().catch(console.error);
}, 86400000);

setInterval(async () => {
try {
await updateWeatherDataManually();
} catch (error) {
console.error('Failed to fetch or store weather data:', error);
}
}, 300000); // 5 minutes
}, 300000);

app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
Expand Down
30 changes: 30 additions & 0 deletions src/controllers/subscriptionController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const pool = require('../db');

async function addSubscription(req, res) {
const { email, city } = req.body;
try {
const client = await pool.connect();
const insertQuery = `
INSERT INTO subscriptions (email, city)
VALUES ($1, $2)
RETURNING *;
`;
const result = await client.query(insertQuery, [email, city]);
client.release();

res.status(200).json({
success: true,
message: 'Subscription added successfully',
subscription: result.rows[0]
});
} catch (error) {
console.error('Error adding subscription:', error);
res.status(500).json({
success: false,
message: 'Error adding subscription'
});
}
}

module.exports = { addSubscription };

35 changes: 30 additions & 5 deletions src/controllers/weatherController.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const { storeWeatherData, fetchAllWeatherData } = require('../models/weatherModel');
const pool = require('../db');

async function updateWeatherDataManually() {
console.log('Fetching and Storing weather data...');

// Define all cities with base information
const cities = [
{ id: 1, city: 'Colombo', lat: 6.932, lng: 79.848 },
{ id: 2, city: 'Kandy', lat: 7.296, lng: 80.636 },
Expand Down Expand Up @@ -93,8 +93,33 @@ async function updateWeatherDataManually() {
}


// async function getWeather(req, res) {
// // Your route logic here
// }
async function getWeather(req, res) {
try {
const weatherData = await fetchAllWeatherData();
const response = {
data: weatherData.map(row => ({
type: 'weather',
id: row.id,
attributes: {
city: row.city,
latitude: row.latitude,
longitude: row.longitude,
temperature: row.temperature,
humidity: row.humidity,
air_pressure: row.air_pressure,
wind_speed: row.wind_speed,
weather_descriptions: row.weather_descriptions,
observation_time: row.observation_time,
weather_icons: row.weather_icons,
is_day: row.is_day,
}
}))
};
res.json(response);
} catch (error) {
console.error('Failed to serve weather data:', error);
res.status(500).send('Server error');
}
}

module.exports = { updateWeatherDataManually };
module.exports = { updateWeatherDataManually, getWeather };
19 changes: 14 additions & 5 deletions src/models/weatherModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,18 @@ async function storeWeatherData(weatherData) {
client.release();
}
}

async function fetchAllWeatherData() {
const client = await pool.connect();
try {
const { rows } = await client.query('SELECT * FROM weather_data');
return rows;
} catch (error) {
console.error('Failed to fetch weather data:', error);
throw error;
} finally {
client.release();
}
}

// async function fetchAllWeatherData() {
// // Logic to fetch all weather data from DB
// }

module.exports = { storeWeatherData };
module.exports = { storeWeatherData, fetchAllWeatherData };
7 changes: 7 additions & 0 deletions src/routes/subscriptionRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const express = require('express');
const router = express.Router();
const { addSubscription } = require('../controllers/subscriptionController');

router.post('/subscribe', addSubscription);

module.exports = router;
2 changes: 1 addition & 1 deletion src/routes/weatherRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ router.get('/api/weather', getWeather);
* @swagger
* /api/weather:
* get:
* summary: Retrieves weather data
* summary: Retrieves weather data from heroku postgresql db.
* description: Fetches weather data for all cities.
* responses:
* 200:
Expand Down
78 changes: 78 additions & 0 deletions src/services/emailService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@

const nodemailer = require('nodemailer');
const pool = require('../db');

async function sendWeatherUpdates() {
const client = await pool.connect();
try {
const { rows: subscriptions } = await client.query('SELECT DISTINCT city FROM subscriptions;');
for (const { city } of subscriptions) {
const weatherData = await fetchWeatherDataForCity(city);
const { rows: subscribers } = await client.query('SELECT email FROM subscriptions WHERE city = $1;', [city]);
for (const { email } of subscribers) {
await sendEmail(email, city, weatherData);
}
}
} catch (error) {
console.error('Failed to send weather updates:', error);
} finally {
client.release();
}
}

async function fetchWeatherDataForCity(city) {
const client = await pool.connect();
try {
const query = `
SELECT MAX(temperature) AS max_temp, MIN(temperature) AS min_temp, AVG(temperature) AS avg_temp
FROM weather_data
WHERE city = $1;
`;
const result = await client.query(query, [city]);
return result.rows[0];
} catch (error) {
console.error(`Failed to fetch weather data for city ${city}:`, error);
throw error;
} finally {
client.release();
}
}


async function sendEmail(recipient, city, weatherData) {
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'geo360.live@gmail.com',
pass: 'aymj fcyu udnc ghpd'
}
});

let mailOptions = {
from: 'geo360.live@gmail.com',
to: recipient,
subject: `Weather Update for ${city}`,
text: `Good day! ✨
Here's your latest weather update for ${city}:
🔺 - Maximum Temperature: ${weatherData.max_temp}°C
🔻 - Minimum Temperature: ${weatherData.min_temp}°C
🔍 - Average Temperature: ${parseFloat(weatherData.avg_temp).toFixed(2)}°C
Stay informed and plan your day accordingly!
Best,
Geo360 Team.`
};

transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log('Email send error:', error);
} else {
console.log('Email sent: ' + info.response);
}
});
}

module.exports = { sendWeatherUpdates };
2 changes: 1 addition & 1 deletion src/swaggerConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const swaggerOptions = {
definition: {
openapi: '3.0.0',
info: {
title: 'Weather API',
title: 'Geo 360 Live Weather API',
version: '1.0.0',
description: 'A simple Express Weather API'
},
Expand Down

0 comments on commit e027ae3

Please sign in to comment.