From 693d15ae5d3ee2c300d9dcbb9d43ecfcae94f6eb Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 19 Dec 2022 16:44:34 -0500 Subject: [PATCH] feat: render userclear messages on ban (#851) --- agent/internal/handler/twitch.go | 25 +++++++++++++++--------- lib/models/adapters/messages.dart | 26 ++++++++++++++----------- lib/models/messages.dart | 14 +++++++++++++ lib/models/messages/twitch/message.dart | 14 +++++++++++++ 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/agent/internal/handler/twitch.go b/agent/internal/handler/twitch.go index 17f689261..a8777ce11 100644 --- a/agent/internal/handler/twitch.go +++ b/agent/internal/handler/twitch.go @@ -40,7 +40,7 @@ func (h *TwitchHandler) bindOutboundClient(ctx context.Context) error { for _, change := range snapshot.Changes { if change.Kind == firestore.DocumentAdded { var action struct { - ChannelId string + ChannelId string Message string TargetChannel string ReplyMessageId string @@ -328,17 +328,24 @@ func (h *TwitchHandler) bindEvents(client *twitch.Client) { // configure handlers client.OnClearChatMessage(func(message twitch.ClearChatMessage) { - if message.TargetUserID != "" || message.TargetUsername != "" { - return - } // handle clear chat message channelID := fmt.Sprintf("twitch:%s", message.RoomID) - data := map[string]interface{}{ - "channelId": channelID, - "timestamp": message.Time, - "type": "clear", + if message.TargetUserID != "" || message.TargetUsername != "" { + data := map[string]interface{}{ + "channelId": channelID, + "targetUserId": message.TargetUserID, + "timestamp": message.Time, + "type": "userclear", + } + go h.write(channelID, fmt.Sprintf("twitch:userclear-%s", message.Time.Format(time.RFC3339)), data) + } else { + data := map[string]interface{}{ + "channelId": channelID, + "timestamp": message.Time, + "type": "clear", + } + go h.write(channelID, fmt.Sprintf("twitch:clear-%s", message.Time.Format(time.RFC3339)), data) } - go h.write(channelID, fmt.Sprintf("twitch:clear-%s", message.Time.Format(time.RFC3339)), data) }) client.OnClearMessage(func(message twitch.ClearMessage) { diff --git a/lib/models/adapters/messages.dart b/lib/models/adapters/messages.dart index be0faf670..60ab3e3d3 100644 --- a/lib/models/adapters/messages.dart +++ b/lib/models/adapters/messages.dart @@ -41,6 +41,12 @@ class UpdateDeltaEvent extends DeltaEvent { : super(timestamp); } +class UpdateAllDeltaEvent extends DeltaEvent { + final MessageModel Function(MessageModel) update; + + const UpdateAllDeltaEvent(DateTime timestamp, this.update) : super(timestamp); +} + class ClearDeltaEvent extends DeltaEvent { final String messageId; @@ -105,17 +111,7 @@ DeltaEvent? _toDeltaEvent( if (message is! TwitchMessageModel) { return message; } - return TwitchMessageModel( - messageId: message.messageId, - author: message.author, - message: message.message, - reply: message.reply, - tags: message.tags, - annotations: message.annotations, - thirdPartyEmotes: [], - timestamp: message.timestamp, - deleted: true, - channelId: data['channelId']); + return message.withDeleted(true); }); case "channel.raid": final model = TwitchRaidEventModel( @@ -132,6 +128,14 @@ DeltaEvent? _toDeltaEvent( messageId: doc.id, timestamp: data['timestamp'].toDate(), ); + case "userclear": + return UpdateAllDeltaEvent(data['timestamp'].toDate(), (message) { + if (message is! TwitchMessageModel || + message.author.userId != data['targetUserId']) { + return message; + } + return message.withDeleted(true); + }); case "host": if (data['hosterChannelId'] == null) { // Since we might have some events saved without this field. diff --git a/lib/models/messages.dart b/lib/models/messages.dart index bb77dc6c3..bc0339ec4 100644 --- a/lib/models/messages.dart +++ b/lib/models/messages.dart @@ -92,8 +92,17 @@ class MessagesModel extends ChangeNotifier { if (message is TwitchMessageModel && message.deleted) { _tts?.unsay(message.messageId); } + break; } } + } else if (event is UpdateAllDeltaEvent) { + for (var i = 0; i < _messages.length; i++) { + final message = event.update(_messages[i]); + if (message is TwitchMessageModel && message.deleted) { + _tts?.unsay(message.messageId); + } + _messages[i] = message; + } } else if (event is ClearDeltaEvent) { _messages = [ ChatClearedEventModel( @@ -155,8 +164,13 @@ class MessagesModel extends ChangeNotifier { final message = messages[i]; if (message.messageId == event.messageId) { messages[i] = event.update(message); + break; } } + } else if (event is UpdateAllDeltaEvent) { + for (var i = 0; i < messages.length; i++) { + messages[i] = event.update(messages[i]); + } } else if (event is ClearDeltaEvent) { messages = [ ChatClearedEventModel( diff --git a/lib/models/messages/twitch/message.dart b/lib/models/messages/twitch/message.dart index a34cd7529..3198cd3d6 100644 --- a/lib/models/messages/twitch/message.dart +++ b/lib/models/messages/twitch/message.dart @@ -280,4 +280,18 @@ class TwitchMessageModel extends MessageModel { } return tokens.toList(); } + + TwitchMessageModel withDeleted(bool deleted) { + return TwitchMessageModel( + messageId: messageId, + author: author, + message: message, + reply: reply, + tags: tags, + annotations: annotations, + thirdPartyEmotes: thirdPartyEmotes, + timestamp: timestamp, + deleted: deleted, + channelId: channelId); + } }