forked from DIYgod/RSSHub
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
da288c5
commit dcab1c4
Showing
5 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
const utils = require('./utils'); | ||
|
||
module.exports = async (ctx) => { | ||
// number is shorthand for company | ||
// id is ticket number | ||
// phone for shunfeng :) | ||
const { number, id, phone } = ctx.params; | ||
|
||
// I am doing these to avoid invaild request. | ||
// First, check if code is vaild | ||
const { status, message, company } = await utils.checkCode(ctx, number, id, phone); | ||
|
||
let data; | ||
let query; | ||
const time = new Date().toString(); | ||
|
||
if (status) { | ||
query = await utils.getQuery(ctx, number, id, phone); | ||
if (query.status !== '200') { | ||
data = [ | ||
{ | ||
context: query.message, | ||
time, | ||
}, | ||
]; | ||
} else { | ||
data = query.data; | ||
} | ||
} else { | ||
data = [ | ||
{ | ||
context: message, | ||
time, | ||
}, | ||
]; | ||
} | ||
|
||
// Maybe we can look into isCheck, condition, and state :) | ||
// But I just want to make it work for now. | ||
ctx.state.data = { | ||
title: `快递 ${company.name}-${number}`, | ||
link: 'https://www.kuaidi100.com', | ||
description: `快递 ${company.name}-${number}`, | ||
item: data.map((item) => ({ | ||
title: item.context, | ||
description: item.context, | ||
pubDate: new Date(item.time || item.ftime).toUTCString(), | ||
link: 'https://www.kuaidi100.com', | ||
})), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
const utils = require('./utils'); | ||
|
||
module.exports = async (ctx) => { | ||
const ls = await utils.company(ctx); | ||
ctx.state.data = { | ||
title: `快递100 快递列表`, | ||
link: 'https://www.kuaidi100.com', | ||
description: `快递100 所支持的快递列表及其查询名称`, | ||
item: ls.map((item) => ({ | ||
title: item.name, | ||
description: item.number, | ||
category: item.comTypeName, | ||
pubDate: new Date().toUTCString(), | ||
link: item.siteUrl, | ||
})), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
const got = require('@/utils/got'); | ||
const wwwid_key = 'kuaidi100-wwwid'; | ||
const csrf_key = 'kuaidi100-csrf'; | ||
const query_count = 'kuaidi100-cookie-count'; | ||
const max_query_count = 30; | ||
|
||
async function getCookie(ctx) { | ||
// Check if this key should be replace? every 30 times should be fine. | ||
await shouldUpdateCookie(ctx); | ||
let wwwid = await ctx.cache.get(wwwid_key); | ||
let csrf = await ctx.cache.get(csrf_key); | ||
if (!wwwid || !csrf) { | ||
const indexResponse = await got({ | ||
method: 'get', | ||
url: 'https://www.kuaidi100.com/?from=appstore', | ||
headers: { | ||
// App store | ||
Referer: 'https://apps.apple.com/cn/app/%E5%BF%AB%E9%80%92100-%E5%8F%8C11%E5%AF%84%E4%BB%B6%E9%80%80%E8%B4%A7-%E4%B8%8A%E5%BF%AB%E9%80%92100/id458270120', | ||
}, | ||
}); | ||
const set_cookie = indexResponse.headers['set-cookie']; | ||
if (set_cookie) { | ||
for (const e of set_cookie) { | ||
if (e.indexOf('WWWID') === 0) { | ||
wwwid = e.split(';')[0]; | ||
} else if (e.indexOf('csrftoken') === 0) { | ||
csrf = e.split(';')[0]; | ||
} | ||
} | ||
} | ||
|
||
ctx.cache.set(wwwid_key, wwwid, 600); | ||
ctx.cache.set(csrf_key, csrf, 600); | ||
// We have acquired new cookie. It may due to cache timeout. | ||
// Force update counter and don't wait it finished. | ||
shouldUpdateCookie(ctx, true); | ||
} | ||
|
||
return { | ||
wwwid, | ||
csrf, | ||
}; | ||
} | ||
|
||
/* | ||
Example Company | ||
{ | ||
"available": false, <- 这个不知道是什么的可用性,反正不是可查询的 | ||
"canOrder": false, | ||
"comTypeName": "国内运输商", | ||
"contactTel": "626-818-2750", | ||
"createTime": 1486202888000, | ||
"hasNetwork": false, | ||
"id": 7172420, | ||
"name": "金岸物流", | ||
"number": "jinan", | ||
"shortName": "金岸物流", | ||
"shortNumber": "jinan", | ||
"siteUrl": "http://www.gpl-express.com/", | ||
"type": 0, | ||
"version": 776 | ||
} | ||
*/ | ||
async function getCompanyList(ctx) { | ||
// Using date as cache key and it will automatically expired by 1d | ||
const key = `kuaidi100-company-name-${new Date().toISOString().split('T')[0]}`; | ||
let list = await ctx.cache.get(key); | ||
if (!list) { | ||
const cookie = await getCookie(ctx); | ||
const wwwid = cookie.wwwid; | ||
const companyResponse = await got({ | ||
method: 'post', | ||
url: 'https://www.kuaidi100.com/company.do?method=js&t=201701051440', | ||
headers: { | ||
Referer: 'https://www.kuaidi100.com/', | ||
Cookie: wwwid, | ||
}, | ||
}); | ||
list = companyResponse.body; | ||
|
||
// Parsing the js file | ||
try { | ||
list = list | ||
.substr(12) | ||
.replace(/};/g, '}') | ||
.replace(/'/g, '"'); | ||
list = JSON.parse(list); | ||
list = list.company; | ||
} catch (e) { | ||
list = []; | ||
} | ||
|
||
ctx.cache.set(key, list); | ||
} else { | ||
list = JSON.parse(list); | ||
} | ||
return list; | ||
} | ||
|
||
async function shouldUpdateCookie(ctx, forcedUpdate = false) { | ||
if (forcedUpdate) { | ||
ctx.cache.set(query_count, 0); | ||
} else { | ||
const count = ctx.cache.get(query_count); | ||
if (!count) { | ||
ctx.cache.set(query_count, 1); | ||
} else { | ||
if (count > max_query_count) { | ||
ctx.cache.set(query_count, 0); | ||
await clearCookie(ctx); | ||
} else { | ||
ctx.cache.set(query_count, count + 1); | ||
} | ||
} | ||
} | ||
} | ||
|
||
async function clearCookie(ctx) { | ||
ctx.cache.set(wwwid_key, null); | ||
ctx.cache.set(csrf_key, null); | ||
} | ||
|
||
module.exports = { | ||
company: async (ctx) => await getCompanyList(ctx), | ||
checkCode: async (ctx, number, id, phone) => { | ||
const list = await getCompanyList(ctx); | ||
const company = list.find((c) => c.number === number); | ||
if (!company) { | ||
return { | ||
status: false, | ||
message: '快递公司编号不受支持!', | ||
company: { | ||
name: '未知', | ||
}, | ||
}; | ||
} else { | ||
if (number.indexOf('shunfeng') !== -1 && !isNaN(phone) && String(phone).length !== 4) { | ||
return { | ||
status: false, | ||
message: '顺丰查询需要手机号后四位!', | ||
company, | ||
}; | ||
} else if (company.checkReg) { | ||
return { | ||
status: true, | ||
regex: new RegExp(company.checkReg).test(id), | ||
company, | ||
}; | ||
} else { | ||
return { | ||
status: true, | ||
regex: undefined, | ||
company, | ||
}; | ||
} | ||
} | ||
}, | ||
|
||
/* | ||
Example Query | ||
{ | ||
"message": "ok", | ||
"nu": "73123917441103", | ||
"ischeck": "1", | ||
"condition": "F00", | ||
"com": "zhongtong", | ||
"status": "200", | ||
"state": "3", | ||
"data": [{ | ||
"time": "2019-12-12 12:41:15", | ||
"ftime": "2019-12-12 12:41:15", | ||
"context": "【温州市】 快件已由【菜鸟的温州燎原华庭7栋103号店】代签收, 如有问题请电联(18581563547 / 4001787878), 感谢您使用中通快递, 期待再次为您服务!", | ||
"location": "" | ||
} | ||
...] | ||
Example failed Query | ||
{ | ||
"message": "快递公司参数异常:验证码错误", | ||
"nu": "", | ||
"ischeck": "0", | ||
"condition": "", | ||
"com": "", | ||
"status": "408", | ||
"state": "0", | ||
"data": [] | ||
} | ||
*/ | ||
|
||
getQuery: async (ctx, number, id, phone) => { | ||
const query_key = `kuaidi100-query-${number}-${id}`; | ||
let query = await ctx.cache.get(query_key); | ||
if (!query) { | ||
const cookie = await getCookie(ctx); | ||
const queryResponse = await got({ | ||
method: 'get', | ||
url: `https://www.kuaidi100.com/query?type=${number}&postid=${id}&temp=${Math.random()}&phone=${phone ? phone : ''}`, | ||
headers: { | ||
Referer: 'https://www.kuaidi100.com/', | ||
Cookie: `${cookie.csrf}; ${cookie.wwwid}`, | ||
}, | ||
}); | ||
|
||
query = queryResponse.data; | ||
if (query.ischeck === '0' && query.status === '200') { | ||
// Not yet complete, don't cache for now. | ||
// Per owner suggestion | ||
} else { | ||
ctx.cache.set(query_key, query); // Finished, or error id | ||
} | ||
} else { | ||
query = JSON.parse(query); | ||
} | ||
|
||
return query; | ||
}, | ||
}; |