-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
executable file
·126 lines (119 loc) · 4.05 KB
/
index.js
1
2
3
4
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
const fs = require('fs');
const path = require('path');
const CONFIG_PATH = path.resolve(path.join(__dirname, 'config.json'));
const CONFIG = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
const LOG_PATH = path.resolve(path.join(__dirname, 'lfh-feed.log'));
const JSON_PATH = path.resolve(path.join(__dirname, 'episodes.json'));
const FEED_PATH = path.resolve(path.join(__dirname, 'feed.xml'));
const log = require('simple-node-logger').createSimpleFileLogger(LOG_PATH);
const puppeteer = require('puppeteer');
const Podcast = require('podcast');
const SFTPClient = require('sftp-promises');
const TARGET_URL = 'https://www.livefromhere.org';
const FTP_CONFIG = {
host: CONFIG.FTP_HOST,
username: CONFIG.FTP_USER,
password: CONFIG.FTP_PW,
};
const handleError = (error) => {
const date = new Date().toLocaleDateString();
log.info(`${date}: ${error}`);
};
const uploadPodcast = async () => {
const sftp = new SFTPClient(FTP_CONFIG);
try {
const success = await sftp.put(FEED_PATH, CONFIG.FTP_FEED_PATH);
const loggingDate = new Date().toLocaleDateString();
log.info(`${loggingDate}: attempted upload, success: ${success}`);
} catch (err) {
handleError(err);
}
};
const createPodcast = (episodes) => {
episodes.reverse();
const feed = new Podcast({
title: 'Live from Here (full episodes)',
description: 'Entire episodes scraped from livefromhere.org.',
feed_url: CONFIG.PUBLISHED_FEED_URL,
site_url: CONFIG.SITE_URL,
image_url: CONFIG.IMG_URL,
author: CONFIG.AUTHOR,
webMaster: CONFIG.WEBMASTER_EMAIL,
copyright: 'no copyright claimed',
language: 'en',
pubDate: new Date().toGMTString(),
ttl: '1440',
categories: ['Music', 'Comedy', 'Live Performance'],
});
episodes.forEach((episode) => {
feed.addItem({
title: episode.title,
description: `Entire Live from Here episode for ${episode.date}`,
url: episode.url,
date: episode.date,
enclosure: {
url: episode.url,
},
});
});
const xml = feed.buildXml();
fs.writeFile(FEED_PATH, xml, (err) => {
if (err) {
handleError('failed to write XML');
} else {
uploadPodcast();
}
});
};
const registerEpisode = async (episodeData) => {
const data = { ...episodeData };
const { url, title } = data;
if (!url || !title) {
handleError('failed to get episode data');
return;
}
const episodeDateString = url.split('lfh_')[1].split('.')[0];
const loggingDate = new Date().toLocaleDateString();
data.date = `${episodeDateString.slice(0, 4)}.${episodeDateString.slice(4, 6)}.${episodeDateString.slice(6, 8)}`;
data.title = `${data.date}: ${title}`;
log.info(`${loggingDate}: found episode '${data.title}'`);
fs.readFile(JSON_PATH, (err, episodesJSON) => {
if (err) {
handleError(err);
} else {
const episodesObj = JSON.parse(episodesJSON);
if (Array.isArray(episodesObj.episodes)) {
const existing = episodesObj.episodes.find((episode) => episode.date === data.date);
if (existing) {
log.info(`found preexisting episode (for ${data.date}) in list; quitting`);
} else {
episodesObj.episodes.push(data);
if (episodesObj.episodes.length >= 10) {
episodesObj.episodes.splice(0, 1);
}
fs.writeFile(JSON_PATH, JSON.stringify(episodesObj, null, 2), (err2) => {
if (err2) {
handleError(err2);
} else {
createPodcast(episodesObj.episodes);
}
});
}
} else {
handleError('invalid episodes.json file');
}
}
});
};
// fetch the page with puppeteer and get latest show data
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage().catch(handleError);
await page.goto(TARGET_URL).catch(handleError);
const showData = await page.evaluate(() => ({
url: document.querySelector('#player').getAttribute('data-src'),
title: document.querySelector('.player_title').innerText,
})).catch(handleError);
registerEpisode(showData);
await browser.close();
})();