mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-11 23:59:56 +08:00
feat(route): add 12306火车票消息 and refactor to V2 (#9031)
* feat(route): add 12306火车票消息 and refactor to V2 * fix(route): change guid * fix(route): change to use RSSHub's default UA * fix(route): add handle exception
This commit is contained in:
@@ -10,6 +10,10 @@ pageClass: routes
|
||||
|
||||
<Route author="LogicJake" example="/12306/zxdt" path="/12306/zxdt/:id?" :paramsDesc="['铁路局id,可在 URL 中找到,不填默认显示所有铁路局动态']"/>
|
||||
|
||||
### 售票信息
|
||||
|
||||
<Route author="Fatpandac" example="/12306/2022-02-19/重庆/永川东" path="/12306/:date/:from/:to/:type?" :paramsDesc="['时间', '始发站', '终点站', '售票类型,成人和学生可选,默认为成人']"/>
|
||||
|
||||
## All the Flight Deals
|
||||
|
||||
### 特价机票
|
||||
|
||||
@@ -1422,9 +1422,6 @@ router.get('/ui-cn/user/:id', lazyloadRouteHandler('./routes/ui-cn/user'));
|
||||
// Dcard
|
||||
router.get('/dcard/:section/:type?', lazyloadRouteHandler('./routes/dcard/section'));
|
||||
|
||||
// 12306
|
||||
router.get('/12306/zxdt/:id?', lazyloadRouteHandler('./routes/12306/zxdt'));
|
||||
|
||||
// 北京天文馆每日一图
|
||||
router.get('/bjp/apod', lazyloadRouteHandler('./routes/bjp/apod'));
|
||||
|
||||
|
||||
108
lib/v2/12306/index.js
Normal file
108
lib/v2/12306/index.js
Normal file
@@ -0,0 +1,108 @@
|
||||
const got = require('@/utils/got');
|
||||
const { art } = require('@/utils/render');
|
||||
const path = require('path');
|
||||
const config = require('@/config').value;
|
||||
|
||||
const rootUrl = 'https://kyfw.12306.cn';
|
||||
|
||||
async function getJSESSIONID(linkUrl) {
|
||||
const res = await got({
|
||||
method: 'get',
|
||||
url: linkUrl,
|
||||
headers: {
|
||||
UserAgent: config.ua,
|
||||
Referer: 'https://www.12306.cn/index/index.html',
|
||||
},
|
||||
});
|
||||
|
||||
return res.headers['set-cookie'].join().match(/JSESSIONID=([^;]+);/)[0];
|
||||
}
|
||||
|
||||
function getStationInfo(stationName, ctx) {
|
||||
return ctx.cache.tryGet(stationName, async () => {
|
||||
const res = await got({
|
||||
method: 'get',
|
||||
url: `${rootUrl}/otn/resources/js/framework/station_name.js`,
|
||||
headers: {
|
||||
UserAgent: config.ua,
|
||||
Referer: 'https://kyfw.12306.cn/otn/leftTicket/init',
|
||||
},
|
||||
});
|
||||
|
||||
return res.data
|
||||
.split('@')
|
||||
.map((item) => {
|
||||
const itemData = item.split('|');
|
||||
|
||||
return itemData.indexOf(stationName) !== -1
|
||||
? {
|
||||
code: itemData[2],
|
||||
name: itemData[1],
|
||||
}
|
||||
: null;
|
||||
})
|
||||
.filter((item) => item)[0];
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const date = ctx.params.date;
|
||||
const fromStationInfo = await getStationInfo(ctx.params.from, ctx);
|
||||
const toStationInfo = await getStationInfo(ctx.params.to, ctx);
|
||||
const type = ctx.params.type ?? 'ADULT';
|
||||
|
||||
const apiUrl = `${rootUrl}/otn/leftTicket/queryA?leftTicketDTO.train_date=${date}&leftTicketDTO.from_station=${fromStationInfo.code}&leftTicketDTO.to_station=${toStationInfo.code}&purpose_codes=${type}`;
|
||||
const linkUrl = `${rootUrl}/otn/leftTicket/init?linktypeid=dc&fs=${fromStationInfo.code}&ts=${toStationInfo.code}&date=${date}&flag=N,N,Y`;
|
||||
|
||||
const response = await got.get(apiUrl, {
|
||||
headers: {
|
||||
UserAgent: config.ua,
|
||||
Referer: 'https://kyfw.12306.cn/otn/leftTicket/init',
|
||||
Cookie: await getJSESSIONID(linkUrl),
|
||||
},
|
||||
});
|
||||
const data = response.data.data.result;
|
||||
const map = response.data.data.map;
|
||||
if (data.length === 0) {
|
||||
throw '没有找到相关车次,请检查参数是否正确';
|
||||
}
|
||||
|
||||
const items = data.map((item) => {
|
||||
const itemData = item.split('|');
|
||||
const trainInfo = {
|
||||
trainNo: itemData[3],
|
||||
fromStation: map[itemData[6]],
|
||||
toStation: map[itemData[7]],
|
||||
startTime: itemData[8],
|
||||
arriveTime: itemData[9],
|
||||
duration: itemData[10],
|
||||
today: itemData[11],
|
||||
A9: itemData[32],
|
||||
M: itemData[31],
|
||||
O: itemData[30],
|
||||
A6: itemData[29],
|
||||
A4: itemData[28],
|
||||
F: itemData[27],
|
||||
A3: itemData[26],
|
||||
A2: itemData[25],
|
||||
A1: itemData[24],
|
||||
WZ: itemData[23],
|
||||
QT: itemData[22],
|
||||
};
|
||||
|
||||
return {
|
||||
title: `${trainInfo.fromStation} → ${trainInfo.toStation} ${trainInfo.startTime} ${trainInfo.arriveTime}`,
|
||||
description: art(path.join(__dirname, 'templates/train.art'), {
|
||||
trainInfo,
|
||||
}),
|
||||
link: linkUrl,
|
||||
guid: item,
|
||||
};
|
||||
});
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${fromStationInfo.name} → ${toStationInfo.name} ${date}`,
|
||||
link: linkUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
4
lib/v2/12306/maintainer.js
Normal file
4
lib/v2/12306/maintainer.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
'/:date/:from/:to/:type?': ['Fatpandac'],
|
||||
'/zxdt/:id?': ['LogicJake'],
|
||||
};
|
||||
28
lib/v2/12306/radar.js
Normal file
28
lib/v2/12306/radar.js
Normal file
@@ -0,0 +1,28 @@
|
||||
module.exports = {
|
||||
'12306.cn': {
|
||||
_name: '12306',
|
||||
kyfw: [
|
||||
{
|
||||
title: '售票信息',
|
||||
docs: 'https://docs.rsshub.app/travel.html#_12306-shou-shu-piao-piao-xin-shen-xi',
|
||||
source: ['/', '/otn/leftTicket/init'],
|
||||
target: (params, url) => {
|
||||
const searchParams = new URL(url).searchParams;
|
||||
const from = searchParams.get('fs').split(',')[0];
|
||||
const to = searchParams.get('ts').split(',')[0];
|
||||
const date = searchParams.get('date');
|
||||
|
||||
return `/12306/${date}/${from}/${to}`;
|
||||
},
|
||||
},
|
||||
],
|
||||
www: [
|
||||
{
|
||||
title: '最新动态',
|
||||
docs: 'https://docs.rsshub.app/travel.html#_12306-zui-cuo-xin-dong-tai',
|
||||
source: ['/', '/mormhweb/1/:id/index_fl.html'],
|
||||
target: '/12306/zxdt/:id',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
4
lib/v2/12306/router.js
Normal file
4
lib/v2/12306/router.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = function (router) {
|
||||
router.get('/:date/:from/:to/:type?', require('./index'));
|
||||
router.get('/zxdt/:id?', require('./zxdt'));
|
||||
};
|
||||
31
lib/v2/12306/templates/train.art
Normal file
31
lib/v2/12306/templates/train.art
Normal file
@@ -0,0 +1,31 @@
|
||||
<text>车次:{{ trainInfo.trainNo}}</text>
|
||||
<br>
|
||||
<text>始发站:{{ trainInfo.fromStation}} → {{ trainInfo.toStation}}</text>
|
||||
<br>
|
||||
<text>出发时间:{{ trainInfo.startTime}}</text>
|
||||
<br>
|
||||
<text>到达时间:{{ trainInfo.arriveTime}}</text>
|
||||
<br>
|
||||
<text>历时:{{ trainInfo.duration}} {{ trainInfo.today === 'N' ? '次日达' : '' }}</text>
|
||||
<br>
|
||||
<text>商务座/特等座:{{ trainInfo.A9 ? trainInfo.A9 : '无' }}</text>
|
||||
<br>
|
||||
<text>一等座:{{ trainInfo.M ? trainInfo.M : '无' }}</text>
|
||||
<br>
|
||||
<text>二等座/二等包座:{{ trainInfo.O ? trainInfo.O : '无' }}</text>
|
||||
<br>
|
||||
<text>高级软卧:{{ trainInfo.A6 ? trainInfo.A6 : '无' }}</text>
|
||||
<br>
|
||||
<text>软卧/一等卧:{{ trainInfo.A4 ? trainInfo.A4 : '无' }}</text>
|
||||
<br>
|
||||
<text>动卧:{{ trainInfo.F ? trainInfo.F : '无' }}</text>
|
||||
<br>
|
||||
<text>硬卧/二等卧:{{ trainInfo.A3 ? trainInfo.A3 : '无' }}</text>
|
||||
<br>
|
||||
<text>软座: {{ trainInfo.A2 ? trainInfo.A2 : '无' }}</text>
|
||||
<br>
|
||||
<text>硬座: {{ trainInfo.A1 ? trainInfo.A1 : '无' }}</text>
|
||||
<br>
|
||||
<text>无座: {{ trainInfo.WZ ? trainInfo.WZ : '无' }}</text>
|
||||
<br>
|
||||
<text>其他: {{ trainInfo.QT ? trainInfo.QT : '无' }}</text>
|
||||
Reference in New Issue
Block a user