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),
25 public function joinChannels() {
26 $this->getLogger()->info('joining channels');
28 foreach ($this->channels as $channel) {
29 $names[] = $channel->twitch_chat;
31 $chunks = array_chunk($names, 10);
32 foreach ($chunks as $chunk) {
33 $this->sendIRCMessage(IRCMessage::join($chunk));
37 public function logMessage(IRCMessage $msg) {
38 $channel = $this->getMessageChannel($msg);
39 if ($channel && !$channel->join) {
44 public function handlePrivMsg(IRCMessage $msg) {
45 if ($msg->nick == 'horstiebot') return;
46 $channel = $this->getMessageChannel($msg);
47 if (!$channel) return;
48 $this->tagChannelRead($channel);
52 private function startTimer() {
53 $this->getLoop()->addPeriodicTimer(1, function () {
54 if (!$this->isReady()) return;
55 foreach ($this->channels as $channel) {
56 $this->decideSend($channel);
61 private function decideSend(Channel $channel) {
62 $notes = $this->notes[$channel->id];
63 if ($notes['read_since_last_write'] < $notes['wait_msgs']) {
66 if (time() - $notes['last_write'] < $notes['wait_time']) {
69 if ($notes['read_since_last_write'] == $notes['wait_msgs'] && time() - $notes['last_read'] < 3) {
70 // don't immediately respond if we crossed the msg threshold last
73 $text = $this->randomMsg($channel);
75 $this->tagChannelWrite($channel);
76 $this->sendIRCMessage(IRCMessage::privmsg($channel->twitch_chat, $text));
79 private function randomMsg(Channel $channel) {
80 $line = ChatLog::where('type', '=', 'chat')
81 ->where('banned', '=', false)
82 ->where('created_at', '<', now()->sub(1, 'day'))
83 ->where(function ($query) use ($channel) {
84 $query->whereNull('detected_language');
85 $query->orWhereIn('detected_language', $channel->languages);
89 return $line->text_content;
92 private function randomWaitMsgs(Channel $channel) {
93 return random_int(1, 10);
96 private function randomWaitTime(Channel $channel) {
97 return random_int(1, 900);
100 private function tagChannelRead(Channel $channel) {
101 $this->notes[$channel->id]['last_read'] = time();
102 ++$this->notes[$channel->id]['read_since_last_write'];
105 private function tagChannelWrite(Channel $channel) {
106 $this->notes[$channel->id]['last_write'] = time();
107 $this->notes[$channel->id]['read_since_last_write'] = 0;
108 $this->notes[$channel->id]['wait_msgs'] = $this->randomWaitMsgs($channel);
109 $this->notes[$channel->id]['wait_time'] = $this->randomWaitTime($channel);