]> git.localhorst.tv Git - alttp.git/commitdiff
twitch chat bot controls
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 21 Jan 2024 12:54:38 +0000 (13:54 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 21 Jan 2024 12:54:38 +0000 (13:54 +0100)
app/Http/Controllers/ChannelController.php
app/Models/TwitchBotCommand.php
app/TwitchBot/TwitchAppBot.php
app/TwitchBot/TwitchBot.php
app/TwitchBot/TwitchChatBot.php
database/migrations/2024_01_21_115350_chat_bot_commands.php [new file with mode: 0644]
resources/js/components/twitch-bot/Controls.js
resources/js/i18n/de.js
resources/js/i18n/en.js

index da1f5ef76590166b5e9cf1827ce93cf2c8240421..b735a6f70b3e3e6fcc45c0df81dfd9446af970e9 100644 (file)
@@ -47,10 +47,12 @@ class ChannelController extends Controller {
                        throw new \Exception('channel has no twitch chat set');
                }
                $validatedData = $request->validate([
+                       'bot_nick' => 'string',
                        'text' => 'string|required',
                ]);
                $this->authorize('editRestream', $channel);
-               TwitchBotCommand::chat($channel->twitch_chat, $validatedData['text'], $request->user());
+               $nick = empty($validatedData['bot_nick']) ? 'localhorsttv' : $validatedData['bot_nick'];
+               TwitchBotCommand::chat($channel->twitch_chat, $validatedData['text'], $request->user(), $nick);
                return $channel->toJson();
        }
 
@@ -58,10 +60,18 @@ class ChannelController extends Controller {
                if (!$channel->twitch_chat) {
                        throw new \Exception('channel has no twitch chat set');
                }
+               $validatedData = $request->validate([
+                       'bot_nick' => 'string',
+               ]);
                $this->authorize('editRestream', $channel);
-               $channel->join = true;
+               $nick = empty($validatedData['bot_nick']) ? 'localhorsttv' : $validatedData['bot_nick'];
+               if ($nick == 'localhorsttv') {
+                       $channel->join = true;
+               } else if ($nick == 'horstiebot') {
+                       $channel->chat = true;
+               }
                $channel->save();
-               TwitchBotCommand::join($channel->twitch_chat, $request->user());
+               TwitchBotCommand::join($channel->twitch_chat, $request->user(), $nick);
                return $channel->toJson();
        }
 
@@ -69,10 +79,18 @@ class ChannelController extends Controller {
                if (!$channel->twitch_chat) {
                        throw new \Exception('channel has no twitch chat set');
                }
+               $validatedData = $request->validate([
+                       'bot_nick' => 'string',
+               ]);
                $this->authorize('editRestream', $channel);
-               $channel->join = false;
+               $nick = empty($validatedData['bot_nick']) ? 'localhorsttv' : $validatedData['bot_nick'];
+               if ($nick == 'localhorsttv') {
+                       $channel->join = false;
+               } else if ($nick == 'horstiebot') {
+                       $channel->chat = false;
+               }
                $channel->save();
-               TwitchBotCommand::part($channel->twitch_chat, $request->user());
+               TwitchBotCommand::part($channel->twitch_chat, $request->user(), $nick);
                return $channel->toJson();
        }
 
