owpengram-server/internal/rpc/ephemeral_push.go
2026-09-01 12:06:31 +03:00

111 lines
3.6 KiB
Go

package rpc
import (
"context"
"time"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
"go.uber.org/zap"
"telesrv/internal/store"
)
const ephemeralPushSubscribeRetry = time.Second
func (r *Router) RunEphemeralPushSubscriber(ctx context.Context) {
if r == nil || r.deps.EphemeralPush == nil {
return
}
for {
err := r.deps.EphemeralPush.SubscribeEphemeralPushes(ctx, func(ctx context.Context, event store.EphemeralPush) {
if event.SourceID == "" || event.SourceID == r.instanceID {
return
}
r.deliverEphemeralPushLocal(ctx, event)
})
if ctx.Err() != nil {
return
}
if err != nil {
r.log.Warn("ephemeral push subscriber stopped", zap.Error(err))
}
select {
case <-ctx.Done():
return
case <-time.After(ephemeralPushSubscribeRetry):
}
}
}
func (r *Router) publishEphemeralPush(ctx context.Context, event store.EphemeralPush) {
if r == nil || event.TargetUserID <= 0 {
return
}
event.SourceID = r.instanceID
if event.Date <= 0 {
event.Date = int(r.clock.Now().Unix())
}
r.deliverEphemeralPushLocal(ctx, event)
if r.deps.EphemeralPush != nil {
if err := r.deps.EphemeralPush.PublishEphemeralPush(ctx, event); err != nil {
r.log.Debug("publish ephemeral push", zap.String("kind", string(event.Kind)), zap.Int64("target_user_id", event.TargetUserID), zap.Error(err))
}
}
}
func (r *Router) deliverEphemeralPushLocal(ctx context.Context, event store.EphemeralPush) {
if r == nil || r.deps.Sessions == nil || event.TargetUserID <= 0 || event.Message.ID <= 0 {
return
}
if online, ok := r.deps.Sessions.(OnlineUserProvider); ok && !online.IsUserOnline(event.TargetUserID) {
return
}
binder, ok := r.deps.Sessions.(SemanticTransientSessionBinder)
if !ok {
return
}
var updates tg.UpdatesClass
var semantic tlprofile.SemanticID
switch event.Kind {
case store.EphemeralPushNew, store.EphemeralPushEdit:
if event.TargetUserID != event.Message.ReceiverUserID || event.Message.Deleted {
return
}
built, err := r.ephemeralMessageUpdates(ctx, event.TargetUserID, event.Message, event.Kind == store.EphemeralPushEdit)
if err != nil {
return
}
updates = built
semantic = tlprofile.SemanticTypeUpdateNewEphemeralMessage
if event.Kind == store.EphemeralPushEdit {
semantic = tlprofile.SemanticTypeUpdateEditEphemeralMessage
}
case store.EphemeralPushDelete:
if !event.Message.Deleted || (event.TargetUserID != event.Message.SenderUserID && event.TargetUserID != event.Message.ReceiverUserID) {
return
}
updates = ephemeralDeleteUpdates(event.Message, event.Date)
semantic = tlprofile.SemanticTypeUpdateDeleteEphemeralMessages
case store.EphemeralPushCallback:
callback := event.Callback
if callback == nil || callback.BotUserID != event.TargetUserID || callback.MessageID != event.Message.ID || callback.Peer != event.Message.Peer {
return
}
update := &tg.UpdateBotCallbackQuery{
QueryID: callback.ID, UserID: callback.UserID, Peer: tgPeer(callback.Peer),
MsgID: callback.MessageID, ChatInstance: callback.ChatInstance,
}
update.SetData(callback.Data)
updates = &tg.Updates{Updates: []tg.UpdateClass{update}, Date: event.Date}
semantic = tlprofile.SemanticTypeUpdateBotCallbackQuery
default:
return
}
if event.TargetBusinessAuthKey != ([8]byte{}) {
_, _ = binder.PushToUserAuthKeyTransientCompatible(ctx, event.TargetUserID, event.TargetBusinessAuthKey, semantic, proto.MessageFromServer, updates, r.cfg.OutboundPushTimeout)
return
}
_, _ = binder.PushToUserTransientCompatible(ctx, event.TargetUserID, semantic, proto.MessageFromServer, updates, r.cfg.OutboundPushTimeout)
}