Add option to output the cheapest flight only by Hopper (#484)

This commit is contained in:
Henry Wang
2018-08-18 13:11:03 +01:00
committed by DIYgod
parent e415a465d2
commit 3543e4c47c
4 changed files with 71 additions and 37 deletions

View File

@@ -172,7 +172,7 @@ id, App Store app id必选如 QQ 的链接为 https://itunes.apple.com/cn/
### App Store/Mac App Store 价格更新(限免) <Author uid="HenryQW"/>
举例: [https://rsshub.app/appstore/price/cn/mac/id115244347](https://rsshub.app/appstore/price/cn/mac/id115244347)
举例: [https://rsshub.app/appstore/price/cn/mac/id1152443474](https://rsshub.app/appstore/price/cn/mac/id1152443474)
路由: `/appstore/price/:country/:type/:id`
@@ -1890,12 +1890,16 @@ type可选不填则默认为 `all`
### Hopper 特价机票 <Author uid="HenryQW"/>
举例: 伦敦希思罗 &#9992; 北京首都国际 [https://rsshub.app/hopper/LHR/PEK](https://rsshub.app/hopper/LHR/PEK)
本路由返回由 Hopper 算法给出的现在可购入最便宜的折扣机票,通常包含 6 个结果。出行日期将由 Hopper 算法定义,可能是明天也可能是 10 个月后。
路由: `/hopper/:from/:to?`
举例: 伦敦希思罗 &#9992; 北京首都国际 [https://rsshub.app/hopper/1/LHR/PEK](https://rsshub.app/hopper/1/LHR/PEK)
路由: `/hopper/:lowestOnly/:from/:to?`
参数:
lowestOnly: 是否只返回最低价机票,`1`:是,其他任意值:否
from: 始发地IATA 国际航空运输协会机场代码
to: 目的地IATA 国际航空运输协会机场代码,可选,缺省则目的地为`任意城市`

View File

@@ -150,7 +150,7 @@ id, App Store app id, obtain from the app URL `https://itunes.apple.com/us/app/r
### App Store/Mac App Store Price Drop Alert <Author uid="HenryQW"/>
eg: [https://rsshub.app/appstore/price/cn/mac/id115244347](https://rsshub.app/appstore/price/cn/mac/id115244347)
eg: [https://rsshub.app/appstore/price/us/mac/id1152443474](https://rsshub.app/appstore/price/cn/mac/id1152443474)
Route: `/appstore/price/:country/:type/:id`
@@ -455,12 +455,16 @@ Parameters:
### Hopper Flight Deals <Author uid="HenryQW"/>
Eg: London Heathrow Airport &#9992; Beijing Capital International Airport [https://rsshub.app/hopper/LHR/PEK](https://rsshub.app/hopper/LHR/PEK)
This route returns a list of flight deals (in most cases, 6 flight deals) for a period defined by Hopper's algorithm, which means the travel date will be totally random (could be tomorrow or 10 months from now).
Route: `/hopper/:from/:to?`
Eg: London Heathrow Airport &#9992; Beijing Capital International Airport [https://rsshub.app/hopper/1/LHR/PEK](https://rsshub.app/hopper/1/LHR/PEK)
Route: `/hopper/:lowestOnly/:from/:to?`
Parameters:
- lowestOnly, set to `1` will return the cheapest deal only, instead of all deals, so you don't get spammed
- from, origin airport IATA code
- to, destination airport IATA code, optional, if unset the destination will be set to `anywhere`

View File

@@ -422,6 +422,6 @@ router.get('/appstore/update/:country/:id', require('./routes/appstore/update'))
router.get('/appstore/price/:country/:type/:id', require('./routes/appstore/price'));
// Hopper
router.get('/hopper/:from/:to?', require('./routes/hopper/index'));
router.get('/hopper/:lowestOnly/:from/:to?', require('./routes/hopper/index'));
module.exports = router;

View File

@@ -3,8 +3,10 @@ const config = require('../../config');
const cheerio = require('cheerio');
module.exports = async (ctx) => {
const from = ctx.params.from;
const to = ctx.params.to || 'Anywhere';
const from = ctx.params.from.toUpperCase();
const to = ctx.params.to !== undefined ? ctx.params.to.toUpperCase() : 'Anywhere';
const type = ctx.params.lowestOnly;
const url = `https://www.hopper.com/deals/best/from/${from}/to/${to}`;
const title = `Hopper - Flights From ${from} to ${to}`;
@@ -23,39 +25,38 @@ module.exports = async (ctx) => {
const $ = cheerio.load(response.data);
const list = $('div.prices li a');
const items = [];
if (type === '1') {
let lowest = 99999;
let lowIndex = 0;
list.map((i, e) => {
const current = parseInt(
$(e)
.find('.price')
.text()
.replace(/\D/g, '')
);
if (current < lowest) {
lowest = current;
lowIndex = i;
}
});
items.push(formatDesc($(list[lowIndex])));
} else {
list.map((i, e) => {
items.push(formatDesc($(e)));
});
}
ctx.state.data = {
title,
link: url,
description: title,
item: list
.map((i, e) => {
const item = $(e).attr('href');
let reg = new RegExp('destination=(.*?)&', 'g');
const destination = reg.exec(item)[1];
reg = new RegExp('origin=(.*?)&', 'g');
const origin = reg.exec(item)[1];
reg = new RegExp('departureDate=(.*?)&', 'g');
const departureDate = reg.exec(item)[1];
reg = new RegExp('returnDate=(.*?)&', 'g');
const returnDate = reg.exec(item)[1];
const price = $(list[i])
.find('.price')
.text();
const title = `${origin} &#9992; ${destination} ${getMonthYear(departureDate)} for ${price}`;
const description = `<table><tbody><tr><th align="left" style="border: 1px solid black;">From</th><th align="left" style="border: 1px solid black;">To</th><th align="left" style="border: 1px solid black;">Price</th></tr><tr><td style="border: 1px solid black;">
${origin}</td><td style="border: 1px solid black;">${destination}</td><td style="border: 1px solid black;">${price}</td></tr></tbody></table>${formatDate(departureDate)} &#9992; ${formatDate(returnDate)}`;
return {
title,
description,
guid: item,
link: item,
};
})
.get(),
item: items,
};
};
@@ -75,3 +76,28 @@ function getMonthYear(v) {
year: 'numeric',
});
}
function formatDesc(e) {
const item = e.attr('href');
let reg = new RegExp('destination=(.*?)&', 'g');
const destination = reg.exec(item)[1];
reg = new RegExp('origin=(.*?)&', 'g');
const origin = reg.exec(item)[1];
reg = new RegExp('departureDate=(.*?)&', 'g');
const departureDate = reg.exec(item)[1];
reg = new RegExp('returnDate=(.*?)&', 'g');
const returnDate = reg.exec(item)[1];
const price = e.find('.price').text();
const title = `${origin} &#9992; ${destination} ${getMonthYear(departureDate)} for ${price}`;
const description = `<table><tbody><tr><th align="left" style="border: 1px solid black;">From</th><th align="left" style="border: 1px solid black;">To</th><th align="left" style="border: 1px solid black;">Price</th></tr><tr><td style="border: 1px solid black;">
${origin}</td><td style="border: 1px solid black;">${destination}</td><td style="border: 1px solid black;">${price}</td></tr></tbody></table>${formatDate(departureDate)} &#9992; ${formatDate(returnDate)}`;
return {
title,
description,
guid: item,
link: item,
};
}