package rpc import ( "context" "errors" "github.com/gotd/td/tg" "telesrv/internal/domain" ) func (r *Router) onChannelsReadMessageContents(ctx context.Context, req *tg.ChannelsReadMessageContentsRequest) (bool, error) { if r.deps.Channels == nil { return false, notImplementedErr() } if req == nil { return false, inputRequestInvalidErr() } userID, _, err := r.currentUserID(ctx) if err != nil { return false, internalErr() } channelID, err := r.channelIDFromInput(ctx, userID, req.Channel) if err != nil { return false, err } read, err := r.deps.Channels.ReadMessageContents(ctx, userID, domain.ReadChannelMessageContentsRequest{ UserID: userID, ChannelID: channelID, IDs: req.ID, }) if err != nil { if errors.Is(err, domain.ErrMessageIDInvalid) { return false, messageIDInvalidErr() } return false, channelInvalidErr(err) } if ids := readChannelMessageContentIDs(read.Messages); len(ids) > 0 { r.pushUserUpdates(ctx, userID, &tg.Updates{ Updates: []tg.UpdateClass{&tg.UpdateChannelReadMessagesContents{ ChannelID: read.Channel.ID, Messages: ids, }}, Users: []tg.UserClass{}, Chats: []tg.ChatClass{tgChannelChatMin(userID, read.Channel)}, Date: int(r.clock.Now().Unix()), Seq: 0, }) } if len(read.ClearedUnreadReactionMessageIDs) > 0 { r.pushUserUpdates(ctx, userID, r.channelMessagesReactionsUpdates(ctx, userID, domain.ChannelMessageReactionsResult{ Channel: read.Channel, Messages: read.Messages, }, read.ClearedUnreadReactionMessageIDs)) } return true, nil } func (r *Router) onChannelsReadHistory(ctx context.Context, req *tg.ChannelsReadHistoryRequest) (bool, error) { if r.deps.Channels == nil { return true, nil } userID, _, err := r.currentUserID(ctx) if err != nil { return false, internalErr() } channelID, err := r.channelIDFromInput(ctx, userID, req.Channel) if err != nil { return false, err } read, err := r.deps.Channels.ReadHistory(ctx, userID, domain.ReadChannelHistoryRequest{ UserID: userID, ChannelID: channelID, MaxID: req.MaxID, Date: int(r.clock.Now().Unix()), }) if err != nil { return false, channelInvalidErr(err) } if _, err := r.recordChannelReadInbox(ctx, userID, read); err != nil { return false, err } r.pushChannelReadOutboxUpdates(ctx, read.ChannelID, read.OutboxUpdates) r.advanceForumGeneralReadAfterChannelRead(ctx, userID, read) return true, nil } func domainChannelReactionPolicy(req *tg.MessagesSetChatAvailableReactionsRequest) (domain.ChannelReactionPolicy, error) { if req == nil || req.AvailableReactions == nil { return domain.ChannelReactionPolicy{}, tgerr400("REACTION_INVALID") } if req.ReactionsLimit < 0 || req.ReactionsLimit > domain.MaxChannelReactionsLimit { return domain.ChannelReactionPolicy{}, limitInvalidErr() } policy := domain.ChannelReactionPolicy{ Limit: req.ReactionsLimit, PaidEnabled: req.PaidEnabled, } switch reactions := req.AvailableReactions.(type) { case *tg.ChatReactionsNone: policy.Type = domain.ChannelReactionPolicyNone case *tg.ChatReactionsAll: policy.Type = domain.ChannelReactionPolicyAll policy.AllowCustom = reactions.AllowCustom case *tg.ChatReactionsSome: if len(reactions.Reactions) > domain.MaxChannelReactionTypes { return domain.ChannelReactionPolicy{}, limitInvalidErr() } policy.Type = domain.ChannelReactionPolicySome seen := make(map[string]struct{}, len(reactions.Reactions)) for _, reaction := range reactions.Reactions { parsed, err := domainMessageReactionFromTL(reaction) if err != nil { return domain.ChannelReactionPolicy{}, tgerr400("REACTION_INVALID") } key := parsed.Key() if _, ok := seen[key]; ok { continue } seen[key] = struct{}{} switch parsed.Type { case domain.MessageReactionEmoji: policy.Emoticons = append(policy.Emoticons, parsed.Emoticon) case domain.MessageReactionCustomEmoji: policy.CustomEmojiIDs = append(policy.CustomEmojiIDs, parsed.DocumentID) } } default: return domain.ChannelReactionPolicy{}, tgerr400("REACTION_INVALID") } return policy, nil }