diff --git a/pkg/connector/client.go b/pkg/connector/client.go index 45252b0..b3c44b2 100644 --- a/pkg/connector/client.go +++ b/pkg/connector/client.go @@ -140,6 +140,8 @@ func (l *LinkedInClient) onDecoratedEvent(ctx context.Context, decoratedEvent *t l.onRealtimeTypingIndicator(decoratedEvent) case linkedingo.RealtimeEventTopicMessageSeenReceipts: l.onRealtimeMessageSeenReceipts(ctx, decoratedEvent.Payload.Data.DecoratedSeenReceipt.Result) + case linkedingo.RealtimeEventTopicMessageReactionSummaries: + l.onRealtimeReactionSummaries(ctx, decoratedEvent.Payload.Data.DecoratedReactionSummary.Result) default: fmt.Printf("UNSUPPORTED %q %+v\n", decoratedEvent.Topic, decoratedEvent) } @@ -239,6 +241,36 @@ func (l *LinkedInClient) onRealtimeMessageSeenReceipts(ctx context.Context, rece }) } +func (l *LinkedInClient) onRealtimeReactionSummaries(ctx context.Context, summary types.RealtimeReactionSummary) { + messageData, err := l.main.Bridge.DB.Message.GetFirstPartByID(context.TODO(), l.userLogin.ID, networkid.MessageID(summary.Message.EntityURN.String())) + if err != nil { + zerolog.Ctx(ctx).Err(err).Msg("failed to get reacted to message") + return + } + + meta := simplevent.EventMeta{ + Type: bridgev2.RemoteEventReaction, + LogContext: func(c zerolog.Context) zerolog.Context { + return c. + Stringer("message_id", summary.Message.EntityURN). + Stringer("sender", summary.Actor.EntityURN) + }, + PortalKey: messageData.Room, + Timestamp: time.Now(), + Sender: l.makeSender(summary.Actor), + } + if !summary.ReactionAdded { + meta.Type = bridgev2.RemoteEventReactionRemove + } + + l.main.Bridge.QueueRemoteEvent(l.userLogin, &simplevent.Reaction{ + EventMeta: meta, + EmojiID: networkid.EmojiID(summary.ReactionSummary.Emoji), + Emoji: summary.ReactionSummary.Emoji, + TargetMessage: networkid.MessageID(summary.Message.EntityURN.String()), + }) +} + func (l *LinkedInClient) getAvatar(img *types.VectorImage) (avatar bridgev2.Avatar) { avatar.ID = networkid.AvatarID(img.RootURL) avatar.Remove = img.RootURL == "" diff --git a/pkg/linkedingo/types/realtime.go b/pkg/linkedingo/types/realtime.go index f158db4..45c5da0 100644 --- a/pkg/linkedingo/types/realtime.go +++ b/pkg/linkedingo/types/realtime.go @@ -35,6 +35,7 @@ type DecoratedEventData struct { DecoratedMessage *DecoratedMessage `json:"doDecorateMessageMessengerRealtimeDecoration,omitempty"` DecoratedTypingIndicator *DecoratedTypingIndicator `json:"doDecorateTypingIndicatorMessengerRealtimeDecoration,omitempty"` DecoratedSeenReceipt *DecoratedSeenReceipt `json:"doDecorateSeenReceiptMessengerRealtimeDecoration,omitempty"` + DecoratedReactionSummary *DecoratedReactionSummary `json:"doDecorateRealtimeReactionSummaryMessengerRealtimeDecoration,omitempty"` } // Conversation represents a com.linkedin.messenger.Conversation object @@ -145,3 +146,24 @@ type SeenReceipt struct { Message Message `json:"message,omitempty"` SeenByParticipant MessagingParticipant `json:"seenByParticipant,omitempty"` } + +type DecoratedReactionSummary struct { + Result RealtimeReactionSummary `json:"result,omitempty"` +} + +// RealtimeReactionSummary represents a +// com.linkedin.messenger.RealtimeReactionSummary object. +type RealtimeReactionSummary struct { + ReactionAdded bool `json:"reactionAdded"` + Actor MessagingParticipant `json:"actor"` + Message Message `json:"message"` + ReactionSummary ReactionSummary `json:"reactionSummary"` +} + +// ReactionSummary represents a com.linkedin.messenger.ReactionSummary object. +type ReactionSummary struct { + Count int `json:"count,omitempty"` + FirstReactedAt int64 `json:"firstReactedAt,omitempty"` + Emoji string `json:"emoji,omitempty"` + ViewerReacted bool `json:"viewerReacted"` +}