b68/packages/bot/src/utils/song.ts

94 lines
2.6 KiB
TypeScript

import { AudioResource, createAudioResource } from '@discordjs/voice'
import youtube from 'youtube-sr'
import { videoPattern, isURL } from './patterns'
import { i18n } from './i18n'
import {
SoundCloudStream,
stream,
video_basic_info,
YouTubeStream,
} from 'play-dl'
export interface SongData {
url: string
title: string
duration: number
}
export class Song {
public readonly url: string
public readonly title: string
public readonly duration: number
public constructor({ url, title, duration }: SongData) {
this.url = url
this.title = title
this.duration = duration
}
public static async from(url = '', search = '') {
const isYoutubeUrl = videoPattern.test(url)
let songInfo
if (isYoutubeUrl) {
songInfo = (await video_basic_info(url)) as any
return new this({
url: songInfo.video_details.url,
title: songInfo.video_details.title,
duration: parseInt(songInfo.video_details.durationInSec),
})
} else {
const result = await youtube.searchOne(search)
result ? null : console.log(`No results found for ${search}`) // This is for handling the case where no results are found (spotify links for example)
if (!result) {
const err = new Error(`No search results found for ${search}`)
err.name = 'NoResults'
if (isURL.test(url)) err.name = 'InvalidURL'
throw err
}
songInfo = (await video_basic_info(
`https://youtube.com/watch?v=${result.id}`
)) as any
return new this({
url: songInfo.video_details.url,
title: songInfo.video_details.title,
duration: parseInt(songInfo.video_details.durationInSec),
})
}
}
public async makeResource(): Promise<AudioResource<Song> | void> {
let playStream: YouTubeStream | SoundCloudStream | any = null
// let type = this.url.includes("youtube.com") ? StreamType.Opus : StreamType.OggOpus;
const source = this.url.includes('youtube') ? 'youtube' : 'soundcloud'
if (source === 'youtube') {
playStream = await stream(this.url)
}
if (!stream) return
return createAudioResource(playStream.stream, {
metadata: this,
inputType: playStream.type,
inlineVolume: true,
})
}
public startMessage() {
return i18n.__mf('play.startedPlaying', {
title: this.title,
url: this.url,
})
}
}