diff --git a/scnserver/api/ginresp/wrapper.go b/scnserver/api/ginresp/wrapper.go index d7b339a..41dd9ad 100644 --- a/scnserver/api/ginresp/wrapper.go +++ b/scnserver/api/ginresp/wrapper.go @@ -68,7 +68,7 @@ func Wrap(rlacc RequestLogAcceptor, fn WHandlerFunc) gin.HandlerFunc { if scn.Conf.ReqLogEnabled { rlacc.InsertRequestLog(createRequestLog(g, t0, ctr, wrap, nil)) } - + statuscode := wrap.Statuscode() if statuscode/100 != 2 { log.Warn().Str("url", g.Request.Method+"::"+g.Request.URL.String()).Msg(fmt.Sprintf("Request failed with statuscode %d", statuscode)) diff --git a/scnserver/api/handler/compat.go b/scnserver/api/handler/compat.go index 9a7277f..562483b 100644 --- a/scnserver/api/handler/compat.go +++ b/scnserver/api/handler/compat.go @@ -9,7 +9,6 @@ import ( "blackforestbytes.com/simplecloudnotifier/logic" "blackforestbytes.com/simplecloudnotifier/models" "database/sql" - "fmt" "github.com/gin-gonic/gin" "gogs.mikescher.com/BlackForestBytes/goext/dataext" "gogs.mikescher.com/BlackForestBytes/goext/langext" @@ -524,7 +523,7 @@ func (h CompatHandler) Requery(g *gin.Context) ginresp.HTTPResponse { } compMsgs = append(compMsgs, models.CompatMessage{ - Title: compatizeMessageTitle(ctx, h.app, v), + Title: h.app.CompatizeMessageTitle(ctx, v), Body: v.Content, Priority: v.Priority, Timestamp: v.Timestamp().Unix(), @@ -772,7 +771,7 @@ func (h CompatHandler) Expand(g *gin.Context) ginresp.HTTPResponse { Success: true, Message: "ok", Data: models.CompatMessage{ - Title: compatizeMessageTitle(ctx, h.app, msg), + Title: h.app.CompatizeMessageTitle(ctx, msg), Body: msg.Content, Trimmed: langext.Ptr(false), Priority: msg.Priority, @@ -919,16 +918,3 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse { IsPro: user.IsPro, })) } - -func compatizeMessageTitle(ctx *logic.AppContext, app *logic.Application, msg models.Message) string { - if msg.ChannelInternalName == "main" { - return msg.Title - } - - channel, err := app.Database.Primary.GetChannelByID(ctx, msg.ChannelID) - if err != nil { - return fmt.Sprintf("[%s] %s", "%SCN-ERR%", msg.Title) - } - - return fmt.Sprintf("[%s] %s", channel.DisplayName, msg.Title) -} diff --git a/scnserver/api/handler/message.go b/scnserver/api/handler/message.go index d81e27e..69cf997 100644 --- a/scnserver/api/handler/message.go +++ b/scnserver/api/handler/message.go @@ -239,7 +239,7 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex return nil, langext.Ptr(ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create message in db", err)) } - cid, err := h.database.CreateCompatID(ctx, "messageid", msg.MessageID.String()) + compatMsgID, err := h.database.CreateCompatID(ctx, "messageid", msg.MessageID.String()) if err != nil { return nil, langext.Ptr(ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create compat-id", err)) } @@ -284,11 +284,13 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex } var titleOverride *string = nil + var msgidOverride *string = nil if isCompatClient { - titleOverride = langext.Ptr(compatizeMessageTitle(ctx, h.app, msg)) + titleOverride = langext.Ptr(h.app.CompatizeMessageTitle(ctx, msg)) + msgidOverride = langext.Ptr(fmt.Sprintf("%d", compatMsgID)) } - fcmDelivID, err := h.app.DeliverMessage(ctx, client, msg, titleOverride) + fcmDelivID, err := h.app.DeliverMessage(ctx, client, msg, titleOverride, msgidOverride) if err != nil { _, err = h.database.CreateRetryDelivery(ctx, client, msg) if err != nil { @@ -308,6 +310,6 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex User: user, Message: msg, MessageIsOld: false, - CompatMessageID: cid, + CompatMessageID: compatMsgID, }, nil } diff --git a/scnserver/jobs/DeliveryRetryJob.go b/scnserver/jobs/DeliveryRetryJob.go index 0c4e01e..8f88d11 100644 --- a/scnserver/jobs/DeliveryRetryJob.go +++ b/scnserver/jobs/DeliveryRetryJob.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "github.com/rs/zerolog/log" + "gogs.mikescher.com/BlackForestBytes/goext/langext" "gogs.mikescher.com/BlackForestBytes/goext/syncext" "time" ) @@ -156,7 +157,29 @@ func (j *DeliveryRetryJob) redeliver(ctx *logic.SimpleContext, delivery models.D } } else { - fcmDelivID, err := j.app.DeliverMessage(ctx, client, msg, nil) + isCompatClient, err := j.app.Database.Primary.IsCompatClient(ctx, client.ClientID) + if err != nil { + log.Err(err).Str("MessageID", delivery.MessageID.String()).Str("ClientID", client.ClientID.String()).Msg("Failed to get ") + ctx.RollbackTransaction() + return + } + + var titleOverride *string = nil + var msgidOverride *string = nil + if isCompatClient { + + messageIdComp, err := j.app.Database.Primary.ConvertToCompatIDOrCreate(ctx, msg.MessageID.String(), "messageid") + if err != nil { + log.Err(err).Str("MessageID", delivery.MessageID.String()).Str("ClientID", client.ClientID.String()).Msg("Failed to query/create messageid") + ctx.RollbackTransaction() + return + } + + titleOverride = langext.Ptr(j.app.CompatizeMessageTitle(ctx, msg)) + msgidOverride = langext.Ptr(fmt.Sprintf("%d", messageIdComp)) + } + + fcmDelivID, err := j.app.DeliverMessage(ctx, client, msg, titleOverride, msgidOverride) if err == nil { err = j.app.Database.Primary.SetDeliverySuccess(ctx, delivery, fcmDelivID) if err != nil { diff --git a/scnserver/logic/appcontext.go b/scnserver/logic/appcontext.go index b91c383..75a86c8 100644 --- a/scnserver/logic/appcontext.go +++ b/scnserver/logic/appcontext.go @@ -13,6 +13,15 @@ import ( "time" ) +type TxContext interface { + Deadline() (deadline time.Time, ok bool) + Done() <-chan struct{} + Err() error + Value(key any) any + + GetOrCreateTransaction(db db.DatabaseImpl) (sq.Tx, error) +} + type AppContext struct { app *Application inner context.Context diff --git a/scnserver/logic/application.go b/scnserver/logic/application.go index 8427f3e..c9618da 100644 --- a/scnserver/logic/application.go +++ b/scnserver/logic/application.go @@ -9,6 +9,7 @@ import ( "blackforestbytes.com/simplecloudnotifier/push" "context" "errors" + "fmt" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/rs/zerolog/log" @@ -357,8 +358,8 @@ func (app *Application) NormalizeUsername(v string) string { return strings.TrimSpace(v) } -func (app *Application) DeliverMessage(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string) (string, error) { - fcmDelivID, err := app.Pusher.SendNotification(ctx, client, msg, compatTitleOverride) +func (app *Application) DeliverMessage(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string, compatMsgIDOverride *string) (string, error) { + fcmDelivID, err := app.Pusher.SendNotification(ctx, client, msg, compatTitleOverride, compatMsgIDOverride) if err != nil { log.Warn().Str("MessageID", msg.MessageID.String()).Str("ClientID", client.ClientID.String()).Err(err).Msg("FCM Delivery failed") return "", err @@ -372,3 +373,16 @@ func (app *Application) InsertRequestLog(data models.RequestLog) { log.Error().Msg("failed to insert request-log (queue full)") } } + +func (app *Application) CompatizeMessageTitle(ctx TxContext, msg models.Message) string { + if msg.ChannelInternalName == "main" { + return msg.Title + } + + channel, err := app.Database.Primary.GetChannelByID(ctx, msg.ChannelID) + if err != nil { + return fmt.Sprintf("[%s] %s", "%SCN-ERR%", msg.Title) + } + + return fmt.Sprintf("[%s] %s", channel.DisplayName, msg.Title) +} diff --git a/scnserver/push/dummy.go b/scnserver/push/dummy.go index c964731..58d81cc 100644 --- a/scnserver/push/dummy.go +++ b/scnserver/push/dummy.go @@ -12,6 +12,6 @@ func NewDummy() NotificationClient { return &DummyConnector{} } -func (d DummyConnector) SendNotification(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string) (string, error) { +func (d DummyConnector) SendNotification(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string, compatMsgIDOverride *string) (string, error) { return "%DUMMY%", nil } diff --git a/scnserver/push/firebase.go b/scnserver/push/firebase.go index 4d9c8e5..22eb8ba 100644 --- a/scnserver/push/firebase.go +++ b/scnserver/push/firebase.go @@ -53,13 +53,13 @@ type Notification struct { Priority int } -func (fb FirebaseConnector) SendNotification(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string) (string, error) { +func (fb FirebaseConnector) SendNotification(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string, compatMsgIDOverride *string) (string, error) { uri := "https://fcm.googleapis.com/v1/projects/" + fb.fbProject + "/messages:send" jsonBody := gin.H{ "data": gin.H{ - "scn_msg_id": msg.MessageID.String(), + "scn_msg_id": langext.Coalesce(compatMsgIDOverride, msg.MessageID.String()), "usr_msg_id": langext.Coalesce(msg.UserMessageID, ""), "client_id": client.ClientID.String(), "timestamp": strconv.FormatInt(msg.Timestamp().Unix(), 10), diff --git a/scnserver/push/notificationClient.go b/scnserver/push/notificationClient.go index 51ea8ea..2990db8 100644 --- a/scnserver/push/notificationClient.go +++ b/scnserver/push/notificationClient.go @@ -6,5 +6,5 @@ import ( ) type NotificationClient interface { - SendNotification(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string) (string, error) + SendNotification(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string, compatMsgIDOverride *string) (string, error) } diff --git a/scnserver/push/testSink.go b/scnserver/push/testSink.go index 7499c77..74671c5 100644 --- a/scnserver/push/testSink.go +++ b/scnserver/push/testSink.go @@ -11,6 +11,7 @@ type SinkData struct { Message models.Message Client models.Client CompatTitleOverride *string + CompatMsgIDOverride *string } type TestSink struct { @@ -25,7 +26,7 @@ func (d *TestSink) Last() SinkData { return d.Data[len(d.Data)-1] } -func (d *TestSink) SendNotification(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string) (string, error) { +func (d *TestSink) SendNotification(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string, compatMsgIDOverride *string) (string, error) { id, err := langext.NewHexUUID() if err != nil { return "", err @@ -37,6 +38,7 @@ func (d *TestSink) SendNotification(ctx context.Context, client models.Client, m Message: msg, Client: client, CompatTitleOverride: compatTitleOverride, + CompatMsgIDOverride: compatMsgIDOverride, }) return key, nil