diff --git a/pkg/connector/client.go b/pkg/connector/client.go index 4354ba8..6e501c4 100644 --- a/pkg/connector/client.go +++ b/pkg/connector/client.go @@ -41,6 +41,7 @@ type LineClient struct { } var _ bridgev2.NetworkAPI = (*LineClient)(nil) +var _ bridgev2.ReadReceiptHandlingNetworkAPI = (*LineClient)(nil) func (lc *LineClient) Connect(ctx context.Context) { if lc.peerKeys == nil { @@ -253,6 +254,26 @@ func (lc *LineClient) handleOperation(_ context.Context, op line.Operation) { // Type 25 = SEND_MESSAGE (Message sent by you from another device) // Type 26 = RECEIVE_MESSAGE (Message received from another user) + if op.Type == 55 { + senderID := makeUserID(op.Param1) + portalID := makePortalID(op.Param2) + // Param 2 is the group id or sender id in 1:1 chats + + ts, _ := op.CreatedTime.Int64() + lc.UserLogin.Bridge.QueueRemoteEvent(lc.UserLogin, &simplevent.Receipt{ + EventMeta: simplevent.EventMeta{ + Type: bridgev2.RemoteEventReadReceipt, + PortalKey: networkid.PortalKey{ + ID: portalID, + Receiver: lc.UserLogin.ID, + }, + Timestamp: time.UnixMilli(ts), + Sender: bridgev2.EventSender{Sender: senderID}, + }, + ReadUpTo: time.UnixMilli(ts), + }) + } + if op.Type == 25 { lc.reqSeqMu.Lock() _, ok := lc.sentReqSeqs[op.ReqSeq] @@ -339,6 +360,27 @@ func (lc *LineClient) queueIncomingMessage(msg *line.Message, opType int) { func (lc *LineClient) Disconnect() {} +func (lc *LineClient) HandleMatrixReadReceipt(ctx context.Context, read *bridgev2.MatrixReadReceipt) error { + if read.ReadUpTo.IsZero() && read.EventID == "" { + return nil + } + + targetID := string(read.EventID) + if read.EventID != "" { + msg, err := lc.UserLogin.Bridge.DB.Message.GetPartByMXID(ctx, read.EventID) + if err == nil && msg != nil && msg.ID != "" { + targetID = string(msg.ID) + } + } + + if targetID == "" || strings.HasPrefix(targetID, "$") { + return nil + } + + client := line.NewClient(lc.AccessToken) + return client.SendChatChecked(string(read.Portal.ID), targetID) +} + func (lc *LineClient) IsLoggedIn() bool { return lc.AccessToken != "" } func (lc *LineClient) LogoutRemote(ctx context.Context) {} diff --git a/pkg/line/methods.go b/pkg/line/methods.go index 8cd4a6b..a0fa5b2 100644 --- a/pkg/line/methods.go +++ b/pkg/line/methods.go @@ -265,6 +265,12 @@ func (c *Client) SendMessage(reqSeq int64, msg *Message) error { return nil } +// SendChatChecked sends a read receipt for a message in a chat +func (c *Client) SendChatChecked(chatMid, messageID string) error { + _, err := c.callRPC("TalkService", "sendChatChecked", 0, chatMid, messageID) + return err +} + // GetContactsV2 fetches contact details for a list of MIDs. func (c *Client) GetContactsV2(mids []string) (*ContactsResponse, error) { req := GetContactsV2Request{TargetUserMids: mids}