예제 #1
0
 public function run(Message $message, Discord $discord, WebSocket $webSocket, Logger $log, &$audioStreams, Channel $channel, cURL $curl)
 {
     $exp = explode(" ", $message->content);
     unset($exp[0]);
     $youtubeLink = implode(" ", $exp);
     // URL Checker
     $parts = parse_url($youtubeLink);
     if (!stristr($parts["host"], "youtube.com")) {
         return $message->reply("Error, you can only use youtube links!");
     }
     // Generate song md5
     $md5 = md5($youtubeLink);
     // Now get the mp3 from the cache
     $songFile = __DIR__ . "/../../../../../cache/songs/{$md5}.mp3";
     $dl = new YoutubeDl(["extract-audio" => true, "audio-format" => "mp3", "audio-quality" => 0, "output" => $songFile]);
     $title = "";
     try {
         $video = $dl->download($youtubeLink);
         $title = $video->getTitle();
         $log->addNotice("Downloading {$title} from YouTube");
     } catch (NotFoundException $e) {
         $log->addError("Error: the song was not found: {$e->getMessage()}");
         $message->reply("Error: the song was not found: {$e->getMessage()}");
     } catch (PrivateVideoException $e) {
         $log->addError("Error: song has been made private: {$e->getMessage()}");
         $message->reply("Error: song has been made private: {$e->getMessage()}");
     } catch (CopyrightException $e) {
         $log->addError("Error: song is under copyright: {$e->getMessage()}");
         $message->reply("Error: song is under copyright: {$e->getMessage()}");
     } catch (\Exception $e) {
         $log->addError("Error: {$e->getMessage()}");
         $message->reply("Error: {$e->getMessage()}");
     }
     $webSocket->joinVoiceChannel($channel)->then(function (VoiceClient $vc) use($message, $discord, $webSocket, $log, &$audioStreams, $channel, $curl, $songFile, $title) {
         $guildID = $message->getChannelAttribute()->guild_id;
         if (file_exists($songFile)) {
             // Add this audio stream to the array of audio streams
             $audioStreams[$guildID] = $vc;
             $vc->setFrameSize(40)->then(function () use($vc, &$audioStreams, $guildID, $songFile, $log, $message, $title, $channel) {
                 $vc->setBitrate(128000);
                 $message->reply("Now playing **{$title}** in {$channel->name}");
                 $vc->playFile($songFile, 2)->done(function () use($vc, &$audioStreams, $guildID) {
                     unset($audioStreams[$guildID]);
                     $vc->close();
                 });
             });
         }
     });
 }
예제 #2
0
 public function run(Message $message, Discord $discord, WebSocket $webSocket, Logger $log, &$audioStreams, Channel $channel, cURL $curl)
 {
     $webSocket->joinVoiceChannel($channel)->then(function (VoiceClient $vc) use($message, $discord, $webSocket, $log, &$audioStreams, $channel) {
         $guildID = $message->getChannelAttribute()->guild_id;
         // Add this audio stream to the array of audio streams
         $audioStreams[$guildID] = $vc;
         $vc->setFrameSize(40)->then(function () use($vc, &$audioStreams, $guildID) {
             $vc->setBitrate(128000);
             $number = mt_rand(1, 6);
             $file = __DIR__ . "/../../../sounds/horns/{$number}.mp3";
             $vc->playFile($file, 2)->done(function () use($vc, &$audioStreams, $guildID) {
                 unset($audioStreams[$guildID]);
                 $vc->close();
             });
         });
     });
 }
예제 #3
0
 /**
  * Starts the bot.
  *
  * @return void 
  */
 public function start()
 {
     set_error_handler(function ($errno, $errstr) {
         if (!(error_reporting() & $errno)) {
             return;
         }
         echo "[Error] {$errno} {$errstr}\r\n";
         throw new \Exception($errstr, $errno);
     }, E_ALL);
     foreach ($this->commands as $command => $data) {
         $this->websocket->on(Event::MESSAGE_CREATE, function ($message, $discord, $new) use($command, $data) {
             $content = explode(' ', $message->content);
             $config = Config::getConfig($this->configfile);
             if ($content[0] == $config['prefix'] . $command) {
                 Arr::forget($content, 0);
                 $user_perms = @$config['perms']['perms'][$message->author->id];
                 if (empty($user_perms)) {
                     $user_perms = $config['perms']['default'];
                 }
                 if ($user_perms >= $data['perms']) {
                     try {
                         $data['class']::handleMessage($message, $content, $discord, $config, $this);
                     } catch (\Exception $e) {
                         $message->reply("There was an error running the command. `{$e->getMessage()}`");
                     }
                 } else {
                     $message->reply('You do not have permission to do this!');
                     echo "[Auth] User {$message->author->username} blocked from running {$config['prefix']}{$command}, <@{$message->author->id}>\r\n";
                 }
             }
         });
     }
     $this->websocket->on('ready', function ($discord) {
         $discord->updatePresence($this->websocket, 'DiscordPHP ' . Discord::VERSION, false);
     });
     $this->websocket->on('error', function ($error, $ws) {
         echo "[Error] {$error}\r\n";
     });
     $this->websocket->on('close', function () {
         echo "[Close] WebSocket was closed.\r\n";
         die;
     });
     $this->websocket->run();
 }
