114 lines
4.1 KiB
Go
114 lines
4.1 KiB
Go
package rpc
|
||
|
||
import (
|
||
"context"
|
||
"github.com/iamxvbaba/td/tg"
|
||
"telesrv/internal/domain"
|
||
)
|
||
|
||
func (r *Router) onChannelsToggleForum(ctx context.Context, req *tg.ChannelsToggleForumRequest) (tg.UpdatesClass, error) {
|
||
return r.applyChannelAdminStateMutation(ctx, req.Channel, func(ctx context.Context, userID, channelID int64) (domain.Channel, error) {
|
||
return r.deps.Channels.SetForum(ctx, userID, channelID, req.Enabled, req.Tabs)
|
||
})
|
||
}
|
||
|
||
func (r *Router) onChannelsToggleViewForumAsMessages(ctx context.Context, req *tg.ChannelsToggleViewForumAsMessagesRequest) (tg.UpdatesClass, error) {
|
||
if r.deps.Channels == nil {
|
||
return nil, notImplementedErr()
|
||
}
|
||
userID, _, err := r.currentUserID(ctx)
|
||
if err != nil {
|
||
return nil, internalErr()
|
||
}
|
||
channelID, err := r.channelIDFromInput(ctx, userID, req.Channel)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
changed, err := r.deps.Channels.SetViewForumAsMessages(ctx, userID, channelID, req.Enabled)
|
||
if err != nil {
|
||
return nil, channelInvalidErr(err)
|
||
}
|
||
if !changed {
|
||
return tgEmptyUpdates(int(r.clock.Now().Unix())), nil
|
||
}
|
||
r.invalidateRPCProjectionForPeer(userID, domain.Peer{Type: domain.PeerTypeChannel, ID: channelID})
|
||
event := domain.UpdateEvent{
|
||
Type: domain.UpdateEventChannelViewForum,
|
||
Peer: domain.Peer{Type: domain.PeerTypeChannel, ID: channelID},
|
||
Bool: req.Enabled,
|
||
PtsCount: 1,
|
||
Date: int(r.clock.Now().Unix()),
|
||
}
|
||
if r.deps.Updates != nil {
|
||
authKeyID, _ := AuthKeyIDFrom(ctx)
|
||
sessionID, _ := SessionIDFrom(ctx)
|
||
event, _, err = r.deps.Updates.RecordChannelViewForumAsMessages(ctx, authKeyID, userID, channelID, req.Enabled, rawAuthKeyIDForOrigin(ctx), sessionID)
|
||
if err != nil {
|
||
return nil, internalErr()
|
||
}
|
||
}
|
||
out := tgUpdateForOutboxEvent(event)
|
||
if out == nil {
|
||
out = tgEmptyUpdates(event.Date)
|
||
}
|
||
r.pushUserUpdatesIfNoReliableDispatch(ctx, userID, out)
|
||
return out, nil
|
||
}
|
||
|
||
func (r *Router) onMessagesUpdatePinnedMessage(ctx context.Context, req *tg.MessagesUpdatePinnedMessageRequest) (tg.UpdatesClass, error) {
|
||
userID, _, err := r.currentUserID(ctx)
|
||
if err != nil {
|
||
return nil, internalErr()
|
||
}
|
||
peer, err := r.checkedDomainPeerFromInputPeer(ctx, userID, req.Peer)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if req.ID <= 0 || req.ID > domain.MaxMessageBoxID {
|
||
return nil, messageIDInvalidErr()
|
||
}
|
||
if peer.Type == domain.PeerTypeUser && peer.ID != 0 {
|
||
return r.updatePrivatePinnedMessage(ctx, userID, peer, req)
|
||
}
|
||
if r.deps.Channels == nil {
|
||
return nil, notImplementedErr()
|
||
}
|
||
if peer.Type != domain.PeerTypeChannel || peer.ID == 0 {
|
||
return nil, peerIDInvalidErr()
|
||
}
|
||
res, err := r.deps.Channels.UpdatePinnedMessage(ctx, userID, domain.UpdateChannelPinnedMessageRequest{
|
||
UserID: userID,
|
||
ChannelID: peer.ID,
|
||
MessageID: req.ID,
|
||
Pinned: !req.Unpin,
|
||
Silent: req.Silent,
|
||
Date: int(r.clock.Now().Unix()),
|
||
})
|
||
if err != nil {
|
||
return nil, channelAdminErr(err)
|
||
}
|
||
r.invalidateRPCProjectionForChannel(res.Channel.ID)
|
||
updates := r.channelPinnedUpdates(userID, res)
|
||
// pin fan-out 异步化(设计 Phase 0),与已异步的 unpinAll(channels_stubs.go) 对齐。
|
||
// builder 无 Users 数组(仅 pinned update + ChatMin),无需 owner 预热。pin 的真实变更由
|
||
// UpdatePinnedChannelMessages{pts} 承载、可经 getChannelDifference 兜底,bundled 的无 pts
|
||
// UpdateChannel 对 pin 冗余(pts payload 已含变更),丢弃无害——与 unpinAll 取舍一致。
|
||
r.enqueueChannelFanout(ctx, channelFanoutMessageBox, userID, res.Channel.ID, res.Event.Pts, res.Recipients, func(_ context.Context, viewerUserID int64) *tg.Updates {
|
||
return r.channelPinnedUpdates(viewerUserID, res)
|
||
})
|
||
return updates, nil
|
||
}
|
||
|
||
func (r *Router) channelPinnedUpdates(viewerUserID int64, res domain.UpdateChannelPinnedMessageResult) *tg.Updates {
|
||
updates := []tg.UpdateClass(nil)
|
||
if update := tgChannelUpdate(viewerUserID, res.Event); update != nil {
|
||
updates = append(updates, update)
|
||
}
|
||
updates = append(updates, &tg.UpdateChannel{ChannelID: res.Channel.ID})
|
||
return &tg.Updates{
|
||
Updates: updates,
|
||
Chats: []tg.ChatClass{tgChannelChatMin(viewerUserID, res.Channel)},
|
||
Date: int(r.clock.Now().Unix()),
|
||
Seq: 0,
|
||
}
|
||
}
|