This repository has been archived by the owner on Dec 9, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First implementation of music streaming command.
- Loading branch information
Showing
4 changed files
with
816 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import { Message, VoiceChannel, VoiceConnection } from "discord.js"; | ||
import { Command, CommandDefinition, Action } from "."; | ||
import { getBasicInfo, validateURL, videoInfo } from "ytdl-core"; | ||
import ytdl from "ytdl-core-discord"; | ||
import cheerio from "cheerio"; | ||
import puppeteer, { Browser, JSHandle, Page, Puppeteer } from "puppeteer"; | ||
|
||
type Song = { | ||
url: string; | ||
username: string; | ||
}; | ||
|
||
const queue = new Map<string, Song>(); | ||
|
||
export const description: CommandDefinition = { | ||
name: "Music Control Commands", | ||
description: "Plays YouTube links or searches YouTube for keywords.", | ||
usage: [ | ||
"!play <youtube url or search terms>", | ||
"!play toxic britney", | ||
"!stop", | ||
], | ||
keys: ["play", "stop", "skip", "queue", "music", "volume"], | ||
}; | ||
|
||
// Functions used by this command | ||
// ============================== | ||
|
||
const playSong = async ( | ||
url: string, | ||
voiceChannel: VoiceChannel, | ||
message: Message | ||
): Promise<any> => { | ||
return getBasicInfo(url).then((info: videoInfo) => { | ||
voiceChannel.join().then(async (x: VoiceConnection) => { | ||
const url = info.videoDetails.video_url; | ||
console.log(`Streaming ${url} to ${message.author.tag}`); | ||
x.play(await ytdl(url), { type: "opus" }); | ||
message.channel.stopTyping(true); | ||
return message.react("❤️"); | ||
}); | ||
}); | ||
}; | ||
|
||
// Required Command Exports | ||
// ======================== | ||
|
||
export const action: Action = async ( | ||
message: Message, | ||
key: string | ||
): Promise<any> => { | ||
console.log("Running music command..."); | ||
console.log(`KEY: ${key}`); | ||
|
||
// Get voice channel and permission status. | ||
const voiceChannel = message.member?.voice?.channel; | ||
if (!voiceChannel) return message.reply("Join a VC to play music."); | ||
const permissions = voiceChannel.permissionsFor(message.author); | ||
if (!permissions || !permissions.has("CONNECT") || !permissions.has("SPEAK")) | ||
return message.reply( | ||
"I need the permissions to join and speak in your voice channel!" | ||
); | ||
|
||
// Play or stop the posted song. | ||
if (key === "play") { | ||
const content: string[] = message.content.split(" "); | ||
if (content.length === 1) { | ||
message.reply( | ||
"...give me something to work with! A name or YouTube URL, perhaps?" | ||
); | ||
return; | ||
} | ||
const input: string = content[1]; | ||
|
||
if (validateURL(input)) { | ||
return playSong(input, voiceChannel, message); | ||
} else { | ||
if (input.toLowerCase().startsWith("http")) | ||
return message.reply( | ||
"That looks like a url, but... it's not on YouTube. Try pasting again?" | ||
); | ||
message.react("🔎"); | ||
// Scrape for the title | ||
// https://iq.opengenus.org/scrapping-youtube-javascript/ | ||
const query: string = input.replace(" ", "+"); | ||
return puppeteer | ||
.launch() | ||
.then((browser: Browser) => { | ||
return browser.newPage().then(async (page: Page) => { | ||
// await page.setViewport({ width: 1920, height: 1080 }); | ||
await page.goto( | ||
`https://www.youtube.com/results?search_query=${query}` | ||
); | ||
const firstVid = await page.waitForSelector("a#video-title"); | ||
const url: JSHandle | undefined = await firstVid?.getProperty( | ||
"href" | ||
); | ||
if (!url) return message.reply("Er, sorry, couldn't find that."); | ||
message.react("✅️"); | ||
return playSong( | ||
url._remoteObject.value.toString(), | ||
voiceChannel, | ||
message | ||
); | ||
}); | ||
}) | ||
.catch(() => { | ||
message.react("⚠️"); | ||
}); | ||
} | ||
} else if (key === "stop") { | ||
voiceChannel.leave(); | ||
} else { | ||
message.reply("Sorry, @RyanFleck hasn't implemented this yet :grimacing:"); | ||
} | ||
}; | ||
|
||
// Exports | ||
// ======= | ||
|
||
export const command: Command = { | ||
definition: description, | ||
action: action, | ||
}; | ||
export default command; |
Oops, something went wrong.