Added support for custom request options

This commit is contained in:
freearhey 2021-04-02 20:12:27 +03:00
parent 6860beba28
commit ee4d3534d5
8 changed files with 2281 additions and 181 deletions

3
babel.config.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
presets: [['@babel/preset-env', { targets: { node: 'current' } }]]
}

2319
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -29,11 +29,16 @@
"commander": "^7.1.0", "commander": "^7.1.0",
"dayjs": "^1.10.4", "dayjs": "^1.10.4",
"glob": "^7.1.6", "glob": "^7.1.6",
"lodash.merge": "^4.6.2",
"tough-cookie": "^4.0.0", "tough-cookie": "^4.0.0",
"xml-js": "^1.6.11" "xml-js": "^1.6.11"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.13.14",
"@babel/preset-env": "^7.13.12",
"babel-jest": "^26.6.3",
"eslint": "^7.22.0", "eslint": "^7.22.0",
"jest": "^26.6.3" "jest": "^26.6.3",
"jest-mock-axios": "^4.3.0"
} }
} }

View File

@ -18,7 +18,6 @@ async function main() {
const options = program.opts() const options = program.opts()
const config = utils.loadConfig(options.config) const config = utils.loadConfig(options.config)
const client = utils.createHttpClient(config)
const channels = utils.parseChannels(config.channels) const channels = utils.parseChannels(config.channels)
const utcDate = utils.getUTCDate() const utcDate = utils.getUTCDate()
const dates = Array.from({ length: config.days }, (_, i) => utcDate.add(i, 'd')) const dates = Array.from({ length: config.days }, (_, i) => utcDate.add(i, 'd'))
@ -33,10 +32,9 @@ async function main() {
let programs = [] let programs = []
console.log('Parsing:') console.log('Parsing:')
for (let item of queue) { for (let item of queue) {
const url = typeof config.url === 'function' ? config.url(item) : config.url
if (options.debug) console.time(' time') if (options.debug) console.time(' time')
const progs = await client const progs = await utils
.get(url) .fetchData(item, config)
.then(response => { .then(response => {
if (!item.channel.logo && config.logo) { if (!item.channel.logo && config.logo) {
item.channel.logo = config.logo({ item.channel.logo = config.logo({

View File

@ -1,9 +1,10 @@
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
const axios = require('axios') const axios = require('axios').default
const axiosCookieJarSupport = require('axios-cookiejar-support').default const axiosCookieJarSupport = require('axios-cookiejar-support').default
const tough = require('tough-cookie') const tough = require('tough-cookie')
const convert = require('xml-js') const convert = require('xml-js')
const merge = require('lodash.merge')
const dayjs = require('dayjs') const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
dayjs.extend(utc) dayjs.extend(utc)
@ -31,20 +32,26 @@ utils.loadConfig = function (file) {
config.channels = path.join(path.dirname(file), config.channels) config.channels = path.join(path.dirname(file), config.channels)
return Object.assign( const defaultConfig = {
{},
{
userAgent:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36 Edg/79.0.309.71',
days: 1, days: 1,
cookie: '',
lang: 'en', lang: 'en',
delay: 3000, delay: 3000,
timeout: 5000, output: 'guide.xml',
output: 'guide.xml' request: {
method: 'GET',
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36 Edg/79.0.309.71',
Cookie: ''
}, },
config timeout: 5000,
) withCredentials: true,
jar: new tough.CookieJar(),
responseType: 'arraybuffer'
}
}
return merge(defaultConfig, config)
} }
utils.parseChannels = function (filename) { utils.parseChannels = function (filename) {
@ -154,7 +161,7 @@ utils.convertToXMLTV = function ({ config, channels, programs }) {
} }
utils.parsePrograms = function ({ response, item, config }) { utils.parsePrograms = function ({ response, item, config }) {
const options = Object.assign({}, item, config, { const options = merge(item, config, {
content: response.data.toString(), content: response.data.toString(),
buffer: response.data buffer: response.data
}) })
@ -177,17 +184,12 @@ utils.writeToFile = function (filename, data) {
fs.writeFileSync(path.resolve(filename), data) fs.writeFileSync(path.resolve(filename), data)
} }
utils.createHttpClient = function (config) { utils.fetchData = function (item, config) {
return axios.create({ const options = config.request
headers: { options.url = typeof config.url === 'function' ? config.url(item) : config.url
'User-Agent': config.userAgent, options.data = typeof options.data === 'function' ? options.data(item) : options.data
Cookie: config.cookie
}, return axios(options)
timeout: config.timeout,
withCredentials: true,
jar: new tough.CookieJar(),
responseType: 'arraybuffer'
})
} }
utils.getUTCDate = function () { utils.getUTCDate = function () {

2
tests/__mocks__/axios.js Normal file
View File

@ -0,0 +1,2 @@
import mockAxios from 'jest-mock-axios'
export default mockAxios

View File

@ -2,6 +2,16 @@ module.exports = {
site: 'example.com', site: 'example.com',
channels: 'example.com.channels.xml', channels: 'example.com.channels.xml',
url: () => 'http://example.com/20210319/1tv.json', url: () => 'http://example.com/20210319/1tv.json',
request: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Cookie: 'abc=123'
},
data() {
return { accountID: '123' }
}
},
parser: () => [], parser: () => [],
logo: () => 'http://example.com/logos/1TV.png' logo: () => 'http://example.com/logos/1TV.png'
} }

View File

@ -1,22 +1,28 @@
const utils = require('../src/utils') import mockAxios from 'jest-mock-axios'
import utils from '../src/utils'
it('can load valid config.js', () => { it('can load valid config.js', () => {
expect(Object.keys(utils.loadConfig('./tests/input/example.com.config.js')).sort()).toEqual( const config = utils.loadConfig('./tests/input/example.com.config.js')
[ expect(config).toMatchObject({
'site', channels: 'tests/input/example.com.channels.xml',
'channels', days: 1,
'url', delay: 3000,
'logo', lang: 'en',
'parser', output: 'guide.xml',
'cookie', site: 'example.com'
'days', })
'delay', expect(config.request).toMatchObject({
'timeout', timeout: 5000,
'lang', headers: {
'output', 'Content-Type': 'application/json',
'userAgent' 'User-Agent':
].sort() 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36 Edg/79.0.309.71',
) Cookie: 'abc=123'
}
})
expect(typeof config.request.data).toEqual('function')
expect(typeof config.url).toEqual('function')
expect(typeof config.logo).toEqual('function')
}) })
it('can parse valid channels.xml', () => { it('can parse valid channels.xml', () => {
@ -70,3 +76,24 @@ it('can escape url', () => {
'http://example.com/logos/1TV.png?param1=val&param2=val' 'http://example.com/logos/1TV.png?param1=val&param2=val'
) )
}) })
it('can fetch data', () => {
const config = utils.loadConfig('./tests/input/example.com.config.js')
utils.fetchData({}, config).then(jest.fn).catch(jest.fn)
expect(mockAxios).toHaveBeenCalledWith(
expect.objectContaining({
data: { accountID: '123' },
headers: {
'Content-Type': 'application/json',
Cookie: 'abc=123',
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36 Edg/79.0.309.71'
},
method: 'POST',
responseType: 'arraybuffer',
timeout: 5000,
url: 'http://example.com/20210319/1tv.json',
withCredentials: true
})
)
})