]> git.localhorst.tv Git - alttp.git/blob - app/TwitchBot/TwitchChatBot.php
chat bot settings
[alttp.git] / app / TwitchBot / TwitchChatBot.php
1 <?php
2
3 namespace App\TwitchBot;
4
5 use App\Models\Channel;
6 use App\Models\ChatLog;
7
8 class TwitchChatBot extends TwitchBot {
9
10         public function __construct() {
11                 parent::__construct('horstiebot');
12                 $this->updateChannels();
13                 $this->startTimer();
14                 $this->listenCommands();
15         }
16
17         public function joinChannels() {
18                 $this->getLogger()->info('joining channels');
19                 $names = [];
20                 foreach ($this->channels as $channel) {
21                         $names[] = $channel->twitch_chat;
22                 }
23                 $chunks = array_chunk($names, 10);
24                 foreach ($chunks as $chunk) {
25                         $this->sendIRCMessage(IRCMessage::join($chunk));
26                 }
27         }
28
29         public function logMessage(IRCMessage $msg) {
30                 $channel = $this->getMessageChannel($msg);
31                 if ($channel && !$channel->join) {
32                         $msg->log();
33                 }
34         }
35
36         public function handlePrivMsg(IRCMessage $msg) {
37                 if ($msg->nick == 'horstiebot') return;
38                 $channel = $this->getMessageChannel($msg);
39                 if (!$channel) return;
40                 $this->tagChannelRead($channel);
41         }
42
43
44         private function startTimer() {
45                 $this->getLoop()->addPeriodicTimer(1, function () {
46                         if (!$this->isReady()) return;
47                         foreach ($this->channels as $channel) {
48                                 $this->decideSend($channel);
49                         }
50                 });
51                 $this->getLoop()->addPeriodicTimer(60, function () {
52                         $this->updateChannels();
53                 });
54         }
55
56         private function updateChannels() {
57                 $this->channels = Channel::where('twitch_chat', '!=', '')->where('chat', '=', true)->get();
58         }
59
60         private function decideSend(Channel $channel) {
61                 $notes = $this->getNotes($channel);
62                 if ($notes['read_since_last_write'] < $notes['wait_msgs']) {
63                         return;
64                 }
65                 if (time() - $notes['last_write'] < $notes['wait_time']) {
66                         return;
67                 }
68                 if ($notes['read_since_last_write'] == $notes['wait_msgs'] && time() - $notes['last_read'] < 3) {
69                         // don't immediately respond if we crossed the msg threshold last
70                         return;
71                 }
72                 $text = $this->randomMsg($channel);
73                 if (!$text) return;
74                 $this->tagChannelWrite($channel);
75                 $this->sendIRCMessage(IRCMessage::privmsg($channel->twitch_chat, $text));
76         }
77
78         private function getChatSetting(Channel $channel, $name, $default = null) {
79                 if (array_key_exists($name, $channel->chat_settings)) {
80                         return $channel->chat_settings[$name];
81                 }
82                 return $default;
83         }
84
85         private function getNotes(Channel $channel) {
86                 if (!isset($this->notes[$channel->id])) {
87                         $this->notes[$channel->id] = [
88                                 'last_read' => 0,
89                                 'last_write' => time(),
90                                 'read_since_last_write' => 0,
91                                 'wait_msgs' => $this->randomWaitMsgs($channel),
92                                 'wait_time' => $this->randomWaitTime($channel),
93                         ];
94                 }
95                 return $this->notes[$channel->id];
96         }
97
98         private function randomMsg(Channel $channel) {
99                 $line = ChatLog::where('type', '=', 'chat')
100                         ->where('banned', '=', false)
101                         ->where('created_at', '<', now()->sub(1, 'day'))
102                         ->where(function ($query) use ($channel) {
103                                 $query->whereNull('detected_language');
104                                 $query->orWhereIn('detected_language', $channel->languages);
105                         })
106                         ->inRandomOrder()
107                         ->first();
108                 return $line->text_content;
109         }
110
111         private function randomWaitMsgs(Channel $channel) {
112                 $min = $this->getChatSetting($channel, 'wait_msgs_min', 1);
113                 $max = $this->getChatSetting($channel, 'wait_msgs_max', 10);
114                 return random_int($min, $max);
115         }
116
117         private function randomWaitTime(Channel $channel) {
118                 $min = $this->getChatSetting($channel, 'wait_time_min', 1);
119                 $max = $this->getChatSetting($channel, 'wait_time_max', 900);
120                 return random_int($min, $max);
121         }
122
123         private function tagChannelRead(Channel $channel) {
124                 $this->getNotes($channel);
125                 $this->notes[$channel->id]['last_read'] = time();
126                 ++$this->notes[$channel->id]['read_since_last_write'];
127         }
128
129         private function tagChannelWrite(Channel $channel) {
130                 $this->getNotes($channel);
131                 $this->notes[$channel->id]['last_write'] = time();
132                 $this->notes[$channel->id]['read_since_last_write'] = 0;
133                 $this->notes[$channel->id]['wait_msgs'] = $this->randomWaitMsgs($channel);
134                 $this->notes[$channel->id]['wait_time'] = $this->randomWaitTime($channel);
135         }
136
137         private $channels;
138         private $notes = [];
139
140 }