Skip to content

Commit b7c4574

Browse files
authored
feat(route): add musify (#19550)
* feat(route): add musify * fix typo
1 parent a8f770d commit b7c4574

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

lib/routes/musify/index.ts

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { type Data, type DataItem, type Route, ViewType } from '@/types';
2+
3+
import ofetch from '@/utils/ofetch';
4+
5+
import { type CheerioAPI, type Cheerio, load } from 'cheerio';
6+
import type { Element } from 'domhandler';
7+
import { type Context } from 'hono';
8+
9+
export const handler = async (ctx: Context): Promise<Data> => {
10+
const { language = '' } = ctx.req.param();
11+
const limit: number = Number.parseInt(ctx.req.query('limit') ?? '30', 10);
12+
13+
const baseUrl: string = 'https://musify.club';
14+
const targetUrl: string = new URL(language, baseUrl).href;
15+
16+
const response = await ofetch(targetUrl);
17+
const $: CheerioAPI = load(response);
18+
19+
const items: DataItem[] = $('div.playlist__item')
20+
.slice(0, limit)
21+
.toArray()
22+
.map((el): Element => {
23+
const $el: Cheerio<Element> = $(el);
24+
25+
const artist: string | undefined = $el.attr('data-artist');
26+
const name: string | undefined = $el.attr('data-name');
27+
28+
const title: string = [artist, name].filter(Boolean).join(' - ');
29+
const linkUrl: string | undefined = $el.find('a.strong').attr('href');
30+
const authorEls: Element[] = $el.find('div.playlist__heading a').toArray();
31+
const authors: DataItem['author'] = authorEls.map((authorEl) => {
32+
const $authorEl: Cheerio<Element> = $(authorEl);
33+
34+
return {
35+
name: $authorEl.text(),
36+
url: $authorEl.attr('href') ? new URL($authorEl.attr('href') as string, baseUrl).href : undefined,
37+
avatar: undefined,
38+
};
39+
});
40+
41+
let processedItem: DataItem = {
42+
title,
43+
link: linkUrl ? new URL(linkUrl, baseUrl).href : undefined,
44+
author: authors,
45+
};
46+
47+
const $enclosureEl: Cheerio<Element> = $el.find('div.playlist__control');
48+
const enclosureUrl: string | undefined = $enclosureEl.attr('data-play-url');
49+
50+
if (enclosureUrl) {
51+
processedItem = {
52+
...processedItem,
53+
enclosure_url: new URL(enclosureUrl, baseUrl).href,
54+
enclosure_type: `audio/${enclosureUrl.split(/\./).pop()}`,
55+
enclosure_title: title,
56+
enclosure_length: undefined,
57+
itunes_duration: undefined,
58+
itunes_item_image: undefined,
59+
};
60+
}
61+
62+
return processedItem;
63+
});
64+
65+
return {
66+
title: $('title').text(),
67+
description: $('meta[property="og:description"]').attr('content'),
68+
link: targetUrl,
69+
item: items,
70+
allowEmpty: true,
71+
image: $('meta[property="og:image"]').attr('content'),
72+
author: $('meta[property="og:site_name"]').attr('content'),
73+
id: $('meta[property="og:url"]').attr('content'),
74+
};
75+
};
76+
77+
export const route: Route = {
78+
path: '/:language?',
79+
name: 'Latest',
80+
url: 'musify.club',
81+
maintainers: ['nczitzk'],
82+
handler,
83+
example: '/musify/en',
84+
parameters: {
85+
category: {
86+
description: 'Language, Russian by default',
87+
options: [
88+
{
89+
label: 'Russian',
90+
value: '',
91+
},
92+
{
93+
label: 'English',
94+
value: 'en',
95+
},
96+
],
97+
},
98+
},
99+
description: `:::tip
100+
To subscribe to [Latest](https://musify.club/en), where the source URL is \`https://musify.club/en\`, extract the certain parts from this URL to be used as parameters, resulting in the route as [\`/musify/en\`](https://rsshub.app/musify/en).
101+
:::
102+
`,
103+
categories: ['multimedia'],
104+
features: {
105+
requireConfig: false,
106+
requirePuppeteer: false,
107+
antiCrawler: false,
108+
supportRadar: true,
109+
supportBT: false,
110+
supportPodcast: false,
111+
supportScihub: false,
112+
},
113+
radar: [
114+
{
115+
source: ['musify.club/:language'],
116+
target: '/:language',
117+
},
118+
{
119+
title: 'Latest',
120+
source: ['musify.club/en'],
121+
target: '/en',
122+
},
123+
{
124+
title: '​​Последняя',
125+
source: ['musify.club'],
126+
target: '/',
127+
},
128+
],
129+
view: ViewType.Articles,
130+
};

lib/routes/musify/namespace.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { Namespace } from '@/types';
2+
3+
export const namespace: Namespace = {
4+
name: 'musify',
5+
url: 'musify.club',
6+
categories: ['multimedia'],
7+
description: '',
8+
lang: 'ru',
9+
};

0 commit comments

Comments
 (0)