3 namespace App\TwitchBot;
5 use App\Models\Channel;
6 use App\Models\ChatLog;
8 class TwitchChatBot extends TwitchBot {
10 public function __construct() {
11 parent::__construct('horstiebot');
12 $this->channels = Channel::where('twitch_chat', '!=', '')->where('chat', '=', true)->get();
13 foreach ($this->channels as $channel) {
14 $this->notes[$channel->id] = [
16 'last_write' => time(),
17 'read_since_last_write' => 0,
18 'wait_msgs' => $this->randomWaitMsgs($channel),
19 'wait_time' => $this->randomWaitTime($channel),
23 $this->listenCommands();
26 public function joinChannels() {
27 $this->getLogger()->info('joining channels');
29 foreach ($this->channels as $channel) {
30 $names[] = $channel->twitch_chat;
32 $chunks = array_chunk($names, 10);
33 foreach ($chunks as $chunk) {
34 $this->sendIRCMessage(IRCMessage::join($chunk));
38 public function logMessage(IRCMessage $msg) {
39 $channel = $this->getMessageChannel($msg);
40 if ($channel && !$channel->join) {
45 public function handlePrivMsg(IRCMessage $msg) {
46 if ($msg->nick == 'horstiebot') return;
47 $channel = $this->getMessageChannel($msg);
48 if (!$channel) return;
49 $this->tagChannelRead($channel);
53 private function startTimer() {
54 $this->getLoop()->addPeriodicTimer(1, function () {
55 if (!$this->isReady()) return;
56 foreach ($this->channels as $channel) {
57 $this->decideSend($channel);
62 private function decideSend(Channel $channel) {
63 $notes = $this->notes[$channel->id];
64 if ($notes['read_since_last_write'] < $notes['wait_msgs']) {
67 if (time() - $notes['last_write'] < $notes['wait_time']) {
70 if ($notes['read_since_last_write'] == $notes['wait_msgs'] && time() - $notes['last_read'] < 3) {
71 // don't immediately respond if we crossed the msg threshold last
74 $text = $this->randomMsg($channel);
76 $this->tagChannelWrite($channel);
77 $this->sendIRCMessage(IRCMessage::privmsg($channel->twitch_chat, $text));
80 private function randomMsg(Channel $channel) {
81 $line = ChatLog::where('type', '=', 'chat')
82 ->where('banned', '=', false)
83 ->where('created_at', '<', now()->sub(1, 'day'))
84 ->where(function ($query) use ($channel) {
85 $query->whereNull('detected_language');
86 $query->orWhereIn('detected_language', $channel->languages);
90 return $line->text_content;
93 private function randomWaitMsgs(Channel $channel) {
94 return random_int(1, 10);
97 private function randomWaitTime(Channel $channel) {
98 return random_int(1, 900);
101 private function tagChannelRead(Channel $channel) {
102 $this->notes[$channel->id]['last_read'] = time();
103 ++$this->notes[$channel->id]['read_since_last_write'];
106 private function tagChannelWrite(Channel $channel) {
107 $this->notes[$channel->id]['last_write'] = time();
108 $this->notes[$channel->id]['read_since_last_write'] = 0;
109 $this->notes[$channel->id]['wait_msgs'] = $this->randomWaitMsgs($channel);
110 $this->notes[$channel->id]['wait_time'] = $this->randomWaitTime($channel);