67 lines
2.5 KiB
Go
67 lines
2.5 KiB
Go
package rpc
|
||
|
||
import (
|
||
"context"
|
||
|
||
"go.uber.org/zap"
|
||
|
||
"telesrv/internal/domain"
|
||
)
|
||
|
||
// sendPhoneCallServiceMessage 把已终结的通话落成 messageActionPhoneCall 历史
|
||
// (完整复刻 pin 服务消息模式,messages_pin.go)。要点:
|
||
// - sender 恒为主叫 AdminID——无论谁发起 discard(官方语义:主叫侧渲染
|
||
// 「呼出」、被叫侧渲染「未接来电/通话 X 分钟」,missed 在被叫侧计未读);
|
||
// - Origin 置零:双方全部设备(含 discard 发起设备)都经 outbox 收到
|
||
// updateNewMessage(带 pts)——发起设备的 RPC 响应里只有 updatePhoneCall,
|
||
// 服务消息必须从 update 流来;离线设备重连经 getDifference 补收,正好
|
||
// 补偿信令直推的不可靠(「未接来电」由此而来);
|
||
// - RandomID 由 callID 确定性派生:状态机保证一通通话只落一次历史,
|
||
// 极端重放也会被发送管道的 random_id 去重吸收;
|
||
// - 失败仅 Warn 不回滚:通话状态是真值,历史是装饰(与 pin 同哲学)。
|
||
//
|
||
// 注意:本路径绕过 RPC 层的 checkSendRateLimit(限速挂在 handler 侧)——
|
||
// 这是有意为之,呼叫轰炸防护由通话并发上限与振铃超时承担。
|
||
func (r *Router) sendPhoneCallServiceMessage(ctx context.Context, call domain.PhoneCall) {
|
||
if r.deps.Messages == nil || !call.Terminal() {
|
||
return
|
||
}
|
||
recipientBlocked, err := r.peerBlocksUser(ctx, call.AdminID, call.ParticipantID)
|
||
if err != nil {
|
||
recipientBlocked = false
|
||
}
|
||
_, err = r.deps.Messages.SendPrivateText(ctx, call.AdminID, domain.SendPrivateTextRequest{
|
||
SenderUserID: call.AdminID,
|
||
RecipientUserID: call.ParticipantID,
|
||
RandomID: phoneCallServiceMessageRandomID(call.ID),
|
||
Media: &domain.MessageMedia{
|
||
Kind: domain.MessageMediaKindService,
|
||
ServiceAction: &domain.MessageServiceAction{
|
||
Kind: domain.MessageServiceActionPhoneCall,
|
||
Call: &domain.MessagePhoneCallAction{
|
||
CallID: call.ID,
|
||
Reason: string(call.DiscardReason),
|
||
Duration: call.Duration,
|
||
Video: call.Video,
|
||
},
|
||
},
|
||
},
|
||
Date: int(r.clock.Now().Unix()),
|
||
RecipientBlocked: recipientBlocked,
|
||
})
|
||
if err != nil {
|
||
r.log.Warn("phone call service message",
|
||
zap.Int64("call_id", call.ID),
|
||
zap.Int64("admin_id", call.AdminID),
|
||
zap.Int64("participant_id", call.ParticipantID),
|
||
zap.Error(err))
|
||
}
|
||
}
|
||
|
||
func phoneCallServiceMessageRandomID(callID int64) int64 {
|
||
id := callID ^ 0x70686f6e6563616c // "phonecal"
|
||
if id == 0 {
|
||
return 1
|
||
}
|
||
return id
|
||
}
|