refactor retrieving ICS file

This commit is contained in:
Ondrej Synacek 2019-10-23 20:37:06 +02:00
parent 52b86953aa
commit a41992d53b
7 changed files with 91 additions and 64 deletions

View File

@ -1,47 +0,0 @@
const request = require('request')
const { checkURLFormat, checkNumberURLParameter } = require('./utils')
const useMobileURL = (originalURL) => {
const urlWithProtocol = originalURL.includes('http') ?
originalURL :
`https://${originalURL}`
const url = new URL(urlWithProtocol)
return `${url.protocol}//mobile.facebook.com${url.port}${url.pathname}${url.hash}`
}
const createURL = (originalURL) => {
if (checkURLFormat(originalURL)) {
return originalURL
}
if (checkNumberURLParameter(originalURL)) {
return `https://facebook.com/events/${originalURL}`
}
return ''
}
const crawl = async (originalURL) => {
const url = useMobileURL(createURL(originalURL))
return new Promise((resolve, reject) => {
console.info(`Started request for URL: ${url}`)
request({
url,
headers: {
'Accept-Language': 'en-US, en',
'User-Agent': 'request',
},
}, (err, res, body) => {
if (err) {
reject(err)
return
}
console.info(`Finished request for URL: ${url}`)
resolve(body)
})
})
}
module.exports = crawl

View File

@ -4,10 +4,12 @@ const path = require('path')
const favicon = require('serve-favicon')
const rateLimit = require('express-rate-limit')
const crawl = require('./crawler')
const parseHTML = require('./parser')
const generateICS = require('./ics')
const { genericErrorHandler, checkURLParameter, forceSecure } = require('./middlewares')
const retrieveICS = require('./services/ics-retriever')
const {
genericErrorHandler,
checkURLParameter,
forceSecure,
} = require('./middlewares')
const port = process.env.PORT
const certEndpoint = process.env.CERT_ENDPOINT || ''
@ -50,22 +52,17 @@ app.get('*', (req, res) => {
app.use('/download', checkURLParameter)
app.use('/download', rateLimit())
app.post('/download', async (req, res, next) => {
const { url } = req.body
try {
const html = await crawl(url)
const data = parseHTML(html)
const ics = await generateICS(data)
const { url } = req.body
if (ics) {
return res
.contentType('text/calendar')
.status(200)
.send(new Buffer(ics, 'utf8'))
}
const ics = await retrieveICS(url)
res
.contentType('text/calendar')
.status(200)
.send(new Buffer(ics, 'utf8'))
} catch (err) {
next(err)
return
}
})

24
lib/services/crawler.js Normal file
View File

@ -0,0 +1,24 @@
const request = require('request')
const crawl = async (url) => {
return new Promise((resolve, reject) => {
console.info(`Started request for URL: ${url}`)
request({
url,
headers: {
'Accept-Language': 'en-US, en',
'User-Agent': 'request',
},
}, (err, res, body) => {
if (err) {
reject(err)
return
}
console.info(`Finished request for URL: ${url}`)
resolve(body)
})
})
}
module.exports = crawl

View File

@ -0,0 +1,18 @@
const crawl = require('./crawler')
const parseHTML = require('./parser')
const generateICS = require('./ics-generator')
const { getNormalizedUrl } = require('../utils')
const retrieveICS = async (URLparameter) => {
try {
const url = getNormalizedUrl(URLparameter)
const html = await crawl(url)
const eventData = parseHTML(html)
const icsFile = await generateICS(eventData)
return icsFile
} catch (err) {
throw err
}
}
module.exports = retrieveICS

View File

@ -1,6 +1,6 @@
const dayjs = require('dayjs')
const cheerio = require('cheerio')
const { createParserError } = require('./utils')
const { createParserError } = require('../utils')
// NOTE: Specific formatting for `ics` library
const parseDates = (startDate, endDate) => {

View File

@ -18,9 +18,44 @@ const createParserError = () => {
return err
}
// NOTE: Using mobile facebook URL because it usually
// contains stringified JSON with event information
const createMobileURL = (originalURL) => {
const urlWithProtocol = originalURL.includes('http') ?
originalURL :
`https://${originalURL}`
const url = new URL(urlWithProtocol)
return `${url.protocol}//mobile.facebook.com${url.port}${url.pathname}${url.hash}`
}
// NOTE: Detect whether URL parameter contains
// number or http address
const createURL = (param) => {
if (checkURLFormat(param)) {
return param
}
if (checkNumberURLParameter(param)) {
return `https://facebook.com/events/${param}`
}
return ''
}
const getNormalizedUrl = (URLparameter) => {
const fbURL = createURL(URLparameter)
const mobileUrl = createMobileURL(fbURL)
return mobileUrl
}
module.exports = {
checkValidURL,
checkURLFormat,
checkNumberURLParameter,
createParserError,
createMobileURL,
createURL,
getNormalizedUrl,
}