From fa23bd14e8a007fe8724b12ead5be16ff617949a Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 23 Feb 2024 21:10:31 +0200 Subject: [PATCH] Update mautrix-go --- backfill.go | 14 ++-- commands.go | 27 +++---- custompuppet.go | 2 +- go.mod | 12 +-- go.sum | 28 +++---- libgm/gmtest/go.mod | 2 +- libgm/gmtest/go.sum | 4 +- libgm/go.mod | 2 +- libgm/go.sum | 4 +- messagetracking.go | 28 +++---- portal.go | 177 ++++++++++++++++++++++---------------------- provisioning.go | 2 +- puppet.go | 32 ++++---- user.go | 122 +++++++++++++++--------------- 14 files changed, 232 insertions(+), 224 deletions(-) diff --git a/backfill.go b/backfill.go index 93fbb11..033da50 100644 --- a/backfill.go +++ b/backfill.go @@ -51,10 +51,10 @@ type pendingBackfill struct { lastMessageTS time.Time } -func (portal *Portal) missedForwardBackfill(user *User, lastMessageTS time.Time, lastMessageID string, markRead, markReadIfNoBackfill bool) { +func (portal *Portal) missedForwardBackfill(ctx context.Context, user *User, lastMessageTS time.Time, lastMessageID string, markRead, markReadIfNoBackfill bool) { if portal.bridge.Config.Bridge.Backfill.MissedLimit == 0 { if markRead && markReadIfNoBackfill { - user.markSelfReadFull(portal, lastMessageID) + user.markSelfReadFull(ctx, portal, lastMessageID) } return } @@ -62,7 +62,7 @@ func (portal *Portal) missedForwardBackfill(user *User, lastMessageTS time.Time, Str("action", "missed forward backfill"). Str("latest_message_id", lastMessageID). Logger() - ctx := log.WithContext(context.TODO()) + ctx = log.WithContext(ctx) if portal.hasSyncedThisRun && !lastMessageTS.IsZero() && time.Since(lastMessageTS) < 5*time.Minute && portal.lastMessageTS.Before(lastMessageTS) { var cancel context.CancelFunc ctx, cancel = context.WithCancel(ctx) @@ -101,7 +101,7 @@ func (portal *Portal) missedForwardBackfill(user *User, lastMessageTS time.Time, Time("last_bridged_ts", portal.lastMessageTS). Msg("Nothing to backfill") if markRead && markReadIfNoBackfill { - user.markSelfReadFull(portal, lastMessageID) + user.markSelfReadFull(ctx, portal, lastMessageID) } return } @@ -172,7 +172,7 @@ func (portal *Portal) forwardBackfill(ctx context.Context, user *User, after tim } else { lastEventID := portal.backfillSendLegacy(ctx, converted) if markRead && user.DoublePuppetIntent != nil { - err = user.DoublePuppetIntent.MarkRead(portal.MXID, lastEventID) + err = user.DoublePuppetIntent.MarkRead(ctx, portal.MXID, lastEventID) if err != nil { log.Err(err).Msg("Failed to mark room as read after backfill") } @@ -212,7 +212,7 @@ func (portal *Portal) backfillSendBatch(ctx context.Context, converted []*Conver } eventType := event.EventMessage var err error - eventType, err = portal.encrypt(msg.Intent, &content, eventType) + eventType, err = portal.encrypt(ctx, msg.Intent, &content, eventType) if err != nil { log.Err(err).Str("message_id", msg.ID).Int("part", i).Msg("Failed to encrypt event") continue @@ -258,7 +258,7 @@ func (portal *Portal) backfillSendBatch(ctx context.Context, converted []*Conver Bool("mark_read", markReadBy != ""). Bool("notify", markReadBy == ""). Msg("Sending batch of messages") - _, err := portal.MainIntent().BeeperBatchSend(portal.MXID, &mautrix.ReqBeeperBatchSend{ + _, err := portal.MainIntent().BeeperBatchSend(ctx, portal.MXID, &mautrix.ReqBeeperBatchSend{ Forward: forward, MarkReadBy: markReadBy, SendNotification: forward && markReadBy == "" && allowNotify, diff --git a/commands.go b/commands.go index d8d98cd..cdc601b 100644 --- a/commands.go +++ b/commands.go @@ -17,6 +17,7 @@ package main import ( + "context" "encoding/json" "fmt" "strings" @@ -188,7 +189,7 @@ func (user *User) sendQREdit(ce *WrappedCommandEvent, content *event.MessageEven if len(prevEvent) != 0 { content.SetEdit(prevEvent) } - resp, err := ce.Bot.SendMessageEvent(ce.RoomID, event.EventMessage, &content) + resp, err := ce.Bot.SendMessageEvent(ce.Ctx, ce.RoomID, event.EventMessage, &content) if err != nil { ce.ZLog.Err(err).Msg("Failed to send edited QR code") } else if len(prevEvent) == 0 { @@ -199,7 +200,7 @@ func (user *User) sendQREdit(ce *WrappedCommandEvent, content *event.MessageEven func (user *User) sendQR(ce *WrappedCommandEvent, code string, prevEvent id.EventID) id.EventID { var content event.MessageEventContent - url, err := user.uploadQR(code) + url, err := user.uploadQR(ce.Ctx, code) if err != nil { ce.ZLog.Err(err).Msg("Failed to upload QR code") content = event.MessageEventContent{ @@ -216,12 +217,12 @@ func (user *User) sendQR(ce *WrappedCommandEvent, code string, prevEvent id.Even return user.sendQREdit(ce, &content, prevEvent) } -func (user *User) uploadQR(code string) (id.ContentURI, error) { +func (user *User) uploadQR(ctx context.Context, code string) (id.ContentURI, error) { qrCode, err := qrcode.Encode(code, qrcode.Low, 256) if err != nil { return id.ContentURI{}, err } - resp, err := user.bridge.Bot.UploadBytes(qrCode, "image/png") + resp, err := user.bridge.Bot.UploadBytes(ctx, qrCode, "image/png") if err != nil { return id.ContentURI{}, err } @@ -415,7 +416,7 @@ func fnPM(ce *WrappedCommandEvent) { ce.Reply("Failed to start chat: no conversation in response") } else if portal := ce.User.GetPortalByID(resp.Conversation.ConversationID); portal.MXID != "" { ce.Reply("Chat already exists at [%s](https://matrix.to/#/%s)", portal.MXID, portal.MXID) - } else if err = portal.CreateMatrixRoom(ce.User, resp.Conversation, false); err != nil { + } else if err = portal.CreateMatrixRoom(ce.Ctx, ce.User, resp.Conversation, false); err != nil { ce.ZLog.Err(err).Msg("Failed to create matrix room") ce.Reply("Failed to create portal room for conversation") } else { @@ -440,8 +441,8 @@ func fnDeletePortal(ce *WrappedCommandEvent) { } ce.ZLog.Info().Str("conversation_id", ce.Portal.ID).Msg("Deleting portal from command") - ce.Portal.Delete() - ce.Portal.Cleanup() + ce.Portal.Delete(ce.Ctx) + ce.Portal.Cleanup(ce.Ctx) } var cmdDeleteAllPortals = &commands.FullHandler{ @@ -462,7 +463,7 @@ func fnDeleteAllPortals(ce *WrappedCommandEvent) { leave := func(portal *Portal) { if len(portal.MXID) > 0 { - _, _ = portal.MainIntent().KickUser(portal.MXID, &mautrix.ReqKickUser{ + _, _ = portal.MainIntent().KickUser(ce.Ctx, portal.MXID, &mautrix.ReqKickUser{ Reason: "Deleting portal", UserID: ce.User.MXID, }) @@ -472,27 +473,27 @@ func fnDeleteAllPortals(ce *WrappedCommandEvent) { if intent != nil { leave = func(portal *Portal) { if len(portal.MXID) > 0 { - _, _ = intent.LeaveRoom(portal.MXID) - _, _ = intent.ForgetRoom(portal.MXID) + _, _ = intent.LeaveRoom(ce.Ctx, portal.MXID) + _, _ = intent.ForgetRoom(ce.Ctx, portal.MXID) } } } roomYeeting := ce.Bridge.SpecVersions.Supports(mautrix.BeeperFeatureRoomYeeting) if roomYeeting { leave = func(portal *Portal) { - portal.Cleanup() + portal.Cleanup(ce.Ctx) } } ce.Reply("Found %d portals, deleting...", len(portals)) for _, portal := range portals { - portal.Delete() + portal.Delete(ce.Ctx) leave(portal) } if !roomYeeting { ce.Reply("Finished deleting portal info. Now cleaning up rooms in background.") go func() { for _, portal := range portals { - portal.Cleanup() + portal.Cleanup(ce.Ctx) } ce.Reply("Finished background cleanup of deleted portal rooms.") }() diff --git a/custompuppet.go b/custompuppet.go index 4580693..0e47f39 100644 --- a/custompuppet.go +++ b/custompuppet.go @@ -51,7 +51,7 @@ func (user *User) ClearCustomMXID() { } func (user *User) StartCustomMXID(reloginOnFail bool) error { - newIntent, newAccessToken, err := user.bridge.DoublePuppet.Setup(user.MXID, user.AccessToken, reloginOnFail) + newIntent, newAccessToken, err := user.bridge.DoublePuppet.Setup(context.TODO(), user.MXID, user.AccessToken, reloginOnFail) if err != nil { user.ClearCustomMXID() return err diff --git a/go.mod b/go.mod index 78d8379..4733178 100644 --- a/go.mod +++ b/go.mod @@ -9,11 +9,11 @@ require ( github.com/rs/zerolog v1.32.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e go.mau.fi/mautrix-gmessages/libgm v0.2.2 - go.mau.fi/util v0.2.1 - golang.org/x/exp v0.0.0-20240213143201-ec583247a57a + go.mau.fi/util v0.4.1-0.20240222202553-953608f657a3 + golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 google.golang.org/protobuf v1.32.0 maunium.net/go/maulogger/v2 v2.4.1 - maunium.net/go/mautrix v0.16.2 + maunium.net/go/mautrix v0.18.0-beta.1.0.20240223191208-581aa8015501 ) require ( @@ -26,14 +26,14 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/tidwall/gjson v1.17.0 // indirect + github.com/tidwall/gjson v1.17.1 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/sjson v1.2.5 // indirect - github.com/yuin/goldmark v1.6.0 // indirect + github.com/yuin/goldmark v1.7.0 // indirect go.mau.fi/zeroconfig v0.1.2 // indirect golang.org/x/crypto v0.19.0 // indirect - golang.org/x/net v0.18.0 // indirect + golang.org/x/net v0.21.0 // indirect golang.org/x/sys v0.17.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect diff --git a/go.sum b/go.sum index 43f80b5..73d1fe5 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= -github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -47,26 +47,26 @@ github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDq github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= -github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= +github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= -github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mau.fi/util v0.2.1 h1:eazulhFE/UmjOFtPrGg6zkF5YfAyiDzQb8ihLMbsPWw= -go.mau.fi/util v0.2.1/go.mod h1:MjlzCQEMzJ+G8RsPawHzpLB8rwTo3aPIjG5FzBvQT/c= +github.com/yuin/goldmark v1.7.0 h1:EfOIvIMZIzHdB/R/zVrikYLPPwJlfMcNczJFMs1m6sA= +github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +go.mau.fi/util v0.4.1-0.20240222202553-953608f657a3 h1:NcRrdzORHKab5bP1Z8BpH0nxsxsvH0iPPZLpOUN+UIc= +go.mau.fi/util v0.4.1-0.20240222202553-953608f657a3/go.mod h1:leeiHtgVBuN+W9aDii3deAXnfC563iN3WK6BF8/AjNw= go.mau.fi/zeroconfig v0.1.2 h1:DKOydWnhPMn65GbXZOafgkPm11BvFashZWLct0dGFto= go.mau.fi/zeroconfig v0.1.2/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -85,5 +85,5 @@ 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/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL8= maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho= -maunium.net/go/mautrix v0.16.2 h1:a6GUJXNWsTEOO8VE4dROBfCIfPp50mqaqzv7KPzChvg= -maunium.net/go/mautrix v0.16.2/go.mod h1:YL4l4rZB46/vj/ifRMEjcibbvHjgxHftOF1SgmruLu4= +maunium.net/go/mautrix v0.18.0-beta.1.0.20240223191208-581aa8015501 h1:3STixn49dd7VXL+p4hW0AEWy5/BeZlgA3i3BVsIgtqM= +maunium.net/go/mautrix v0.18.0-beta.1.0.20240223191208-581aa8015501/go.mod h1:1Q8P5C/uNmSBmull6DSqcawpg/E7hcGLQCD+JoU+vUo= diff --git a/libgm/gmtest/go.mod b/libgm/gmtest/go.mod index ffba760..31744cb 100644 --- a/libgm/gmtest/go.mod +++ b/libgm/gmtest/go.mod @@ -11,7 +11,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - go.mau.fi/util v0.2.1 // indirect + go.mau.fi/util v0.4.1-0.20240222202553-953608f657a3 // indirect golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect golang.org/x/sys v0.17.0 // indirect diff --git a/libgm/gmtest/go.sum b/libgm/gmtest/go.sum index aa1ab00..b38ec0e 100644 --- a/libgm/gmtest/go.sum +++ b/libgm/gmtest/go.sum @@ -20,8 +20,8 @@ github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.mau.fi/util v0.2.1 h1:eazulhFE/UmjOFtPrGg6zkF5YfAyiDzQb8ihLMbsPWw= -go.mau.fi/util v0.2.1/go.mod h1:MjlzCQEMzJ+G8RsPawHzpLB8rwTo3aPIjG5FzBvQT/c= +go.mau.fi/util v0.4.1-0.20240222202553-953608f657a3 h1:NcRrdzORHKab5bP1Z8BpH0nxsxsvH0iPPZLpOUN+UIc= +go.mau.fi/util v0.4.1-0.20240222202553-953608f657a3/go.mod h1:leeiHtgVBuN+W9aDii3deAXnfC563iN3WK6BF8/AjNw= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= diff --git a/libgm/go.mod b/libgm/go.mod index bad76a6..e41b24e 100644 --- a/libgm/go.mod +++ b/libgm/go.mod @@ -6,7 +6,7 @@ require ( github.com/google/uuid v1.6.0 github.com/rs/zerolog v1.32.0 github.com/stretchr/testify v1.8.4 - go.mau.fi/util v0.2.1 + go.mau.fi/util v0.4.1-0.20240222202553-953608f657a3 golang.org/x/crypto v0.19.0 golang.org/x/exp v0.0.0-20240213143201-ec583247a57a google.golang.org/protobuf v1.32.0 diff --git a/libgm/go.sum b/libgm/go.sum index 6ae2f72..3d804b6 100644 --- a/libgm/go.sum +++ b/libgm/go.sum @@ -19,8 +19,8 @@ github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.mau.fi/util v0.2.1 h1:eazulhFE/UmjOFtPrGg6zkF5YfAyiDzQb8ihLMbsPWw= -go.mau.fi/util v0.2.1/go.mod h1:MjlzCQEMzJ+G8RsPawHzpLB8rwTo3aPIjG5FzBvQT/c= +go.mau.fi/util v0.4.1-0.20240222202553-953608f657a3 h1:NcRrdzORHKab5bP1Z8BpH0nxsxsvH0iPPZLpOUN+UIc= +go.mau.fi/util v0.4.1-0.20240222202553-953608f657a3/go.mod h1:leeiHtgVBuN+W9aDii3deAXnfC563iN3WK6BF8/AjNw= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= diff --git a/messagetracking.go b/messagetracking.go index c13a6b9..e51a213 100644 --- a/messagetracking.go +++ b/messagetracking.go @@ -104,7 +104,7 @@ func errorToStatusReason(err error) (reason event.MessageStatusReason, status ev } } -func (portal *Portal) sendErrorMessage(evt *event.Event, err error, msgType string, confirmed bool, editID id.EventID) id.EventID { +func (portal *Portal) sendErrorMessage(ctx context.Context, evt *event.Event, err error, msgType string, confirmed bool, editID id.EventID) id.EventID { if !portal.bridge.Config.Bridge.MessageErrorNotices { return "" } @@ -125,7 +125,7 @@ func (portal *Portal) sendErrorMessage(evt *event.Event, err error, msgType stri } else { content.SetReply(evt) } - resp, err := portal.sendMainIntentMessage(content) + resp, err := portal.sendMainIntentMessage(ctx, content) if err != nil { portal.zlog.Warn().Err(err).Str("event_id", evt.ID.String()).Msg("Failed to send bridging error message") return "" @@ -153,7 +153,7 @@ func (portal *Portal) sendCheckpoint(dbMsg *database.Message, err error, deliver go portal.bridge.SendRawMessageCheckpoint(&checkpoint) } -func (portal *Portal) sendStatusEvent(evtID, lastRetry id.EventID, err error, deliveredTo *[]id.UserID) { +func (portal *Portal) sendStatusEvent(ctx context.Context, evtID, lastRetry id.EventID, err error, deliveredTo *[]id.UserID) { if !portal.bridge.Config.Bridge.MessageStatusEvents { return } @@ -181,22 +181,22 @@ func (portal *Portal) sendStatusEvent(evtID, lastRetry id.EventID, err error, de content.Reason, content.Status, _, _, content.Message = errorToStatusReason(err) content.Error = err.Error() } - _, err = intent.SendMessageEvent(portal.MXID, event.BeeperMessageStatus, &content) + _, err = intent.SendMessageEvent(ctx, portal.MXID, event.BeeperMessageStatus, &content) if err != nil { portal.zlog.Warn().Err(err).Str("event_id", evtID.String()).Msg("Failed to send message status event") } } -func (portal *Portal) sendDeliveryReceipt(eventID id.EventID) { +func (portal *Portal) sendDeliveryReceipt(ctx context.Context, eventID id.EventID) { if portal.bridge.Config.Bridge.DeliveryReceipts { - err := portal.bridge.Bot.SendReceipt(portal.MXID, eventID, event.ReceiptTypeRead, nil) + err := portal.bridge.Bot.SendReceipt(ctx, portal.MXID, eventID, event.ReceiptTypeRead, nil) if err != nil { portal.zlog.Warn().Err(err).Str("event_id", eventID.String()).Msg("Failed to send delivery receipt") } } } -func (portal *Portal) sendMessageMetrics(user *User, evt *event.Event, err error, part string, ms *metricSender) { +func (portal *Portal) sendMessageMetrics(ctx context.Context, user *User, evt *event.Event, err error, part string, ms *metricSender) { var msgType string switch evt.Type { case event.EventMessage: @@ -232,21 +232,21 @@ func (portal *Portal) sendMessageMetrics(user *User, evt *event.Event, err error } portal.bridge.SendMessageCheckpoint(evt, status.MsgStepRemote, checkpointErr, checkpointStatus, ms.getRetryNum()) if sendNotice { - ms.setNoticeID(portal.sendErrorMessage(evt, err, msgType, isCertain, ms.getNoticeID())) + ms.setNoticeID(portal.sendErrorMessage(ctx, evt, err, msgType, isCertain, ms.getNoticeID())) } - portal.sendStatusEvent(origEvtID, evt.ID, err, nil) + portal.sendStatusEvent(ctx, origEvtID, evt.ID, err, nil) } else { portal.zlog.Debug(). Str("event_id", evt.ID.String()). Str("event_type", evt.Type.Type). Msg("Handled Matrix event") - portal.sendDeliveryReceipt(evt.ID) + portal.sendDeliveryReceipt(ctx, evt.ID) if msgType != "message" { portal.bridge.SendMessageSuccessCheckpoint(evt, status.MsgStepRemote, ms.getRetryNum()) - portal.sendStatusEvent(origEvtID, evt.ID, nil, nil) + portal.sendStatusEvent(ctx, origEvtID, evt.ID, nil, nil) } if prevNotice := ms.popNoticeID(); prevNotice != "" { - _, _ = portal.MainIntent().RedactEvent(portal.MXID, prevNotice, mautrix.ReqRedact{ + _, _ = portal.MainIntent().RedactEvent(ctx, portal.MXID, prevNotice, mautrix.ReqRedact{ Reason: "error resolved", }) } @@ -313,13 +313,13 @@ func (ms *metricSender) setNoticeID(evtID id.EventID) { } } -func (ms *metricSender) sendMessageMetrics(user *User, evt *event.Event, err error, part string, completed bool) { +func (ms *metricSender) sendMessageMetrics(ctx context.Context, user *User, evt *event.Event, err error, part string, completed bool) { ms.lock.Lock() defer ms.lock.Unlock() if !completed && ms.completed { return } - ms.portal.sendMessageMetrics(user, evt, err, part, ms) + ms.portal.sendMessageMetrics(ctx, user, evt, err, part, ms) ms.retryNum++ ms.completed = completed } diff --git a/portal.go b/portal.go index 4b8221f..da839f6 100644 --- a/portal.go +++ b/portal.go @@ -313,10 +313,10 @@ func (portal *Portal) handleMessageLoopItem(msg PortalMessage) { func (portal *Portal) handleMatrixMessageLoopItem(msg PortalMatrixMessage) { if msg.user.RowID != portal.Receiver { - go portal.sendMessageMetrics(msg.user, msg.evt, errIncorrectUser, "Ignoring", nil) + go portal.sendMessageMetrics(context.TODO(), msg.user, msg.evt, errIncorrectUser, "Ignoring", nil) return } else if msg.user.Client == nil { - go portal.sendMessageMetrics(msg.user, msg.evt, errNotLoggedIn, "Ignoring", nil) + go portal.sendMessageMetrics(context.TODO(), msg.user, msg.evt, errNotLoggedIn, "Ignoring", nil) return } portal.forwardBackfillLock.Lock() @@ -476,14 +476,14 @@ func (portal *Portal) redactMessage(ctx context.Context, msg *database.Message) } for partID, part := range msg.Status.MediaParts { if part.EventID != "" { - if _, err := intent.RedactEvent(msg.RoomID, part.EventID); err != nil { + if _, err := intent.RedactEvent(ctx, msg.RoomID, part.EventID); err != nil { log.Err(err).Str("part_id", partID).Msg("Failed to redact part of message") } part.EventID = "" msg.Status.MediaParts[partID] = part } } - if _, err := intent.RedactEvent(msg.RoomID, msg.MXID); err != nil { + if _, err := intent.RedactEvent(ctx, msg.RoomID, msg.MXID); err != nil { log.Err(err).Msg("Failed to redact message") } msg.MXID = "" @@ -594,7 +594,7 @@ func (portal *Portal) handleExistingMessageUpdate(ctx context.Context, source *U ts = converted.Timestamp.UnixMilli() isEdit = false } - resp, err := portal.sendMessage(converted.Intent, event.EventMessage, part.Content, part.Extra, ts) + resp, err := portal.sendMessage(ctx, converted.Intent, event.EventMessage, part.Content, part.Extra, ts) if err != nil { log.Err(err).Msg("Failed to send message") continue @@ -611,7 +611,7 @@ func (portal *Portal) handleExistingMessageUpdate(ctx context.Context, source *U } } if len(eventIDs) > 0 { - portal.sendDeliveryReceipt(eventIDs[len(eventIDs)-1]) + portal.sendDeliveryReceipt(ctx, eventIDs[len(eventIDs)-1]) log.Debug().Interface("event_ids", eventIDs).Msg("Handled update to message") } case !dbMsg.Status.ReadReceiptSent && portal.IsPrivateChat() && newStatus == gmproto.MessageStatusType_OUTGOING_DISPLAYED: @@ -622,10 +622,10 @@ func (portal *Portal) handleExistingMessageUpdate(ctx context.Context, source *U if !dbMsg.Status.MSSDeliverySent { dbMsg.Status.MSSDeliverySent = true dbMsg.Status.MSSSent = true - go portal.sendStatusEvent(dbMsg.MXID, "", nil, &[]id.UserID{portal.MainIntent().UserID}) + go portal.sendStatusEvent(ctx, dbMsg.MXID, "", nil, &[]id.UserID{portal.MainIntent().UserID}) portal.sendCheckpoint(dbMsg, nil, true) } - err := portal.MainIntent().MarkRead(portal.MXID, dbMsg.MXID) + err := portal.MainIntent().MarkRead(ctx, portal.MXID, dbMsg.MXID) if err != nil { log.Warn().Err(err).Msg("Failed to mark message as read") } @@ -636,7 +636,7 @@ func (portal *Portal) handleExistingMessageUpdate(ctx context.Context, source *U portal.sendCheckpoint(dbMsg, nil, true) dbMsg.Status.MSSDeliverySent = true dbMsg.Status.MSSSent = true - go portal.sendStatusEvent(dbMsg.MXID, "", nil, &[]id.UserID{portal.MainIntent().UserID}) + go portal.sendStatusEvent(ctx, dbMsg.MXID, "", nil, &[]id.UserID{portal.MainIntent().UserID}) case !dbMsg.Status.MSSSent && isSuccessfullySentStatus(newStatus): dbMsg.Status.MSSSent = true var deliveredTo *[]id.UserID @@ -644,10 +644,10 @@ func (portal *Portal) handleExistingMessageUpdate(ctx context.Context, source *U if portal.IsPrivateChat() && portal.Type == gmproto.ConversationType_RCS { deliveredTo = &[]id.UserID{} } - go portal.sendStatusEvent(dbMsg.MXID, "", nil, deliveredTo) + go portal.sendStatusEvent(ctx, dbMsg.MXID, "", nil, deliveredTo) portal.sendCheckpoint(dbMsg, nil, false) case !dbMsg.Status.MSSFailSent && !dbMsg.Status.MSSSent && isFailSendStatus(newStatus): - go portal.sendStatusEvent(dbMsg.MXID, "", OutgoingStatusError(newStatus), nil) + go portal.sendStatusEvent(ctx, dbMsg.MXID, "", OutgoingStatusError(newStatus), nil) portal.sendCheckpoint(dbMsg, OutgoingStatusError(newStatus), false) // TODO error notice default: @@ -735,7 +735,7 @@ func (portal *Portal) handleMessage(source *User, evt *gmproto.Message, raw []by converted := portal.convertGoogleMessage(ctx, source, evt, false, raw) eventIDs := portal.sendMessageParts(ctx, converted, nil) if len(eventIDs) > 0 { - portal.sendDeliveryReceipt(eventIDs[len(eventIDs)-1]) + portal.sendDeliveryReceipt(ctx, eventIDs[len(eventIDs)-1]) log.Debug().Interface("event_ids", eventIDs).Msg("Handled message") } } @@ -762,7 +762,7 @@ func (portal *Portal) sendMessageParts(ctx context.Context, converted *Converted } } } - resp, err := portal.sendMessage(converted.Intent, event.EventMessage, part.Content, part.Extra, converted.Timestamp.UnixMilli()) + resp, err := portal.sendMessage(ctx, converted.Intent, event.EventMessage, part.Content, part.Extra, converted.Timestamp.UnixMilli()) if err != nil { zerolog.Ctx(ctx).Err(err).Int("part_index", i).Str("part_id", part.ID).Msg("Failed to send message") } else { @@ -817,7 +817,7 @@ func (portal *Portal) syncReactions(ctx context.Context, source *User, message * continue } var resp *mautrix.RespSendEvent - resp, err = intent.SendMessageEvent(portal.MXID, event.EventReaction, &event.ReactionEventContent{ + resp, err = intent.SendMessageEvent(ctx, portal.MXID, event.EventReaction, &event.ReactionEventContent{ RelatesTo: event.RelatesTo{ EventID: message.MXID, Type: event.RelAnnotation, @@ -833,7 +833,7 @@ func (portal *Portal) syncReactions(ctx context.Context, source *User, message * dbReaction.Chat = portal.Key dbReaction.Sender = participant dbReaction.MessageID = message.ID - } else if _, err = intent.RedactEvent(portal.MXID, dbReaction.MXID); err != nil { + } else if _, err = intent.RedactEvent(ctx, portal.MXID, dbReaction.MXID); err != nil { log.Err(err).Str("reaction_sender_id", participant).Msg("Failed to redact old reaction after adding new one") } dbReaction.Reaction = emoji @@ -849,7 +849,7 @@ func (portal *Portal) syncReactions(ctx context.Context, source *User, message * if intent == nil { continue } - _, err = intent.RedactEvent(portal.MXID, reaction.MXID) + _, err = intent.RedactEvent(ctx, portal.MXID, reaction.MXID) if err != nil { log.Err(err).Str("reaction_sender_id", reaction.Sender).Msg("Failed to redact removed reaction") } else if err = reaction.Delete(ctx); err != nil { @@ -1017,7 +1017,7 @@ func (portal *Portal) convertGoogleMessage(ctx context.Context, source *User, ev MsgType: event.MsgNotice, Body: fmt.Sprintf("Waiting for attachment %s", data.MediaContent.GetMediaName()), } - } else if contentPtr, err := portal.convertGoogleMedia(source, cm.Intent, data.MediaContent); err != nil { + } else if contentPtr, err := portal.convertGoogleMedia(ctx, source, cm.Intent, data.MediaContent); err != nil { pendingMedia = true log.Err(err).Msg("Failed to copy attachment") content = event.MessageEventContent{ @@ -1185,7 +1185,7 @@ func (msg *ConvertedMessage) MergeCaption() { msg.Parts = []ConvertedMessagePart{filePart} } -func (portal *Portal) convertGoogleMedia(source *User, intent *appservice.IntentAPI, msg *gmproto.MediaContent) (*event.MessageEventContent, error) { +func (portal *Portal) convertGoogleMedia(ctx context.Context, source *User, intent *appservice.IntentAPI, msg *gmproto.MediaContent) (*event.MessageEventContent, error) { var data []byte var err error if msg.MediaID != "" { @@ -1221,7 +1221,7 @@ func (portal *Portal) convertGoogleMedia(source *User, intent *appservice.Intent Size: len(data), }, } - return content, portal.uploadMedia(intent, data, content) + return content, portal.uploadMedia(ctx, intent, data, content) } func (portal *Portal) isRecentlyHandled(id string) bool { @@ -1261,12 +1261,12 @@ func (portal *Portal) markHandled(cm *ConvertedMessage, eventID id.EventID, medi return msg } -func (portal *Portal) SyncParticipants(source *User, metadata *gmproto.Conversation) (userIDs []id.UserID, changed bool) { +func (portal *Portal) SyncParticipants(ctx context.Context, source *User, metadata *gmproto.Conversation) (userIDs []id.UserID, changed bool) { var firstParticipant *gmproto.Participant var manyParticipants bool for _, participant := range metadata.Participants { if participant.IsMe { - err := source.AddSelfParticipantID(context.TODO(), participant.ID.ParticipantID) + err := source.AddSelfParticipantID(ctx, participant.ID.ParticipantID) if err != nil { portal.zlog.Warn().Err(err). Str("participant_id", participant.ID.ParticipantID). @@ -1288,9 +1288,9 @@ func (portal *Portal) SyncParticipants(source *User, metadata *gmproto.Conversat continue } userIDs = append(userIDs, puppet.MXID) - puppet.Sync(source, participant) + puppet.Sync(ctx, source, participant) if portal.MXID != "" { - err := puppet.IntentFor(portal).EnsureJoined(portal.MXID) + err := puppet.IntentFor(portal).EnsureJoined(ctx, portal.MXID) if err != nil { portal.zlog.Err(err). Str("user_id", puppet.MXID.String()). @@ -1313,7 +1313,7 @@ func (portal *Portal) SyncParticipants(source *User, metadata *gmproto.Conversat changed = true } if portal.MXID != "" { - members, err := portal.MainIntent().JoinedMembers(portal.MXID) + members, err := portal.MainIntent().JoinedMembers(ctx, portal.MXID) if err != nil { portal.zlog.Warn().Err(err).Msg("Failed to get joined members") } else { @@ -1323,7 +1323,7 @@ func (portal *Portal) SyncParticipants(source *User, metadata *gmproto.Conversat delete(members.Joined, userID) } for userID := range members.Joined { - _, err = portal.MainIntent().KickUser(portal.MXID, &mautrix.ReqKickUser{ + _, err = portal.MainIntent().KickUser(ctx, portal.MXID, &mautrix.ReqKickUser{ UserID: userID, Reason: "User is not participating in chat", }) @@ -1342,14 +1342,14 @@ func (portal *Portal) SyncParticipants(source *User, metadata *gmproto.Conversat return userIDs, changed } -func (portal *Portal) UpdateName(name string, updateInfo bool) bool { +func (portal *Portal) UpdateName(ctx context.Context, name string, updateInfo bool) bool { if portal.Name != name || (!portal.NameSet && len(portal.MXID) > 0 && portal.shouldSetDMRoomMetadata()) { portal.zlog.Debug().Str("old_name", portal.Name).Str("new_name", name).Msg("Updating name") portal.Name = name portal.NameSet = false if updateInfo { defer func() { - err := portal.Update(context.TODO()) + err := portal.Update(ctx) if err != nil { portal.zlog.Err(err).Msg("Failed to save portal after updating name") } @@ -1357,17 +1357,17 @@ func (portal *Portal) UpdateName(name string, updateInfo bool) bool { } if len(portal.MXID) > 0 && !portal.shouldSetDMRoomMetadata() { - portal.UpdateBridgeInfo() + portal.UpdateBridgeInfo(ctx) } else if len(portal.MXID) > 0 { intent := portal.MainIntent() - _, err := intent.SetRoomName(portal.MXID, name) + _, err := intent.SetRoomName(ctx, portal.MXID, name) if errors.Is(err, mautrix.MForbidden) && intent != portal.MainIntent() { - _, err = portal.MainIntent().SetRoomName(portal.MXID, name) + _, err = portal.MainIntent().SetRoomName(ctx, portal.MXID, name) } if err == nil { portal.NameSet = true if updateInfo { - portal.UpdateBridgeInfo() + portal.UpdateBridgeInfo(ctx) } return true } else { @@ -1378,8 +1378,8 @@ func (portal *Portal) UpdateName(name string, updateInfo bool) bool { return false } -func (portal *Portal) UpdateMetadata(user *User, info *gmproto.Conversation) []id.UserID { - participants, update := portal.SyncParticipants(user, info) +func (portal *Portal) UpdateMetadata(ctx context.Context, user *User, info *gmproto.Conversation) []id.UserID { + participants, update := portal.SyncParticipants(ctx, user, info) if portal.Type != info.Type { portal.zlog.Debug(). Str("old_type", portal.Type.String()). @@ -1397,17 +1397,17 @@ func (portal *Portal) UpdateMetadata(user *User, info *gmproto.Conversation) []i update = true } if portal.MXID != "" { - update = portal.addToPersonalSpace(user, false) || update + update = portal.addToPersonalSpace(ctx, user, false) || update } if portal.shouldSetDMRoomMetadata() { - update = portal.UpdateName(info.Name, false) || update + update = portal.UpdateName(ctx, info.Name, false) || update } if portal.MXID != "" { - pls, err := portal.MainIntent().PowerLevels(portal.MXID) + pls, err := portal.MainIntent().PowerLevels(ctx, portal.MXID) if err != nil { portal.zlog.Warn().Err(err).Msg("Failed to get power levels") } else if portal.updatePowerLevels(info, pls) { - resp, err := portal.MainIntent().SetPowerLevels(portal.MXID, pls) + resp, err := portal.MainIntent().SetPowerLevels(ctx, portal.MXID, pls) if err != nil { portal.zlog.Warn().Err(err).Msg("Failed to update power levels") } else { @@ -1418,19 +1418,19 @@ func (portal *Portal) UpdateMetadata(user *User, info *gmproto.Conversation) []i // TODO avatar if update { - err := portal.Update(context.TODO()) + err := portal.Update(ctx) if err != nil { portal.zlog.Err(err).Msg("Failed to save portal after updating metadata") } if portal.MXID != "" { - portal.UpdateBridgeInfo() + portal.UpdateBridgeInfo(ctx) } } return participants } -func (portal *Portal) ensureUserInvited(user *User) bool { - return user.ensureInvited(portal.MainIntent(), portal.MXID, portal.IsPrivateChat()) +func (portal *Portal) ensureUserInvited(ctx context.Context, user *User) bool { + return user.ensureInvited(ctx, portal.MainIntent(), portal.MXID, portal.IsPrivateChat()) } func (portal *Portal) GetBasePowerLevels() *event.PowerLevelsEventContent { @@ -1504,19 +1504,19 @@ func (portal *Portal) getBridgeInfo() (string, event.BridgeEventContent) { return portal.getBridgeInfoStateKey(), content } -func (portal *Portal) UpdateBridgeInfo() { +func (portal *Portal) UpdateBridgeInfo(ctx context.Context) { if len(portal.MXID) == 0 { portal.zlog.Debug().Msg("Not updating bridge info: no Matrix room created") return } portal.zlog.Debug().Msg("Updating bridge info...") stateKey, content := portal.getBridgeInfo() - _, err := portal.MainIntent().SendStateEvent(portal.MXID, event.StateBridge, stateKey, content) + _, err := portal.MainIntent().SendStateEvent(ctx, portal.MXID, event.StateBridge, stateKey, content) if err != nil { portal.zlog.Warn().Err(err).Msg("Failed to update m.bridge") } // TODO remove this once https://github.com/matrix-org/matrix-doc/pull/2346 is in spec - _, err = portal.MainIntent().SendStateEvent(portal.MXID, event.StateHalfShotBridge, stateKey, content) + _, err = portal.MainIntent().SendStateEvent(ctx, portal.MXID, event.StateHalfShotBridge, stateKey, content) if err != nil { portal.zlog.Warn().Err(err).Msg("Failed to update uk.half-shot.bridge") } @@ -1538,7 +1538,7 @@ func (portal *Portal) GetEncryptionEventContent() (evt *event.EncryptionEventCon return } -func (portal *Portal) CreateMatrixRoom(user *User, conv *gmproto.Conversation, isFromSync bool) error { +func (portal *Portal) CreateMatrixRoom(ctx context.Context, user *User, conv *gmproto.Conversation, isFromSync bool) error { portal.roomCreateLock.Lock() defer portal.roomCreateLock.Unlock() if len(portal.MXID) > 0 { @@ -1554,7 +1554,7 @@ func (portal *Portal) CreateMatrixRoom(user *User, conv *gmproto.Conversation, i } } - members := portal.UpdateMetadata(user, conv) + members := portal.UpdateMetadata(ctx, user, conv) var avatarURL id.ContentURI if portal.IsPrivateChat() { @@ -1569,7 +1569,7 @@ func (portal *Portal) CreateMatrixRoom(user *User, conv *gmproto.Conversation, i } intent := portal.MainIntent() - if err = intent.EnsureRegistered(); err != nil { + if err = intent.EnsureRegistered(ctx); err != nil { return err } @@ -1639,7 +1639,7 @@ func (portal *Portal) CreateMatrixRoom(user *User, conv *gmproto.Conversation, i if !portal.shouldSetDMRoomMetadata() { req.Name = "" } - resp, err := intent.CreateRoom(req) + resp, err := intent.CreateRoom(ctx, req) if err != nil { return err } @@ -1663,37 +1663,38 @@ func (portal *Portal) CreateMatrixRoom(user *User, conv *gmproto.Conversation, i inviteMembership = event.MembershipJoin } for _, userID := range invite { - portal.bridge.StateStore.SetMembership(portal.MXID, userID, inviteMembership) + // TODO handle errors + portal.bridge.StateStore.SetMembership(ctx, portal.MXID, userID, inviteMembership) } if !autoJoinInvites { if !portal.IsPrivateChat() { - portal.SyncParticipants(user, conv) + portal.SyncParticipants(ctx, user, conv) } else { if portal.bridge.Config.Bridge.Encryption.Default { - err = portal.bridge.Bot.EnsureJoined(portal.MXID) + err = portal.bridge.Bot.EnsureJoined(ctx, portal.MXID) if err != nil { portal.zlog.Err(err).Msg("Failed to join created portal with bridge bot for e2be") } } - user.UpdateDirectChats(map[id.UserID][]id.RoomID{portal.GetDMPuppet().MXID: {portal.MXID}}) + user.UpdateDirectChats(ctx, map[id.UserID][]id.RoomID{portal.GetDMPuppet().MXID: {portal.MXID}}) } - portal.ensureUserInvited(user) + portal.ensureUserInvited(ctx, user) } - user.syncChatDoublePuppetDetails(portal, conv, true) + user.syncChatDoublePuppetDetails(ctx, portal, conv, true) allowNotify := !isFromSync go portal.initialForwardBackfill(user, !conv.GetUnread(), allowNotify) - go portal.addToPersonalSpace(user, true) + go portal.addToPersonalSpace(context.TODO(), user, true) return nil } -func (portal *Portal) addToPersonalSpace(user *User, updateInfo bool) bool { - spaceID := user.GetSpaceRoom() +func (portal *Portal) addToPersonalSpace(ctx context.Context, user *User, updateInfo bool) bool { + spaceID := user.GetSpaceRoom(ctx) if len(spaceID) == 0 || portal.InSpace { return false } - _, err := portal.bridge.Bot.SendStateEvent(spaceID, event.StateSpaceChild, portal.MXID.String(), &event.SpaceChildEventContent{ + _, err := portal.bridge.Bot.SendStateEvent(ctx, spaceID, event.StateSpaceChild, portal.MXID.String(), &event.SpaceChildEventContent{ Via: []string{portal.bridge.Config.Homeserver.Domain}, }) if err != nil { @@ -1704,7 +1705,7 @@ func (portal *Portal) addToPersonalSpace(user *User, updateInfo bool) bool { portal.InSpace = true } if updateInfo { - err = portal.Update(context.TODO()) + err = portal.Update(ctx) if err != nil { portal.zlog.Err(err).Msg("Failed to update portal after adding to personal space") } @@ -1731,11 +1732,11 @@ func (portal *Portal) MainIntent() *appservice.IntentAPI { return portal.bridge.Bot } -func (portal *Portal) sendMainIntentMessage(content *event.MessageEventContent) (*mautrix.RespSendEvent, error) { - return portal.sendMessage(portal.MainIntent(), event.EventMessage, content, nil, 0) +func (portal *Portal) sendMainIntentMessage(ctx context.Context, content *event.MessageEventContent) (*mautrix.RespSendEvent, error) { + return portal.sendMessage(ctx, portal.MainIntent(), event.EventMessage, content, nil, 0) } -func (portal *Portal) encrypt(intent *appservice.IntentAPI, content *event.Content, eventType event.Type) (event.Type, error) { +func (portal *Portal) encrypt(ctx context.Context, intent *appservice.IntentAPI, content *event.Content, eventType event.Type) (event.Type, error) { if !portal.Encrypted || portal.bridge.Crypto == nil { return eventType, nil } @@ -1743,26 +1744,26 @@ func (portal *Portal) encrypt(intent *appservice.IntentAPI, content *event.Conte // TODO maybe the locking should be inside mautrix-go? portal.encryptLock.Lock() defer portal.encryptLock.Unlock() - err := portal.bridge.Crypto.Encrypt(portal.MXID, eventType, content) + err := portal.bridge.Crypto.Encrypt(ctx, portal.MXID, eventType, content) if err != nil { return eventType, fmt.Errorf("failed to encrypt event: %w", err) } return event.EventEncrypted, nil } -func (portal *Portal) sendMessage(intent *appservice.IntentAPI, eventType event.Type, content *event.MessageEventContent, extraContent map[string]interface{}, timestamp int64) (*mautrix.RespSendEvent, error) { +func (portal *Portal) sendMessage(ctx context.Context, intent *appservice.IntentAPI, eventType event.Type, content *event.MessageEventContent, extraContent map[string]interface{}, timestamp int64) (*mautrix.RespSendEvent, error) { wrappedContent := event.Content{Parsed: content, Raw: extraContent} var err error - eventType, err = portal.encrypt(intent, &wrappedContent, eventType) + eventType, err = portal.encrypt(ctx, intent, &wrappedContent, eventType) if err != nil { return nil, err } - _, _ = intent.UserTyping(portal.MXID, false, 0) + _, _ = intent.UserTyping(ctx, portal.MXID, false, 0) if timestamp == 0 { - return intent.SendMessageEvent(portal.MXID, eventType, &wrappedContent) + return intent.SendMessageEvent(ctx, portal.MXID, eventType, &wrappedContent) } else { - return intent.SendMassagedMessageEvent(portal.MXID, eventType, &wrappedContent, timestamp) + return intent.SendMassagedMessageEvent(ctx, portal.MXID, eventType, &wrappedContent, timestamp) } } @@ -1779,7 +1780,7 @@ func (portal *Portal) encryptFileInPlace(data []byte, mimeType string) (string, return "application/octet-stream", file } -func (portal *Portal) uploadMedia(intent *appservice.IntentAPI, data []byte, content *event.MessageEventContent) error { +func (portal *Portal) uploadMedia(ctx context.Context, intent *appservice.IntentAPI, data []byte, content *event.MessageEventContent) error { uploadMimeType, file := portal.encryptFileInPlace(data, content.Info.MimeType) req := mautrix.ReqUploadMedia{ @@ -1788,13 +1789,13 @@ func (portal *Portal) uploadMedia(intent *appservice.IntentAPI, data []byte, con } var mxc id.ContentURI if portal.bridge.Config.Homeserver.AsyncMedia { - uploaded, err := intent.UploadAsync(req) + uploaded, err := intent.UploadAsync(ctx, req) if err != nil { return err } mxc = uploaded.ContentURI } else { - uploaded, err := intent.UploadMedia(req) + uploaded, err := intent.UploadMedia(ctx, req) if err != nil { return err } @@ -1906,7 +1907,7 @@ func (portal *Portal) reuploadMedia(ctx context.Context, sender *User, content * if url.IsEmpty() { return nil, errMissingMediaURL } - data, err := portal.MainIntent().DownloadBytesContext(ctx, url) + data, err := portal.MainIntent().DownloadBytes(ctx, url) if err != nil { return nil, exerrors.NewDualError(errMediaDownloadFailed, err) } @@ -1957,7 +1958,7 @@ func (portal *Portal) HandleMatrixMessage(sender *User, evt *event.Event, timing req, err := portal.convertMatrixMessage(ctx, sender, content, txnID) timings.convert = time.Since(start) if err != nil { - go ms.sendMessageMetrics(sender, evt, err, "Error converting", true) + go ms.sendMessageMetrics(ctx, sender, evt, err, "Error converting", true) return } log.Debug(). @@ -1968,11 +1969,11 @@ func (portal *Portal) HandleMatrixMessage(sender *User, evt *event.Event, timing resp, err := sender.Client.SendMessage(req) timings.send = time.Since(start) if err != nil { - go ms.sendMessageMetrics(sender, evt, err, "Error sending", true) + go ms.sendMessageMetrics(ctx, sender, evt, err, "Error sending", true) } else if resp.Status != gmproto.SendMessageResponse_SUCCESS { - go ms.sendMessageMetrics(sender, evt, fmt.Errorf("response status %d", resp.Status), "Error sending", true) + go ms.sendMessageMetrics(ctx, sender, evt, fmt.Errorf("response status %d", resp.Status), "Error sending", true) } else { - go ms.sendMessageMetrics(sender, evt, nil, "", true) + go ms.sendMessageMetrics(ctx, sender, evt, nil, "", true) } } @@ -2019,7 +2020,7 @@ func (portal *Portal) HandleMatrixReadReceipt(brUser bridge.User, eventID id.Eve func (portal *Portal) HandleMatrixReaction(sender *User, evt *event.Event) { err := portal.handleMatrixReaction(sender, evt) - go portal.sendMessageMetrics(sender, evt, err, "Error sending", nil) + go portal.sendMessageMetrics(context.TODO(), sender, evt, err, "Error sending", nil) } func (portal *Portal) handleMatrixReaction(sender *User, evt *event.Event) error { @@ -2070,12 +2071,12 @@ func (portal *Portal) handleMatrixReaction(sender *User, evt *event.Event) error existingReaction.MessageID = msg.ID existingReaction.Sender = portal.OutgoingID } else if sender.DoublePuppetIntent != nil { - _, err = sender.DoublePuppetIntent.RedactEvent(portal.MXID, existingReaction.MXID) + _, err = sender.DoublePuppetIntent.RedactEvent(ctx, portal.MXID, existingReaction.MXID) if err != nil { log.Err(err).Msg("Failed to redact old reaction with double puppet after new Matrix reaction") } } else { - _, err = portal.MainIntent().RedactEvent(portal.MXID, existingReaction.MXID) + _, err = portal.MainIntent().RedactEvent(ctx, portal.MXID, existingReaction.MXID) if err != nil { log.Err(err).Msg("Failed to redact old reaction with main intent after new Matrix reaction") } @@ -2091,7 +2092,7 @@ func (portal *Portal) handleMatrixReaction(sender *User, evt *event.Event) error func (portal *Portal) HandleMatrixRedaction(sender *User, evt *event.Event) { err := portal.handleMatrixRedaction(sender, evt) - go portal.sendMessageMetrics(sender, evt, err, "Error sending", nil) + go portal.sendMessageMetrics(context.TODO(), sender, evt, err, "Error sending", nil) } func (portal *Portal) handleMatrixMessageRedaction(ctx context.Context, sender *User, redacts id.EventID) error { @@ -2159,8 +2160,8 @@ func (portal *Portal) handleMatrixRedaction(sender *User, evt *event.Event) erro return err } -func (portal *Portal) Delete() { - err := portal.Portal.Delete(context.TODO()) +func (portal *Portal) Delete(ctx context.Context) { + err := portal.Portal.Delete(ctx) if err != nil { portal.zlog.Err(err).Msg("Failed to delete portal from database") } @@ -2194,7 +2195,7 @@ func (portal *Portal) RemoveMXID(ctx context.Context) { } } -func (portal *Portal) Cleanup() { +func (portal *Portal) Cleanup(ctx context.Context) { if len(portal.MXID) == 0 { return } @@ -2206,13 +2207,13 @@ func (portal *Portal) Cleanup() { })) } if portal.bridge.SpecVersions.Supports(mautrix.BeeperFeatureRoomYeeting) { - err := intent.BeeperDeleteRoom(portal.MXID) + err := intent.BeeperDeleteRoom(ctx, portal.MXID) if err != nil && !errors.Is(err, mautrix.MNotFound) { portal.zlog.Err(err).Msg("Failed to delete room using hungryserv yeet endpoint") } return } - members, err := intent.JoinedMembers(portal.MXID) + members, err := intent.JoinedMembers(ctx, portal.MXID) if err != nil { portal.zlog.Err(err).Msg("Failed to get portal members for cleanup") return @@ -2222,18 +2223,18 @@ func (portal *Portal) Cleanup() { continue } if portal.bridge.IsGhost(member) { - _, err = portal.bridge.AS.Intent(member).LeaveRoom(portal.MXID) + _, err = portal.bridge.AS.Intent(member).LeaveRoom(ctx, portal.MXID) if err != nil { portal.zlog.Err(err).Msg("Failed to leave as puppet while cleaning up portal") } } else { - _, err = intent.KickUser(portal.MXID, &mautrix.ReqKickUser{UserID: member, Reason: "Deleting portal"}) + _, err = intent.KickUser(ctx, portal.MXID, &mautrix.ReqKickUser{UserID: member, Reason: "Deleting portal"}) if err != nil { portal.zlog.Err(err).Msg("Failed to kick user while cleaning up portal") } } } - _, err = intent.LeaveRoom(portal.MXID) + _, err = intent.LeaveRoom(ctx, portal.MXID) if err != nil { portal.zlog.Err(err).Msg("Failed to leave with main intent while cleaning up portal") } diff --git a/provisioning.go b/provisioning.go index d32b722..8cd426f 100644 --- a/provisioning.go +++ b/provisioning.go @@ -252,7 +252,7 @@ func (prov *ProvisioningAPI) StartChat(w http.ResponseWriter, r *http.Request) { convCopy.LatestMessage = nil prov.zlog.Debug().Any("conversation_data", convCopy).Msg("Got conversation data for start chat") portal := user.GetPortalByID(resp.Conversation.ConversationID) - err = portal.CreateMatrixRoom(user, resp.Conversation, false) + err = portal.CreateMatrixRoom(r.Context(), user, resp.Conversation, false) if err != nil { prov.zlog.Err(err).Msg("Failed to create matrix room") jsonResponse(w, http.StatusInternalServerError, Error{ diff --git a/puppet.go b/puppet.go index f0dd664..e9009dc 100644 --- a/puppet.go +++ b/puppet.go @@ -199,7 +199,7 @@ func (puppet *Puppet) DefaultIntent() *appservice.IntentAPI { const MinAvatarUpdateInterval = 24 * time.Hour -func (puppet *Puppet) UpdateAvatar(source *User) bool { +func (puppet *Puppet) UpdateAvatar(ctx context.Context, source *User) bool { if (puppet.AvatarSet && time.Since(puppet.AvatarUpdateTS) < MinAvatarUpdateInterval) || puppet.ContactID == "" { return false } @@ -226,7 +226,7 @@ func (puppet *Puppet) UpdateAvatar(source *User) bool { puppet.AvatarHash = hash puppet.AvatarSet = false avatarBytes := thumbData.GetImageBuffer() - uploadResp, err := puppet.DefaultIntent().UploadMedia(mautrix.ReqUploadMedia{ + uploadResp, err := puppet.DefaultIntent().UploadMedia(ctx, mautrix.ReqUploadMedia{ ContentBytes: avatarBytes, ContentType: http.DetectContentType(avatarBytes), }) @@ -236,17 +236,17 @@ func (puppet *Puppet) UpdateAvatar(source *User) bool { } puppet.AvatarMXC = uploadResp.ContentURI } - err = puppet.DefaultIntent().SetAvatarURL(puppet.AvatarMXC) + err = puppet.DefaultIntent().SetAvatarURL(ctx, puppet.AvatarMXC) if err != nil { puppet.log.Err(err).Msg("Failed to set avatar") } else { puppet.AvatarSet = true } - go puppet.updatePortalAvatar() + go puppet.updatePortalAvatar(ctx) return true } -func (puppet *Puppet) updatePortalAvatar() { +func (puppet *Puppet) updatePortalAvatar(ctx context.Context) { portal := puppet.bridge.GetPortalByOtherUser(puppet.Key) if portal == nil { return @@ -256,19 +256,19 @@ func (puppet *Puppet) updatePortalAvatar() { if portal.MXID == "" || !portal.shouldSetDMRoomMetadata() { return } - _, err := portal.MainIntent().SetRoomAvatar(portal.MXID, puppet.AvatarMXC) + _, err := portal.MainIntent().SetRoomAvatar(ctx, portal.MXID, puppet.AvatarMXC) if err != nil { puppet.log.Err(err).Str("room_id", portal.MXID.String()).Msg("Failed to update DM room avatar") } } -func (puppet *Puppet) UpdateName(formattedPhone, fullName, firstName string) bool { +func (puppet *Puppet) UpdateName(ctx context.Context, formattedPhone, fullName, firstName string) bool { newName := puppet.bridge.Config.Bridge.FormatDisplayname(formattedPhone, fullName, firstName) if puppet.Name != newName || !puppet.NameSet { oldName := puppet.Name puppet.Name = newName puppet.NameSet = false - err := puppet.DefaultIntent().SetDisplayName(newName) + err := puppet.DefaultIntent().SetDisplayName(ctx, newName) if err == nil { puppet.log.Debug().Str("old_name", oldName).Str("new_name", newName).Msg("Updated displayname") puppet.NameSet = true @@ -280,7 +280,7 @@ func (puppet *Puppet) UpdateName(formattedPhone, fullName, firstName string) boo return false } -func (puppet *Puppet) UpdateContactInfo() bool { +func (puppet *Puppet) UpdateContactInfo(ctx context.Context) bool { if !puppet.bridge.SpecVersions.Supports(mautrix.BeeperFeatureArbitraryProfileMeta) { return false } @@ -298,7 +298,7 @@ func (puppet *Puppet) UpdateContactInfo() bool { "com.beeper.bridge.service": "gmessages", "com.beeper.bridge.network": "gmessages", } - err := puppet.DefaultIntent().BeeperUpdateProfile(contactInfo) + err := puppet.DefaultIntent().BeeperUpdateProfile(ctx, contactInfo) if err != nil { puppet.log.Warn().Err(err).Msg("Failed to store custom contact info in profile") return false @@ -308,8 +308,8 @@ func (puppet *Puppet) UpdateContactInfo() bool { } } -func (puppet *Puppet) Sync(source *User, contact *gmproto.Participant) { - err := puppet.DefaultIntent().EnsureRegistered() +func (puppet *Puppet) Sync(ctx context.Context, source *User, contact *gmproto.Participant) { + err := puppet.DefaultIntent().EnsureRegistered(ctx) if err != nil { puppet.log.Err(err).Msg("Failed to ensure registered") } @@ -323,11 +323,11 @@ func (puppet *Puppet) Sync(source *User, contact *gmproto.Participant) { puppet.ContactID = contact.ContactID update = true } - update = puppet.UpdateName(contact.GetFormattedNumber(), contact.GetFullName(), contact.GetFirstName()) || update - update = puppet.UpdateAvatar(source) || update - update = puppet.UpdateContactInfo() || update + update = puppet.UpdateName(ctx, contact.GetFormattedNumber(), contact.GetFullName(), contact.GetFirstName()) || update + update = puppet.UpdateAvatar(ctx, source) || update + update = puppet.UpdateContactInfo(ctx) || update if update { - err = puppet.Update(context.TODO()) + err = puppet.Update(ctx) if err != nil { puppet.log.Err(err).Msg("Failed to save puppet to database after sync") } diff --git a/user.go b/user.go index 98aa19a..784165e 100644 --- a/user.go +++ b/user.go @@ -239,7 +239,7 @@ func (br *GMBridge) NewUser(dbUser *database.User) *User { return user } -func (user *User) ensureInvited(intent *appservice.IntentAPI, roomID id.RoomID, isDirect bool) (ok bool) { +func (user *User) ensureInvited(ctx context.Context, intent *appservice.IntentAPI, roomID id.RoomID, isDirect bool) (ok bool) { extraContent := make(map[string]any) if isDirect { extraContent["is_direct"] = true @@ -247,10 +247,11 @@ func (user *User) ensureInvited(intent *appservice.IntentAPI, roomID id.RoomID, if user.DoublePuppetIntent != nil { extraContent["fi.mau.will_auto_accept"] = true } - _, err := intent.InviteUser(roomID, &mautrix.ReqInviteUser{UserID: user.MXID}, extraContent) + _, err := intent.InviteUser(ctx, roomID, &mautrix.ReqInviteUser{UserID: user.MXID}, extraContent) var httpErr mautrix.HTTPError if err != nil && errors.As(err, &httpErr) && httpErr.RespError != nil && strings.Contains(httpErr.RespError.Err, "is already in the room") { - user.bridge.StateStore.SetMembership(roomID, user.MXID, event.MembershipJoin) + // TODO log errors from SetMembership + user.bridge.StateStore.SetMembership(ctx, roomID, user.MXID, event.MembershipJoin) ok = true return } else if err != nil { @@ -260,7 +261,7 @@ func (user *User) ensureInvited(intent *appservice.IntentAPI, roomID id.RoomID, } if user.DoublePuppetIntent != nil { - err = user.DoublePuppetIntent.EnsureJoined(roomID, appservice.EnsureJoinedParams{IgnoreCache: true}) + err = user.DoublePuppetIntent.EnsureJoined(ctx, roomID, appservice.EnsureJoinedParams{IgnoreCache: true}) if err != nil { user.zlog.Warn().Err(err).Str("room_id", roomID.String()).Msg("Failed to auto-join room") ok = false @@ -271,7 +272,7 @@ func (user *User) ensureInvited(intent *appservice.IntentAPI, roomID id.RoomID, return } -func (user *User) GetSpaceRoom() id.RoomID { +func (user *User) GetSpaceRoom(ctx context.Context) id.RoomID { if !user.bridge.Config.Bridge.PersonalFilteringSpaces { return "" } @@ -283,7 +284,7 @@ func (user *User) GetSpaceRoom() id.RoomID { return user.SpaceRoom } - resp, err := user.bridge.Bot.CreateRoom(&mautrix.ReqCreateRoom{ + resp, err := user.bridge.Bot.CreateRoom(ctx, &mautrix.ReqCreateRoom{ Visibility: "private", Name: "Google Messages", Topic: "Your Google Messages bridged chats", @@ -314,17 +315,17 @@ func (user *User) GetSpaceRoom() id.RoomID { if err != nil { user.zlog.Err(err).Msg("Failed to update database after creating space room") } - user.ensureInvited(user.bridge.Bot, user.SpaceRoom, false) + user.ensureInvited(ctx, user.bridge.Bot, user.SpaceRoom, false) } - } else if !user.spaceMembershipChecked && !user.bridge.StateStore.IsInRoom(user.SpaceRoom, user.MXID) { - user.ensureInvited(user.bridge.Bot, user.SpaceRoom, false) + } else if !user.spaceMembershipChecked && !user.bridge.StateStore.IsInRoom(ctx, user.SpaceRoom, user.MXID) { + user.ensureInvited(ctx, user.bridge.Bot, user.SpaceRoom, false) } user.spaceMembershipChecked = true return user.SpaceRoom } -func (user *User) GetManagementRoom() id.RoomID { +func (user *User) GetManagementRoom(ctx context.Context) id.RoomID { if len(user.ManagementRoom) == 0 { user.mgmtCreateLock.Lock() defer user.mgmtCreateLock.Unlock() @@ -335,7 +336,7 @@ func (user *User) GetManagementRoom() id.RoomID { if !user.bridge.Config.Bridge.FederateRooms { creationContent["m.federate"] = false } - resp, err := user.bridge.Bot.CreateRoom(&mautrix.ReqCreateRoom{ + resp, err := user.bridge.Bot.CreateRoom(ctx, &mautrix.ReqCreateRoom{ Topic: "Google Messages bridge notices", IsDirect: true, CreationContent: creationContent, @@ -354,10 +355,11 @@ func (user *User) SetManagementRoom(roomID id.RoomID) { Str("management_room_id", roomID.String()). Str("action", "SetManagementRoom"). Logger() + ctx := context.TODO() existingUser, ok := user.bridge.managementRooms[roomID] if ok { existingUser.ManagementRoom = "" - err := existingUser.Update(context.TODO()) + err := existingUser.Update(ctx) if err != nil { log.Err(err). Str("prev_user_id", existingUser.MXID.String()). @@ -367,7 +369,7 @@ func (user *User) SetManagementRoom(roomID id.RoomID) { user.ManagementRoom = roomID user.bridge.managementRooms[user.ManagementRoom] = user - err := user.Update(context.TODO()) + err := user.Update(ctx) if err != nil { log.Err(err).Msg("Failed to update database with management room ID") } @@ -611,7 +613,7 @@ func (user *User) IsLoggedIn() bool { return user.IsConnected() && user.Client.IsLoggedIn() } -func (user *User) sendMarkdownBridgeAlert(important bool, formatString string, args ...interface{}) { +func (user *User) sendMarkdownBridgeAlert(ctx context.Context, important bool, formatString string, args ...interface{}) { if user.bridge.Config.Bridge.DisableBridgeAlerts { return } @@ -620,13 +622,14 @@ func (user *User) sendMarkdownBridgeAlert(important bool, formatString string, a if !important { content.MsgType = event.MsgNotice } - _, err := user.bridge.Bot.SendMessageEvent(user.GetManagementRoom(), event.EventMessage, content) + _, err := user.bridge.Bot.SendMessageEvent(ctx, user.GetManagementRoom(ctx), event.EventMessage, content) if err != nil { user.zlog.Warn().Err(err).Str("notice", notice).Msg("Failed to send bridge alert") } } func (user *User) syncHandleEvent(event any) { + ctx := context.TODO() switch v := event.(type) { case *events.ListenFatalError: go user.Logout(status.BridgeState{ @@ -634,7 +637,7 @@ func (user *User) syncHandleEvent(event any) { Error: GMFatalError, Info: map[string]any{"go_error": v.Error.Error()}, }, false) - go user.sendMarkdownBridgeAlert(true, "Fatal error while listening to Google Messages: %v - Log in again to continue using the bridge", v.Error) + go user.sendMarkdownBridgeAlert(ctx, true, "Fatal error while listening to Google Messages: %v - Log in again to continue using the bridge", v.Error) case *events.ListenTemporaryError: user.longPollingError = v.Error user.BridgeState.Send(status.BridgeState{ @@ -643,14 +646,14 @@ func (user *User) syncHandleEvent(event any) { Info: map[string]any{"go_error": v.Error.Error()}, }) if !user.pollErrorAlertSent { - go user.sendMarkdownBridgeAlert(false, "Temporary error while listening to Google Messages: %v", v.Error) + go user.sendMarkdownBridgeAlert(ctx, false, "Temporary error while listening to Google Messages: %v", v.Error) user.pollErrorAlertSent = true } case *events.ListenRecovered: user.longPollingError = nil user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) if user.pollErrorAlertSent { - go user.sendMarkdownBridgeAlert(false, "Reconnected to Google Messages") + go user.sendMarkdownBridgeAlert(ctx, false, "Reconnected to Google Messages") user.pollErrorAlertSent = false } case *events.PhoneNotResponding: @@ -658,14 +661,14 @@ func (user *User) syncHandleEvent(event any) { user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) // TODO make this properly configurable if user.zlog.Trace().Enabled() && !user.phoneNotRespondingAlertSent { - go user.sendMarkdownBridgeAlert(false, "Phone is not responding") + go user.sendMarkdownBridgeAlert(ctx, false, "Phone is not responding") user.phoneNotRespondingAlertSent = true } case *events.PhoneRespondingAgain: user.phoneResponding = true user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) if user.phoneNotRespondingAlertSent { - go user.sendMarkdownBridgeAlert(false, "Phone is responding again") + go user.sendMarkdownBridgeAlert(ctx, false, "Phone is responding again") user.phoneNotRespondingAlertSent = false } case *events.PingFailed: @@ -710,14 +713,14 @@ func (user *User) syncHandleEvent(event any) { StateEvent: status.StateBadCredentials, Error: GMUnpaired, }, false) - go user.sendMarkdownBridgeAlert(true, "Unpaired from Google Messages. Log in again to continue using the bridge.") + go user.sendMarkdownBridgeAlert(ctx, true, "Unpaired from Google Messages. Log in again to continue using the bridge.") case *events.GaiaLoggedOut: user.zlog.Info().Msg("Got gaia logout event") go user.Logout(status.BridgeState{ StateEvent: status.StateBadCredentials, Error: GMUnpaired, }, false) - go user.sendMarkdownBridgeAlert(true, "Unpaired from Google Messages. Log in again to continue using the bridge.") + go user.sendMarkdownBridgeAlert(ctx, true, "Unpaired from Google Messages. Log in again to continue using the bridge.") case *events.AuthTokenRefreshed: go func() { err := user.Update(context.TODO()) @@ -755,14 +758,14 @@ func (user *User) ResetState() { portals := user.bridge.GetAllPortalsForUser(user.RowID) user.zlog.Debug().Int("portal_count", len(portals)).Msg("Deleting portals") for _, portal := range portals { - portal.Delete() + portal.Delete(context.TODO()) } user.bridge.DeleteAllPuppetsForUser(user.RowID) user.PhoneID = "" go func() { user.zlog.Debug().Msg("Cleaning up portal rooms in background") for _, portal := range portals { - portal.Cleanup() + portal.Cleanup(context.TODO()) } user.zlog.Debug().Msg("Finished cleaning up portals") }() @@ -810,11 +813,12 @@ func (user *User) handleAccountChange(v *events.AccountChange) { Bool("fake", v.IsFake). Msg("Got account change event") user.switchedToGoogleLogin = v.GetEnabled() || v.IsFake + ctx := context.TODO() if !v.IsFake { if user.switchedToGoogleLogin { - go user.sendMarkdownBridgeAlert(true, "Switched to Google account pairing, please switch back or relogin with `login-google`.") + go user.sendMarkdownBridgeAlert(ctx, true, "Switched to Google account pairing, please switch back or relogin with `login-google`.") } else { - go user.sendMarkdownBridgeAlert(false, "Switched back to QR pairing, bridge should be reconnected") + go user.sendMarkdownBridgeAlert(ctx, false, "Switched back to QR pairing, bridge should be reconnected") // Assume connection is ready now even if it wasn't before user.ready = true } @@ -823,6 +827,7 @@ func (user *User) handleAccountChange(v *events.AccountChange) { } func (user *User) handleUserAlert(v *gmproto.UserAlertEvent) { + ctx := context.TODO() user.zlog.Debug().Str("alert_type", v.GetAlertType().String()).Msg("Got user alert event") becameInactive := false switch v.GetAlertType() { @@ -842,7 +847,7 @@ func (user *User) handleUserAlert(v *gmproto.UserAlertEvent) { Msg("Session ID changed for browser active event, resyncing") user.sessionID = newSessionID go user.fetchAndSyncConversations() - go user.sendMarkdownBridgeAlert(false, "Connected to Google Messages") + go user.sendMarkdownBridgeAlert(ctx, false, "Connected to Google Messages") } else { user.zlog.Debug(). Str("session_id", user.sessionID). @@ -861,13 +866,13 @@ func (user *User) handleUserAlert(v *gmproto.UserAlertEvent) { case gmproto.AlertType_MOBILE_BATTERY_LOW: user.batteryLow = true if time.Since(user.batteryLowAlertSent) > 30*time.Minute { - go user.sendMarkdownBridgeAlert(true, "Your phone's battery is low") + go user.sendMarkdownBridgeAlert(ctx, true, "Your phone's battery is low") user.batteryLowAlertSent = time.Now() } case gmproto.AlertType_MOBILE_BATTERY_RESTORED: user.batteryLow = false if !user.batteryLowAlertSent.IsZero() { - go user.sendMarkdownBridgeAlert(false, "Phone battery restored") + go user.sendMarkdownBridgeAlert(ctx, false, "Phone battery restored") user.batteryLowAlertSent = time.Time{} } default: @@ -877,7 +882,7 @@ func (user *User) handleUserAlert(v *gmproto.UserAlertEvent) { if user.bridge.Config.GoogleMessages.AggressiveReconnect { go user.aggressiveSetActive() } else { - go user.sendMarkdownBridgeAlert(true, "Google Messages was opened in another browser. Use `set-active` to reconnect the bridge.") + go user.sendMarkdownBridgeAlert(ctx, true, "Google Messages was opened in another browser. Use `set-active` to reconnect the bridge.") } } user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) @@ -1003,12 +1008,13 @@ func (user *User) syncConversation(v *gmproto.Conversation, source string) { Str("data_source", source). Interface("conversation_data", convCopy). Logger() + ctx := log.WithContext(context.TODO()) if cancel := portal.cancelCreation.Load(); cancel != nil { if updateType == gmproto.ConversationStatus_SPAM_FOLDER || updateType == gmproto.ConversationStatus_BLOCKED_FOLDER { (*cancel)(fmt.Errorf("conversation was moved to spam")) } else if updateType == gmproto.ConversationStatus_DELETED { (*cancel)(fmt.Errorf("conversation was deleted")) - portal.Delete() + portal.Delete(ctx) } else { log.Debug().Msg("Conversation creation is still pending, ignoring new sync event") return @@ -1018,11 +1024,11 @@ func (user *User) syncConversation(v *gmproto.Conversation, source string) { switch updateType { case gmproto.ConversationStatus_DELETED: log.Info().Msg("Got delete event, cleaning up portal") - portal.Delete() - portal.Cleanup() + portal.Delete(ctx) + portal.Cleanup(ctx) case gmproto.ConversationStatus_SPAM_FOLDER, gmproto.ConversationStatus_BLOCKED_FOLDER: log.Info().Msg("Got spam/block event, cleaning up portal") - portal.Cleanup() + portal.Cleanup(ctx) portal.RemoveMXID(context.TODO()) default: if v.Participants == nil { @@ -1033,9 +1039,10 @@ func (user *User) syncConversation(v *gmproto.Conversation, source string) { return } log.Debug().Msg("Syncing existing portal") - portal.UpdateMetadata(user, v) - user.syncChatDoublePuppetDetails(portal, v, false) + portal.UpdateMetadata(ctx, user, v) + user.syncChatDoublePuppetDetails(ctx, portal, v, false) go portal.missedForwardBackfill( + ctx, user, time.UnixMicro(v.LastMessageTimestamp), v.LatestMessageID, @@ -1064,14 +1071,14 @@ func (user *User) syncConversation(v *gmproto.Conversation, source string) { log.Debug().Err(ctx.Err()).Msg("Portal creation was cancelled") return } - err := portal.CreateMatrixRoom(user, v, source == "sync") + err := portal.CreateMatrixRoom(ctx, user, v, source == "sync") if err != nil { log.Err(err).Msg("Error creating Matrix room from conversation event") } }() } else { log.Debug().Msg("Creating portal for conversation") - err := portal.CreateMatrixRoom(user, v, source == "sync") + err := portal.CreateMatrixRoom(ctx, user, v, source == "sync") if err != nil { log.Err(err).Msg("Error creating Matrix room from conversation event") } @@ -1081,7 +1088,7 @@ func (user *User) syncConversation(v *gmproto.Conversation, source string) { } } -func (user *User) updateChatMute(portal *Portal, mutedUntil time.Time) { +func (user *User) updateChatMute(ctx context.Context, portal *Portal, mutedUntil time.Time) { intent := user.DoublePuppetIntent if intent == nil || len(portal.MXID) == 0 { return @@ -1089,10 +1096,10 @@ func (user *User) updateChatMute(portal *Portal, mutedUntil time.Time) { var err error if mutedUntil.IsZero() && mutedUntil.Before(time.Now()) { user.log.Debugfln("Portal %s is muted until %s, unmuting...", portal.MXID, mutedUntil) - err = intent.DeletePushRule("global", pushrules.RoomRule, string(portal.MXID)) + err = intent.DeletePushRule(ctx, "global", pushrules.RoomRule, string(portal.MXID)) } else { user.log.Debugfln("Portal %s is muted until %s, muting...", portal.MXID, mutedUntil) - err = intent.PutPushRule("global", pushrules.RoomRule, string(portal.MXID), &mautrix.ReqPutPushRule{ + err = intent.PutPushRule(ctx, "global", pushrules.RoomRule, string(portal.MXID), &mautrix.ReqPutPushRule{ Actions: []pushrules.PushActionType{pushrules.ActionDontNotify}, }) } @@ -1110,16 +1117,16 @@ type CustomTagEventContent struct { Tags map[string]CustomTagData `json:"tags"` } -func (user *User) updateChatTag(portal *Portal, tag string, active bool, existingTags CustomTagEventContent) { +func (user *User) updateChatTag(ctx context.Context, portal *Portal, tag string, active bool, existingTags CustomTagEventContent) { var err error currentTag, ok := existingTags.Tags[tag] if active && !ok { user.zlog.Debug().Str("tag", tag).Str("room_id", portal.MXID.String()).Msg("Adding room tag") data := CustomTagData{Order: "0.5", DoublePuppet: user.bridge.Name} - err = user.DoublePuppetIntent.AddTagWithCustomData(portal.MXID, tag, &data) + err = user.DoublePuppetIntent.AddTagWithCustomData(ctx, portal.MXID, tag, &data) } else if !active && ok && currentTag.DoublePuppet == user.bridge.Name { user.zlog.Debug().Str("tag", tag).Str("room_id", portal.MXID.String()).Msg("Removing room tag") - err = user.DoublePuppetIntent.RemoveTag(portal.MXID, tag) + err = user.DoublePuppetIntent.RemoveTag(ctx, portal.MXID, tag) } else { err = nil } @@ -1139,11 +1146,10 @@ type CustomReadMarkers struct { FullyReadExtra CustomReadReceipt `json:"com.beeper.fully_read.extra"` } -func (user *User) markSelfReadFull(portal *Portal, lastMessageID string) { +func (user *User) markSelfReadFull(ctx context.Context, portal *Portal, lastMessageID string) { if user.DoublePuppetIntent == nil || portal.lastUserReadID == lastMessageID { return } - ctx := context.TODO() lastMessage, err := user.bridge.DB.Message.GetByID(ctx, portal.Receiver, lastMessageID) if err == nil && lastMessage == nil || lastMessage.IsFakeMXID() { lastMessage, err = user.bridge.DB.Message.GetLastInChatWithMXID(ctx, portal.Key) @@ -1160,7 +1166,7 @@ func (user *User) markSelfReadFull(portal *Portal, lastMessageID string) { Str("room_id", portal.ID). Str("event_id", lastMessage.MXID.String()). Logger() - err = user.DoublePuppetIntent.SetReadMarkers(portal.MXID, &CustomReadMarkers{ + err = user.DoublePuppetIntent.SetReadMarkers(ctx, portal.MXID, &CustomReadMarkers{ ReqSetReadMarkers: mautrix.ReqSetReadMarkers{ Read: lastMessage.MXID, FullyRead: lastMessage.MXID, @@ -1176,22 +1182,22 @@ func (user *User) markSelfReadFull(portal *Portal, lastMessageID string) { } } -func (user *User) syncChatDoublePuppetDetails(portal *Portal, conv *gmproto.Conversation, justCreated bool) { +func (user *User) syncChatDoublePuppetDetails(ctx context.Context, portal *Portal, conv *gmproto.Conversation, justCreated bool) { if user.DoublePuppetIntent == nil || len(portal.MXID) == 0 { return } if justCreated || !user.bridge.Config.Bridge.TagOnlyOnCreate { var existingTags CustomTagEventContent - err := user.DoublePuppetIntent.GetTagsWithCustomData(portal.MXID, &existingTags) + err := user.DoublePuppetIntent.GetTagsWithCustomData(ctx, portal.MXID, &existingTags) if err != nil && !errors.Is(err, mautrix.MNotFound) { user.zlog.Warn().Err(err).Str("room_id", portal.MXID.String()).Msg("Failed to get existing room tags") } - user.updateChatTag(portal, user.bridge.Config.Bridge.ArchiveTag, conv.Status == gmproto.ConversationStatus_ARCHIVED || conv.Status == gmproto.ConversationStatus_KEEP_ARCHIVED, existingTags) - user.updateChatTag(portal, user.bridge.Config.Bridge.PinnedTag, conv.Pinned, existingTags) + user.updateChatTag(ctx, portal, user.bridge.Config.Bridge.ArchiveTag, conv.Status == gmproto.ConversationStatus_ARCHIVED || conv.Status == gmproto.ConversationStatus_KEEP_ARCHIVED, existingTags) + user.updateChatTag(ctx, portal, user.bridge.Config.Bridge.PinnedTag, conv.Pinned, existingTags) } } -func (user *User) UpdateDirectChats(chats map[id.UserID][]id.RoomID) { +func (user *User) UpdateDirectChats(ctx context.Context, chats map[id.UserID][]id.RoomID) { if !user.bridge.Config.Bridge.SyncDirectChatList || user.DoublePuppetIntent == nil { return } @@ -1205,7 +1211,7 @@ func (user *User) UpdateDirectChats(chats map[id.UserID][]id.RoomID) { var err error if user.bridge.Config.Homeserver.Software == bridgeconfig.SoftwareAsmux { urlPath := intent.BuildClientURL("unstable", "com.beeper.asmux", "dms") - _, err = intent.MakeFullRequest(mautrix.FullRequest{ + _, err = intent.MakeFullRequest(ctx, mautrix.FullRequest{ Method: method, URL: urlPath, Headers: http.Header{"X-Asmux-Auth": {user.bridge.AS.Registration.AppToken}}, @@ -1213,7 +1219,7 @@ func (user *User) UpdateDirectChats(chats map[id.UserID][]id.RoomID) { }) } else { existingChats := make(map[id.UserID][]id.RoomID) - err = intent.GetAccountData(event.AccountDataDirectChats.Type, &existingChats) + err = intent.GetAccountData(ctx, event.AccountDataDirectChats.Type, &existingChats) if err != nil { user.log.Warnln("Failed to get m.direct list to update it:", err) return @@ -1227,21 +1233,21 @@ func (user *User) UpdateDirectChats(chats map[id.UserID][]id.RoomID) { chats[userID] = rooms } } - err = intent.SetAccountData(event.AccountDataDirectChats.Type, &chats) + err = intent.SetAccountData(ctx, event.AccountDataDirectChats.Type, &chats) } if err != nil { user.log.Warnln("Failed to update m.direct list:", err) } } -func (user *User) markUnread(portal *Portal, unread bool) { +func (user *User) markUnread(ctx context.Context, portal *Portal, unread bool) { if user.DoublePuppetIntent == nil { return } log := user.zlog.With().Str("room_id", portal.MXID.String()).Logger() - err := user.DoublePuppetIntent.SetRoomAccountData(portal.MXID, "m.marked_unread", map[string]bool{"unread": unread}) + err := user.DoublePuppetIntent.SetRoomAccountData(ctx, portal.MXID, "m.marked_unread", map[string]bool{"unread": unread}) if err != nil { log.Warn().Err(err).Str("event_type", "m.marked_unread"). Msg("Failed to mark room as unread") @@ -1249,7 +1255,7 @@ func (user *User) markUnread(portal *Portal, unread bool) { log.Debug().Str("event_type", "m.marked_unread").Msg("Marked room as unread") } - err = user.DoublePuppetIntent.SetRoomAccountData(portal.MXID, "com.famedly.marked_unread", map[string]bool{"unread": unread}) + err = user.DoublePuppetIntent.SetRoomAccountData(ctx, portal.MXID, "com.famedly.marked_unread", map[string]bool{"unread": unread}) if err != nil { log.Warn().Err(err).Str("event_type", "com.famedly.marked_unread"). Msg("Failed to mark room as unread")