index 14cabf7a9513d0f812d317710b457652d397ac77..716b8d5841cd1c2c628d6ddff5b1b0b623567c4f 100644 (file)
@@ -11,7 +11,7 @@ class TwitchBotCommand extends Model
 {
        use HasFactory;
 
-       public static function chat($channel, $text, User $user = null) {
+       public static function chat($channel, $text, User $user = null, $nick = 'localhorsttv') {
                $cmd = new TwitchBotCommand();
                $cmd->command = 'chat';
                $cmd->parameters = [
@@ -20,10 +20,11 @@ class TwitchBotCommand extends Model
                ];
                $cmd->status = 'pending';
                $cmd->user()->associate($user);
+               $cmd->bot_nick = $nick;
                $cmd->save();
        }
 
-       public static function join($channel, User $user = null) {
+       public static function join($channel, User $user = null, $nick = 'localhorsttv') {
                $cmd = new TwitchBotCommand();
                $cmd->command = 'join';
                $cmd->parameters = [
@@ -31,10 +32,11 @@ class TwitchBotCommand extends Model
                ];
                $cmd->status = 'pending';
                $cmd->user()->associate($user);
+               $cmd->bot_nick = $nick;
                $cmd->save();
        }
 
-       public static function part($channel, User $user = null) {
+       public static function part($channel, User $user = null, $nick = 'localhorsttv') {
                $cmd = new TwitchBotCommand();
                $cmd->command = 'part';
                $cmd->parameters = [
@@ -42,6 +44,7 @@ class TwitchBotCommand extends Model
                ];
                $cmd->status = 'pending';
                $cmd->user()->associate($user);
+               $cmd->bot_nick = $nick;
                $cmd->save();
        }
 
index 4e2c7d493ff5050c36fa6d0ed37dcfeb0fb0260b..ce0f75112558563f9cf7f8e7866082e50bc850e9 100644 (file)
@@ -3,7 +3,6 @@
 namespace App\TwitchBot;
 
 use App\Models\Channel;
-use App\Models\TwitchBotCommand;
 
 class TwitchAppBot extends TwitchBot {
 
@@ -52,18 +51,4 @@ class TwitchAppBot extends TwitchBot {
                }
        }
 
-
-       private function listenCommands() {
-               $this->getLoop()->addPeriodicTimer(1, function () {
-                       if (!$this->isReady()) return;
-                       $command = TwitchBotCommand::where('status', '=', 'pending')->oldest()->first();
-                       if ($command) {
-                               try {
-                                       $command->execute($this);
-                               } catch (\Exception $e) {
-                               }
-                       }
-               });
-       }
-
 }
index 79b6bf13f1861af5bde63e400992cbc060e08ae0..bb3724d6844bbf7f0990f5306fb3f04069f834a3 100644 (file)
@@ -3,6 +3,7 @@
 namespace App\TwitchBot;
 
 use App\Models\Channel;
+use App\Models\TwitchBotCommand;
 use App\Models\TwitchToken;
 use Monolog\Handler\StreamHandler;
 use Monolog\Logger;
@@ -169,6 +170,20 @@ class TwitchBot {
        }
 
 
+       protected function listenCommands() {
+               $this->getLoop()->addPeriodicTimer(1, function () {
+                       if (!$this->isReady()) return;
+                       $command = TwitchBotCommand::where('bot_nick', '=', $this->nick)->where('status', '=', 'pending')->oldest()->first();
+                       if ($command) {
+                               try {
+                                       $command->execute($this);
+                               } catch (\Exception $e) {
+                               }
+                       }
+               });
+       }
+
+
        private $logger;
 
        private $nick;
index 576bf04a9dfdcf8b938598b3d129f8b3f2869c8b..7a6eb1c1357cb9c59d12c2bfc9af81467383ae53 100644 (file)
@@ -20,6 +20,7 @@ class TwitchChatBot extends TwitchBot {
                        ];
                }
                $this->startTimer();
+               $this->listenCommands();
        }
 
        public function joinChannels() {
diff --git a/database/migrations/2024_01_21_115350_chat_bot_commands.php b/database/migrations/2024_01_21_115350_chat_bot_commands.php
new file mode 100644 (file)
index 0000000..513484c
--- /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('twitch_bot_commands', function(Blueprint $table) {
+                       $table->string('bot_nick')->default('localhorsttv');
+               });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+               Schema::table('twitch_bot_commands', function(Blueprint $table) {
+                       $table->dropColumn('bot_nick');
+               });
+    }
+};
index 1faa912fa0c95525dcc7bf1983fac4113f0243f1..cc062e8aff53805bf4a78cfa6499c4ab81915cf0 100644 (file)
@@ -13,10 +13,11 @@ const Controls = () => {
 
        const { t } = useTranslation();
 
-       const chat = React.useCallback(async text => {
+       const chat = React.useCallback(async (text, bot_nick) => {
                try {
                        await axios.post(`/api/channels/${channel.id}/chat`, {
                                text,
+                               bot_nick,
                        });
                        toastr.success(t('twitchBot.chatSuccess'));
                } catch (e) {
@@ -24,9 +25,9 @@ const Controls = () => {
                }
        }, [channel, chatText, t]);
 
-       const join = React.useCallback(async () => {
+       const join = React.useCallback(async (bot_nick) => {
                try {
-                       const rsp = await axios.post(`/api/channels/${channel.id}/join`);
+                       const rsp = await axios.post(`/api/channels/${channel.id}/join`, { bot_nick });
                        setChannel(rsp.data);
                        toastr.success(t('twitchBot.joinSuccess'));
                } catch (e) {
@@ -34,9 +35,9 @@ const Controls = () => {
                }
        }, [channel, t]);
 
-       const part = React.useCallback(async () => {
+       const part = React.useCallback(async (bot_nick) => {
                try {
-                       const rsp = await axios.post(`/api/channels/${channel.id}/part`);
+                       const rsp = await axios.post(`/api/channels/${channel.id}/part`, { bot_nick });
                        setChannel(rsp.data);
                        toastr.success(t('twitchBot.partSuccess'));
                } catch (e) {
@@ -56,24 +57,40 @@ const Controls = () => {
                                        value={channel ? channel.id : ''}
                                />
                        </Form.Group>
-                       {channel ?
-                               <Form.Group as={Col} md={6}>
-                                       <Form.Label>{t('twitchBot.join')}</Form.Label>
+                       {channel ? <>
+                               <Form.Group as={Col} md={3}>
+                                       <Form.Label>{t('twitchBot.joinApp')}</Form.Label>
                                        <div>
                                                <Form.Control
                                                        as={ToggleSwitch}
                                                        onChange={({ target: { value } }) => {
                                                                if (value) {
-                                                                       join();
+                                                                       join('localhorsttv');
                                                                } else {
-                                                                       part();
+                                                                       part('localhorsttv');
                                                                }
                                                        }}
                                                        value={channel.join}
                                                />
                                        </div>
                                </Form.Group>
-                       : null}
+                               <Form.Group as={Col} md={3}>
+                                       <Form.Label>{t('twitchBot.joinChat')}</Form.Label>
+                                       <div>
+                                               <Form.Control
+                                                       as={ToggleSwitch}
+                                                       onChange={({ target: { value } }) => {
+                                                               if (value) {
+                                                                       join('horstiebot');
+                                                               } else {
+                                                                       part('horstiebot');
+                                                               }
+                                                       }}
+                                                       value={channel.chat}
+                                               />
+                                       </div>
+                               </Form.Group>
+                       </> : null}
                </Row>
                {channel ?
                        <Row>
@@ -86,16 +103,28 @@ const Controls = () => {
                                                }}
                                                value={chatText}
                                        />
-                                       <Button
-                                               className="mt-2"
-                                               disabled={!chatText}
-                                               onClick={() => {
-                                                       if (chatText) chat(chatText);
-                                               }}
-                                               variant="twitch"
-                                       >
-                                               {t('button.send')}
-                                       </Button>
+                                       <div className="button-bar">
+                                               <Button
+                                                       className="mt-2"
+                                                       disabled={!chatText || !channel.join}
+                                                       onClick={() => {
+                                                               if (chatText) chat(chatText, 'localhorsttv');
+                                                       }}
+                                                       variant="twitch"
+                                               >
+                                                       {t('twitchBot.sendApp')}
+                                               </Button>
+                                               <Button
+                                                       className="mt-2"
+                                                       disabled={!chatText || !channel.chat}
+                                                       onClick={() => {
+                                                               if (chatText) chat(chatText, 'horstiebot');
+                                                       }}
+                                                       variant="twitch"
+                                               >
+                                                       {t('twitchBot.sendChat')}
+                                               </Button>
+                                       </div>
                                </Form.Group>
                        </Row>
                :
index 4b7e8dd5b5e65bea1fa975e879ecc0209a0ef206..bb5c08c8b0de74d72205908e0957bf42e2beb5fb 100644 (file)
@@ -487,18 +487,22 @@ export default {
                },
                twitchBot: {
                        channel: 'Channel',
-                       chat: 'Chat',
+                       chatApp: 'Chat als App Bot',
+                       chatChat: 'Chat als Chat Bot',
                        chatError: 'Fehler beim Senden',
                        chatSuccess: 'Nachricht in Warteschlange',
                        controls: 'Controls',
                        heading: 'Twitch Bot',
-                       join: 'Join',
+                       joinApp: 'Join als App Bot',
+                       joinChat: 'Join als Chat Bot',
                        joinError: 'Fehler beim Betreten',
                        joinSuccess: 'Betreten',
                        noManagePermission: 'Du verfügst nicht über die notwendigen Berechtigungen, um den Twitch Bot zu administrieren.',
                        partError: 'Fehler beim Verlassen',
                        partSuccess: 'Verlassen',
                        selectChannel: 'Bitte wählen einen Channel, den du verändern möchtest.',
+                       sendApp: 'Als App Bot senden',
+                       sendChat: 'Als Chat Bot senden',
                },
                users: {
                        discordTag: 'Discord Tag',
index 133f1dc006a46d5dc30f75a881d135bfaa195bcf..669c56e8ed81b51fd8ef4953bc9b7664d11992b4 100644 (file)
@@ -492,13 +492,16 @@ export default {
                        chatSuccess: 'Message queued',
                        controls: 'Controls',
                        heading: 'Twitch Bot',
-                       join: 'Join',
+                       joinApp: 'Join as App Bot',
+                       joinChat: 'Join as Chat Bot',
                        joinError: 'Error joining channel',
                        joinSuccess: 'Joined',
                        noManagePermission: 'You lack the required privileges to manage the twitch bot.',
                        partError: 'Error parting channel',
                        partSuccess: 'Parted',
                        selectChannel: 'Please select a channel to manage.',
+                       sendApp: 'Send as App Bot',
+                       sendChat: 'Send as Chat Bot',
                },
                users: {
                        discordTag: 'Discord tag',