forked from BRETT/BRETT
Initial Commit
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
export interface TwitchTarget {
|
||||
kind: 'video' | 'channel' | 'clip'
|
||||
id: string
|
||||
}
|
||||
|
||||
// Twitch-Pfade, die keine Kanalnamen sind
|
||||
const RESERVED_PATHS = new Set([
|
||||
'directory', 'downloads', 'drops', 'friends', 'inventory', 'jobs', 'messages',
|
||||
'moderator', 'notifications', 'p', 'payments', 'popout', 'products', 'settings',
|
||||
'subscriptions', 'turbo', 'videos', 'wallet', 'broadcast', 'search', 'activate',
|
||||
])
|
||||
|
||||
export function getTwitchTarget(href: string): TwitchTarget | null {
|
||||
try {
|
||||
const url = new URL(href)
|
||||
const host = url.hostname.replace(/^(www\.|m\.)/, '')
|
||||
|
||||
// clips.twitch.tv/{slug}
|
||||
if (host === 'clips.twitch.tv') {
|
||||
const slug = url.pathname.split('/').filter(Boolean)[0]
|
||||
return slug ? { kind: 'clip', id: slug } : null
|
||||
}
|
||||
|
||||
if (host !== 'twitch.tv') return null
|
||||
const seg = url.pathname.split('/').filter(Boolean)
|
||||
|
||||
// twitch.tv/videos/{id}
|
||||
if (seg[0] === 'videos' && /^\d+$/.test(seg[1] ?? '')) {
|
||||
return { kind: 'video', id: seg[1]! }
|
||||
}
|
||||
// twitch.tv/{channel}/clip/{slug}
|
||||
if (seg.length === 3 && seg[1] === 'clip') {
|
||||
return { kind: 'clip', id: seg[2]! }
|
||||
}
|
||||
// twitch.tv/{channel}
|
||||
if (seg.length === 1 && /^[\w]{2,25}$/.test(seg[0]!) && !RESERVED_PATHS.has(seg[0]!.toLowerCase())) {
|
||||
return { kind: 'channel', id: seg[0]! }
|
||||
}
|
||||
return null
|
||||
}
|
||||
catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function serializeTwitchTarget(t: TwitchTarget | null): string | null {
|
||||
return t ? `${t.kind}:${t.id}` : null
|
||||
}
|
||||
|
||||
export function parseTwitchTarget(value: string): TwitchTarget | null {
|
||||
const i = value.indexOf(':')
|
||||
if (i < 0) return null
|
||||
const kind = value.slice(0, i)
|
||||
const id = value.slice(i + 1)
|
||||
if ((kind !== 'video' && kind !== 'channel' && kind !== 'clip') || !id) return null
|
||||
return { kind, id }
|
||||
}
|
||||
|
||||
// Twitch-Embeds brauchen zwingend ?parent=<Hostname der einbettenden Seite>
|
||||
export function twitchEmbedUrl(target: TwitchTarget | string | null, parent: string): string | null {
|
||||
const t = typeof target === 'string' ? parseTwitchTarget(target) : target
|
||||
if (!t) return null
|
||||
const p = `parent=${encodeURIComponent(parent)}`
|
||||
const id = encodeURIComponent(t.id)
|
||||
if (t.kind === 'clip') return `https://clips.twitch.tv/embed?clip=${id}&${p}&autoplay=false`
|
||||
if (t.kind === 'channel') return `https://player.twitch.tv/?channel=${id}&${p}`
|
||||
return `https://player.twitch.tv/?video=${id}&${p}&autoplay=false`
|
||||
}
|
||||
Reference in New Issue
Block a user