diff --git a/lib/v2/showstart/params.js b/lib/v2/showstart/params.js new file mode 100644 index 000000000..26a94d5da --- /dev/null +++ b/lib/v2/showstart/params.js @@ -0,0 +1,22 @@ +const { TITLE, HOST } = require('./const'); +const { fetchCityList, fetchStyleList } = require('./service'); + +module.exports = async (ctx) => { + const type = ctx.params.type; + switch (type) { + case 'city': + ctx.state.data = { + title: `${TITLE} - 演出城市`, + link: `HOST`, + item: await fetchCityList(), + }; + break; + case 'style': + ctx.state.data = { + title: `${TITLE} - 演出风格`, + link: HOST, + item: await fetchStyleList(), + }; + break; + } +}; diff --git a/lib/v2/showstart/router.js b/lib/v2/showstart/router.js index e8588a62a..b4d932712 100644 --- a/lib/v2/showstart/router.js +++ b/lib/v2/showstart/router.js @@ -1,4 +1,5 @@ module.exports = (router) => { router.get('/event/:cityCode/:showStyle?', require('./event')); - router.get('/search/:keyword', require('./search')); + router.get('/search/:keyword?', require('./search')); + router.get('/params/:type', require('./params')); }; diff --git a/lib/v2/showstart/service.js b/lib/v2/showstart/service.js index 925918ab2..2a0b53915 100644 --- a/lib/v2/showstart/service.js +++ b/lib/v2/showstart/service.js @@ -1,5 +1,5 @@ const { HOST } = require('./const'); -const { getAccessToken, post } = require('./utils'); +const { getAccessToken, post, sortBy, uniqBy } = require('./utils'); async function fetchActivityList( params = { @@ -25,18 +25,53 @@ async function fetchActivityList( ) { const accessToken = await getAccessToken(); const resp = await post('/web/activity/list', accessToken, params); + + const image = (src) => (src ? `` : ''); + const time = (time) => (time ? `

演出时间:${time}

` : ''); + const address = (cityName, siteName) => (cityName || siteName ? `

地址:${[cityName, siteName].join(' - ')}

` : ''); + const performers = (name) => (name ? `

艺人:${name}

` : ''); + const price = (price) => (price ? `

票价:${price}

` : ''); + return { items: resp.result.result.map((item) => ({ title: item.title, link: `${HOST}/event/${item.id}`, - description: `地点:${item.cityName} | ${item.siteName}`, + description: [image(item.poster), time(item.showTime), address(item.cityName, item.siteName), performers(item.performers), price(item.price)].join(''), })), }; } -async function fetchDictionary(cityCode, showStyle) { +async function fetchParams() { const accessToken = await getAccessToken(); - const resp = await post('/web/activity/list/params', accessToken); + return post('/web/activity/list/params', accessToken); +} + +async function fetchCityList() { + const resp = await fetchParams(); + const cities = sortBy(resp.result, 'cityCode'); + return cities.map((item) => ({ + title: item.cityName, + link: `${HOST}/event/list?cityCode=${item.cityCode}`, + description: `cityCode: ${item.cityCode}`, + })); +} + +// styles is embed in each city item +// so we need to fetch all city items and then extract styles from them +async function fetchStyleList() { + const resp = await fetchParams(); + let styles = resp.result.flatMap((item) => item.styles); + styles = uniqBy(styles, 'key'); + styles = sortBy(styles, 'key'); + return styles.map((item) => ({ + title: item.showName, + link: `${HOST}/event/list?showStyle=${item.key}`, + description: `showStyle: ${item.key}`, + })); +} + +async function fetchDictionary(cityCode, showStyle) { + const resp = await fetchParams(); const target = resp.result.find((item) => item.cityCode === cityCode); if (!target) { return {}; @@ -49,5 +84,7 @@ async function fetchDictionary(cityCode, showStyle) { module.exports = { fetchActivityList, + fetchCityList, + fetchStyleList, fetchDictionary, }; diff --git a/lib/v2/showstart/utils.js b/lib/v2/showstart/utils.js index 7a8b9a551..025a8be8f 100644 --- a/lib/v2/showstart/utils.js +++ b/lib/v2/showstart/utils.js @@ -60,8 +60,33 @@ const post = async (requestPath, accessToken = md5(Date.now().toString()), paylo return response; }; +function sortBy(items, key) { + return items.sort((a, b) => { + if (a[key] < b[key]) { + return -1; + } + if (a[key] > b[key]) { + return 1; + } + return 0; + }); +} + +function uniqBy(items, key) { + const set = new Set(); + return items.filter((item) => { + if (set.has(item[key])) { + return false; + } + set.add(item[key]); + return true; + }); +} + module.exports = { post, getAccessToken, uuid, + sortBy, + uniqBy, }; diff --git a/website/docs/routes/shopping.mdx b/website/docs/routes/shopping.mdx index 08450ea95..4e5e9cc7d 100644 --- a/website/docs/routes/shopping.mdx +++ b/website/docs/routes/shopping.mdx @@ -703,7 +703,14 @@ For instance, in `https://www.zagg.com/en_us/new-arrivals?brand=164&cat=3038%2C3 -相关路由参数可在 URL 中找到,如:`https://www.showstart.com/event/list?pageNo=1&pageSize=20&cityCode=571&showStyle=26` +:::tip + +路由参数查询 + +- cityCode: https://rsshub.app/showstart/params/city +- showStyle: https://rsshub.app/showstart/params/style + +::: ### 演出搜索 {#xiu-dong-wang-yan-chu-sou-suo}