typing: support TG <-> Matrix
Signed-off-by: Sumner Evans <sumner.evans@automattic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ require (
|
|||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||||
golang.org/x/net v0.27.0
|
golang.org/x/net v0.27.0
|
||||||
maunium.net/go/mautrix v0.19.1-0.20240806185340-213f9df4a467
|
maunium.net/go/mautrix v0.19.1-0.20240807155838-eabab275895d
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
@@ -112,8 +112,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
|
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
|
||||||
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
|
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
|
||||||
maunium.net/go/mautrix v0.19.1-0.20240806185340-213f9df4a467 h1:QptF4mA070qVG2isInl2HjtPOZ1TTqf0zM38uHPeWM8=
|
maunium.net/go/mautrix v0.19.1-0.20240807155838-eabab275895d h1:+PtYgqxswmN5UM9XSLKO88TjYJHApwWn0j4fAnCslxg=
|
||||||
maunium.net/go/mautrix v0.19.1-0.20240806185340-213f9df4a467/go.mod h1:ZWyxoQxRTBxzWIMs0kQCVogZIY0clTu33h102veCT/Q=
|
maunium.net/go/mautrix v0.19.1-0.20240807155838-eabab275895d/go.mod h1:ZWyxoQxRTBxzWIMs0kQCVogZIY0clTu33h102veCT/Q=
|
||||||
nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0=
|
nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0=
|
||||||
nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
||||||
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
|
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
|
||||||
|
|||||||
+25
-2
@@ -129,6 +129,19 @@ func NewTelegramClient(ctx context.Context, tc *TelegramConnector, login *bridge
|
|||||||
dispatcher.OnEditChannelMessage(func(ctx context.Context, e tg.Entities, update *tg.UpdateEditChannelMessage) error {
|
dispatcher.OnEditChannelMessage(func(ctx context.Context, e tg.Entities, update *tg.UpdateEditChannelMessage) error {
|
||||||
return client.onMessageEdit(ctx, update)
|
return client.onMessageEdit(ctx, update)
|
||||||
})
|
})
|
||||||
|
dispatcher.OnUserTyping(func(ctx context.Context, e tg.Entities, update *tg.UpdateUserTyping) error {
|
||||||
|
return client.handleTyping(ids.PeerTypeUser.AsPortalKey(update.UserID, login.ID), update.UserID, update.Action)
|
||||||
|
})
|
||||||
|
dispatcher.OnChatUserTyping(func(ctx context.Context, e tg.Entities, update *tg.UpdateChatUserTyping) error {
|
||||||
|
if update.FromID.TypeID() != tg.PeerUserTypeID {
|
||||||
|
log.Warn().Str("from_id_type", update.FromID.TypeName()).Msg("unsupported from_id type")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return client.handleTyping(ids.PeerTypeChat.AsPortalKey(update.ChatID, login.ID), update.FromID.(*tg.PeerUser).UserID, update.Action)
|
||||||
|
})
|
||||||
|
dispatcher.OnChannelUserTyping(func(ctx context.Context, e tg.Entities, update *tg.UpdateChannelUserTyping) error {
|
||||||
|
return client.handleTyping(ids.PeerTypeChannel.AsPortalKey(update.ChannelID, ""), update.FromID.(*tg.PeerUser).UserID, update.Action)
|
||||||
|
})
|
||||||
|
|
||||||
client.ScopedStore = tc.Store.GetScopedStore(telegramUserID)
|
client.ScopedStore = tc.Store.GetScopedStore(telegramUserID)
|
||||||
|
|
||||||
@@ -202,9 +215,19 @@ func NewTelegramClient(ctx context.Context, tc *TelegramConnector, login *bridge
|
|||||||
|
|
||||||
var portalKey networkid.PortalKey
|
var portalKey networkid.PortalKey
|
||||||
if strings.HasPrefix(group, "C/") || strings.HasPrefix(group, "c/") {
|
if strings.HasPrefix(group, "C/") || strings.HasPrefix(group, "c/") {
|
||||||
portalKey = networkid.PortalKey{ID: networkid.PortalID(fmt.Sprintf("%s:%s", ids.PeerTypeChannel, group[2:]))}
|
chatID, err := strconv.ParseInt(submatches[1][2:], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Err(err).Msg("error parsing channel ID")
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
portalKey = ids.PeerTypeChannel.AsPortalKey(chatID, "")
|
||||||
} else {
|
} else {
|
||||||
portalKey = networkid.PortalKey{ID: networkid.PortalID(fmt.Sprintf("%s:%s", ids.PeerTypeUser, group))}
|
userID, err := strconv.ParseInt(submatches[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Err(err).Msg("error parsing user ID")
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
portalKey = ids.PeerTypeUser.AsPortalKey(userID, login.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
portal, err := tc.Bridge.DB.Portal.GetByKey(ctx, portalKey)
|
portal, err := tc.Bridge.DB.Portal.GetByKey(ctx, portalKey)
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ func (tc *TelegramConnector) Download(ctx context.Context, mediaID networkid.Med
|
|||||||
ctx = log.WithContext(ctx)
|
ctx = log.WithContext(ctx)
|
||||||
log.Info().Msg("handling direct download")
|
log.Info().Msg("handling direct download")
|
||||||
|
|
||||||
logins, err := tc.Bridge.GetUserLoginsInPortal(ctx, info.PeerType.AsPortalKey(info.ChatID))
|
// TODO fix this
|
||||||
|
logins, err := tc.Bridge.GetUserLoginsInPortal(ctx, info.PeerType.AsPortalKey(info.ChatID, ""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if len(logins) == 0 {
|
} else if len(logins) == 0 {
|
||||||
|
|||||||
@@ -68,16 +68,28 @@ func (pt PeerType) AsByte() byte {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pt PeerType) AsPortalKey(chatID int64) networkid.PortalKey {
|
func (pt PeerType) AsPortalKey(chatID int64, receiver networkid.UserLoginID) networkid.PortalKey {
|
||||||
return networkid.PortalKey{ID: networkid.PortalID(fmt.Sprintf("%s:%d", pt, chatID))}
|
portalKey := networkid.PortalKey{
|
||||||
|
ID: networkid.PortalID(fmt.Sprintf("%s:%d", pt, chatID)),
|
||||||
|
}
|
||||||
|
if pt == PeerTypeUser || pt == PeerTypeChat {
|
||||||
|
portalKey.Receiver = receiver
|
||||||
|
}
|
||||||
|
return portalKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakePortalKey(peer tg.PeerClass) networkid.PortalKey {
|
func MakePortalKey(peer tg.PeerClass, receiver networkid.UserLoginID) networkid.PortalKey {
|
||||||
switch v := peer.(type) {
|
switch v := peer.(type) {
|
||||||
case *tg.PeerUser:
|
case *tg.PeerUser:
|
||||||
return networkid.PortalKey{ID: networkid.PortalID(fmt.Sprintf("%s:%d", PeerTypeUser, v.UserID))}
|
return networkid.PortalKey{
|
||||||
|
ID: networkid.PortalID(fmt.Sprintf("%s:%d", PeerTypeUser, v.UserID)),
|
||||||
|
Receiver: receiver,
|
||||||
|
}
|
||||||
case *tg.PeerChat:
|
case *tg.PeerChat:
|
||||||
return networkid.PortalKey{ID: networkid.PortalID(fmt.Sprintf("%s:%d", PeerTypeChat, v.ChatID))}
|
return networkid.PortalKey{
|
||||||
|
ID: networkid.PortalID(fmt.Sprintf("%s:%d", PeerTypeChat, v.ChatID)),
|
||||||
|
Receiver: receiver,
|
||||||
|
}
|
||||||
case *tg.PeerChannel:
|
case *tg.PeerChannel:
|
||||||
return networkid.PortalKey{ID: networkid.PortalID(fmt.Sprintf("%s:%d", PeerTypeChannel, v.ChannelID))}
|
return networkid.PortalKey{ID: networkid.PortalID(fmt.Sprintf("%s:%d", PeerTypeChannel, v.ChannelID))}
|
||||||
default:
|
default:
|
||||||
|
|||||||
+10
-3
@@ -182,7 +182,7 @@ func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.
|
|||||||
DB: &database.Message{
|
DB: &database.Message{
|
||||||
ID: ids.MakeMessageID(tgMessageID),
|
ID: ids.MakeMessageID(tgMessageID),
|
||||||
MXID: msg.Event.ID,
|
MXID: msg.Event.ID,
|
||||||
Room: networkid.PortalKey{ID: msg.Portal.ID},
|
Room: msg.Portal.PortalKey,
|
||||||
SenderID: t.userID,
|
SenderID: t.userID,
|
||||||
Timestamp: time.Unix(int64(tgDate), 0),
|
Timestamp: time.Unix(int64(tgDate), 0),
|
||||||
Metadata: &MessageMetadata{
|
Metadata: &MessageMetadata{
|
||||||
@@ -401,6 +401,13 @@ func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridg
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TelegramClient) HandleMatrixTyping(ctx context.Context, msg *bridgev2.MatrixTyping) error {
|
func (t *TelegramClient) HandleMatrixTyping(ctx context.Context, msg *bridgev2.MatrixTyping) error {
|
||||||
// TODO
|
inputPeer, err := t.inputPeerForPortalID(ctx, msg.Portal.ID)
|
||||||
return nil
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = t.client.API().MessagesSetTyping(ctx, &tg.MessagesSetTypingRequest{
|
||||||
|
Peer: inputPeer,
|
||||||
|
Action: &tg.SendMessageTypingAction{},
|
||||||
|
})
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ func (t *TelegramClient) onUpdateNewMessage(ctx context.Context, update IGetMess
|
|||||||
Stringer("peer_id", msg.PeerID)
|
Stringer("peer_id", msg.PeerID)
|
||||||
},
|
},
|
||||||
Sender: sender,
|
Sender: sender,
|
||||||
PortalKey: ids.MakePortalKey(msg.PeerID),
|
PortalKey: ids.MakePortalKey(msg.PeerID, t.loginID),
|
||||||
CreatePortal: true,
|
CreatePortal: true,
|
||||||
Timestamp: time.Unix(int64(msg.Date), 0),
|
Timestamp: time.Unix(int64(msg.Date), 0),
|
||||||
},
|
},
|
||||||
@@ -69,7 +69,7 @@ func (t *TelegramClient) onUpdateNewMessage(ctx context.Context, update IGetMess
|
|||||||
chatInfoChange := simplevent.ChatInfoChange{
|
chatInfoChange := simplevent.ChatInfoChange{
|
||||||
EventMeta: simplevent.EventMeta{
|
EventMeta: simplevent.EventMeta{
|
||||||
Type: bridgev2.RemoteEventChatInfoChange,
|
Type: bridgev2.RemoteEventChatInfoChange,
|
||||||
PortalKey: ids.MakePortalKey(msg.PeerID),
|
PortalKey: ids.MakePortalKey(msg.PeerID, t.loginID),
|
||||||
Sender: sender,
|
Sender: sender,
|
||||||
Timestamp: time.Unix(int64(msg.Date), 0),
|
Timestamp: time.Unix(int64(msg.Date), 0),
|
||||||
LogContext: func(c zerolog.Context) zerolog.Context {
|
LogContext: func(c zerolog.Context) zerolog.Context {
|
||||||
@@ -279,7 +279,7 @@ func (t *TelegramClient) onMessageEdit(ctx context.Context, update IGetMessage)
|
|||||||
Int("message_id", msg.ID)
|
Int("message_id", msg.ID)
|
||||||
},
|
},
|
||||||
Sender: sender,
|
Sender: sender,
|
||||||
PortalKey: ids.MakePortalKey(msg.PeerID),
|
PortalKey: ids.MakePortalKey(msg.PeerID, t.loginID),
|
||||||
Timestamp: time.Unix(int64(msg.EditDate), 0),
|
Timestamp: time.Unix(int64(msg.EditDate), 0),
|
||||||
},
|
},
|
||||||
ID: ids.MakeMessageID(msg.ID),
|
ID: ids.MakeMessageID(msg.ID),
|
||||||
@@ -305,6 +305,27 @@ func (t *TelegramClient) onMessageEdit(ctx context.Context, update IGetMessage)
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (t *TelegramClient) handleTyping(portal networkid.PortalKey, userID int64, action tg.SendMessageActionClass) error {
|
||||||
|
if userID == t.telegramUserID {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
timeout := time.Duration(6) * time.Second
|
||||||
|
if action.TypeID() != tg.SendMessageTypingActionTypeID {
|
||||||
|
timeout = 0
|
||||||
|
}
|
||||||
|
t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Typing{
|
||||||
|
EventMeta: simplevent.EventMeta{
|
||||||
|
Type: bridgev2.RemoteEventTyping,
|
||||||
|
PortalKey: portal,
|
||||||
|
Sender: bridgev2.EventSender{
|
||||||
|
SenderLogin: ids.MakeUserLoginID(userID),
|
||||||
|
Sender: ids.MakeUserID(userID),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Timeout: timeout,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *TelegramClient) handleTelegramReactions(ctx context.Context, msg *tg.Message) {
|
func (t *TelegramClient) handleTelegramReactions(ctx context.Context, msg *tg.Message) {
|
||||||
log := zerolog.Ctx(ctx).With().
|
log := zerolog.Ctx(ctx).With().
|
||||||
@@ -353,7 +374,7 @@ func (t *TelegramClient) handleTelegramReactions(ctx context.Context, msg *tg.Me
|
|||||||
// return
|
// return
|
||||||
|
|
||||||
// TODO should calls to this be limited?
|
// TODO should calls to this be limited?
|
||||||
} else if peer, err := t.inputPeerForPortalID(ctx, ids.MakePortalKey(msg.PeerID).ID); err != nil {
|
} else if peer, err := t.inputPeerForPortalID(ctx, ids.MakePortalKey(msg.PeerID, t.loginID).ID); err != nil {
|
||||||
log.Err(err).Msg("failed to get input peer")
|
log.Err(err).Msg("failed to get input peer")
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@@ -447,7 +468,11 @@ func (t *TelegramClient) inputPeerForPortalID(ctx context.Context, portalID netw
|
|||||||
}
|
}
|
||||||
switch peerType {
|
switch peerType {
|
||||||
case ids.PeerTypeUser:
|
case ids.PeerTypeUser:
|
||||||
return &tg.InputPeerUser{UserID: id}, nil
|
if ghost, err := t.main.Bridge.DB.Ghost.GetByID(ctx, ids.MakeUserID(id)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return &tg.InputPeerUser{UserID: id, AccessHash: ghost.Metadata.(*GhostMetadata).AccessHash}, nil
|
||||||
|
}
|
||||||
case ids.PeerTypeChat:
|
case ids.PeerTypeChat:
|
||||||
return &tg.InputPeerChat{ChatID: id}, nil
|
return &tg.InputPeerChat{ChatID: id}, nil
|
||||||
case ids.PeerTypeChannel:
|
case ids.PeerTypeChannel:
|
||||||
|
|||||||
Reference in New Issue
Block a user