예제 #4
0
 /**
  * Starts the bot.
  *
  * @return void 
  */
 public function start()
 {
     // set_error_handler(function ($errno, $errstr) {
     // 	if (!(error_reporting() & $errno)) {
     // 		return;
     // 	}
     // 	echo "[Error] {$errno} {$errstr}\r\n";
     // 	throw new \Exception($errstr, $errno);
     // }, E_ALL);
     $this->websocket->on(Event::MESSAGE_CREATE, function ($message, $discord, $new) {
         $config = Config::getConfig($this->configfile);
         if (substr($message->content, 0, strlen($config['prefix'])) == $config['prefix']) {
             foreach ($this->commands as $command => $data) {
                 $parts = [];
                 $content = explode(' ', $message->content);
                 foreach ($content as $index => $c) {
                     foreach (explode("\n", $c) as $p) {
                         $parts[] = $p;
                     }
                 }
                 $content = $parts;
                 if ($content[0] == $config['prefix'] . $command) {
                     array_shift($content);
                     $user_perms = @$config['perms']['perms'][$message->author->id];
                     if (empty($user_perms)) {
                         $user_perms = $config['perms']['default'];
                     }
                     if ($user_perms >= $data['perms']) {
                         try {
                             $data['class']::handleMessage($message, $content, $new, $config, $this);
                             $this->log->addInfo("{$message->author->username}#{$message->author->discriminator} ({$message->author}) ran command {$config['prefix']}{$command}", $content);
                         } catch (\Throwable $e) {
                             try {
                                 $this->log->addError("Error running the command {$config['prefix']}{$command}", ['message' => $e->getMessage()]);
                                 $message->reply("There was an error running the command. `{$e->getMessage()}`");
                             } catch (\Throwable $e2) {
                             }
                         }
                     } else {
                         try {
                             $message->reply('You do not have permission to do this!');
                         } catch (\Throwable $e2) {
                         }
                         $this->log->addWarning("{$message->author->username}#{$message->author->discriminator} ({$message->author}) attempted to run command {$config['prefix']}{$command}", $content);
                     }
                 }
             }
         }
     });
     $this->websocket->on(Event::MESSAGE_CREATE, function ($message, $discord, $new) {
         $triggers = ['bless up', ':pray:', '🙏'];
         if (Str::contains(strtolower($message->content), $triggers) && $message->author->id != $discord->id) {
             $config = Config::getConfig($this->configfile);
             $content = explode(' ', $message->content);
             Arr::forget($content, 0);
             Khaled::handleMessage($message, $content, $new, $config, $this);
         }
     });
     $this->websocket->on(Event::MESSAGE_CREATE, function ($message, $discord, $new) {
         if ($message->author->id == '81726071573061632' && strtolower($message->content) == 'we dem') {
             $message->channel->sendMessage('BOIZ');
         }
     });
     $this->websocket->on('ready', function ($discord) {
         $this->log->addInfo('WebSocket is ready.');
         $discord->updatePresence($this->websocket, 'DiscordPHP ' . Discord::VERSION, false);
     });
     $this->websocket->on('error', function ($error, $ws) {
         $this->log->addError("WebSocket encountered an error", [$error->getMessage()]);
     });
     // $this->websocket->on('heartbeat', function ($epoch) {
     // 	echo "Heartbeat at {$epoch}\r\n";
     // });
     $this->websocket->on('close', function ($op, $reason) {
         $this->log->addWarning("WebSocket closed.", ['code' => $op, 'reason' => $reason]);
     });
     $this->websocket->on('reconnecting', function () {
         $this->log->addInfo('WebSocket is reconnecting...');
     });
     $this->websocket->on('reconnected', function () {
         $this->log->addInfo('WebSocket has reconnected.');
     });
     $config = Config::getConfig($this->configfile);
     if (isset($config['cache']) && $config['cache'] == 'redis') {
         Cache::setCache(new RedisCacheDriver('localhost'));
     }
     if (isset($config['carbon_bot']) && $config['carbon_bot']['enabled']) {
         $guzzle = new Client(['http_errors' => false]);
         $body = ['key' => $config['carbon_bot']['key']];
         $this->log->addInfo('Enabling Carbon server count updates...');
         $carbonHeartbeat = function () use($guzzle, &$body) {
             $body['servercount'] = $this->discord->guilds->count();
             $this->log->addDebug('Sending Carbon server count update...');
             $request = new Request('POST', 'https://www.carbonitex.net/discord/data/botdata.php', ['Content-Type' => 'application/json'], json_encode($body));
             $response = $guzzle->send($request);
             if ($response->getStatusCode() !== 200) {
                 $this->log->addWarning('Carbon server count update failed.', ['status' => $response->getStatusCode(), 'reason' => $response->getReasonPhrase()]);
             } else {
                 $this->log->addDebug('Sent Carbon server count update successfully.');
             }
         };
         $carbonHeartbeat();
         $this->websocket->loop->addPeriodicTimer(60, $carbonHeartbeat);
     }
     $this->websocket->run();
 }
