Spaces:
Running
Running
Upload 5 files
Browse files- emails.js +228 -0
- index.js +33 -266
- news.js +123 -0
- package-lock.json +0 -0
- package.json +21 -20
emails.js
ADDED
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const nodemailer = require("nodemailer");
|
2 |
+
require('dotenv').config()
|
3 |
+
const { Pool } = require('pg');
|
4 |
+
var parse = require('pg-connection-string').parse;
|
5 |
+
|
6 |
+
var config = parse(process.env.DATABASE_URL);
|
7 |
+
const pool = new Pool(config);
|
8 |
+
|
9 |
+
|
10 |
+
// ***** update daily top 3 news
|
11 |
+
|
12 |
+
const updateEmailNews = async (req, res) => {
|
13 |
+
try {
|
14 |
+
|
15 |
+
const catList = ["science", "india", 'business',
|
16 |
+
"sports", "entertainment", "technology", "world"];
|
17 |
+
|
18 |
+
catList.forEach(async (cat) => {
|
19 |
+
|
20 |
+
const data = await getTopNews(cat);
|
21 |
+
|
22 |
+
data.forEach(async (d) => {
|
23 |
+
|
24 |
+
const summary = await getSummary(d.article_url);
|
25 |
+
|
26 |
+
//set news in database
|
27 |
+
try {
|
28 |
+
const query = `
|
29 |
+
update top_news set
|
30 |
+
title = $1, article_url = $2, source = $3, summary = $4, published_date = $5 where category = '${cat}_${data.indexOf(d) + 1}' ;
|
31 |
+
`;
|
32 |
+
const values = [
|
33 |
+
d.title,
|
34 |
+
d.article_url,
|
35 |
+
d.source_name,
|
36 |
+
summary,
|
37 |
+
d.published_date
|
38 |
+
];
|
39 |
+
|
40 |
+
await pool.query(query, values);
|
41 |
+
} catch (er) {
|
42 |
+
console.log(er);
|
43 |
+
}
|
44 |
+
|
45 |
+
});
|
46 |
+
|
47 |
+
});
|
48 |
+
|
49 |
+
res.send({ "status": "running" });
|
50 |
+
|
51 |
+
|
52 |
+
} catch (e) {
|
53 |
+
console.log(e);
|
54 |
+
}
|
55 |
+
|
56 |
+
}
|
57 |
+
|
58 |
+
async function getTopNews(category) {
|
59 |
+
const query = `
|
60 |
+
select title, article_url, category, source_name, published_date from news where category like '%${category}%' order by published_date desc limit 3;
|
61 |
+
`;
|
62 |
+
|
63 |
+
const data = await pool.query(query);
|
64 |
+
|
65 |
+
return data.rows;
|
66 |
+
}
|
67 |
+
|
68 |
+
async function getSummary(url) {
|
69 |
+
|
70 |
+
//console.log(url)
|
71 |
+
const apiUrl = 'https://yashxx07-summarize-articles.hf.space/summarize-v1';
|
72 |
+
const options = {
|
73 |
+
method: 'POST',
|
74 |
+
headers: {
|
75 |
+
'content-type': 'application/json',
|
76 |
+
},
|
77 |
+
body: JSON.stringify({
|
78 |
+
"url": url,
|
79 |
+
"max_tokens": 500
|
80 |
+
})
|
81 |
+
};
|
82 |
+
|
83 |
+
try {
|
84 |
+
const response = await fetch(apiUrl, options);
|
85 |
+
|
86 |
+
const result = await response.text();
|
87 |
+
//console.log(result);
|
88 |
+
return result;
|
89 |
+
} catch (error) {
|
90 |
+
console.error(error);
|
91 |
+
}
|
92 |
+
|
93 |
+
}
|
94 |
+
|
95 |
+
|
96 |
+
// const transporter = nodemailer.createTransport({
|
97 |
+
// host: 'smtp.mailchimp.com',
|
98 |
+
// port: 587, // Mailchimp SMTP port
|
99 |
+
// secure: false, // true for 465, false for other ports
|
100 |
+
// auth: {
|
101 |
+
// user: 'your_mailchimp_username',
|
102 |
+
// pass: 'your_mailchimp_password'
|
103 |
+
// }
|
104 |
+
// });
|
105 |
+
|
106 |
+
|
107 |
+
const transporter = nodemailer.createTransport({
|
108 |
+
host: "smtp.elasticemail.com",
|
109 |
+
port: 2525,
|
110 |
+
auth: {
|
111 |
+
user: "zerothtest@mail.com",
|
112 |
+
pass: "E6DADFA42CB201B8BA973C46DEA509951E20",
|
113 |
+
},
|
114 |
+
});
|
115 |
+
|
116 |
+
|
117 |
+
async function sendToUser(email, mailContent) {
|
118 |
+
try {
|
119 |
+
await transporter.sendMail({
|
120 |
+
from: {
|
121 |
+
name: "RapidRecap",
|
122 |
+
address: 'yashgaude77@gmail.com'
|
123 |
+
},
|
124 |
+
to: email,
|
125 |
+
subject: "Today's Top News",
|
126 |
+
html: mailContent
|
127 |
+
});
|
128 |
+
|
129 |
+
return "Email sent successfully!";
|
130 |
+
} catch (error) {
|
131 |
+
console.error(error);
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
async function getEmailsList(time) {
|
136 |
+
|
137 |
+
try {
|
138 |
+
const query = `
|
139 |
+
select * from subs where time = '${time}';`;
|
140 |
+
const data = await pool.query(query);
|
141 |
+
return data.rows;
|
142 |
+
|
143 |
+
} catch (e) {
|
144 |
+
console.log(e);
|
145 |
+
}
|
146 |
+
|
147 |
+
}
|
148 |
+
|
149 |
+
async function getAllNews() {
|
150 |
+
try {
|
151 |
+
const query = `
|
152 |
+
select * from top_news;
|
153 |
+
`;
|
154 |
+
const data = await pool.query(query);
|
155 |
+
return data.rows;
|
156 |
+
|
157 |
+
} catch (e) {
|
158 |
+
console.log(e);
|
159 |
+
}
|
160 |
+
}
|
161 |
+
|
162 |
+
function craftEmailTemplate(user, newsList) {
|
163 |
+
|
164 |
+
const filteredNews = newsList.filter(item => user.category.includes(item.category.slice(0, -2)) && item.summary != `""`);
|
165 |
+
shuffleArray(filteredNews);
|
166 |
+
|
167 |
+
// Construct the mail content
|
168 |
+
const mailContent = filteredNews.slice(0, 3).map(doc => `
|
169 |
+
<div style='line-height: 1.4;max-width:400px;background:white;margin-top:5px;color:#545454;padding:5px;border:1px solid black; text-align:left; border-radius:2px '>
|
170 |
+
<a href='${doc.article_url}' style='color:Black;text-decoration:none;'><h1 style='margin:0'>${doc.title}</h1></a>
|
171 |
+
<div style='display:flex;justify-content:start;align-items:center;'>
|
172 |
+
<p style='text-align:left;margin:0;color:#545454;text-decoration:none;'><strong>Source: </strong>${doc.source}<p>
|
173 |
+
</div>
|
174 |
+
<div style='display:flex;justify-content:start;align-items:center;'>
|
175 |
+
<p style='text-align:left;margin:0;color:#545454;text-decoration:none;'><strong>Published On: </strong>${convertToDateString(doc.published_date)}<p>
|
176 |
+
</div>
|
177 |
+
<p style='text-align:left;margin:0'>${doc.summary.slice(2, -1)}</p>
|
178 |
+
</div>`
|
179 |
+
).join('');
|
180 |
+
|
181 |
+
return mailContent;
|
182 |
+
}
|
183 |
+
|
184 |
+
function convertToDateString(publishedDate) {
|
185 |
+
const date = new Date(publishedDate);
|
186 |
+
|
187 |
+
const year = date.getFullYear();
|
188 |
+
const month = date.getMonth() + 1;
|
189 |
+
const day = date.getDate();
|
190 |
+
|
191 |
+
|
192 |
+
const formattedDate = `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
|
193 |
+
|
194 |
+
return formattedDate;
|
195 |
+
}
|
196 |
+
|
197 |
+
function shuffleArray(array) {
|
198 |
+
for (let i = array.length - 1; i > 0; i--) {
|
199 |
+
const j = Math.floor(Math.random() * (i + 1));
|
200 |
+
[array[i], array[j]] = [array[j], array[i]];
|
201 |
+
}
|
202 |
+
}
|
203 |
+
|
204 |
+
async function sendEmail(req, res) {
|
205 |
+
|
206 |
+
try {
|
207 |
+
const time = req.query.time;
|
208 |
+
const emailsList = await getEmailsList(time);
|
209 |
+
const newsList = await getAllNews();
|
210 |
+
|
211 |
+
emailsList.forEach(async (user) => {
|
212 |
+
|
213 |
+
const mailTemplate = craftEmailTemplate(user, newsList);
|
214 |
+
res.send(mailTemplate);
|
215 |
+
//await sendToUser(user.email, mailTemplate);
|
216 |
+
|
217 |
+
});
|
218 |
+
//const result = await sendEmail();
|
219 |
+
//res.send({ "news": newsList, "emails": emailsList });
|
220 |
+
} catch (error) {
|
221 |
+
console.log(error);
|
222 |
+
res.status(500).send("Error sending email.");
|
223 |
+
}
|
224 |
+
|
225 |
+
}
|
226 |
+
|
227 |
+
|
228 |
+
module.exports = { updateEmailNews, sendEmail }
|
index.js
CHANGED
@@ -1,266 +1,33 @@
|
|
1 |
-
const express = require("express");
|
2 |
-
|
3 |
-
|
4 |
-
const
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
"health",
|
35 |
-
"science",
|
36 |
-
"sports",
|
37 |
-
"technology",
|
38 |
-
"india",
|
39 |
-
"world",
|
40 |
-
];
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
// Function to fetch new news from API and write to Firestore
|
45 |
-
async function fetchDataAndWriteToFirestore(para) {
|
46 |
-
|
47 |
-
const url = `https://news67.p.rapidapi.com/v2/topic-search?languages=en&search=${para}`;
|
48 |
-
const options = {
|
49 |
-
method: 'GET',
|
50 |
-
headers: {
|
51 |
-
'X-RapidAPI-Key': '836bb8ca1fmsh79ad9dd5bf8734fp1460bejsn5eac87118b33',
|
52 |
-
'X-RapidAPI-Host': 'news67.p.rapidapi.com'
|
53 |
-
}
|
54 |
-
};
|
55 |
-
|
56 |
-
const parameter = para;
|
57 |
-
|
58 |
-
|
59 |
-
try {
|
60 |
-
// Make API call
|
61 |
-
const response = await fetch(url, options);
|
62 |
-
const data = await response.json();
|
63 |
-
|
64 |
-
|
65 |
-
// Write each object in the array to Firestore
|
66 |
-
data.news.forEach(async (item) => {
|
67 |
-
item['category_key'] = parameter;
|
68 |
-
|
69 |
-
let documentName = item.Title.replace(/[^a-zA-Z]/g, '');
|
70 |
-
|
71 |
-
await db.collection("news").doc(documentName).set(item);
|
72 |
-
//console.log("Document written to Firestore:", item);
|
73 |
-
});
|
74 |
-
|
75 |
-
} catch (error) {
|
76 |
-
console.error("Error fetching data:", error);
|
77 |
-
}
|
78 |
-
|
79 |
-
|
80 |
-
}
|
81 |
-
|
82 |
-
// ********* Route to trigger fetching data and writing to Firestore
|
83 |
-
app.get("/get-news", async (req, res) => {
|
84 |
-
|
85 |
-
|
86 |
-
for (const param of categoryCodes) {
|
87 |
-
await fetchDataAndWriteToFirestore(param);
|
88 |
-
}
|
89 |
-
|
90 |
-
res.send("Data fetched and written to Firestore successfully!");
|
91 |
-
});
|
92 |
-
|
93 |
-
|
94 |
-
// ***** update daily top 3 news
|
95 |
-
app.get("/update-today-top-for-emails", async (req, res) => {
|
96 |
-
const key = req.query.key;
|
97 |
-
const data = [];
|
98 |
-
|
99 |
-
try {
|
100 |
-
const newsRef = db.collection('news');
|
101 |
-
const snapshot = await newsRef.orderBy('PublishedOn', "desc").limit(1).where("category_key", "==", key).get();
|
102 |
-
|
103 |
-
const promises = snapshot.docs.map(async (doc) => {
|
104 |
-
const d = doc.data();
|
105 |
-
let summary;
|
106 |
-
|
107 |
-
try {
|
108 |
-
summary = await getSummary(d.Url);
|
109 |
-
} catch (error) {
|
110 |
-
console.error("Failed to get summary:", error);
|
111 |
-
return; // Optionally handle this case differently
|
112 |
-
}
|
113 |
-
|
114 |
-
const data_obj = {
|
115 |
-
"title": d.Title,
|
116 |
-
"link": d.Url,
|
117 |
-
"summary": summary,
|
118 |
-
"source": d.Source
|
119 |
-
};
|
120 |
-
|
121 |
-
data.push(data_obj);
|
122 |
-
|
123 |
-
try {
|
124 |
-
await db.collection('mail-template').doc(key).set(data_obj);
|
125 |
-
} catch (error) {
|
126 |
-
console.error("Failed to update mail template:", error);
|
127 |
-
// Handle error appropriately
|
128 |
-
}
|
129 |
-
});
|
130 |
-
|
131 |
-
await Promise.all(promises); // Ensure all promises are resolved
|
132 |
-
res.send({ data });
|
133 |
-
} catch (e) {
|
134 |
-
res.send({ "ERROR": e });
|
135 |
-
}
|
136 |
-
});
|
137 |
-
|
138 |
-
async function getSummary(url) {
|
139 |
-
|
140 |
-
console.log(url)
|
141 |
-
const apiUrl = 'https://yashxx07-summarize-articles.hf.space/summarize-v2';
|
142 |
-
const options = {
|
143 |
-
method: 'POST',
|
144 |
-
headers: {
|
145 |
-
'content-type': 'application/json',
|
146 |
-
},
|
147 |
-
body: JSON.stringify({
|
148 |
-
"url": url,
|
149 |
-
"percentage": 20
|
150 |
-
})
|
151 |
-
};
|
152 |
-
|
153 |
-
try {
|
154 |
-
const response = await fetch(apiUrl, options);
|
155 |
-
|
156 |
-
const result = await response.json();
|
157 |
-
//console.log(result);
|
158 |
-
return result.summary;
|
159 |
-
} catch (error) {
|
160 |
-
console.error(error);
|
161 |
-
}
|
162 |
-
|
163 |
-
return "";
|
164 |
-
|
165 |
-
|
166 |
-
}
|
167 |
-
|
168 |
-
|
169 |
-
/// ******* email service code starts here
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
async function sendEmail(emailsList, mailContent) {
|
176 |
-
try {
|
177 |
-
const transporter = nodemailer.createTransport({
|
178 |
-
host: "smtp.elasticemail.com",
|
179 |
-
port: 2525,
|
180 |
-
auth: {
|
181 |
-
user: "zerothtest@mail.com",
|
182 |
-
pass: "E6DADFA42CB201B8BA973C46DEA509951E20",
|
183 |
-
},
|
184 |
-
});
|
185 |
-
|
186 |
-
let successCount = 0;
|
187 |
-
for (const email of emailsList) {
|
188 |
-
const info = await transporter.sendMail({
|
189 |
-
from: {
|
190 |
-
name: "RapidRecap",
|
191 |
-
address: process.env.MAIL
|
192 |
-
},
|
193 |
-
to: email,
|
194 |
-
subject: "Today's Top News",
|
195 |
-
html: mailContent
|
196 |
-
});
|
197 |
-
successCount++;
|
198 |
-
console.log(`Message sent: ${info.messageId}`);
|
199 |
-
}
|
200 |
-
|
201 |
-
return { STATUS: `${successCount} emails sent successfully` };
|
202 |
-
} catch (error) {
|
203 |
-
console.error(error);
|
204 |
-
return { ERROR: error };
|
205 |
-
}
|
206 |
-
}
|
207 |
-
|
208 |
-
|
209 |
-
async function getEmailsList(time) {
|
210 |
-
const emailsList = [];
|
211 |
-
|
212 |
-
try{
|
213 |
-
const subRef = db.collection('subscriptions');
|
214 |
-
const snapshot = await subRef.where('time', '==', time).get();
|
215 |
-
|
216 |
-
snapshot.forEach(doc => {
|
217 |
-
emailsList.push(doc.data().email);
|
218 |
-
});
|
219 |
-
return emailsList;
|
220 |
-
|
221 |
-
}catch(e){
|
222 |
-
console.log(e);
|
223 |
-
return emailsList;
|
224 |
-
}
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
}
|
229 |
-
|
230 |
-
async function getTopNews() {
|
231 |
-
let mailContent = "";
|
232 |
-
|
233 |
-
try{
|
234 |
-
const newsRef = db.collection('mail-template');
|
235 |
-
const snapshot = await newsRef.get();
|
236 |
-
|
237 |
-
snapshot.forEach(doc => {
|
238 |
-
mailContent += `<div style='background:white;margin-top:5px;color:#545454;padding:10px;border:1px solid white; text-align:center'>
|
239 |
-
<a href='${doc.data().link}'><h1>${doc.data().title}</h1></a>`;
|
240 |
-
mailContent += `<div style='display:flex;justify-content:center;align-items:center;'>
|
241 |
-
<h1>Source: </h1>
|
242 |
-
<a href='${doc.data().source}'><h1>${doc.data().source}</h1></a> </div>`
|
243 |
-
mailContent += `<p>${doc.data().summary}</p>`
|
244 |
-
mailContent += `</div>`;
|
245 |
-
});
|
246 |
-
return mailContent;
|
247 |
-
|
248 |
-
}catch(e){
|
249 |
-
console.log(e);
|
250 |
-
return mailContent;
|
251 |
-
}
|
252 |
-
|
253 |
-
}
|
254 |
-
|
255 |
-
app.get('/send-email', async (req, res) => {
|
256 |
-
try {
|
257 |
-
const time = req.query.time;
|
258 |
-
const emailsList = await getEmailsList(time);
|
259 |
-
const mailContent = await getTopNews();
|
260 |
-
const result = await sendEmail(emailsList, mailContent);
|
261 |
-
res.send("success");
|
262 |
-
} catch (error) {
|
263 |
-
console.log(error);
|
264 |
-
res.send({"Error": error});
|
265 |
-
}
|
266 |
-
});
|
|
|
1 |
+
const express = require("express");
|
2 |
+
require('dotenv').config();
|
3 |
+
|
4 |
+
const { getNews, getNews2 } = require("./news");
|
5 |
+
const { updateEmailNews, sendEmail } = require("./emails");
|
6 |
+
|
7 |
+
|
8 |
+
const app = express();
|
9 |
+
const port = 8000;
|
10 |
+
app.listen(port, () => {
|
11 |
+
console.log(`Server running at http://localhost:${port}`)
|
12 |
+
});
|
13 |
+
|
14 |
+
app.get("/", (requset, response) => {
|
15 |
+
response.send({
|
16 |
+
STATUS: "OK"
|
17 |
+
});
|
18 |
+
});
|
19 |
+
|
20 |
+
|
21 |
+
app.get("/rss-parse", getNews);
|
22 |
+
|
23 |
+
app.get("/update-email-news", updateEmailNews);
|
24 |
+
|
25 |
+
app.get("/send-email", sendEmail);
|
26 |
+
|
27 |
+
|
28 |
+
|
29 |
+
|
30 |
+
|
31 |
+
|
32 |
+
|
33 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
news.js
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
require('dotenv').config()
|
2 |
+
let Parser = require('rss-parser');
|
3 |
+
let parser = new Parser();
|
4 |
+
|
5 |
+
const { Pool } = require('pg');
|
6 |
+
var parse = require('pg-connection-string').parse;
|
7 |
+
|
8 |
+
|
9 |
+
var config = parse(process.env.DATABASE_URL);
|
10 |
+
const pool = new Pool(config);
|
11 |
+
|
12 |
+
|
13 |
+
const rssList = [
|
14 |
+
{
|
15 |
+
"https://search.cnbc.com/rs/search/combinedcms/view.xml?partnerId=wrss01&id=100003114": ["top", "https://www.cnbc.com", "cnbc.com"],
|
16 |
+
"https://search.cnbc.com/rs/search/combinedcms/view.xml?partnerId=wrss01&id=100727362": ["world", "https://www.cnbc.com", "cnbc.com"],
|
17 |
+
"https://search.cnbc.com/rs/search/combinedcms/view.xml?partnerId=wrss01&id=10001147": ["business", "https://www.cnbc.com", "cnbc.com"],
|
18 |
+
"https://search.cnbc.com/rs/search/combinedcms/view.xml?partnerId=wrss01&id=10001054": ["science", "https://www.cnbc.com", "cnbc.com"],
|
19 |
+
"https://search.cnbc.com/rs/search/combinedcms/view.xml?partnerId=wrss01&id=19854910": ["technology", "https://www.cnbc.com", "cnbc.com"],
|
20 |
+
|
21 |
+
"http://timesofindia.indiatimes.com/rssfeeds/1081479906.cms": ["entertainment", "https://timesofindia.indiatimes.com/", "timesofindia.indiatimes.com"],
|
22 |
+
"https://timesofindia.indiatimes.com/rssfeedstopstories.cms": ["top", "https://timesofindia.indiatimes.com/", "timesofindia.indiatimes.com"],
|
23 |
+
"https://timesofindia.indiatimes.com/rssfeeds/296589292.cms": ["world", "https://timesofindia.indiatimes.com/", "timesofindia.indiatimes.com"],
|
24 |
+
"https://timesofindia.indiatimes.com/rssfeeds/1898055.cms": ["business", "https://timesofindia.indiatimes.com/", "timesofindia.indiatimes.com"],
|
25 |
+
"https://timesofindia.indiatimes.com/rssfeeds/-2128672765.cms": ["science", "https://timesofindia.indiatimes.com/", "timesofindia.indiatimes.com"],
|
26 |
+
"https://timesofindia.indiatimes.com/rssfeeds/4719148.cms": ["sports", "https://timesofindia.indiatimes.com/", "timesofindia.indiatimes.com"],
|
27 |
+
"https://timesofindia.indiatimes.com/rssfeeds/66949542.cms": ["technology", "https://timesofindia.indiatimes.com/", "timesofindia.indiatimes.com"],
|
28 |
+
"http://timesofindia.indiatimes.com/rssfeeds/1081479906.cms": ["entertainment", "https://timesofindia.indiatimes.com/", "timesofindia.indiatimes.com"],
|
29 |
+
"http://timesofindia.indiatimes.com/rssfeeds/-2128936835.cms": ["india", "https://timesofindia.indiatimes.com/", "timesofindia.indiatimes.com"],
|
30 |
+
|
31 |
+
},
|
32 |
+
|
33 |
+
{
|
34 |
+
"https://feeds.abcnews.com/abcnews/topstories": ["top", "https://abcnews.go.com/", "abcnews.go.com"],
|
35 |
+
"https://feeds.abcnews.com/abcnews/internationalheadlines": ["world", "https://abcnews.go.com/", "abcnews.go.com"],
|
36 |
+
"https://feeds.abcnews.com/abcnews/moneyheadlines": ["business", "https://abcnews.go.com/", "abcnews.go.com"],
|
37 |
+
"https://feeds.abcnews.com/abcnews/technologyheadlines": ["technology", "https://abcnews.go.com/", "abcnews.go.com"],
|
38 |
+
"https://feeds.abcnews.com/abcnews/entertainmentheadlines": ["entertainment", "https://abcnews.go.com/", "abcnews.go.com"],
|
39 |
+
"https://feeds.abcnews.com/abcnews/sportsheadlines": ["sports", "https://abcnews.go.com/", "abcnews.go.com"],
|
40 |
+
|
41 |
+
"https://moxie.foxnews.com/google-publisher/latest.xml": ["top", "https://www.foxnews.com/", "foxnews.com"],
|
42 |
+
"https://moxie.foxnews.com/google-publisher/science.xml": ["science", "https://www.foxnews.com/", "foxnews.com"],
|
43 |
+
"https://moxie.foxnews.com/google-publisher/sports.xml": ["sports", "https://www.foxnews.com/", "foxnews.com"],
|
44 |
+
"https://moxie.foxnews.com/google-publisher/tech.xml": ["technology", "https://www.foxnews.com/", "foxnews.com"],
|
45 |
+
"https://moxie.foxnews.com/google-publisher/world.xml": ["world", "https://www.foxnews.com/", "foxnews.com"],
|
46 |
+
|
47 |
+
"http://www.moneycontrol.com/rss/MCtopnews.xml": ["india business", "http://www.moneycontrol.com", "moneycontrol.com"],
|
48 |
+
"https://www.livemint.com/rss/sports": ["india sports", "https://www.livemint.com", "livemint.com"],
|
49 |
+
|
50 |
+
}
|
51 |
+
|
52 |
+
];
|
53 |
+
|
54 |
+
|
55 |
+
|
56 |
+
const getNews = async (req, res) => {
|
57 |
+
|
58 |
+
|
59 |
+
|
60 |
+
try {
|
61 |
+
const id = req.query.id;
|
62 |
+
|
63 |
+
//console.log(id,rssList[id]);
|
64 |
+
|
65 |
+
for (const url in rssList[id]) {
|
66 |
+
|
67 |
+
const data = [];
|
68 |
+
let feed = await parser.parseURL(url);
|
69 |
+
|
70 |
+
|
71 |
+
for (let i = 0; i < 6; i++) {
|
72 |
+
data.push(feed.items[i]);
|
73 |
+
}
|
74 |
+
|
75 |
+
//console.log(data, rssList[id][url][0], rssList[id][url][1], rssList[id][url][2]);
|
76 |
+
await uploadNewsOnDatabase(data, rssList[id][url][0], rssList[id][url][1], rssList[id][url][2]);
|
77 |
+
}
|
78 |
+
|
79 |
+
res.send({ STATUS: "SUCCESS" });
|
80 |
+
|
81 |
+
|
82 |
+
} catch (e) {
|
83 |
+
return e;
|
84 |
+
}
|
85 |
+
|
86 |
+
}
|
87 |
+
|
88 |
+
function convertToISO8601(dateString) {
|
89 |
+
return new Date(dateString).toISOString();
|
90 |
+
}
|
91 |
+
|
92 |
+
const uploadNewsOnDatabase = async (data, category, newsSource, newsSourceName) => {
|
93 |
+
try {
|
94 |
+
|
95 |
+
|
96 |
+
data.forEach(async (item) => {
|
97 |
+
|
98 |
+
const query = `
|
99 |
+
INSERT INTO news (title, source, article_url, image_url, published_date, category, source_name)
|
100 |
+
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
101 |
+
`;
|
102 |
+
const values = [
|
103 |
+
item.title,
|
104 |
+
newsSource,
|
105 |
+
item.link,
|
106 |
+
item.enclosure ? item.enclosure.url : null,
|
107 |
+
convertToISO8601(item.pubDate),
|
108 |
+
//item.pubDate,
|
109 |
+
category,
|
110 |
+
newsSourceName
|
111 |
+
];
|
112 |
+
|
113 |
+
await pool.query(query, values);
|
114 |
+
|
115 |
+
});
|
116 |
+
|
117 |
+
|
118 |
+
} catch (error) {
|
119 |
+
console.error("Error fetching data:", error);
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
module.exports = { getNews };
|
package-lock.json
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
package.json
CHANGED
@@ -1,20 +1,21 @@
|
|
1 |
-
{
|
2 |
-
"name": "sum-api",
|
3 |
-
"version": "1.0.0",
|
4 |
-
"description": "",
|
5 |
-
"main": "index.js",
|
6 |
-
"scripts": {
|
7 |
-
"test": "echo \"Error: no test specified\" && exit 1"
|
8 |
-
},
|
9 |
-
"author": "",
|
10 |
-
"license": "ISC",
|
11 |
-
"
|
12 |
-
|
13 |
-
"
|
14 |
-
"
|
15 |
-
"
|
16 |
-
"
|
17 |
-
"
|
18 |
-
"
|
19 |
-
|
20 |
-
}
|
|
|
|
1 |
+
{
|
2 |
+
"name": "sum-api",
|
3 |
+
"version": "1.0.0",
|
4 |
+
"description": "",
|
5 |
+
"main": "index.js",
|
6 |
+
"scripts": {
|
7 |
+
"test": "echo \"Error: no test specified\" && exit 1"
|
8 |
+
},
|
9 |
+
"author": "",
|
10 |
+
"license": "ISC",
|
11 |
+
"live": "nodemon server.js",
|
12 |
+
"dependencies": {
|
13 |
+
"dotenv": "^16.4.5",
|
14 |
+
"express": "^4.19.2",
|
15 |
+
"live-server": "^1.2.2",
|
16 |
+
"nodemailer": "^6.9.13",
|
17 |
+
"pg": "^8.11.5",
|
18 |
+
"postgres": "^3.4.4",
|
19 |
+
"rss-parser": "^3.13.0"
|
20 |
+
}
|
21 |
+
}
|