]> git.localhorst.tv Git - alttp.git/commitdiff
adlib chat
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 8 May 2024 13:10:27 +0000 (15:10 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 8 May 2024 13:10:27 +0000 (15:10 +0200)
app/Http/Controllers/ChannelController.php
app/Models/TwitchBotCommand.php
app/TwitchBot/TwitchChatBot.php
app/TwitchBotCommands/AdlibChatCommand.php [new file with mode: 0644]
app/TwitchBotCommands/BaseCommand.php
resources/js/components/twitch-bot/ChatSettingsForm.js
resources/js/components/twitch-bot/Controls.js
resources/js/i18n/de.js
resources/js/i18n/en.js

index 026b9aa8ce9fe18c7d0978be820fc1e911c12018..121ae4e9ce9149fc2162001128dc2943d4a9a004 100644 (file)
@@ -54,13 +54,16 @@ class ChannelController extends Controller {
                        throw new \Exception('channel has no twitch chat set');
                }
                $validatedData = $request->validate([
+                       'adlib' => 'boolean',
                        'bot_nick' => 'string',
                        'category' => 'string',
                        'text' => 'string',
                ]);
                $this->authorize('editRestream', $channel);
                $nick = empty($validatedData['bot_nick']) ? 'localhorsttv' : $validatedData['bot_nick'];
-               if (empty($validatedData['category'])) {
+               if (isset($validatedData['adlib']) && $validatedData['adlib']) {
+                       TwitchBotCommand::adlibChat($channel, $request->user());
+               } else if (empty($validatedData['category'])) {
                        TwitchBotCommand::chat($channel->twitch_chat, $validatedData['text'], $request->user(), $nick);
                } else {
                        TwitchBotCommand::randomChat($channel, $validatedData['category'], $request->user(), $nick);
@@ -83,6 +86,7 @@ class ChannelController extends Controller {
                        throw new \Exception('channel has no twitch chat set');
                }
                $validatedData = $request->validate([
+                       'adlib' => 'integer|min:0|max:100',
                        'language' => 'string|in:de,en,es,fr',
                        'min_age' => 'integer|min:1',
                        'respond' => 'string|in:50,no,yes',
index 6dc5a218087a8530103a4f998b9ed42fcc32a91e..e232bdf9a7a1aebdb079fbc7915928469ded9281 100644 (file)
@@ -11,6 +11,18 @@ class TwitchBotCommand extends Model
 {
        use HasFactory;
 
+       public static function adlibChat(Channel $channel, User $user = null) {
+               $cmd = new TwitchBotCommand();
+               $cmd->command = 'adlib-chat';
+               $cmd->parameters = [
+                       'channel' => $channel->id,
+               ];
+               $cmd->status = 'pending';
+               $cmd->user()->associate($user);
+               $cmd->bot_nick = 'horstiebot';
+               $cmd->save();
+       }
+
        public static function chat($channel, $text, User $user = null, $nick = 'localhorsttv') {
                $cmd = new TwitchBotCommand();
                $cmd->command = 'chat';
index 92894262f3b108d42826f76238dca6c909146a94..6ec517e93f62ba55926e40b5a6bfa15303a3c9a7 100644 (file)
@@ -4,6 +4,7 @@ namespace App\TwitchBot;
 
 use App\Models\Channel;
 use App\Models\ChatBotLog;
+use App\Models\ChatLib;
 use App\Models\ChatLog;
 use Illuminate\Support\Arr;
 use Illuminate\Support\Str;
@@ -15,6 +16,8 @@ class TwitchChatBot extends TwitchBot {
                $this->updateChannels();
                $this->startTimer();
                $this->listenCommands();
+               $this->chatlib = new ChatLib();
+               $this->chatlib->loadFrom('de');
        }
 
        public function joinChannels() {
@@ -43,6 +46,10 @@ class TwitchChatBot extends TwitchBot {
                $this->tagChannelRead($channel, $msg);
        }
 
+       public function getChatlibDatabase(Channel $channel) {
+               return $this->chatlib;
+       }
+
 
        private function startTimer() {
                $this->getLoop()->addPeriodicTimer(1, function () {
@@ -73,6 +80,10 @@ class TwitchChatBot extends TwitchBot {
                        return;
                }
                $text = $this->contextualMsg($channel);
+               if ($this->shouldAdlib($channel)) {
+                       $this->performAdlib($channel);
+                       return;
+               }
                if (!$text) $text = $this->randomChat($channel);
                if (!$text) return;
                $actual_text = is_object($text) ? $text->text_content : $text;
@@ -245,6 +256,18 @@ class TwitchChatBot extends TwitchBot {
                return $channel->queryChatlog()->first();
        }
 
+       private function performAdlib(Channel $channel) {
+               $db = $this->getChatlibDatabase($channel);
+               $text = $db->generate();
+               $this->tagChannelWrite($channel);
+               $this->sendIRCMessage(IRCMessage::privmsg($channel->twitch_chat, $text));
+               $log = new ChatBotLog();
+               $log->channel()->associate($channel);
+               $log->category = 'adlib';
+               $log->text = $text;
+               $log->save();
+       }
+
        private function randomWaitMsgs(Channel $channel) {
                $min = $channel->getChatSetting('wait_msgs_min', 1);
                $max = $channel->getChatSetting('wait_msgs_max', 10);
@@ -348,6 +371,17 @@ class TwitchChatBot extends TwitchBot {
                return false;
        }
 
+       private function shouldAdlib(Channel $channel) {
+               $setting = $channel->getChatSetting('adlib', 50);
+               if ($setting == 0) {
+                       return false;
+               }
+               if ($setting == 100) {
+                       return true;
+               }
+               return random_int(0, 100) <= $setting;
+       }
+
        private function shouldRespond(Channel $channel) {
                $setting = $channel->getChatSetting('respond', 'yes');
                if ($setting == 'yes') {
@@ -387,5 +421,6 @@ class TwitchChatBot extends TwitchBot {
 
        private $channels;
        private $notes = [];
+       private $chatlib;
 
 }
diff --git a/app/TwitchBotCommands/AdlibChatCommand.php b/app/TwitchBotCommands/AdlibChatCommand.php
new file mode 100644 (file)
index 0000000..8079b8c
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+namespace App\TwitchBotCommands;
+
+use App\Models\Channel;
+use App\Models\ChatBotLog;
+use App\Models\TwitchBotCommand;
+use App\TwitchBot\IRCMessage;
+use App\TwitchBot\TwitchBot;
+use React\Promise\Promise;
+
+class AdlibChatCommand extends BaseCommand {
+
+       public function __construct(TwitchBot $bot, TwitchBotCommand $cmd) {
+               parent::__construct($bot, $cmd);
+       }
+
+       public function execute() {
+               return new Promise(function($resolve) {
+                       $channel = Channel::findOrFail($this->getParameter('channel'));
+                       $db = $this->bot->getChatlibDatabase($channel);
+                       $text = $db->generate();
+                       $this->bot->sendIRCMessage(IRCMessage::privmsg($channel->twitch_chat, $text));
+                       $log = new ChatBotLog();
+                       $log->channel()->associate($channel);
+                       $log->text = $text;
+                       $log->user()->associate($this->getExecutingUser());
+                       $log->category = 'adlib';
+                       $log->save();
+                       $resolve();
+               });
+       }
+
+}
index e2df728d0eb76a59970dff23aca17ed0a13705e3..32ef41d19d5959fd3b2cca8a30cb1099906250ab 100644 (file)
@@ -10,6 +10,8 @@ abstract class BaseCommand {
 
        public static function resolve(TwitchBot $bot, TwitchBotCommand $cmd) {
                switch ($cmd->command) {
+                       case 'adlib-chat':
+                               return new AdlibChatCommand($bot, $cmd);
                        case 'chat':
                                return new ChatCommand($bot, $cmd);
                        case 'join':
index 9f6a1836afcc67a6e355276170ac05764331cdc6..24b2a0aca5146f39c4f98a8c256dc36a64925f60 100644 (file)
@@ -160,6 +160,19 @@ const ChatSettingsForm = ({
                                        </Form.Control.Feedback>
                                : null}
                        </Form.Group>
+                       <Form.Group as={Col} md={6} controlId="chatSettings.adlib">
+                               <Form.Label>{t('twitchBot.chatAdlibChance')}</Form.Label>
+                               <Form.Control
+                                       isInvalid={!!(touched.adlib && errors.adlib)}
+                                       name="adlib"
+                                       min="0"
+                                       max="100"
+                                       onBlur={handleBlur}
+                                       onChange={handleChange}
+                                       type="number"
+                                       value={values.adlib || 1}
+                               />
+                       </Form.Group>
                </Row>
                <div className="button-bar mt-3">
                        <Button disabled={!dirty || isSubmitting} type="submit" variant="primary">
@@ -172,6 +185,7 @@ const ChatSettingsForm = ({
 ChatSettingsForm.propTypes = {
        dirty: PropTypes.bool,
        errors: PropTypes.shape({
+               adlib: PropTypes.string,
                language: PropTypes.string,
                min_age: PropTypes.string,
                respond: PropTypes.string,
@@ -186,6 +200,7 @@ ChatSettingsForm.propTypes = {
        handleSubmit: PropTypes.func,
        isSubmitting: PropTypes.bool,
        touched: PropTypes.shape({
+               adlib: PropTypes.bool,
                language: PropTypes.bool,
                min_age: PropTypes.bool,
                respond: PropTypes.bool,
@@ -196,6 +211,7 @@ ChatSettingsForm.propTypes = {
                wait_time_max: PropTypes.bool,
        }),
        values: PropTypes.shape({
+               adlib: PropTypes.number,
                language: PropTypes.string,
                min_age: PropTypes.number,
                respond: PropTypes.string,
@@ -219,6 +235,7 @@ export default withFormik({
                });
        },
        mapPropsToValues: ({ channel }) => ({
+               adlib: channel.chat_settings.adlib || 50,
                language: channel.chat_settings.language || channel.languages[0] || 'de',
                min_age: channel.chat_settings.min_age || 1,
                respond: channel.chat_settings.respond || 'yes',
@@ -231,6 +248,7 @@ export default withFormik({
                        ? formatTime({ time: channel.chat_settings.wait_time_max }) : '15:00',
        }),
        validationSchema: yup.object().shape({
+               adlib: yup.number().min(0).max(100),
                language: yup.string(),
                min_age: yup.number().min(1),
                respond: yup.string(),
index f64ee62712a658da228c4ebacbc895d55931bf35..394f5464c6369ec4049d342861a287396bb468f1 100644 (file)
@@ -68,6 +68,18 @@ const Controls = () => {
                }
        }, [channel, chatText, t]);
 
+       const adlibChat = React.useCallback(async () => {
+               try {
+                       await axios.post(`/api/channels/${channel.id}/chat`, {
+                               bot_nick: 'horstiebot',
+                               adlib: true,
+                       });
+                       toastr.success(t('twitchBot.chatSuccess'));
+               } catch (e) {
+                       toastr.error(t('twitchBot.chatError'));
+               }
+       }, [channel, chatText, t]);
+
        const join = React.useCallback(async (bot_nick) => {
                try {
                        const rsp = await axios.post(`/api/channels/${channel.id}/join`, { bot_nick });
@@ -247,6 +259,16 @@ const Controls = () => {
                                                        </Button>
                                                )}
                                        </div>
+                                       <div className="mt-3">
+                                               <Button
+                                                       onClick={() => { adlibChat(); }}
+                                                       title={t('twitchBot.adlibChatDesc')}
+                                                       variant="outline-secondary"
+                                               >
+                                                       {t('twitchBot.adlibChat')}
+                                               </Button>
+                                               <p className="text-muted">{t('twitchBot.adlibChatNote')}</p>
+                                       </div>
                                </Col>
                                <Col className="mt-5" md={6}>
                                        <div className="d-flex justify-content-between">
index 85d8fcbde346993bf66f2232db621e0c1e7c5aec..f2713548ab79dbc0dca5bf7136f0e562e451bcac 100644 (file)
@@ -695,9 +695,14 @@ export default {
                },
                twitchBot: {
                        addCommand: 'Command hinzufügen',
+                       adlibChat: 'ad lib Chat',
+                       adlibChatDesc: 'Generier eine Nachricht basierend auf alten.',
+                       adlibChatNote: 'Aufgrund der benötigten Datenmenge aktuell nur in deutsch verfügbar.',
                        channel: 'Channel',
                        chat: 'Chat',
+                       chatAdlibChance: 'ad lib Chance',
                        chatCategories: {
+                               adlib: 'ad lib',
                                eyes: 'Augen',
                                gg: 'Good Game',
                                gl: 'Good Luck',
index 5d5a1e41da1925d3ec8cb89a45b1cc0aa7cfc877..8d8ccdce56b3983d5c3cf380cb04727aeef8fd09 100644 (file)
@@ -695,9 +695,14 @@ export default {
                },
                twitchBot: {
                        addCommand: 'Add command',
+                       adlibChat: 'ad lib Chat',
+                       adlibChatDesc: 'Generate a message inspired by the chatlog.',
+                       adlibChatNote: 'Due to the amount of data required currently only supported in german.',
                        channel: 'Channel',
                        chat: 'Chat',
+                       chatAdlibChance: 'ad lib chance',
                        chatCategories: {
+                               adlib: 'ad lib',
                                eyes: 'Eyes',
                                gg: 'Good Game',
                                gl: 'Good Luck',