From 8645b77ea2dc402f0265e1c8022ba18302506ca1 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sun, 14 Apr 2024 14:12:31 +0200 Subject: [PATCH] log who sent manual random chats --- app/Http/Controllers/ChannelController.php | 2 +- app/Models/ChatBotLog.php | 4 +++ app/TwitchBot/TwitchChatBot.php | 3 ++ app/TwitchBotCommands/BaseCommand.php | 4 +++ app/TwitchBotCommands/RandomChatCommand.php | 7 ++-- .../2024_04_14_112456_better_chat_bot_log.php | 30 ++++++++++++++++ resources/js/components/chat-bot-logs/Item.js | 34 ++++++++++++++---- resources/js/helpers/User.js | 30 ++++++++-------- resources/js/i18n/de.js | 7 +++- resources/js/i18n/en.js | 7 +++- tests/js/helpers/User.test.js | 36 +++++++++++++++++++ 11 files changed, 137 insertions(+), 27 deletions(-) create mode 100644 database/migrations/2024_04_14_112456_better_chat_bot_log.php create mode 100644 tests/js/helpers/User.test.js diff --git a/app/Http/Controllers/ChannelController.php b/app/Http/Controllers/ChannelController.php index 15213b4..f9cf0d2 100644 --- a/app/Http/Controllers/ChannelController.php +++ b/app/Http/Controllers/ChannelController.php @@ -71,7 +71,7 @@ class ChannelController extends Controller { public function chatBotLog(Request $request, Channel $channel) { $this->authorize('editRestream', $channel); $log = $channel->chat_bot_logs() - ->with('origin') + ->with(['origin', 'user']) ->orderBy('created_at', 'DESC') ->limit(150) ->get(); diff --git a/app/Models/ChatBotLog.php b/app/Models/ChatBotLog.php index 34d2feb..a4f1f93 100644 --- a/app/Models/ChatBotLog.php +++ b/app/Models/ChatBotLog.php @@ -17,4 +17,8 @@ class ChatBotLog extends Model { return $this->morphTo(); } + public function user() { + return $this->belongsTo(User::class); + } + } diff --git a/app/TwitchBot/TwitchChatBot.php b/app/TwitchBot/TwitchChatBot.php index 442173d..9289426 100644 --- a/app/TwitchBot/TwitchChatBot.php +++ b/app/TwitchBot/TwitchChatBot.php @@ -82,6 +82,9 @@ class TwitchChatBot extends TwitchBot { $log->channel()->associate($channel); if (is_object($text)) { $log->origin()->associate($text); + $log->category = $text->classification; + } else { + $log->category = $this->getLastSpecialSent($channel); } $log->text = $actual_text; $log->save(); diff --git a/app/TwitchBotCommands/BaseCommand.php b/app/TwitchBotCommands/BaseCommand.php index d803fb7..e2df728 100644 --- a/app/TwitchBotCommands/BaseCommand.php +++ b/app/TwitchBotCommands/BaseCommand.php @@ -44,6 +44,10 @@ abstract class BaseCommand { return User::findOrFail($this->getParameter('user')); } + protected function getExecutingUser() { + return $this->command->user; + } + protected function hasParameter($name) { return array_key_exists($name, $this->command->parameters); } diff --git a/app/TwitchBotCommands/RandomChatCommand.php b/app/TwitchBotCommands/RandomChatCommand.php index cc49c00..f3ee928 100644 --- a/app/TwitchBotCommands/RandomChatCommand.php +++ b/app/TwitchBotCommands/RandomChatCommand.php @@ -19,13 +19,16 @@ class RandomChatCommand extends BaseCommand { return new Promise(function($resolve) { $channel = Channel::findOrFail($this->getParameter('channel')); $text = $channel->randomOfClass($this->getParameter('category')); - $this->bot->sendIRCMessage(IRCMessage::privmsg($channel->twitch_chat, $text->text_content)); + $actual_text = is_object($text) ? $text->text_content : $text; + $this->bot->sendIRCMessage(IRCMessage::privmsg($channel->twitch_chat, $actual_text)); $log = new ChatBotLog(); $log->channel()->associate($channel); if (is_object($text)) { $log->origin()->associate($text); } - $log->text = $text->text_content; + $log->text = $actual_text; + $log->user()->associate($this->getExecutingUser()); + $log->category = $this->getParameter('category'); $log->save(); $resolve(); }); diff --git a/database/migrations/2024_04_14_112456_better_chat_bot_log.php b/database/migrations/2024_04_14_112456_better_chat_bot_log.php new file mode 100644 index 0000000..6f0326f --- /dev/null +++ b/database/migrations/2024_04_14_112456_better_chat_bot_log.php @@ -0,0 +1,30 @@ +foreignId('user_id')->nullable()->default(null)->constrained(); + $table->string('category')->default(''); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('chat_bot_logs', function (Blueprint $table) { + $table->dropColumn('user_id'); + $table->dropColumn('category'); + }); + } +}; diff --git a/resources/js/components/chat-bot-logs/Item.js b/resources/js/components/chat-bot-logs/Item.js index 8340e4e..f50d078 100644 --- a/resources/js/components/chat-bot-logs/Item.js +++ b/resources/js/components/chat-bot-logs/Item.js @@ -4,12 +4,9 @@ import React from 'react'; import { ListGroup } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -const getEntryDate = entry => { - const dateStr = moment(entry.created_at).fromNow(); - return entry.user - ? `${entry.user.username} ${dateStr}` - : dateStr; -}; +import { getUserName } from '../../helpers/User'; + +const getEntryDate = entry => moment(entry.created_at).fromNow(); const getEntryOrigin = (entry, t) => { return t('chatBotLog.origin.chatLog', { @@ -19,6 +16,29 @@ const getEntryOrigin = (entry, t) => { }); }; +const getEntryInfo = (entry, t) => { + if (entry.user && entry.category) { + return t('chatBotLog.info.userCat', { + category: t(`twitchBot.chatCategories.${entry.category}`), + date: getEntryDate(entry), + user: getUserName(entry.user), + }); + } + if (entry.category) { + return t('chatBotLog.info.cat', { + category: t(`twitchBot.chatCategories.${entry.category}`), + date: getEntryDate(entry), + }); + } + if (entry.user) { + return t('chatBotLog.info.user', { + date: getEntryDate(entry), + user: getUserName(entry.user), + }); + } + return getEntryDate(entry); +}; + const Item = ({ entry }) => { const { t } = useTranslation(); @@ -38,7 +58,7 @@ const Item = ({ entry }) => { className="text-muted" title={moment(entry.created_at).format('LLLL')} > - {getEntryDate(entry)} + {getEntryInfo(entry, t)} ; diff --git a/resources/js/helpers/User.js b/resources/js/helpers/User.js index 0705bed..b00c853 100644 --- a/resources/js/helpers/User.js +++ b/resources/js/helpers/User.js @@ -1,3 +1,18 @@ +export const getUserName = user => (user && + (user.nickname || user.discord_nickname || user.username)) || ''; + +export const compareUsername = (a, b) => { + const a_name = getUserName(a); + const b_name = getUserName(b); + return a_name.localeCompare(b_name); +}; + +export const findResult = (user, round) => { + if (!user || !user.id) return null; + if (!round || !round.results || !round.results.length) return null; + return round.results.find(result => result.user_id == user.id); +}; + export const compareFinished = round => (a, b) => { const a_result = findResult(a, round); const b_result = findResult(b, round); @@ -34,18 +49,6 @@ export const compareResult = round => (a, b) => { return compareUsername(a, b); }; -export const compareUsername = (a, b) => { - const a_name = getUserName(a); - const b_name = getUserName(b); - return a_name.localeCompare(b_name); -}; - -export const findResult = (user, round) => { - if (!user || !user.id) return null; - if (!round || !round.results || !round.results.length) return null; - return round.results.find(result => result.user_id == user.id); -}; - export const getAvatarUrl = user => { if (user && user.avatar) { if (user.avatar_cached) { @@ -56,9 +59,6 @@ export const getAvatarUrl = user => { return '/default-avatar.png'; }; -export const getUserName = user => (user && - (user.nickname || user.discord_nickname || user.username)) || ''; - export const hasFinishedRound = (user, round) => { const result = findResult(user, round); return result && result.has_finished; diff --git a/resources/js/i18n/de.js b/resources/js/i18n/de.js index 14f18fa..21275f0 100644 --- a/resources/js/i18n/de.js +++ b/resources/js/i18n/de.js @@ -100,8 +100,13 @@ export default { chatBotLog: { empty: 'Noch keine Nachrichten erfasst', heading: 'Chat Bot Protokoll', + info: { + cat: '{{ category }} {{ date }}', + user: '{{ user }} {{ date }}', + userCat: '{{ category }} von {{ user }} {{ date }}', + }, origin: { - chatLog: '{{ nick }} in {{ channel }} am {{ date, L LT }}', + chatLog: 'Quelle: {{ nick }} in {{ channel }} am {{ date, L LT }}', }, }, content: { diff --git a/resources/js/i18n/en.js b/resources/js/i18n/en.js index f696504..2645cc9 100644 --- a/resources/js/i18n/en.js +++ b/resources/js/i18n/en.js @@ -100,8 +100,13 @@ export default { chatBotLog: { empty: 'No messages on protocol yet', heading: 'Chat Bot Log', + info: { + cat: '{{ category }} {{ date }}', + user: '{{ user }} {{ date }}', + userCat: '{{ category }} from {{ user }} {{ date }}', + }, origin: { - chatLog: '{{ nick }} in {{ channel }} on {{ date, L LT }}', + chatLog: 'Source: {{ nick }} in {{ channel }} on {{ date, L LT }}', }, }, content: { diff --git a/tests/js/helpers/User.test.js b/tests/js/helpers/User.test.js new file mode 100644 index 0000000..86233f8 --- /dev/null +++ b/tests/js/helpers/User.test.js @@ -0,0 +1,36 @@ +import { + getUserName, +} from 'helpers/User'; + +describe('getUserName', () => { + test('empty on missing user', () => { + expect(getUserName()).toEqual(''); + }); + test('nickname if available', () => { + expect(getUserName({ + nickname: 'Holy', + })).toEqual('Holy'); + expect(getUserName({ + nickname: 'Holy', + discord_nickname: 'HolySmoke', + })).toEqual('Holy'); + expect(getUserName({ + nickname: 'Holy', + username: 'holysmoke86', + })).toEqual('Holy'); + }); + test('discord_nickname if no nickname', () => { + expect(getUserName({ + discord_nickname: 'HolySmoke', + })).toEqual('HolySmoke'); + expect(getUserName({ + discord_nickname: 'HolySmoke', + username: 'holysmoke86', + })).toEqual('HolySmoke'); + }); + test('username if no nicknames', () => { + expect(getUserName({ + username: 'holysmoke86', + })).toEqual('holysmoke86'); + }); +}); -- 2.39.2