owpengram-server/internal/rpc/phone_group_call_scheduled.go

112 lines
4.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package rpc
import (
"context"
"github.com/iamxvbaba/td/tg"
"go.uber.org/zap"
"telesrv/internal/domain"
)
// Scheduled video chat定时通话RPC。客户端流程TDesktop calls_group_call.cpp
// createGroupCall(schedule_date) → State::Waiting 倒计时(不 join→ 管理员
// startScheduledGroupCall 清 schedule_date → updateGroupCall无 schedule_date
// 客户端 setScheduledDate(0) 触发 initialJoin 正式入会。开播提醒是 per-viewer 的
// schedule_start_subscribed flagtoggleGroupCallStartSubscription
// applyScheduleSubscription 为单个 viewer 回填 ScheduleStartSubscribed 投影字段。
func (r *Router) applyScheduleSubscription(ctx context.Context, call domain.GroupCall, viewerUserID int64) domain.GroupCall {
if call.ScheduleDate == 0 || viewerUserID == 0 {
return call
}
subs, err := r.deps.GroupCalls.ScheduleSubscriberIDs(ctx, call.ID)
if err != nil {
return call
}
for _, id := range subs {
if id == viewerUserID {
call.ScheduleStartSubscribed = true
break
}
}
return call
}
func (r *Router) onPhoneStartScheduledGroupCall(ctx context.Context, in tg.InputGroupCallClass) (tg.UpdatesClass, error) {
scope, err := r.groupCallScopeFrom(ctx, in)
if err != nil {
return nil, err
}
if scope.call.Conference() || scope.channel.ID == 0 {
return nil, groupCallInvalidErr()
}
if !scope.canManage() {
return nil, tgerr400("CHAT_ADMIN_REQUIRED")
}
call, changed, err := r.deps.GroupCalls.StartScheduled(ctx, scope.call.ID)
if err != nil {
return nil, groupCallErr(err)
}
channel := scope.channel
if !changed {
// 幂等:已开始,只回快照,不重复扇出/服务消息。
return r.groupCallUpdateContainer(ctx, scope.userID, channel,
groupCallUpdateFor(channel, call, scope.userID, true, r.cfg.PublicBaseURL), nil), nil
}
now := int(r.clock.Now().Unix())
// started 服务消息(与即时创建的 started 同构)。
var serviceRes domain.SendChannelMessageResult
if res, err := r.deps.Channels.AppendCallServiceMessage(ctx, channel.ID, scope.userID, now, domain.ChannelMessageAction{
Type: domain.ChannelActionGroupCall,
CallID: call.ID,
CallAccessHash: call.AccessHash,
}); err == nil {
serviceRes = res
_ = r.deps.GroupCalls.SetStartedMessageID(ctx, call.ID, res.Message.ID)
} else {
r.log.Warn("scheduled group call started service message", zap.Int64("channel_id", channel.ID), zap.Error(err))
}
// 扇出updateGroupCallschedule_date 已清,客户端据此自动入会)+ 服务消息。
// 订阅者与普通在线成员走同一在线扇出离线订阅者的推送提醒push notification
// 属通知系统范围,当前不实现(记矩阵 todo
r.pushGroupCallUpdate(ctx, channel, call)
if serviceRes.Event.Pts != 0 {
r.pushGroupCallServiceMessage(ctx, scope.userID, serviceRes)
}
out := r.groupCallUpdateContainer(ctx, scope.userID, channel,
groupCallUpdateFor(channel, call, scope.userID, true, r.cfg.PublicBaseURL), nil)
if serviceRes.Event.Pts != 0 {
if msgUpdate := tgChannelUpdate(scope.userID, serviceRes.Event); msgUpdate != nil {
out.Updates = append(out.Updates, msgUpdate)
}
}
return out, nil
}
func (r *Router) onPhoneToggleGroupCallStartSubscription(ctx context.Context, req *tg.PhoneToggleGroupCallStartSubscriptionRequest) (tg.UpdatesClass, error) {
if req == nil {
return nil, inputRequestInvalidErr()
}
scope, err := r.groupCallScopeFrom(ctx, req.Call)
if err != nil {
return nil, err
}
if !scope.call.Active() {
return nil, groupCallAlreadyDiscardedErr()
}
if scope.call.ScheduleDate == 0 {
// 只有未开始的定时通话才有开播提醒可订。
return nil, groupCallInvalidErr()
}
if err := r.deps.GroupCalls.SetScheduleSubscription(ctx, scope.call.ID, scope.userID, req.Subscribed); err != nil {
return nil, groupCallErr(err)
}
call := scope.call
call.ScheduleStartSubscribed = req.Subscribed
// 订阅是 per-viewer 私有状态:响应给本设备,推送同步本人其它在线设备即可。
update := groupCallUpdateFor(scope.channel, call, scope.userID, scope.canManage(), r.cfg.PublicBaseURL)
r.pushUserMessage(ctx, scope.userID, "schedule subscription update",
r.groupCallUpdateContainer(ctx, scope.userID, scope.channel, update, nil))
return r.groupCallUpdateContainer(ctx, scope.userID, scope.channel, update, nil), nil
}