From 7c89ba8940222b7fb1f210de5c1a82064b4b4c13 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Thu, 31 Jul 2025 11:33:27 +0200 Subject: [PATCH] discord app events show command --- app/Console/Commands/DiscordBotCommand.php | 12 +++-- app/DiscordAppCommands/AlttpCommand.php | 4 +- app/DiscordAppCommands/AlttpTechCommand.php | 24 ++++++---- app/DiscordAppCommands/EventsCommand.php | 27 +++++++++++ app/DiscordAppCommands/EventsShowCommand.php | 47 ++++++++++++++++++ app/Models/DiscordGuild.php | 50 ++++++++++++++++++-- app/Models/Event.php | 4 ++ 7 files changed, 146 insertions(+), 22 deletions(-) create mode 100644 app/DiscordAppCommands/EventsCommand.php create mode 100644 app/DiscordAppCommands/EventsShowCommand.php diff --git a/app/Console/Commands/DiscordBotCommand.php b/app/Console/Commands/DiscordBotCommand.php index 769f284..26e7f91 100644 --- a/app/Console/Commands/DiscordBotCommand.php +++ b/app/Console/Commands/DiscordBotCommand.php @@ -3,13 +3,13 @@ namespace App\Console\Commands; use App\DiscordAppCommands\AlttpCommand; +use App\DiscordAppCommands\EventsCommand; use App\Models\DiscordBotCommand as CommandModel; use App\Models\DiscordChannel; use App\Models\DiscordGuild; use App\Models\DiscordRole; use Discord\Discord; use Discord\Parts\Channel\Channel; -use Discord\Parts\Channel\Message; use Discord\Parts\Guild\Guild; use Discord\Parts\Guild\Role; use Discord\Parts\User\Activity; @@ -17,8 +17,8 @@ use Discord\WebSockets\Event; use Discord\WebSockets\Intents; use Illuminate\Console\Command; use Monolog\Handler\StreamHandler; +use Monolog\Level; use Monolog\Logger; -use React\EventLoop\Loop; class DiscordBotCommand extends Command { @@ -44,7 +44,7 @@ class DiscordBotCommand extends Command public function handle() { $logger = new Logger('DiscordBot'); - $logger->pushHandler(new StreamHandler('php://stdout', Logger::INFO)); + $logger->pushHandler(new StreamHandler('php://stdout', Level::Info)); $discord = new Discord([ 'intents' => Intents::getDefaultIntents() | Intents::GUILD_MEMBERS, 'logger' => $logger, @@ -58,7 +58,7 @@ class DiscordBotCommand extends Command $discord->updatePresence($activity); $discord->getLoop()->addPeriodicTimer(1, function () use ($discord) { - $command = CommandModel::where('status', '=', 'pending')->oldest()->first(); + $command = CommandModel::query()->where('status', '=', 'pending')->oldest()->first(); if ($command) { $this->line('executing command '.$command->id.': '.$command->command); try { @@ -70,9 +70,11 @@ class DiscordBotCommand extends Command if (config('discord.enable_commands')) { AlttpCommand::listen($discord); + EventsCommand::listen($discord); } if (config('discord.create_commands')) { AlttpCommand::create($discord); + EventsCommand::create($discord); } }); $discord->on(Event::GUILD_CREATE, function (Guild $guild, Discord $discord) { @@ -131,7 +133,7 @@ class DiscordBotCommand extends Command $this->error('guild role delete: '.$e->getMessage()); } }); - $discord->getLoop()->addSignal(SIGINT, function() use ($discord) { + $discord->getLoop()->addSignal(SIGINT, function () use ($discord) { $discord->close(); }); $discord->run(); diff --git a/app/DiscordAppCommands/AlttpCommand.php b/app/DiscordAppCommands/AlttpCommand.php index e27767b..c7d782e 100644 --- a/app/DiscordAppCommands/AlttpCommand.php +++ b/app/DiscordAppCommands/AlttpCommand.php @@ -7,7 +7,7 @@ use Discord\Discord; class AlttpCommand { - public static function create(Discord $discord) { + public static function create(Discord $discord): void { $command = CommandBuilder::new(); $command->setName('alttp'); $command->setDescription('A Link to the Past'); @@ -17,7 +17,7 @@ class AlttpCommand { ); } - public static function listen(Discord $discord) { + public static function listen(Discord $discord): void { AlttpTechCommand::listen('alttp', $discord); } diff --git a/app/DiscordAppCommands/AlttpTechCommand.php b/app/DiscordAppCommands/AlttpTechCommand.php index ac341ba..1cd9b20 100644 --- a/app/DiscordAppCommands/AlttpTechCommand.php +++ b/app/DiscordAppCommands/AlttpTechCommand.php @@ -6,13 +6,12 @@ use App\Models\Technique; use Discord\Builders\MessageBuilder; use Discord\Discord; use Discord\Parts\Embed\Embed; -use Discord\Parts\Embed\Footer; use Discord\Parts\Interactions\Command\Option; use Discord\Parts\Interactions\Interaction; class AlttpTechCommand { - public static function create(Discord $discord) { + public static function create(Discord $discord): Option { $command = new Option($discord); $command->setType(Option::SUB_COMMAND); $command->setName('tech'); @@ -27,17 +26,17 @@ class AlttpTechCommand { return $command; } - public static function listen($parent, Discord $discord) { + public static function listen(string $parent, Discord $discord): void { $discord->listenCommand( [$parent, 'tech'], function (Interaction $interaction) use ($discord) { $interaction ->acknowledgeWithResponse() - ->done(function() use ($discord, $interaction) { + ->done(function () use ($discord, $interaction) { try { $lang = Technique::locale2lang($interaction->locale); - $tech = Technique - ::where('type', '=', 'tech') + $tech = Technique::query() + ->where('type', '=', 'tech') ->where('name', '=', $interaction->data->options['tech']->options['name']->value) ->firstOrFail(); $properties = [ @@ -51,7 +50,7 @@ class AlttpTechCommand { $properties['image'] = [ 'url' => url($tech->gif), ]; - } else if ($tech->image) { + } elseif ($tech->image) { $properties['image'] = [ 'url' => url($tech->image), ]; @@ -74,13 +73,16 @@ class AlttpTechCommand { $phrase = $interaction->data->options['tech']->options['name']->value; } catch (\Exception $e) { } - $tech = Technique::where('type', '=', 'tech')->where('index', '=', 1)->whereNotNull('name'); + $tech = Technique::query() + ->where('type', '=', 'tech') + ->where('index', '=', 1) + ->whereNotNull('name'); if (!empty($phrase)) { if ($lang == 'en') { $tech->where('title', 'LIKE', '%'.$phrase.'%'); $tech->orWhere('short', 'LIKE', '%'.$phrase.'%'); } else { - $tech = $tech->whereHas('translations', function ($query) use ($lang, $phrase) { + $tech->whereHas('translations', function ($query) use ($lang, $phrase) { $query->where('locale', '=', $lang); $query->where(function ($subquery) use ($phrase) { $subquery->where('title', 'LIKE', '%'.$phrase.'%'); @@ -95,7 +97,9 @@ class AlttpTechCommand { 'name' => $t->getTranslatedProperty('title', $lang), 'value' => $t->name, ]; - if (count($choices) == 25) break; + if (count($choices) == 25) { + break; + } } usort($choices, function ($a, $b) use ($phrase) { $a_head = stripos($a['name'], $phrase) === 0; diff --git a/app/DiscordAppCommands/EventsCommand.php b/app/DiscordAppCommands/EventsCommand.php new file mode 100644 index 0000000..9a273c2 --- /dev/null +++ b/app/DiscordAppCommands/EventsCommand.php @@ -0,0 +1,27 @@ +setName('events'); + $command->setDescription('Event subscriptions'); + $command->setDescriptionLocalization('de', 'Event Abonnements'); + $command->setDmPermission(false); + $command->setDefaultMemberPermissions("0"); + $command->addOption(EventsShowCommand::create($discord)); + $discord->application->commands->save( + $discord->application->commands->create($command->toArray()) + ); + } + + public static function listen(Discord $discord): void { + EventsShowCommand::listen('events', $discord); + } + +} diff --git a/app/DiscordAppCommands/EventsShowCommand.php b/app/DiscordAppCommands/EventsShowCommand.php new file mode 100644 index 0000000..f7b177d --- /dev/null +++ b/app/DiscordAppCommands/EventsShowCommand.php @@ -0,0 +1,47 @@ +setType(Option::SUB_COMMAND); + $command->setName('show'); + $command->setDescription('Show what events your server subscribes to on alttp.localhorst.tv'); + return $command; + } + + public static function listen(string $parent, Discord $discord): void { + $discord->listenCommand( + [$parent, 'show'], + function (Interaction $interaction) use ($discord) { + $interaction + ->acknowledgeWithResponse() + ->done(function () use ($discord, $interaction) { + try { + // TODO: translation + $lang = Technique::locale2lang($interaction->locale); + $guild = DiscordGuild::query()->where('guild_id', '=', $interaction->guild_id)->firstOrFail(); + $embed = $guild->getSubscriptionsEmbed($discord); + $message = MessageBuilder::new(); + $message->addEmbed($embed); + $interaction->updateOriginalResponse($message); + } catch (\Throwable $e) { + $message = MessageBuilder::new(); + $message->setContent('Error: '.$e->getMessage()); + $interaction->updateOriginalResponse($message); + } + }); + }, + ); + } + +} diff --git a/app/Models/DiscordGuild.php b/app/Models/DiscordGuild.php index c210bab..bfbd2d5 100644 --- a/app/Models/DiscordGuild.php +++ b/app/Models/DiscordGuild.php @@ -2,24 +2,25 @@ namespace App\Models; +use Discord\Discord; +use Discord\Parts\Embed\Embed; use Discord\Parts\Guild\Guild; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -class DiscordGuild extends Model -{ +class DiscordGuild extends Model { use HasFactory; - public static function onUpstreamCreate(Guild $guild) { + public static function onUpstreamCreate(Guild $guild): void { static::sync($guild); } - public static function onUpstreamUpdate(Guild $guild) { + public static function onUpstreamUpdate(Guild $guild): void { static::sync($guild); } - public static function sync(Guild $guild) { + public static function sync(Guild $guild): void { $model = static::firstOrNew([ 'guild_id' => $guild->id, ]); @@ -72,6 +73,45 @@ class DiscordGuild extends Model return $this->hasMany(DiscordGuildUserSubscription::class); } + + public function getSubscriptionsEmbed(Discord $discord): Embed { + $any = count($this->event_subscriptions) + count($this->ladder_subscriptions) + count($this->user_subscriptions); + $title = 'Creating events for:'; + $text = ''; + if (count($this->event_subscriptions)) { + $text .= "Events:\n"; + foreach ($this->event_subscriptions as $esub) { + $text .= '- ['.$esub->event->title.']('.$esub->event->getURL().")\n"; + } + $text .= "\n"; + } + if (count($this->ladder_subscriptions)) { + $text .= "Ladder Modes:\n"; + foreach ($this->ladder_subscriptions as $lsub) { + $text .= '- '.$lsub->step_ladder_mode->name.' ('.substr($lsub->step_ladder_mode->ext_id, 11).")\n"; + } + $text .= "\n"; + } + if (count($this->user_subscriptions)) { + $text .= "Runners:\n"; + foreach ($this->user_subscriptions as $usub) { + $text .= '- '.$usub->user->getName()."\n"; + } + $text .= "\n"; + } + if (empty($text)) { + $text = 'Nothing, really'; + } + $properties = [ + 'color' => 0x389c38, + 'description' => $text, + 'title' => $title, + 'type' => 'rich', + ]; + return new Embed($discord, $properties); + } + + protected $fillable = [ 'guild_id', ]; diff --git a/app/Models/Event.php b/app/Models/Event.php index f63a558..6ebaa62 100644 --- a/app/Models/Event.php +++ b/app/Models/Event.php @@ -36,6 +36,10 @@ class Event extends Model return ''; } + public function getURL(): string { + return url('/events/'.$this->name); + } + protected $casts = [ 'end' => 'datetime', 'start' => 'datetime', -- 2.39.5