benbot/src/BenBot.php

333 lines
11 KiB
PHP

<?php
namespace BenBot;
use Discord\Discord;
use Discord\Parts\User\Game;
use Discord\Parts\Embed\Embed;
use Discord\WebSockets\Event;
use BenBot\Utils;
use BenBot\PersistentArray;
use BenBot\Command;
use BenBot\Commands;
use BenBot\FontConverter;
use Carbon\Carbon;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Dotenv\Dotenv;
use function Stringy\create as s;
final class BenBot extends Discord
{
public $start_time;
public $dir;
public $defs;
public $imgs;
public $cities;
public $emails;
public $jokes;
public $yomamajokes;
public $copypastas;
public $devbot;
public $tictactoe;
public $hangman;
protected $help;
protected $banner;
protected $cmds = [];
protected $aliases = [];
public function __construct($dir)
{
(new Dotenv($dir))->load();
parent::__construct([
'token' => getenv('DISCORD_TOKEN'),
'pmChannels' => true,
'loadAllMembers' => true,
]);
$this->dir = $dir;
$this->help = [];
$this->jokes = explode("---", file_get_contents("$dir/miscjokes.txt"));
$this->copypastas = explode("---", file_get_contents("$dir/copypasta.txt"));
$this->yomamajokes = file("$dir/yomamajokes.txt");
$this->banner = file_get_contents("{$this->dir}/banner.txt");
$this->tictactoe = [];
$this->hangman = [];
try {
$this->defs = new PersistentArray("$dir/bot_data/defs.mp");
$this->imgs = new PersistentArray("$dir/bot_data/img_urls.mp");
$this->cities = new PersistentArray("$dir/bot_data/cities.mp");
$this->emails = new PersistentArray("$dir/bot_data/emails.mp");
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), PHP_EOL;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
$this->on('ready', function () {
Utils::init($this);
FontConverter::init();
$this->updatePresence($this->factory(Game::class, [
'name' => ';help for info',
]));
$this->devbot = $this->client->user->id == 296304785018322947;
$this->registerAllCommands();
$msghandler = function ($msg) {
$str = s($msg->content);
if (!$msg->author->bot) {
// handle game move for players
if (Commands\TicTacToe::isActive($msg)) {
Commands\TicTacToe::handleMove($msg);
return;
}
if ($str->startsWith(';')) {
// is command!
$args = $str->removeLeft(';')->split(' ');
$cmd = (string) array_shift($args)->toLowerCase();
// look up definition
if (isset($this->defs[$cmd])) {
Utils::send($msg, "**$cmd**: " . $this->defs[$cmd]);
}
// look up image
if (isset($this->imgs[$cmd])) {
$msg->channel->broadcastTyping();
Utils::sendFile($msg,
"{$this->dir}/uploaded_images/{$this->imgs[$cmd]}",
$this->imgs[$cmd],
"$cmd\nby {$msg->author}"
)->then(function ($result) use ($msg) {
Utils::deleteMessage($msg);
});
}
// make sure stringys are strings
foreach ($args as $key => $arg) {
$args[$key] = (string) $arg;
}
// do the font stuff!
if (array_key_exists($cmd, FontConverter::$fonts)) {
Utils::send($msg, FontConverter::$cmd(implode(" ", $args)) . "\n--{$msg->author}")->then(function ($result) use ($msg) {
Utils::deleteMessage($msg);
});
return;
}
// look up command
if (array_key_exists($cmd, $this->cmds)) {
$command = $this->cmds[$cmd];
} elseif (array_key_exists($cmd, $this->aliases)) {
$command = $this->cmds[$this->aliases[$cmd]];
} else {
return;
}
// do the command
$result = $command->handle($msg, $args);
// respond if the command handler returned a string
if (is_string($result)) {
Utils::send($msg, $result);
}
} elseif (Utils::isDM($msg)) {
return call_user_func_array(["BenBot\Commands\CleverBot", "chat"], [$msg, explode(' ', $msg->content)]);
}
}
if (!Utils::isDM($msg) && $msg->channel->guild->id === "233603102047993856") {
if ($str->contains('dib', false)) {
$msg->react(":dib:284335774823088129")->otherwise(function ($e) {
echo $e->getMessage(), PHP_EOL;
});
}
}
}; // --onmsg
$this->on('message', $msghandler);
$this->on(Event::MESSAGE_UPDATE, $msghandler);
$this->start_time = Carbon::now();
// register help function
$this->registerCommand('help', function ($msg, $args) {
if (count($args) > 0 && $args[0] != "") {
$cmdstr = implode(" ", $args);
$command = $this->getCommand($cmdstr, true);
if (is_null($command)) {
return "The command `;$cmdstr` does not exist";
}
$help = $command->getHelp()["text"];
return "```$help```";
} else {
$response = "```{$this->banner}\n- a bot made by benh. avatar by hirose.\n\n";
sort($this->help);
$response .= implode("", $this->help);
$response .= "\n-------------------------------------------------------------\n;help [command] - get more information about a specific command\ncommands are case-insensitive.\n\n[optional]\n<required>\n| = available options```";
return $response;
}
}, [
'description' => 'shows help text',
'usage' => '<command>',
]);
Utils::ping("bot started successfully");
echo PHP_EOL, "BOT STARTED SUCCESSFULLY", PHP_EOL, PHP_EOL;
});
}
///////////////////////////////////////////////////////////////////////////////////////////////////
public function registerAllCommands()
{
Commands\AsciiArt::register($this);
Commands\Cities::register($this);
Commands\CleverBot::register($this);
Commands\Debug::register($this);
Commands\Definitions::register($this);
Commands\Emails::register($this);
Commands\Fonts::register($this);
Commands\Fun::register($this);
Commands\Hangman::register($this);
Commands\Images::register($this);
Commands\Jokes::register($this);
Commands\Misc::register($this);
Commands\Music::register($this);
Commands\Poll::register($this);
Commands\TicTacToe::register($this);
Commands\Time::register($this);
Commands\Weather::register($this);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
public function registerCommand($command, $callable, array $options = [])
{
if (array_key_exists($command, $this->cmds)) {
throw new \Exception("A command with the name $command already exists.");
}
[$commandInstance, $options] = $this->buildCommand($command, $callable, $options);
$this->cmds[$command] = $commandInstance;
foreach ($options['aliases'] as $alias) {
$this->registerAlias($alias, $command);
}
if ($options['registerHelp']) {
$this->help[$command] = $commandInstance->getHelp()["text"];
}
return $commandInstance;
}
public function unregisterCommand($command)
{
if (!array_key_exists($command, $this->cmds)) {
throw new \Exception("A command with the name $command does not exist.");
}
unset($this->cmds[$command]);
}
public function registerAlias($alias, $command)
{
$this->aliases[$alias] = $command;
}
public function unregisterAlias($alias)
{
if (!array_key_exist($alias, $this->aliases)) {
throw new \Exception("A command alias with the name $alias does not exist.");
}
unset($this->aliases[$alias]);
}
public function getCommand($command, $aliases = true)
{
if (array_key_exists($command, $this->cmds)) {
return $this->cmds[$command];
}
if (array_key_exists($command, $this->aliases) && $aliases) {
return $this->cmds[$this->aliases[$command]];
}
}
public function buildCommand($command, $callable, array $options = [])
{
if (!is_callable($callable)) {
throw new \Exception("The callable has to be a callable....");
}
$options = $this->resolveCommandOptions($options);
$commandInstance = new Command(
$this, $command, $callable,
$options['description'], $options['usage'], $options['aliases']);
return [$commandInstance, $options];
}
public function resolveCommandOptions(array $options)
{
$resolver = new OptionsResolver();
$resolver
->setDefined([
'description',
'usage',
'aliases',
'registerHelp',
])
->setDefaults([
'description' => 'No description provided yet',
'usage' => '',
'aliases' => [],
'registerHelp' => false,
]);
$options = $resolver->resolve($options);
if (!empty($options['usage'])) {
$options['usage'] .= ' ';
}
return $options;
}
public function __get($name)
{
$allowed = ['cmds', 'aliases'];
if (array_search($name, $allowed) !== false) {
return $this->$name;
}
return parent::__get($name);
}
}