diff --git a/lib/v2/showstart/artist.js b/lib/v2/showstart/artist.js new file mode 100644 index 00000000000000..bb2e0d5d4e99ff --- /dev/null +++ b/lib/v2/showstart/artist.js @@ -0,0 +1,15 @@ +const { TITLE, HOST } = require('./const'); +const { fetchPerformerInfo } = require('./service'); + +module.exports = async (ctx) => { + const id = ctx.params.id; + const artist = await fetchPerformerInfo({ + performerId: id, + }); + ctx.state.data = { + title: `${TITLE} - ${artist.name}`, + description: artist.content, + link: `${HOST}/artist/${artist.id}`, + item: artist.activityList, + }; +}; diff --git a/lib/v2/showstart/brand.js b/lib/v2/showstart/brand.js new file mode 100644 index 00000000000000..0b7fc4d8c43487 --- /dev/null +++ b/lib/v2/showstart/brand.js @@ -0,0 +1,15 @@ +const { TITLE, HOST } = require('./const'); +const { fetchBrandInfo } = require('./service'); + +module.exports = async (ctx) => { + const id = ctx.params.id; + const brand = await fetchBrandInfo({ + brandId: id, + }); + ctx.state.data = { + title: `${TITLE} - ${brand.name}`, + description: brand.content, + link: `${HOST}/host/${brand.id}`, + item: brand.activityList, + }; +}; diff --git a/lib/v2/showstart/event.js b/lib/v2/showstart/event.js index 38e6aafc15f692..080db7f8bb82cd 100644 --- a/lib/v2/showstart/event.js +++ b/lib/v2/showstart/event.js @@ -4,7 +4,7 @@ const { fetchActivityList, fetchDictionary } = require('./service'); module.exports = async (ctx) => { const cityCode = parseInt(ctx.params.cityCode); const showStyle = parseInt(ctx.params.showStyle); - const { items } = await fetchActivityList({ + const items = await fetchActivityList({ cityCode, showStyle, }); diff --git a/lib/v2/showstart/maintainer.js b/lib/v2/showstart/maintainer.js index 1eea6511d8e381..6526631fcf6dd8 100644 --- a/lib/v2/showstart/maintainer.js +++ b/lib/v2/showstart/maintainer.js @@ -1,4 +1,6 @@ module.exports = { + '/artist/:id': ['lchtao26'], + '/brand/:id': ['lchtao26'], '/event/:cityCode/:showStyle?': ['lchtao26'], - '/search/:keyword': ['lchtao26'], + '/search/:type/:keyword?': ['lchtao26'], }; diff --git a/lib/v2/showstart/params.js b/lib/v2/showstart/params.js deleted file mode 100644 index 26a94d5da5becb..00000000000000 --- a/lib/v2/showstart/params.js +++ /dev/null @@ -1,22 +0,0 @@ -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/radar.js b/lib/v2/showstart/radar.js index 55548479980b24..51c6e4af0957c3 100644 --- a/lib/v2/showstart/radar.js +++ b/lib/v2/showstart/radar.js @@ -20,9 +20,21 @@ module.exports = { target: (_, url) => { const search = new URL(url).searchParams; const keyword = search.get('keyword') || ''; - return `/showstart/search/${keyword}`; + return `/showstart/search/event/${keyword}`; }, }, + { + title: '音乐人 - 演出更新', + docs: 'https://docs.rsshub.app/routes/shopping#yin-yue-ren-yan-chu-geng-xin', + source: ['/artist/:id'], + target: '/showstart/artist/:id', + }, + { + title: '厂牌 - 演出更新', + docs: 'https://docs.rsshub.app/routes/shopping#chang-pai-yan-chu-geng-xin', + source: ['/host/:id'], + target: '/showstart/brand/:id', + }, ], }, }; diff --git a/lib/v2/showstart/router.js b/lib/v2/showstart/router.js index b4d932712082fa..8dd29cee311569 100644 --- a/lib/v2/showstart/router.js +++ b/lib/v2/showstart/router.js @@ -1,5 +1,6 @@ module.exports = (router) => { + router.get('/artist/:id', require('./artist')); + router.get('/brand/:id', require('./brand')); router.get('/event/:cityCode/:showStyle?', require('./event')); - router.get('/search/:keyword?', require('./search')); - router.get('/params/:type', require('./params')); + router.get('/search/:type/:keyword?', require('./search')); }; diff --git a/lib/v2/showstart/search.js b/lib/v2/showstart/search.js index 3a9bddb58f8edc..cc222c1a25e62e 100644 --- a/lib/v2/showstart/search.js +++ b/lib/v2/showstart/search.js @@ -1,14 +1,51 @@ const { TITLE, HOST } = require('./const'); -const { fetchActivityList } = require('./service'); +const { fetchActivityList, fetchPerformerList, fetchBrandList, fetchCityList, fetchStyleList } = require('./service'); module.exports = async (ctx) => { - const keyword = ctx.params.keyword; - const { items } = await fetchActivityList({ - keyword, - }); - ctx.state.data = { - title: `${TITLE} - ${keyword}`, - link: HOST, - item: items, - }; + const type = ctx.params.type || ''; + const keyword = ctx.params.keyword || ''; + + switch (type) { + case 'event': + ctx.state.data = { + title: `${TITLE} - 搜演出 - ${keyword || '全部'}`, + link: HOST, + item: await fetchActivityList({ keyword }), + }; + break; + case 'artist': + ctx.state.data = { + title: `${TITLE} - 搜艺人 - ${keyword || '全部'}`, + link: HOST, + item: await fetchPerformerList({ searchKeyword: keyword }), + }; + break; + case 'brand': + ctx.state.data = { + title: `${TITLE} - 搜厂牌 - ${keyword || '全部'}`, + link: HOST, + item: await fetchBrandList({ searchKeyword: keyword }), + }; + break; + case 'city': + ctx.state.data = { + title: `${TITLE} - 搜城市 - ${keyword || '全部'}`, + link: HOST, + item: await fetchCityList(keyword), + }; + break; + case 'style': + ctx.state.data = { + title: `${TITLE} - 搜风格 - ${keyword || '全部'}`, + link: HOST, + item: await fetchStyleList(keyword), + }; + break; + default: + ctx.state.data = { + title: `${TITLE} - 搜演出 - ${type || '全部'}`, + link: HOST, + item: await fetchActivityList({ keyword: type }), + }; + } }; diff --git a/lib/v2/showstart/service.js b/lib/v2/showstart/service.js index 2a0b53915bc02f..f5d1a67cc21e9c 100644 --- a/lib/v2/showstart/service.js +++ b/lib/v2/showstart/service.js @@ -25,49 +25,121 @@ async function fetchActivityList( ) { const accessToken = await getAccessToken(); const resp = await post('/web/activity/list', accessToken, params); + return resp.result.result.map((item) => formatActivity(item)); +} +function formatActivity(item) { 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 { + title: item.title, + link: `${HOST}/event/${item.id}`, + description: [image(item.poster), time(item.showTime), address(item.cityName, item.siteName), performers(item.performers), price(item.price)].join(''), + }; +} +async function fetchPerformerList( + params = { + pageNo: '1', + pageSize: '30', + searchKeyword: '', + styleId: '', + } +) { + const accessToken = await getAccessToken(); + const resp = await post('/web/performer/list', accessToken, params); + return resp.result.result.map((item) => ({ + title: item.name, + link: `${HOST}/artist/${item.id}`, + description: `id: ${item.id}`, + })); +} + +async function fetchPerformerInfo( + params = { + performerId: '', + } +) { + const accessToken = await getAccessToken(); + const resp = await post('/web/performer/info', accessToken, params); return { - items: resp.result.result.map((item) => ({ - title: item.title, - link: `${HOST}/event/${item.id}`, - description: [image(item.poster), time(item.showTime), address(item.cityName, item.siteName), performers(item.performers), price(item.price)].join(''), - })), + id: params.id, + name: resp.result.name, + content: resp.result.content, + avatar: resp.result.avatar, + poster: resp.result.poster, + styles: resp.result.styles, + activityList: resp.result.activities.map((item) => formatActivity(item)), }; } +async function fetchBrandInfo( + params = { + brandId: '', + } +) { + const accessToken = await getAccessToken(); + const resp = await post('/web/brand/info', accessToken, params); + return { + id: params.id, + name: resp.result.name, + content: resp.result.content, + avatar: resp.result.avatar, + poster: resp.result.poster, + activityList: resp.result.activities.map((item) => formatActivity(item)), + }; +} + +async function fetchBrandList( + params = { + pageNo: '1', + pageSize: '30', + searchKeyword: '', + } +) { + const accessToken = await getAccessToken(); + const resp = await post('/web/brand/list', accessToken, params); + return resp.result.result.map((item) => ({ + title: item.name, + link: `${HOST}/host/${item.id}`, + description: `id: ${item.id}`, + })); +} + async function fetchParams() { const accessToken = await getAccessToken(); return post('/web/activity/list/params', accessToken); } -async function fetchCityList() { +async function fetchCityList(keyword = '') { 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}`, - })); + return cities + .filter((item) => item.cityName.includes(keyword.trim())) + .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() { +async function fetchStyleList(keyword = '') { 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}`, - })); + return styles + .filter((item) => item.showName.includes(keyword.trim())) + .map((item) => ({ + title: item.showName, + link: `${HOST}/event/list?showStyle=${item.key}`, + description: `showStyle: ${item.key}`, + })); } async function fetchDictionary(cityCode, showStyle) { @@ -86,5 +158,9 @@ module.exports = { fetchActivityList, fetchCityList, fetchStyleList, + fetchPerformerList, + fetchPerformerInfo, + fetchBrandList, + fetchBrandInfo, fetchDictionary, }; diff --git a/website/docs/routes/shopping.mdx b/website/docs/routes/shopping.mdx index 0bbe35fc3e3f80..91cedb9a7d6ee0 100644 --- a/website/docs/routes/shopping.mdx +++ b/website/docs/routes/shopping.mdx @@ -711,10 +711,9 @@ For instance, in `https://www.zagg.com/en_us/new-arrivals?brand=164&cat=3038%2C3 :::tip -路由参数查询 +- 演出城市 `cityCode` 查询: `/showstart/search/city/:keyword`, 如: https://rsshub.app/showstart/search/city/杭州 -- cityCode: https://rsshub.app/showstart/params/city -- showStyle: https://rsshub.app/showstart/params/style +- 演出风格 `showStyle` 查询: `/showstart/search/style/:keyword`,如: https://rsshub.app/showstart/search/style/摇滚 ::: @@ -722,6 +721,26 @@ For instance, in `https://www.zagg.com/en_us/new-arrivals?brand=164&cat=3038%2C3