music playergd --cachedgd --cached!

This commit is contained in:
Ben Harris 2017-05-01 00:00:06 -04:00
parent b806a04da1
commit 52a8c6e659
7 changed files with 188 additions and 53 deletions

View File

@ -15,7 +15,7 @@
✔ Save a preferred city for each user for time and weather [2 pts] @done (17-03-27 00:53)
✔ Look up a random joke [2 pts] @done (17-03-27 00:53)
☐ Send an image from Google Image Search Results [5 pts]
Stream music from YouTube to a voice channel [10 pts]
Stream music from YouTube to a voice channel [10 pts] @done (17-04-30 23:56)
✔ Create and vote on polls [5 pts] @done (17-04-18 23:22)
☐ Hangman [5 pts]
✔ TicTacToe [5 pts] @done (17-04-24 02:04)

10
bot
View File

@ -1,14 +1,16 @@
#!/bin/bash
source .env
# pid=$(ps -ef | grep BenBot | grep -v grep | awk '{print $2}')
pid=$(pidof BenBot)
pid=$(pidof $WHICHBOT)
case "$1" in
nohup)
if [ $pid ]; then
echo "starting BenBot in background (nohup)"
nohup php run.php > bot.out 2> bot.err < /dev/null &
nohup php run.php $WHICHBOT > bot.out 2> bot.err < /dev/null &
else
echo "BenBot already running"
fi
@ -55,7 +57,7 @@ case "$1" in
;;
cloc)
cloc --exclude-dir=vendor --include-lang=PHP .
cloc --exclude-dir=vendor --by-file-by-lang .
;;
sync)
@ -70,7 +72,7 @@ case "$1" in
kill $pid
fi
echo "starting BenBot in background (nohup)"
nohup php run.php > bot.out 2> bot.err < /dev/null &
nohup php run.php $WHICHBOT > bot.out 2> bot.err < /dev/null &
;;

View File

@ -1,6 +0,0 @@
#!/bin/sh
# Uses more "sensible" (for English keyboards) key mapping for the
# Jerusalem figlet font.
tr "abgdhvzctykflmonieypujwqrsx,.;/'" "tcdsvuzjyhflknobixgp;m.era,'/\`qw" | figlet -f jerusalem $*

3
run.php Normal file → Executable file
View File

@ -4,8 +4,9 @@
ini_set('display_errors', true);
error_reporting(-1);
$procname = $argv[1] ?? "BenBot";
if (!cli_set_process_title("BenBot")) {
if (!cli_set_process_title($procname)) {
die("couldn't set process title");
}

View File

@ -56,6 +56,8 @@ final class Debug
],
]);
self::$bot->registerCommand('edittest', [__CLASS__, 'editMsgTest']);
echo __CLASS__ . " registered", PHP_EOL;
}
@ -264,4 +266,22 @@ final class Debug
}
public static function editMsgTest($msg, $args)
{
Utils::send($msg, count($msg->channel->guild->channels))->then(function ($result) {
$result->content = 'ben is best';
self::$bot->loop->addTimer(3, function ($timer) use ($result) {
$result->channel->messages->save($result)->then(function ($res) {
self::$bot->loop->addTimer(2, function ($timer) use ($res) {
$res->channel->messages->delete($res);
});
}, function ($e) {
echo $e->getMessage(), PHP_EOL;
echo $e->getTraceAsString(), PHP_EOL;
});
});
});
}
}

View File

@ -34,7 +34,6 @@ final class Hangman
public static function startGame($msg, $args)
{
return "```" . self::$gallows . "```";
return "not done yet";
}
}
}

View File

