-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpodcast.js
161 lines (153 loc) · 4.32 KB
/
podcast.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import { setLang, $t } from './podcast_l10n'
import { Podcast } from 'podcast'
import dayjs from 'dayjs'
const SUISEI_AFFILIATED = [
'星街すいせい',
'Midnight Grand Orchestra', // https://twitter.com/m_g_orchestra
]
function generateNotice(item) {
let ret = []
const status = item.status || 0
if (status & 1) {
ret.push($t('🎤 This clip is an acappella with no background music.'))
}
if (status & 2) {
ret.push(
$t('😟 The source for this clip is corrupted due to various problems.'),
)
}
if (status & 4) {
ret.push(
$t('🔇 This clip is muted in the source due to concerns on copyright.'),
)
}
if (ret.length !== 0) {
return (
$t('<p>This episode has the following flags:\n<ul>') +
ret.map((x) => `<li>${x}</li>`).join('\n') +
'</ul>\n</p>'
)
} else {
return ''
}
}
function generateContent(item, time) {
const original = SUISEI_AFFILIATED.includes(item.artist)
return `
<p>${$t('Song name')}: ${item.title}</p>
${
original
? $t('<p>An original song by %s</p>', item.artist)
: item.artist
? `<p>${$t('Originally by')}: ${item.artist}</p>`
: ''
}
<p>${$t('Performed by')}: ${item.performer}</p>
<p>${$t('Performed at')}: ${time}</p>
<p>${$t('Source')}: <a href="${item.source}">${item.source}</a></p>
${generateNotice(item)}
<br>
<p>
${$t(
'This podcast is powered by suisei-cn. See the music list <a href="%s">here</a>.<br>If things don\'t seem right, report it <a href="%s">here</a>.',
'https://github.com/suisei-cn/suisei-music/',
'https://github.com/suisei-cn/suisei-podcast/issues',
)}
</p>
`
}
function getFilterTitle(filter) {
let ret = []
if (filter & 1) {
ret.push('Acappella')
}
if (filter & 2) {
ret.push('Corrupted')
}
if (filter & 4) {
ret.push('Slient')
}
return ret.join(', ')
}
function createPodcast(body, url, lang, filter) {
setLang(lang)
let filterTitle = getFilterTitle(filter)
const feed = new Podcast({
title: 'Suisei Music Podcast' + (filter !== 0 ? ` (${filterTitle})` : ''),
description:
$t('Collection of music of suisei. Powered by suisei-cn.') +
(filter !== 0 ? ` (Filter applied: ${filterTitle})` : ''),
generator: 'podcast@npmjs',
feedUrl: url || 'https://suisei.moe/podcast.xml',
siteUrl: 'https://github.com/suisei-cn/suisei-worker',
imageUrl:
'https://cdn.jsdelivr.net/gh/suisei-cn/suisei-podcast@0423b62/logo/logo-202108.jpg',
author: 'すいせい工房',
categories: ['music', 'virtual youtuber'],
itunesType: 'episodic',
itunesCategory: [
{
text: 'Arts',
subcats: [{ text: 'Performing Arts' }],
},
],
pubDate: new Date(),
})
let bodyFiltered = body
if (filter !== 0) {
bodyFiltered = body.filter((x) => x.status & filter)
}
for (const i of bodyFiltered) {
const time = new Date(i.datetime)
const readableTime = dayjs(time).add(9, 'hour').format('YYYY/MM/DD HH:mm')
feed.addItem({
title: i.title,
description:
i.artist === '星街すいせい'
? $t(
'%s, an original song by 星街すいせい performed on %s',
i.title,
readableTime,
)
: $t(
'%s, originally by %s, performed by %s on %s',
i.title,
i.artist,
i.performer,
readableTime,
),
content: generateContent(i, readableTime),
url: i.url,
guid: i.url.replace(
'https://suisei-podcast.outv.im/',
'https://static.suisei.moe/music/',
),
enclosure: {
url: i.url,
},
date: time,
})
}
return feed.buildXml(' ')
}
export async function genPodcast(url, lang, filter, method) {
const resp = await fetch('https://suisei-podcast.outv.im/meta.json')
const items = await resp.json()
const ret = createPodcast(items, url, lang, filter)
if (method === 'HEAD') {
return new Response('', {
status: 200,
headers: {
'content-type': 'application/rss+xml; charset=utf-8',
'content-length': ret.length,
},
})
}
return new Response(ret, {
status: 200,
headers: {
'content-type': 'application/rss+xml; charset=utf-8',
'content-length': ret.length,
},
})
}