]> git.localhorst.tv Git - alttp.git/commitdiff
first simple twitch commands
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 2 Mar 2023 14:11:57 +0000 (15:11 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 2 Mar 2023 14:11:57 +0000 (15:11 +0100)
app/Models/Channel.php
app/Models/EpisodeCrew.php
app/Models/EpisodePlayer.php
app/TwitchBot/ChatCommand.php [new file with mode: 0644]
app/TwitchBot/CrewCommand.php [new file with mode: 0644]
app/TwitchBot/IRCMessage.php
app/TwitchBot/RunnerCommand.php [new file with mode: 0644]
app/TwitchBot/TwitchBot.php
database/migrations/2023_03_01_143514_channel_twitch_chat.php
database/migrations/2023_03_02_084058_channel_commands.php [new file with mode: 0644]

index 8b5ff9007e2359c93bc105cdcd9b7e13fb1f73ce..0536aef36e9638ace6387d2f3fbba3f50c2bcace 100644 (file)
@@ -9,6 +9,13 @@ class Channel extends Model
 {
        use HasFactory;
 
+       public function getCurrentEpisode() {
+               return $this->episodes()
+                       ->where('start', '<', now()->subMinutes(10))
+                       ->orderBy('start', 'DESC')
+                       ->first();
+       }
+
        public function episodes() {
                return $this->belongsToMany(Episode::class)
                        ->using(Restream::class)
@@ -20,6 +27,7 @@ class Channel extends Model
        }
 
        protected $casts = [
+               'chat_commands' => 'array',
                'languages' => 'array',
        ];
 
index d06276e537d234d0b7e2e068910881cad8c43a1e..04bec5c7d68bdf209f9b9ef2ffac10de61e94e7f 100644 (file)
@@ -21,6 +21,31 @@ class EpisodeCrew extends Model
                return $this->belongsTo(User::class);
        }
 
+       public function getName() {
+               if (!empty($this->name_override)) {
+                       return $this->name_override;
+               }
+               if ($this->user) {
+                       if (!empty($this->user->nickname)) {
+                               return $this->user->nickname;
+                       }
+                       if (!empty($this->user->username)) {
+                               return $this->user->username;
+                       }
+               }
+               return '';
+       }
+
+       public function getStreamLink() {
+               if (!empty($this->stream_override)) {
+                       return $this->stream_override;
+               }
+               if ($this->user && !empty($this->user->stream_link)) {
+                       return $this->user->stream_link;
+               }
+               return '';
+       }
+
        protected $casts = [
                'confirmed' => 'boolean',
                'user_id' => 'string',
index 1125701e4a9f38e15775cd2edbdbf98c1a00a1bd..26ccc044950d9bedd1dcc08203c9f4e58ea09bd6 100644 (file)
@@ -17,6 +17,31 @@ class EpisodePlayer extends Model
                return $this->belongsTo(User::class);
        }
 
+       public function getName() {
+               if (!empty($this->name_override)) {
+                       return $this->name_override;
+               }
+               if ($this->user) {
+                       if (!empty($this->user->nickname)) {
+                               return $this->user->nickname;
+                       }
+                       if (!empty($this->user->username)) {
+                               return $this->user->username;
+                       }
+               }
+               return '';
+       }
+
+       public function getStreamLink() {
+               if (!empty($this->stream_override)) {
+                       return $this->stream_override;
+               }
+               if ($this->user && !empty($this->user->stream_link)) {
+                       return $this->user->stream_link;
+               }
+               return '';
+       }
+
        protected $casts = [
                'user_id' => 'string',
        ];
diff --git a/app/TwitchBot/ChatCommand.php b/app/TwitchBot/ChatCommand.php
new file mode 100644 (file)
index 0000000..feea8ab
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+
+namespace App\TwitchBot;
+
+use App\Models\Channel;
+
+abstract class ChatCommand {
+
+       public static function create(TwitchBot $bot, Channel $channel, $config) {
+               $cmd = null;
+               switch ($config['command']) {
+                       case 'crew':
+                               $cmd = new CrewCommand();
+                               break;
+                       case 'runner':
+                               $cmd = new RunnerCommand();
+                               break;
+                       default:
+                               throw new \Exception('command '.$str.' not found');
+               }
+               $cmd->bot = $bot;
+               $cmd->channel = $channel;
+               $cmd->config = $config;
+               return $cmd;
+       }
+
+       public abstract function execute($args);
+
+       protected function getBooleanConfig($name, $default = false) {
+               return array_key_exists($name, $this->config) ? $this->config[$name] : $default;
+       }
+
+       protected function messageChannel($str) {
+               $msg = IRCMessage::privmsg($this->channel->twitch_chat, $str);
+               $this->bot->sendIRCMessage($msg);
+       }
+
+       protected $bot;
+       protected $channel;
+       protected $config;
+
+}
+
+?>
diff --git a/app/TwitchBot/CrewCommand.php b/app/TwitchBot/CrewCommand.php
new file mode 100644 (file)
index 0000000..2fd0426
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+
+namespace App\TwitchBot;
+
+class CrewCommand extends ChatCommand {
+
+       public function execute($args) {
+               $episode = $this->channel->getCurrentEpisode();
+               if (!$episode) return;
+               $links = [];
+               foreach ($episode->crew as $crew) {
+                       $link = $crew->getStreamLink();
+                       if (empty($link)) {
+                               $link = $crew->getName();
+                       }
+                       if (!empty($link)) {
+                               if (!isset($links[$crew->role])) {
+                                       $links[$crew->role] = [];
+                               }
+                               $links[$crew->role][] = $link;
+                       }
+               }
+               $parts = [];
+               if (!empty($links['commentary']) && $this->getBooleanConfig('commentary', true)) {
+                       $parts[] = 'Kommentar: '.implode(' ', $links['commentary']);
+               }
+               if (!empty($links['tracking']) && $this->getBooleanConfig('tracking', true)) {
+                       $parts[] = 'Tracking: '.implode(' ', $links['tracking']);
+               }
+               if (!empty($links['setup']) && $this->getBooleanConfig('setup', false)) {
+                       $parts[] = 'Setup: '.implode(' ', $links['setup']);
+               }
+               if (!empty($parts)) {
+                       $message = implode(' ', $parts);
+                       $this->messageChannel($message);
+               }
+       }
+
+}
+
+?>
index c0acfbb547cc2d205fff7ef5420fdfbe07ce9ad1..00217dc044660b1a5b70c471a8f20497e611fad1 100644 (file)
@@ -132,6 +132,14 @@ class IRCMessage {
                return $msg;
        }
 
+       public static function privmsg($target, $message) {
+               $msg = new IRCMessage();
+               $msg->command = 'PRIVMSG';
+               $msg->params[] = $target;
+               $msg->params[] = $message;
+               return $msg;
+       }
+
        public function getPrivMsgTarget() {
                if (!empty($this->params)) {
                        return $this->params[0];
diff --git a/app/TwitchBot/RunnerCommand.php b/app/TwitchBot/RunnerCommand.php
new file mode 100644 (file)
index 0000000..2cc41b2
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+
+namespace App\TwitchBot;
+
+class RunnerCommand extends ChatCommand {
+
+       public function execute($args) {
+               $episode = $this->channel->getCurrentEpisode();
+               if (!$episode) return;
+               $links = [];
+               foreach ($episode->players as $player) {
+                       $link = $player->getStreamLink();
+                       if (empty($link)) {
+                               $link = $player->getName();
+                       }
+                       if (!empty($link)) {
+                               $links[] = $link;
+                       }
+               }
+               $message = 'Runner: '.implode(' ', $links);
+               $this->messageChannel($message);
+       }
+
+}
+
+?>
index 3ca2db9283e6651e521fa2fe4aeaa596d94f9e2e..3cba5d958bac4975fd2e3fdf93fd901208ffcc18 100644 (file)
@@ -15,7 +15,7 @@ class TwitchBot {
 
        public function __construct() {
                $this->logger = new Logger('TwitchBot');
-               $this->logger->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG));
+               $this->logger->pushHandler(new StreamHandler('php://stdout', Logger::INFO));
 
                $this->token = TwitchToken::firstWhere('nick', 'localhorsttv');
                if (!$this->token) {
@@ -122,7 +122,20 @@ class TwitchBot {
                if ($text[0] != '!') return;
                $channel = Channel::firstWhere('twitch_chat', '=', $target);
                if (!$channel) return;
-               $this->logger->info('got command '.$text.' on channel '.$channel->title);
+               $this->handleChatCommand($channel, $msg);
+       }
+
+       public function handleChatCommand(Channel $channel, IRCMessage $msg) {
+               $cmd = explode(' ', ltrim($msg->getText(), '!'), 2);
+               if (!isset($channel->chat_commands[$cmd[0]])) return;
+               $config = $channel->chat_commands[$cmd[0]];
+               $this->logger->info('got command '.$cmd[0].' on channel '.$channel->title);
+               try {
+                       $command = ChatCommand::create($this, $channel, $config);
+                       $command->execute($cmd[1] ?? '');
+               } catch (\Exception $e) {
+                       $this->logger->warning('error executing command '.$cmd[0].' on channel '.$channel->title.': '.$e->getMessage());
+               }
        }
 
        public function login() {
index b9d39018770f6ae1437313d50b27304ed893dbce..64290634f9750457cfcaa31f934cf583ad175762 100644 (file)
@@ -25,7 +25,7 @@ return new class extends Migration
         */
        public function down()
        {
-               Schema::table('events', function(Blueprint $table) {
+               Schema::table('channels', function(Blueprint $table) {
                        $table->dropColumn('twitch_chat');
                });
        }
diff --git a/database/migrations/2023_03_02_084058_channel_commands.php b/database/migrations/2023_03_02_084058_channel_commands.php
new file mode 100644 (file)
index 0000000..df639b1
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+       /**
+        * Run the migrations.
+        *
+        * @return void
+        */
+       public function up()
+       {
+               Schema::table('channels', function(Blueprint $table) {
+                       $table->text('chat_commands')->default('{}');
+               });
+       }
+
+       /**
+        * Reverse the migrations.
+        *
+        * @return void
+        */
+       public function down()
+       {
+               Schema::table('channels', function(Blueprint $table) {
+                       $table->dropColumn('chat_commands');
+               });
+       }
+};