scripts/latest-news/index.js (92 lines of code) (raw):
const https = require('https');
const fs = require('fs');
const path = require('path');
const { XMLParser } = require('fast-xml-parser');
const projectRoot = process.cwd();
const LATEST_NEWS_FOLDER_NAME = 'latest-news';
const NEWS_DATA = 'latest-news.json';
const latestNewsDirectory = path.join(projectRoot, LATEST_NEWS_FOLDER_NAME);
if (!fs.existsSync(latestNewsDirectory)) {
fs.mkdirSync(latestNewsDirectory);
}
getLatestNews();
function normalizeText(text) {
return text.replace(/&#(\d+);/gi, (_, ascii_code) => String.fromCharCode(ascii_code));
}
async function getLatestNews() {
const latestNewsXMl = await getLatestNewsXML();
const parser = new XMLParser({
ignoreDeclaration: true
});
const allJson = parser.parse(latestNewsXMl);
const items = allJson['rss']['channel']['item'];
const latestNews = [];
for (const [i, item] of items.splice(0, 4).entries()) {
console.log('Processing item', i, 'with link:', item.link);
const imagePath = await saveImage(i, item.featuredImage);
latestNews.push({
title: normalizeText(item.title),
date: item.pubDate,
link: item.link,
image: imagePath,
description: normalizeText(item.description)
})
}
fs.writeFileSync(path.join(latestNewsDirectory, NEWS_DATA), JSON.stringify(latestNews, null, ' '), 'utf8');
}
async function getLatestNewsXML() {
return await doRequest({
hostname: 'blog.jetbrains.com',
port: 443,
path: `/kotlin/feed/?rnd=${Date.now()}`,
method: 'GET',
headers: {
'User-Agent': 'Kotlin Parser',
'Cache-Control': 'no-cache',
'Pragma': 'no-cache'
}
});
}
async function saveImage(index, imageUrl) {
const url = new URL(imageUrl);
const localFilePath = path.join(latestNewsDirectory, 'news-' + index + '.png');
const relativePath = path.relative(projectRoot, localFilePath);
if (fs.existsSync(relativePath)) fs.unlinkSync(relativePath);
const fileStream = fs.createWriteStream(localFilePath);
return new Promise((resolve, reject) => {
const request = https.get(url, (response) => {
if (response.statusCode !== 200) {
reject(new Error(`Failed to download image. HTTP status code: ${response.statusCode}`));
return;
}
response.pipe(fileStream);
fileStream.on('finish', () => {
fileStream.close();
resolve(relativePath);
});
fileStream.on('error', (err) => {
reject(err);
});
});
request.on('error', reject);
request.end();
});
}
function doRequest(options) {
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
res.setEncoding('utf8');
let responseBody = '';
res.on('data', (chunk) => {
responseBody += chunk;
});
res.on('end', () => {
resolve(responseBody);
});
});
req.on('error', (err) => {
reject(err);
});
req.end();
});
}