X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=app%2FTwitchBot%2FTwitchChatBot.php;h=a403b0b57b716ae488c1056e8f3e6d8be53573f8;hb=1b9629ce7f600b4aa9c9d51a281e514031871828;hp=8aac9d70bd66652eee0edad17161007732ad0586;hpb=cb9234cb76d8f7509e9280b8cd7d63180acf2ba0;p=alttp.git diff --git a/app/TwitchBot/TwitchChatBot.php b/app/TwitchBot/TwitchChatBot.php index 8aac9d7..a403b0b 100644 --- a/app/TwitchBot/TwitchChatBot.php +++ b/app/TwitchBot/TwitchChatBot.php @@ -3,6 +3,7 @@ namespace App\TwitchBot; use App\Models\Channel; +use App\Models\ChatBotLog; use App\Models\ChatLog; use Illuminate\Support\Arr; use Illuminate\Support\Str; @@ -72,26 +73,28 @@ class TwitchChatBot extends TwitchBot { return; } $text = $this->contextualMsg($channel); - if (!$text) $text = $this->randomMsg($channel); + if (!$text) $text = $this->randomChat($channel); if (!$text) return; + $actual_text = is_object($text) ? $text->text_content : $text; $this->tagChannelWrite($channel); - $this->sendIRCMessage(IRCMessage::privmsg($channel->twitch_chat, $text)); - } - - private function getChatSetting(Channel $channel, $name, $default = null) { - if (array_key_exists($name, $channel->chat_settings)) { - return $channel->chat_settings[$name]; + $this->sendIRCMessage(IRCMessage::privmsg($channel->twitch_chat, $actual_text)); + $log = new ChatBotLog(); + $log->channel()->associate($channel); + if (is_object($text)) { + $log->origin()->associate($text); } - return $default; + $log->text = $actual_text; + $log->save(); } private function getNotes(Channel $channel) { if (!isset($this->notes[$channel->id])) { $this->notes[$channel->id] = [ 'last_read' => 0, - 'last_special' => '', + 'last_special' => [], 'last_write' => time(), 'latest_msgs' => [], + 'queued_special' => false, 'read_since_last_write' => 0, 'wait_msgs' => $this->randomWaitMsgs($channel), 'wait_time' => $this->randomWaitTime($channel), @@ -113,134 +116,92 @@ class TwitchChatBot extends TwitchBot { $this->notes[$channel->id][$name] = $value; } - private function checkForGG(Channel $channel) { - $notes = $this->getNotes($channel); - $ggs = 0; - foreach ($notes['latest_msgs'] as $text) { - if (ChatLog::classify($text) == 'gg') { - ++$ggs; - } - } - return $ggs > 2; - } - - private function checkForGLHF(Channel $channel) { + private function collectClassifications(Channel $channel) { + $classifications = []; $notes = $this->getNotes($channel); - $gls = 0; - foreach ($notes['latest_msgs'] as $text) { - if (ChatLog::classify($text) == 'gl') { - ++$gls; + foreach ($notes['latest_msgs'] as $msg) { + $classification = $msg->classify(); + if ($classification == 'unclassified') continue; + if (isset($classifications[$classification])) { + ++$classifications[$classification]; + } else { + $classifications[$classification] = 1; } } - return $gls > 2; + arsort($classifications); + return $classifications; } - private function checkForGreeting(Channel $channel) { - $notes = $this->getNotes($channel); - $his = 0; - foreach ($notes['latest_msgs'] as $text) { - if (ChatLog::classify($text) == 'hi') { - ++$his; + private function contextualMsg(Channel $channel) { + if ($this->hasQueuedSpecial($channel)) { + $classification = $this->getQueuedSpecial($channel); + if (is_string($classification)) { + $this->tagChannelSpecialSent($channel, $classification); } - } - return $his > 2; - } - - private function checkForHype(Channel $channel) { - $notes = $this->getNotes($channel); - $hypes = 0; - foreach ($notes['latest_msgs'] as $text) { - if (ChatLog::classify($text) == 'hype') { - ++$hypes; + $this->clearQueuedSpecial($channel); + if ($classification == 'number') { + return $this->randomContextualNumber($channel); } - } - return $hypes > 2; - } - - private function checkForLaughter(Channel $channel) { - $notes = $this->getNotes($channel); - $lulz = 0; - foreach ($notes['latest_msgs'] as $text) { - if (ChatLog::classify($text) == 'lol') { - ++$lulz; + if ($classification == 'lol') { + return $this->randomLaughter($channel); } + return $channel->randomOfClass($classification); } - return $lulz > 2; - } - - private function checkForNumbers(Channel $channel) { - $notes = $this->getNotes($channel); - $numbers = 0; - foreach ($notes['latest_msgs'] as $text) { - if (is_numeric(trim($text))) { - ++$numbers; + $last = $this->getLastSpecialSent($channel); + $classifications = $this->collectClassifications($channel); + $count_quotas = [ + 'gg' => 2, + 'gl' => 2, + 'hi' => 2, + 'hype' => 2, + 'lol' => 2, + 'love' => 2, + 'number' => 2, + 'pog' => 2, + 'o7' => 2, + 'wtf' => 2, + ]; + $time_quotas = [ + 'gg' => 600, + 'gl' => 900, + 'hi' => 60, + 'hype' => 60, + 'lol' => 60, + 'love' => 60, + 'number' => 300, + 'pog' => 60, + 'o7' => 300, + 'wtf' => 60, + ]; + foreach ($classifications as $classification => $count) { + if ($classification == $last) continue; + if (!isset($count_quotas[$classification]) || $count < $count_quotas[$classification]) continue; + if (!isset($time_quotas[$classification]) || $this->getTimeSinceSpecial($channel, $classification) < $time_quotas[$classification]) continue; + $this->tagChannelSpecialSent($channel, $classification); + if ($classification == 'number') { + return $this->randomContextualNumber($channel); } - } - return $numbers > 2; - } - - private function checkForPog(Channel $channel) { - $notes = $this->getNotes($channel); - $pogs = 0; - foreach ($notes['latest_msgs'] as $text) { - if (ChatLog::classify($text) == 'pog') { - ++$pogs; + if ($classification == 'lol') { + return $this->randomLaughter($channel); } - } - return $pogs > 2; - } - - private function contextualMsg(Channel $channel) { - $last = $this->getNote($channel, 'last_special'); - if ($last != 'gg' && $this->checkForGG($channel)) { - $this->setNote($channel, 'last_special', 'gg'); - return $this->randomOfClass($channel, 'gg'); - } - if ($last != 'number' && $this->checkForNumbers($channel)) { - $this->setNote($channel, 'last_special', 'number'); - return $this->randomContextualNumber($channel); - } - if ($last != 'lol' && $this->checkForLaughter($channel)) { - $this->setNote($channel, 'last_special', 'lol'); - return $this->randomLaughter($channel); - } - if ($last != 'glhf' && $this->checkForGLHF($channel)) { - $this->setNote($channel, 'last_special', 'glhf'); - return $this->randomOfClass($channel, 'gl'); - } - if ($last != 'hi' && $this->checkForGreeting($channel)) { - $this->setNote($channel, 'last_special', 'hi'); - return $this->randomOfClass($channel, 'hi'); - } - if ($last != 'hype' && $this->checkForHype($channel)) { - $this->setNote($channel, 'last_special', 'hype'); - return $this->randomOfClass($channel, 'hype'); - } - if ($last != 'pog' && $this->checkForPog($channel)) { - $this->setNote($channel, 'last_special', 'pog'); - return $this->randomOfClass($channel, 'pog'); + return $channel->randomOfClass($classification); } return false; } - private function queryChatlog(Channel $channel) { - return ChatLog::where('type', '=', 'chat') - ->where('banned', '=', false) - ->where('created_at', '<', now()->sub(1, 'day')) - ->where(function ($query) use ($channel) { - $query->whereNull('detected_language'); - $query->orWhereIn('detected_language', $channel->languages); - }) - ->inRandomOrder(); + private function randomChat(Channel $channel) { + return $channel->queryChatlog() + ->whereNotIn('classification', ['gg', 'gl', 'number', 'o7']) + ->first(); } private function randomContextualNumber(Channel $channel) { $notes = $this->getNotes($channel); $min = 100000; $max = 0; - foreach ($notes['latest_msgs'] as $text) { - if (is_numeric(trim($text))) { - $number = intval(trim($text)); + foreach ($notes['latest_msgs'] as $msg) { + if ($msg->classify() == 'number') { + $number = $msg->getNumericValue(); $min = min($min, $number); $max = max($max, $number); } @@ -248,14 +209,10 @@ class TwitchChatBot extends TwitchBot { return random_int($min, $max); } - private function randomOfClass(Channel $channel, $class) { - $line = $this->queryChatlog($channel) - ->where('classification', '=', $class) - ->first(); - return $line->text_content; - } - private function randomLaughter(Channel $channel) { + if (!random_int(0, 2)) { + return $channel->randomOfClass('lol'); + } return Arr::random([ ':tf:', '4Head', @@ -266,7 +223,6 @@ class TwitchChatBot extends TwitchBot { 'GunRun', 'heh', 'Hhhehehe', - 'HypeLUL', 'Jebaited', 'Jebasted', 'KEKW', @@ -285,34 +241,63 @@ class TwitchChatBot extends TwitchBot { 'SUBprise', 'xD', 'YouDontSay', - $this->randomOfClass($channel, 'lol'), ]); } private function randomMsg(Channel $channel) { - $line = $this->queryChatlog($channel)->first(); - return $line->text_content; + return $channel->queryChatlog()->first(); } private function randomWaitMsgs(Channel $channel) { - $min = $this->getChatSetting($channel, 'wait_msgs_min', 1); - $max = $this->getChatSetting($channel, 'wait_msgs_max', 10); + $min = $channel->getChatSetting('wait_msgs_min', 1); + $max = $channel->getChatSetting('wait_msgs_max', 10); return random_int($min, $max); } private function randomWaitTime(Channel $channel) { - $min = $this->getChatSetting($channel, 'wait_time_min', 1); - $max = $this->getChatSetting($channel, 'wait_time_max', 900); + $min = $channel->getChatSetting('wait_time_min', 1); + $max = $channel->getChatSetting('wait_time_max', 900); return random_int($min, $max); } + private function queueSpecial(Channel $channel, $classification) { + $this->getNotes($channel); + $this->notes[$channel->id]['queued_special'] = $classification; + } + + private function hasQueuedSpecial(Channel $channel) { + return !!$this->getQueuedSpecial($channel); + } + + private function getQueuedSpecial(Channel $channel) { + $notes = $this->getNotes($channel); + return $notes['queued_special']; + } + + private function clearQueuedSpecial(Channel $channel) { + $this->getNotes($channel); + $this->notes[$channel->id]['queued_special'] = false; + } + private function tagChannelRead(Channel $channel, IRCMessage $msg) { $this->getNotes($channel); $this->notes[$channel->id]['last_read'] = time(); ++$this->notes[$channel->id]['read_since_last_write']; - $this->notes[$channel->id]['latest_msgs'][] = $msg->getText(); - if (count($this->notes[$channel->id]['latest_msgs']) > 10) { - array_shift($this->notes[$channel->id]['latest_msgs']); + + $tokenized = $msg->tokenize(); + if (!ChatLog::isKnownBot($msg->nick) && !$tokenized->isSpammy()) { + $this->notes[$channel->id]['latest_msgs'][] = $tokenized; + if (count($this->notes[$channel->id]['latest_msgs']) > 10) { + array_shift($this->notes[$channel->id]['latest_msgs']); + } + } + if ($this->isDirectedAtMe($msg->getText()) && $this->shouldRespond($channel)) { + $this->notes[$channel->id]['wait_msgs'] = 0; + $this->notes[$channel->id]['wait_time'] = 0; + $response = $this->getResponseTo($tokenized); + if ($response) { + $this->queueSpecial($channel, $response); + } } } @@ -324,6 +309,73 @@ class TwitchChatBot extends TwitchBot { $this->notes[$channel->id]['wait_time'] = $this->randomWaitTime($channel); } + private function tagChannelSpecialSent(Channel $channel, $classification) { + $this->getNotes($channel); + $this->notes[$channel->id]['last_special'][$classification] = time(); + } + + private function getLastSpecialSent(Channel $channel) { + $notes = $this->getNotes($channel); + $max_time = 0; + $max_classification = ''; + foreach ($notes['last_special'] as $classification => $time) { + if ($time > $max_time) { + $max_time = $time; + $max_classification = $classification; + } + } + return $max_classification; + } + + private function getTimeSinceSpecial(Channel $channel, $classification) { + $notes = $this->getNotes($channel); + if (isset($notes['last_special'][$classification])) { + return time() - $notes['last_special'][$classification]; + } + return 999999; + } + + private function isDirectedAtMe($raw_text) { + $text = strtolower($raw_text); + if (strpos($text, 'horsti') !== false) { + return true; + } + return false; + } + + private function shouldRespond(Channel $channel) { + $setting = $channel->getChatSetting('respond', 'yes'); + if ($setting == 'yes') { + return true; + } + if ($setting == '50') { + return random_int(0, 1); + } + return false; + } + + private function getResponseTo(TokenizedMessage $msg) { + switch ($msg->classify()) { + case 'gg': + return ['love', 'eyes', 'thx', 'pog', 'kappa']; + case 'gl': + return ['love', 'eyes', 'thx']; + case 'hi': + return ['hi', 'love', 'eyes', 'hype', 'pog']; + case 'kappa': + return ['kappa', 'lol', 'eyes']; + case 'love': + return ['hi', 'love', 'eyes', 'thx']; + case 'question': + return ['yes', 'no', 'kappa', 'lol', 'wtf', 'number']; + case 'rage': + return ['kappa', 'lol', 'rage']; + case 'wtf': + return ['kappa', 'lol', 'rage']; + } + return false; + } + private $channels; private $notes = [];