+ public function channel() {
+ return $this->belongsTo(Channel::class);
+ }
+
+ public function user() {
+ return $this->belongsTo(User::class);
+ }
+
+ public function tokenize() {
+ return TokenizedMessage::fromLog($this);
+ }
+
+ public function isReply() {
+ return !empty($this->tags['reply-parent-msg-body']);
+ }
+
+ public function getReplyParent() {
+ return str_replace('\\s', ' ', $this->tags['reply-parent-msg-body']);
+ }
+
+ public function getReplyParentUser() {
+ return $this->tags['reply-parent-display-name'];
+ }
+
+ public function getText() {
+ return $this->params[1];
+ }
+
+ public function getTextWithoutEmotes() {
+ $text = $this->params[1];
+ if (isset($this->tags['emotes']) && !empty($this->tags['emotes'])) {
+ $emotes = explode('/', $this->tags['emotes']);
+ foreach ($emotes as $emote) {
+ $set = explode(':', $emote);
+ $positions = explode(',', $set[1]);
+ foreach ($positions as $position) {
+ $coords = explode('-', $position);
+ $text = mb_substr($text, 0, $coords[0]).str_repeat(' ', $coords[1] - $coords[0] + 1).mb_substr($text, $coords[1] + 1);
+ }
+ }
+ }
+ return trim(preg_replace('/\s+/', ' ', $text));
+ }
+
+ public function getTextWithoutReply() {
+ if ($this->isReply()) {
+ return mb_substr($this->params[1], mb_strlen($this->getReplyParentUser()) + 2);
+ }
+ return $this->params[1];
+ }
+
+ public function evaluate() {
+ $this->evaluateUser();
+ $this->evaluateChannel();
+
+ if (is_null($this->nick)) {
+ $this->type = 'system';
+ return;
+ }
+ if (in_array($this->nick, ['horstiebot', 'localhorsttv'])) {
+ $this->type = 'self';
+ return;
+ }
+ if (!empty($this->params) && $this->params[0] == '#'.$this->nick) {
+ $this->type = 'owner';
+ return;
+ }
+
+ if ($this->command == 'PRIVMSG' || $this->command == 'WHISPER') {
+ if (static::isKnownBot($this->nick)) {
+ $this->type = 'bot';
+ } else if (substr($this->params[0], 0, 1) == '#') {
+ $this->type = 'chat';
+ } else {
+ $this->type = 'dm';
+ }
+ $this->text_content = $this->getTextWithoutReply();
+ $this->detectLanguage();
+ $tokenized = $this->tokenize();
+ if ($tokenized->isSpammy()) {
+ $this->banned = true;
+ }
+ $this->emote_only = $tokenized->isEmoteOnly();
+ $this->classification = $tokenized->classify();
+ return;
+ }
+
+ throw new \Exception('unidentified message');
+ }
+
+ public static function isKnownBot($nick) {
+ return in_array(strtolower($nick), [
+ 'a_n_i_v',
+ 'birrellthesquirrel',
+ 'creatisbot',
+ 'funtoon',
+ 'nidbot2000',
+ 'nightbot',
+ 'pokemoncommunitygame',
+ 'sery_bot',
+ 'speedgaming',
+ 'starbase47',
+ 'streamelements',
+ 'wizebot',
+ 'zockerstuebchen',
+ ]);
+ }
+
+ protected function evaluateUser() {
+ }
+
+ protected function evaluateChannel() {
+ if (empty($this->params)) {
+ return;
+ }
+ $cname = $this->params[0];
+ if (substr($cname, 0, 1) != '#') {
+ $cname = '#'.$cname;
+ }
+ $channel = Channel::firstWhere('twitch_chat', '=', $cname);
+ if (!is_null($channel)) {
+ $this->channel()->associate($channel);
+ if (empty($this->twitch_category) && now()->sub(15, 'minute')->isBefore($this->created_at)) {
+ $this->twitch_category = $channel->twitch_category;
+ }
+ }
+ }
+
+ protected function detectLanguage() {
+ $languages = ['de', 'en', 'es', 'fr'];
+ if (!is_null($this->channel)) {
+ $languages = array_values($this->channel->languages);
+ if (!in_array('en', $languages)) {
+ $languages[] = 'en';
+ }
+ }
+ $detector = (new Language($languages))->detect($this->getTextWithoutEmotes());
+ $scores = $detector->close();
+ $lang = strval($detector);
+ //var_dump($scores, $lang, $this->text_content);
+ if (!empty($lang) && $scores[$lang] > 0.4) {
+ $this->detected_language = $lang;
+ }
+ }
+