]> git.localhorst.tv Git - alttp.git/blob - app/Models/ChatLog.php
f1777b804a1cb26c80cdfe8ada9ddbc07a3d7d30
[alttp.git] / app / Models / ChatLog.php
1 <?php
2
3 namespace App\Models;
4
5 use App\TwitchBot\TokenizedMessage;
6 use Illuminate\Database\Eloquent\Factories\HasFactory;
7 use Illuminate\Database\Eloquent\Model;
8 use Illuminate\Support\Arr;
9 use Illuminate\Support\Str;
10 use LanguageDetection\Language;
11
12 class ChatLog extends Model {
13
14         use HasFactory;
15
16         public function channel() {
17                 return $this->belongsTo(Channel::class);
18         }
19
20         public function user() {
21                 return $this->belongsTo(User::class);
22         }
23
24         public function tokenize() {
25                 return TokenizedMessage::fromLog($this);
26         }
27
28         public function isReply() {
29                 return !empty($this->tags['reply-parent-msg-body']);
30         }
31
32         public function getReplyParent() {
33                 return str_replace('\\s', ' ', $this->tags['reply-parent-msg-body']);
34         }
35
36         public function getReplyParentUser() {
37                 return $this->tags['reply-parent-display-name'];
38         }
39
40         public function getText() {
41                 return $this->params[1];
42         }
43
44         public function getTextWithoutEmotes() {
45                 $text = $this->params[1];
46                 if (isset($this->tags['emotes']) && !empty($this->tags['emotes'])) {
47                         $emotes = explode('/', $this->tags['emotes']);
48                         foreach ($emotes as $emote) {
49                                 $set = explode(':', $emote);
50                                 $positions = explode(',', $set[1]);
51                                 foreach ($positions as $position) {
52                                         $coords = explode('-', $position);
53                                         $text = mb_substr($text, 0, $coords[0]).str_repeat(' ', $coords[1] - $coords[0] + 1).mb_substr($text, $coords[1] + 1);
54                                 }
55                         }
56                 }
57                 return trim(preg_replace('/\s+/', ' ', $text));
58         }
59
60         public function getTextWithoutReply() {
61                 if ($this->isReply()) {
62                         return mb_substr($this->params[1], mb_strlen($this->getReplyParentUser()) + 2);
63                 }
64                 return $this->params[1];
65         }
66
67         public function evaluate() {
68                 $this->evaluateUser();
69                 $this->evaluateChannel();
70
71                 if (is_null($this->nick)) {
72                         $this->type = 'system';
73                         return;
74                 }
75                 if (in_array($this->nick, ['horstiebot', 'localhorsttv'])) {
76                         $this->type = 'self';
77                         return;
78                 }
79
80                 if ($this->command == 'PRIVMSG' || $this->command == 'WHISPER') {
81                         if (static::isKnownBot($this->nick)) {
82                                 $this->type = 'bot';
83                         } else if (substr($this->params[0], 0, 1) == '#') {
84                                 $this->type = 'chat';
85                         } else {
86                                 $this->type = 'dm';
87                         }
88                         $this->text_content = $this->getTextWithoutReply();
89                         $this->detectLanguage();
90                         $tokenized = $this->tokenize();
91                         if ($tokenized->isSpammy()) {
92                                 $this->banned = true;
93                         }
94                         $this->classification = $tokenized->classify();
95                         return;
96                 }
97
98                 throw new \Exception('unidentified message');
99         }
100
101         public static function isKnownBot($nick) {
102                 return in_array(strtolower($nick), [
103                         'a_n_i_v',
104                         'birrellthesquirrel',
105                         'creatisbot',
106                         'funtoon',
107                         'nidbot2000',
108                         'nightbot',
109                         'pokemoncommunitygame',
110                         'sery_bot',
111                         'speedgaming',
112                         'starbase47',
113                         'streamelements',
114                         'wizebot',
115                         'zockerstuebchen',
116                 ]);
117         }
118
119         protected function evaluateUser() {
120         }
121
122         protected function evaluateChannel() {
123                 if (empty($this->params)) {
124                         return;
125                 }
126                 $cname = $this->params[0];
127                 if (substr($cname, 0, 1) != '#') {
128                         $cname = '#'.$cname;
129                 }
130                 $channel = Channel::firstWhere('twitch_chat', '=', $cname);
131                 if (!is_null($channel)) {
132                         $this->channel()->associate($channel);
133                         if (empty($this->twitch_category) && now()->sub(15, 'minute')->isBefore($this->created_at)) {
134                                 $this->twitch_category = $channel->twitch_category;
135                         }
136                 }
137         }
138
139         protected function detectLanguage() {
140                 $languages = ['de', 'en', 'es', 'fr'];
141                 if (!is_null($this->channel)) {
142                         $languages = array_values($this->channel->languages);
143                         if (!in_array('en', $languages)) {
144                                 $languages[] = 'en';
145                         }
146                 }
147                 $detector = (new Language($languages))->detect($this->getTextWithoutEmotes());
148                 $scores = $detector->close();
149                 $lang = strval($detector);
150                 //var_dump($scores, $lang, $this->text_content);
151                 if (!empty($lang) && $scores[$lang] > 0.4) {
152                         $this->detected_language = $lang;
153                 }
154         }
155
156         protected $casts = [
157                 'banned' => 'boolean',
158                 'params' => 'array',
159                 'tags' => 'array',
160                 'user_id' => 'string',
161         ];
162
163         protected $fillable = [
164                 'command',
165                 'nick',
166                 'params',
167                 'tags',
168         ];
169
170 }