chore: refresh gramsrv public release

This commit is contained in:
A 2026-06-30 14:37:43 +08:00
parent 75cebe8dbf
commit 70b6820474
1274 changed files with 378751 additions and 59919 deletions

View file

@ -0,0 +1,109 @@
package rpc
import (
"context"
"github.com/gotd/td/tg"
"telesrv/internal/domain"
)
// 群通话推送策略(updateGroupCall / updateGroupCallParticipants / connection 均无
// pts,不进 getDifference):扇出对象统一为「在线群成员」(OnlineChannelMemberUserIDs,
// MaxChannelRealtimeFanout 封顶)——覆盖未入会的面板观察者(Android 点 banner 的
// 参与者列表靠它增量刷新)。离线一致性三板斧:服务消息带频道 pts 可补收;banner 靠
// channel.call_active/call_not_empty flag(拉 dialogs/getFullChannel 重建);房间内
// 状态靠 checkGroupCall 与 version 跳号触发 getGroupParticipants 全量 reload 自愈。
// groupCallOnlineRecipients 返回在线群成员(含 originUserID 本人,推送时由
// pushUserMessage 的 ctx except 排除发起 session、保留其它设备)。
func (r *Router) groupCallOnlineRecipients(channelID int64) []int64 {
provider, ok := r.deps.Sessions.(OnlineUserProvider)
if !ok {
return nil
}
return provider.OnlineChannelMemberUserIDs(channelID, domain.MaxChannelRealtimeFanout)
}
// groupCallUpdateContainer 把单条 update 包进 viewer 视角的 Updates 容器。
func (r *Router) groupCallUpdateContainer(ctx context.Context, viewerUserID int64, channel domain.Channel, update tg.UpdateClass, userIDs []int64) *tg.Updates {
chats := []tg.ChatClass{}
if channel.ID != 0 {
chats = append(chats, tgChannel(viewerUserID, channel, nil))
}
return &tg.Updates{
Updates: []tg.UpdateClass{update},
Users: r.tgUsersForIDs(ctx, viewerUserID, userIDs),
Chats: chats,
Date: int(r.clock.Now().Unix()),
Seq: 0,
}
}
// pushGroupCallUpdate 把 updateGroupCall(call 行变化)推给在线群成员。
func (r *Router) pushGroupCallUpdate(ctx context.Context, channel domain.Channel, call domain.GroupCall) {
recipients := r.groupCallOnlineRecipients(channel.ID)
for _, viewerID := range recipients {
update := &tg.UpdateGroupCall{Call: tgGroupCall(call, viewerID, false)}
update.SetPeer(&tg.PeerChannel{ChannelID: channel.ID})
r.pushUserMessage(ctx, viewerID, "group call update",
r.groupCallUpdateContainer(ctx, viewerID, channel, update, []int64{call.CreatorUserID}))
}
}
// pushGroupCallParticipantsUpdate 把参与者增量(version=N)推给在线群成员。
// 每个 viewer 单独构建:participant.Self flag 是 per-viewer 的。
func (r *Router) pushGroupCallParticipantsUpdate(ctx context.Context, channel domain.Channel, call domain.GroupCall, rows []domain.GroupCallParticipant) {
if len(rows) == 0 {
return
}
userIDs := make([]int64, 0, len(rows))
for _, p := range rows {
userIDs = append(userIDs, p.UserID)
}
recipients := r.groupCallOnlineRecipients(channel.ID)
for _, viewerID := range recipients {
update := &tg.UpdateGroupCallParticipants{
Call: &tg.InputGroupCall{ID: call.ID, AccessHash: call.AccessHash},
Participants: tgGroupCallParticipants(rows, viewerID),
Version: call.Version,
}
r.pushUserMessage(ctx, viewerID, "group call participants",
r.groupCallUpdateContainer(ctx, viewerID, channel, update, userIDs))
}
}
// pushGroupCallServiceMessage 把 started/ended/invite 服务消息(带频道 pts)推给
// 活跃成员(res.Recipients)。复用 channelOperationUpdates 的 per-viewer 构建。
func (r *Router) pushGroupCallServiceMessage(ctx context.Context, originUserID int64, res domain.SendChannelMessageResult) {
if res.Event.Pts == 0 {
return
}
op := domain.CreateChannelResult{
Channel: res.Channel,
Message: res.Message,
Event: res.Event,
Recipients: res.Recipients,
}
r.pushChannelUpdates(ctx, originUserID, res.Channel.ID, res.Recipients, func(viewerUserID int64) *tg.Updates {
return r.channelOperationUpdates(ctx, viewerUserID, op)
})
}
// groupCallMutationFanout 是参与者维度变更后的统一扇出:participants 增量 +
// call_not_empty 翻转时的 channel 维度刷新(Android banner 对 flag 依赖更重)。
func (r *Router) groupCallMutationFanout(ctx context.Context, channel domain.Channel, mut domain.GroupCallMutation) domain.Channel {
r.pushGroupCallParticipantsUpdate(ctx, channel, mut.Call, []domain.GroupCallParticipant{mut.Participant})
wantNotEmpty := mut.Call.Active() && mut.Call.ParticipantsCount > 0
if channel.ActiveCallNotEmpty != wantNotEmpty && r.deps.Channels != nil {
updated, err := r.deps.Channels.SetActiveCall(ctx, channel.ID, channel.ActiveCallID, channel.ActiveCallAccessHash, wantNotEmpty)
if err == nil {
channel = updated
r.pushGroupCallUpdate(ctx, channel, mut.Call)
r.pushChannelStateToMembers(ctx, 0, channel)
}
} else {
r.pushGroupCallUpdate(ctx, channel, mut.Call)
}
return channel
}