@ -3,6 +3,8 @@ namespace BenBot\Commands;
use BenBot\Utils;
use React\Promise\Deferred;
use Discord\Helpers\Process;
use Discord\Voice\VoiceClient;
use Discord\Parts\Channel\Channel;
@ -11,11 +13,14 @@ final class Music
{
private static $bot;
private static $voiceclients;
public static function register(&$that)
{
self::$bot = $that;
self::$voiceclients = [];
self::$bot->registerCommand('play', [__CLASS__, 'playFromYouTube'], [
'description' => 'plays',
'usage' => '<yt ID|URL|search>',
@ -23,7 +28,15 @@ final class Music
'yt',
],
]);
self::$bot->registerCommand('pause', [__CLASS__, 'pauseAudio'], [
'description' => 'pauses the currently playing song',
]);
self::$bot->registerCommand('resume', [__CLASS__, 'resumeAudio'], [
'description' => 'resumes a paused song',
]);
self::$bot->registerCommand('stop', [__CLASS__, 'stopAudio'], [
'description' => 'stops the currently playing song',
]);
self::$bot->registerCommand('mytype', [__CLASS__, 'playTest'], [
'description' => 'ur just my type',
]);
@ -32,15 +45,6 @@ final class Music
echo __CLASS__ . " registered", PHP_EOL;
}
public static function playSong($msg, $args)
{
self::$bot->joinVoiceChannel($msg->channel)->then(function (VoiceClient $vc) {
echo "joined voice channel", PHP_EOL;
$vc->playFile(self::$bot->dir . "/music/mytype.m4a");
}, function ($e) {
echo "there was an error joining the voice channel: {$e->getMessage()}", PHP_EOL, $e->getTraceAsString(), PHP_EOL;
});
}
public static function playTest($msg, $args)
{
@ -61,23 +65,86 @@ final class Music
public static function playFromYouTube($msg, $args)
{
$channel = null;
foreach ($msg->channel->guild->channels as $chnl) {
if ($chnl->type != Channel::TYPE_VOICE) {
continue;
}
// print_r($chnl);
if ($chnl->members->get('id', $msg->author->id)) {
$channel = $chnl;
break;
}
}
$channel = self::getVoiceChannel($msg);
print_r($channel);
if (!$channel instanceof Channel) {
return "you're not in a voice channel, silly";
}
$cmd = "youtube-dl --extract-audio --audio-format mp3 --audio-quality 0 -o - ";
if (isset(self::$voiceclients[$msg->channel->guild->id]) && self::$voiceclients[$msg->channel->guild->id] instanceof VoiceClient) {
self::$voiceclients[$msg->channel->guild->id]->stop();
self::getVideoJSON($args)->then(function ($json) use ($msg) {
Utils::send($msg, "preparing...")->then(function ($statusmsg) use ($msg, $json) {
self::downloadAudio($json)->then(function ($file) use ($statusmsg, $msg) {
$statusmsg->channel->messages->delete($statusmsg);
self::$voiceclients[$msg->channel->guild->id]->playFile(self::$bot->dir . "/music/$file")->then(function () {
self::$voiceclients[$msg->channel->guild->id]->close();
}, function ($e) {
echo $e->getMessage(), PHP_EOL;
echo $e->getTraceAsString(), PHP_EOL;
});
});
});
});
}
self::getVideoJSON($args)->then(function ($json) use ($channel, $msg) {
Utils::send($msg, "preparing...")->then(function ($statusmsg) use ($channel, $msg, $json) {
self::downloadAudio($json)->then(function ($file) use ($channel, $statusmsg, $msg) {
$statusmsg->channel->messages->delete($statusmsg);
self::$bot->joinVoiceChannel($channel)->then(function (VoiceClient $vc) use ($file, $msg) {
self::$voiceclients[$msg->channel->guild->id] = $vc;
$vc->playFile(self::$bot->dir . "/music/$file")->then(function () use ($vc) {
$vc->close();
}, function ($e) {
echo $e->getMessage(), PHP_EOL;
echo $e->getTraceAsString(), PHP_EOL;
});
});
});
});
});
}
public static function pauseAudio($msg, $args)
{
if (self::$voiceclients[$msg->channel->guild->id] instanceof VoiceClient) {
self::$voiceclients[$msg->channel->guild->id]->pause();
return "paused";
} else {
return "not playing...";
}
}
public static function resumeAudio($msg, $args)
{
if (self::$voiceclients[$msg->channel->guild->id] instanceof VoiceClient) {
self::$voiceclients[$msg->channel->guild->id]->unpause();
return "resuming";
} else {
return "not stopped...";
}
}
public static function stopAudio($msg, $args)
{
if (self::$voiceclients[$msg->channel->guild->id] instanceof VoiceClient) {
self::$voiceclients[$msg->channel->guild->id]->stop();
return "stopped";
} else {
return "not playing...";
}
}
private static function getVideoJSON($args)
{
$deferred = new Deferred();
$cmd = "youtube-dl --dump-single-json ";
if ($args[0] != "") {
if (strlen($args[0]) === 11 || strpos($args[0], "http") !== false) {
// is yt vid ID or URL
@ -86,27 +153,79 @@ final class Music
$query = implode(" ", $args);
$cmd .= "'ytsearch:$query'";
}
} else {
return "gotta pick something to play, silly";
}
echo $cmd, PHP_EOL;
self::$bot->joinVoiceChannel($channel)->then(function (VoiceClient $vc) use ($cmd) {
$process = new Process($cmd);
$process->start(self::$bot->loop);
echo "process started", PHP_EOL;
$vc->playRawStream($process->stdout)->then(function () use ($vc) {
echo "stream done playing", PHP_EOL;
$vc->close();
}, function ($e) {
echo $e->getMessage(), PHP_EOL;
echo $e->getTraceAsString(), PHP_EOL;
});
}, function ($e) {
echo $e->getMessage(), PHP_EOL;
echo $e->getTraceAsString(), PHP_EOL;
$process = new Process($cmd);
$process->on('exit', function ($exitcode, $termsig) use (&$data, $deferred) {
if (intval($exitcode) === 1) {
$deferred->reject("invalid url");
} else {
$deferred->resolve(json_decode($data));
}
echo "$exitcode, $termsig", PHP_EOL;
});
self::$bot->loop->addTimer(0.001, function ($timer) use (&$data, $deferred, $process) {
$process->start(self::$bot->loop);
$process->stdout->on('data', function ($output) use (&$data) {
$data .= $output;
});
});
return $deferred->promise();
}
private static function downloadAudio($result)
{
$deferred = new Deferred();
$json = $result->entries[0];
$url = escapeshellarg($json->webpage_url);
$filename = $json->id . '-' . md5($json->title) . '-' . $json->duration;
foreach (scandir(self::$bot->dir . '/music') as $file) {
// check if we've already downloaded the file!
if (pathinfo($file, PATHINFO_FILENAME) === $filename) {
$deferred->resolve($file);
return $deferred->promise();
}
}
$file = escapeshellarg(self::$bot->dir . "/music/$filename.%(ext)s");
$cmd = "youtube-dl --extract-audio --audio-format mp3 --audio-quality 0 --restrict-filenames --no-check-certificate --no-warnings --source-address 0.0.0.0 -o $file $url";
echo $cmd, PHP_EOL;
$process = new Process($cmd);
$process->on('exit', function ($exitcode, $termsig) use ($deferred, $filename) {
if (intval($exitcode) !== 0) {
$deferred->reject('error downloading video');
} else {
foreach (scandir(self::$bot->dir . '/music') as $file) {
if (pathinfo($file, PATHINFO_FILENAME) === $filename) {
$deferred->resolve($file);
}
}
}
});
self::$bot->loop->addTimer(0.001, function ($timer) use ($deferred, $process) {
$process->start(self::$bot->loop);
});
return $deferred->promise();
}
private static function getVoiceChannel($msg)
{
foreach ($msg->channel->guild->channels->getAll('type', Channel::TYPE_VOICE) as $voicechannel) {
if (!empty($voicechannel->members->get('user_id', $msg->author->id))) {
return $voicechannel;
}
}
return null;
}
}