mirror of
https://github.com/comatory/fb2iCal
synced 2025-02-24 23:47:44 +01:00
refactor retrieving ICS file
This commit is contained in:
parent
52b86953aa
commit
a41992d53b
@ -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
|
|
29
lib/index.js
29
lib/index.js
@ -4,10 +4,12 @@ const path = require('path')
|
|||||||
const favicon = require('serve-favicon')
|
const favicon = require('serve-favicon')
|
||||||
const rateLimit = require('express-rate-limit')
|
const rateLimit = require('express-rate-limit')
|
||||||
|
|
||||||
const crawl = require('./crawler')
|
const retrieveICS = require('./services/ics-retriever')
|
||||||
const parseHTML = require('./parser')
|
const {
|
||||||
const generateICS = require('./ics')
|
genericErrorHandler,
|
||||||
const { genericErrorHandler, checkURLParameter, forceSecure } = require('./middlewares')
|
checkURLParameter,
|
||||||
|
forceSecure,
|
||||||
|
} = require('./middlewares')
|
||||||
|
|
||||||
const port = process.env.PORT
|
const port = process.env.PORT
|
||||||
const certEndpoint = process.env.CERT_ENDPOINT || ''
|
const certEndpoint = process.env.CERT_ENDPOINT || ''
|
||||||
@ -50,22 +52,17 @@ app.get('*', (req, res) => {
|
|||||||
app.use('/download', checkURLParameter)
|
app.use('/download', checkURLParameter)
|
||||||
app.use('/download', rateLimit())
|
app.use('/download', rateLimit())
|
||||||
app.post('/download', async (req, res, next) => {
|
app.post('/download', async (req, res, next) => {
|
||||||
const { url } = req.body
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const html = await crawl(url)
|
const { url } = req.body
|
||||||
const data = parseHTML(html)
|
|
||||||
const ics = await generateICS(data)
|
|
||||||
|
|
||||||
if (ics) {
|
const ics = await retrieveICS(url)
|
||||||
return res
|
|
||||||
.contentType('text/calendar')
|
res
|
||||||
.status(200)
|
.contentType('text/calendar')
|
||||||
.send(new Buffer(ics, 'utf8'))
|
.status(200)
|
||||||
}
|
.send(new Buffer(ics, 'utf8'))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
next(err)
|
next(err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
24
lib/services/crawler.js
Normal file
24
lib/services/crawler.js
Normal 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
|
18
lib/services/ics-retriever.js
Normal file
18
lib/services/ics-retriever.js
Normal 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
|
@ -1,6 +1,6 @@
|
|||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
const cheerio = require('cheerio')
|
const cheerio = require('cheerio')
|
||||||
const { createParserError } = require('./utils')
|
const { createParserError } = require('../utils')
|
||||||
|
|
||||||
// NOTE: Specific formatting for `ics` library
|
// NOTE: Specific formatting for `ics` library
|
||||||
const parseDates = (startDate, endDate) => {
|
const parseDates = (startDate, endDate) => {
|
35
lib/utils.js
35
lib/utils.js
@ -18,9 +18,44 @@ const createParserError = () => {
|
|||||||
return err
|
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 = {
|
module.exports = {
|
||||||
checkValidURL,
|
checkValidURL,
|
||||||
checkURLFormat,
|
checkURLFormat,
|
||||||
checkNumberURLParameter,
|
checkNumberURLParameter,
|
||||||
createParserError,
|
createParserError,
|
||||||
|
createMobileURL,
|
||||||
|
createURL,
|
||||||
|
getNormalizedUrl,
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user