예제 #5
0
 /**
  *
  */
 public function run()
 {
     // Reap the threads!
     $this->websocket->loop->addPeriodicTimer(600, function () {
         $this->log->addInfo('Restarting the threading pool, to clear out old threads..');
         // Shutdown the pool
         $this->pool->shutdown();
         $this->timers->shutdown();
         // Startup the pool again
         $this->pool = new \Pool(count($this->onMessage), \Worker::class);
         $this->timers = new \Pool(count($this->onTimer), \Worker::class);
     });
     // Handle the onReady event, and setup some timers and so forth
     $this->websocket->on('ready', function (Discord $discord) {
         $this->log->addInfo('Websocket connected..');
         // Update our presence status
         $game = new Game(array('name' => $this->globalConfig->get('presence', 'bot', "table flippin'"), 'url' => null, 'type' => null), true);
         $this->websocket->updatePresence($game, false);
         // Count the amount of people we are available to..
         /** @var Guild $guild */
         foreach ($this->discord->getClient()->getGuildsAttribute()->all() as $guild) {
             $this->extras['memberCount'] += $guild->member_count;
             $this->extras['guildCount']++;
             $this->extras['guild']['memberCount']["id{$guild->id}"] = $guild->member_count;
             $this->extras['onMessagePlugins'] = $this->onMessage;
             $this->extras['onVoicePlugins'] = $this->onVoice;
         }
         $this->log->addInfo("Member count, currently available to: {$this->extras['memberCount']} people");
         // Setup the timers for the timer plugins
         foreach ($this->onTimer as $command => $data) {
             $this->websocket->loop->addPeriodicTimer($data['timer'], function () use($data, $discord) {
                 try {
                     $plugin = new $data['class']($discord, $this->log, $this->globalConfig, $this->db, $this->curl, $this->settings, $this->permissions, $this->container->get('serverConfig'), $this->users, $this->extras);
                     $this->timers->submit($plugin);
                 } catch (\Exception $e) {
                     $this->log->addError("Error running the periodic timer: {$e->getMessage()}");
                 }
             });
         }
         // Issue periodically recounting and other things (Needed because of pthreads not putting the entire context into children - leading to some weirdness in some plugins)
         $this->websocket->loop->addPeriodicTimer(600, function () {
             $this->extras['memberCount'] = 0;
             $this->extras['guildCount'] = 0;
             /** @var Guild $guild */
             foreach ($this->discord->getClient()->getGuildsAttribute()->all() as $guild) {
                 $this->extras['memberCount'] += $guild->member_count;
                 $this->extras['guildCount']++;
                 $this->extras['guild']['memberCount']["id{$guild->id}"] = $guild->member_count;
                 $this->extras['onMessagePlugins'] = $this->onMessage;
                 $this->extras['onVoicePlugins'] = $this->onVoice;
             }
             // Output periodic information while doing the recounting stuff
             $this->log->addInfo('Currently running audio streams: ' . count($this->audioStreams));
             $this->log->addInfo("Member recount, currently available to: {$this->extras['memberCount']} people");
         });
         // @todo run a timer to check if there are any active voice sessions - and if there are, if there are any people in those voice sessions
         // If not, stop the session and leave the channel (To save some bandwidth)
     });
     $this->websocket->on('error', function ($error, $websocket) {
         $this->log->addError('An error occurred on the websocket', [$error->getMessage()]);
         die(1);
     });
     $this->websocket->on('close', function ($opCode, $reason) {
         $this->log->addWarning('Websocket got closed', ['code' => $opCode, 'reason' => $reason]);
         die(1);
     });
     $this->websocket->on('reconnecting', function () {
         $this->log->addInfo('Websocket is reconnecting..');
     });
     $this->websocket->on('reconnected', function () {
         $this->log->addInfo('Websocket was reconnected..');
     });
     // Handle incoming message logging
     $this->websocket->on(Event::MESSAGE_CREATE, function (Message $message, Discord $discord) {
         $this->log->addInfo("Message from {$message->author->username}", [$message->content]);
         // Don't update data for ourselves..
         if ($message->author->id !== $discord->getClient()->id) {
             $this->users->set($message->author->id, $message->author->username, 'online', null, date('Y-m-d H:i:s'), date('Y-m-d H:i:s'), $message->content);
         }
         // @todo Create text logs
     });
     // Handle plugin running
     $this->websocket->on(Event::MESSAGE_CREATE, function (Message $message, Discord $discord) {
         $guildID = $message->getChannelAttribute()->guild_id;
         // Get server config
         $config = $this->settings->get($guildID);
         // Is the person admin?
         $userDiscordID = $message->author->id;
         foreach ($this->globalConfig->get('admins', 'permissions') as $admins) {
             $message->isAdmin = $admins === $userDiscordID;
         }
         // Define the prefix if it isn't already set..
         @($config->prefix = $config->prefix ?? $this->globalConfig->get('prefix', 'bot'));
         // Check if the user requested an onMessage plugin
         if (substr($message->content, 0, strlen($config->prefix)) === $config->prefix) {
             $content = explode(' ', $message->content);
             foreach ($this->onMessage as $command => $data) {
                 $parts = [];
                 foreach ($content as $index => $c) {
                     foreach (explode("\n", $c) as $p) {
                         $parts[] = $p;
                     }
                 }
                 if ($parts[0] === $config->prefix . $command) {
                     // If they are listed under the admins array in the bot config, they're the super admins
                     if (in_array($message->author->id, $this->globalConfig->get('admins', 'permissions'))) {
                         $userPerms = 3;
                     } elseif (null !== $message->getChannelAttribute()->getGuildAttribute()->owner_id && $message->author->id === $message->getChannelAttribute()->getGuildAttribute()->owner_id) {
                         $userPerms = 2;
                     } else {
                         $userPerms = 1;
                     }
                     if ($userPerms >= $data['permissions']) {
                         try {
                             $message->getChannelAttribute()->broadcastTyping();
                             if ($data['class'] === "\\Sovereign\\Plugins\\onMessage\\auth") {
                                 /** @var \Threaded $plugin */
                                 $plugin = new $data['class']($message, $discord, $config, $this->log, $this->globalConfig, $this->db, $this->curl, $this->settings, $this->permissions, $this->container->get('serverConfig'), $this->users, $this->extras);
                                 $plugin->run();
                             } else {
                                 /** @var \Threaded $plugin */
                                 $plugin = new $data['class']($message, $discord, $config, $this->log, $this->globalConfig, $this->db, $this->curl, $this->settings, $this->permissions, $this->container->get('serverConfig'), $this->users, $this->extras);
                                 $this->pool->submit($plugin);
                             }
                             $this->log->addInfo("{$message->author->username}#{$message->author->discriminator} ({$message->author}) ran command {$config->prefix}{$command}", $content);
                         } catch (\Exception $e) {
                             $this->log->addError("Error running command {$config->prefix}{$command}. Command run by {$message->author->username} in {$message->getChannelAttribute()->name}. Error: {$e->getMessage()}");
                             $message->reply("**Error:** There was a problem running the command: {$e->getMessage()}");
                         }
                     }
                 }
             }
         }
     });
     // Handle joining a voice channel, and playing.. stuff....
     $this->websocket->on(Event::MESSAGE_CREATE, function (Message $message, Discord $discord) {
         // Get the guildID
         $guildID = $message->getChannelAttribute()->guild_id;
         // Get this guilds settings
         $config = $this->settings->get($guildID);
         // Get the prefix for this guild
         @($config->prefix = $config->prefix ?? $this->globalConfig->get('prefix', 'bot'));
         if (substr($message->content, 0, strlen($config->prefix)) === $config->prefix) {
             $content = explode(' ', $message->content);
             foreach ($this->onVoice as $command => $data) {
                 $parts = [];
                 foreach ($content as $index => $c) {
                     foreach (explode("\n", $c) as $p) {
                         $parts[] = $p;
                     }
                 }
                 if ($parts[0] === $config->prefix . $command) {
                     try {
                         $voiceChannels = $message->getFullChannelAttribute()->getGuildAttribute()->channels->getAll('type', 'voice');
                         foreach ($voiceChannels as $channel) {
                             if (!empty($channel->members[$message->author->id])) {
                                 $voice = new $data['class']();
                                 $voice->run($message, $discord, $this->websocket, $this->log, $this->audioStreams, $channel, $this->curl);
                             }
                         }
                     } catch (\Exception $e) {
                         $this->log->addError("Error running voice command {$config->prefix}{$command}. Command run by {$message->author->username} in {$message->getChannelAttribute()->name}. Error: {$e->getMessage()}");
                         $message->reply("**Error:** There was a problem running the command: {$e->getMessage()}");
                     }
                 }
             }
         }
     });
     // Handle if it's a message for the bot (CleverBot invocation)
     $this->websocket->on(Event::MESSAGE_CREATE, function (Message $message, Discord $discord) {
         // If we got highlighted we should probably answer back
         if (stristr($message->content, $discord->getClient()->id)) {
             try {
                 $this->pool->submit(new cleverBotMessage($message, $discord, $this->log, $this->globalConfig, $this->db, $this->curl, $this->settings, $this->permissions, $this->container->get('serverConfig'), $this->users));
             } catch (\Exception $e) {
                 $message->reply("**Error:** There was an error with CleverBot: {$e->getMessage()}");
             }
         }
     });
     // Handle presence updates
     $this->websocket->on(Event::PRESENCE_UPDATE, function (PresenceUpdate $presenceUpdate) {
         if ($presenceUpdate->user->id && $presenceUpdate->user->username) {
             try {
                 $this->log->addInfo("Updating presence info for {$presenceUpdate->user->username}");
                 $game = $presenceUpdate->getGameAttribute()->name ?? null;
                 $this->users->set($presenceUpdate->user->id, $presenceUpdate->user->username, $presenceUpdate->status, $game, date('Y-m-d H:i:s'), null, null);
             } catch (\Exception $e) {
                 $this->log->addError("Error: {$e->getMessage()}");
             }
         }
     });
     // Create a new cleverbot \nick\ for this new guild
     $this->websocket->on(Event::GUILD_CREATE, function (Guild $guild) {
         $cleverBotExists = $this->db->queryField("SELECT serverID FROM cleverbot WHERE serverID = :serverID", "serverID", array(":serverID" => $guild->id));
         $guildExists = $this->db->queryField("SELECT guildID FROM guilds WHERE guildID = :serverID", "guildID", array(":serverID" => $guild->id));
         // Only create a new server nick if the cleverbot instance doesn't exist.. (Hopefully cleverbot.io is done deleting them at random)
         if (!isset($cleverBotExists)) {
             $this->log->addInfo("Setting up Cleverbot for {$guild->name}");
             $serverID = $guild->id;
             $result = $this->curl->post('https://cleverbot.io/1.0/create', ['user' => $this->globalConfig->get('user', 'cleverbot'), 'key' => $this->globalConfig->get('key', 'cleverbot')]);
             if ($result) {
                 $result = @json_decode($result);
                 $nick = $result->nick ?? false;
                 if ($nick) {
                     $this->db->execute('INSERT INTO cleverbot (serverID, nick) VALUES (:serverID, :nick) ON DUPLICATE KEY UPDATE nick = :nick', [':serverID' => $serverID, ':nick' => $nick]);
                 }
             }
         }
         if (!isset($guildExists)) {
             $this->db->execute("INSERT IGNORE INTO guilds (guildID) VALUES (:guildID)", array(":guildID" => $guild->id));
             // Send a hello message to the channel (Only if it's new!)
             //$message = "Hello, i was invited here by someone with admin permissions, i have quite a few features that you can discover by doing %help\n";
             //$message .= "I am sorry if i am triggering other bots aswell, you can change my trigger with %config setTrigger newTrigger (Example: %config setTrigger *)\n";
             //$message .= "If you for some reason don't want me here after all, just kick me ;)";
             // Get the first channel in the list (usually the default channel)
             //$channel = $guild->channels->first();
             //$channel->sendMessage($message);
         }
     });
     // Run the websocket, and in turn, the bot!
     $this->websocket->run();
 }