owpengram-server/internal/rpc/premium.go
2026-06-04 01:37:39 +08:00

142 lines
4 KiB
Go

package rpc
import (
"context"
"github.com/gotd/td/tg"
"telesrv/internal/domain"
)
const (
maxPremiumBoostsListLimit = 100
maxPremiumBoostsOffsetBytes = 128
maxPremiumApplyBoostSlots = 16
)
func (r *Router) registerPremium(d *tg.ServerDispatcher) {
d.OnPremiumGetBoostsStatus(r.onPremiumGetBoostsStatus)
d.OnPremiumGetBoostsList(r.onPremiumGetBoostsList)
d.OnPremiumGetMyBoosts(r.onPremiumGetMyBoosts)
d.OnPremiumApplyBoost(r.onPremiumApplyBoost)
d.OnPremiumGetUserBoosts(r.onPremiumGetUserBoosts)
}
func (r *Router) onPremiumGetBoostsStatus(ctx context.Context, peer tg.InputPeerClass) (*tg.PremiumBoostsStatus, error) {
if _, _, err := r.premiumBoostChannelView(ctx, peer, false); err != nil {
return nil, err
}
return emptyPremiumBoostsStatus(), nil
}
func (r *Router) onPremiumGetBoostsList(ctx context.Context, req *tg.PremiumGetBoostsListRequest) (*tg.PremiumBoostsList, error) {
if req.Limit < 0 || req.Limit > maxPremiumBoostsListLimit || len(req.Offset) > maxPremiumBoostsOffsetBytes {
return nil, limitInvalidErr()
}
if _, _, err := r.premiumBoostChannelView(ctx, req.Peer, true); err != nil {
return nil, err
}
return emptyPremiumBoostsList(), nil
}
func (r *Router) onPremiumGetMyBoosts(ctx context.Context) (*tg.PremiumMyBoosts, error) {
if _, _, err := r.currentUserID(ctx); err != nil {
return nil, internalErr()
}
return emptyPremiumMyBoosts(), nil
}
func (r *Router) onPremiumApplyBoost(ctx context.Context, req *tg.PremiumApplyBoostRequest) (*tg.PremiumMyBoosts, error) {
slots, ok := req.GetSlots()
if !ok {
return nil, tgerr400("BOOSTS_EMPTY")
}
if len(slots) == 0 {
return nil, tgerr400("SLOTS_EMPTY")
}
if len(slots) > maxPremiumApplyBoostSlots {
return nil, limitInvalidErr()
}
for _, slot := range slots {
if slot < 0 {
return nil, tgerr400("SLOTS_INVALID")
}
}
if _, _, err := r.premiumBoostChannelView(ctx, req.Peer, false); err != nil {
return nil, err
}
return emptyPremiumMyBoosts(), nil
}
func (r *Router) onPremiumGetUserBoosts(ctx context.Context, req *tg.PremiumGetUserBoostsRequest) (*tg.PremiumBoostsList, error) {
userID, view, err := r.premiumBoostChannelView(ctx, req.Peer, true)
if err != nil {
return nil, err
}
if _, err := r.userIDsFromInputUsers(ctx, userID, []tg.InputUserClass{req.UserID}); err != nil {
return nil, err
}
_ = view
return emptyPremiumBoostsList(), nil
}
func (r *Router) premiumBoostChannelView(ctx context.Context, peer tg.InputPeerClass, requireAdmin bool) (int64, domain.ChannelView, error) {
ref, ok := premiumBoostChannelRef(peer)
if !ok {
return 0, domain.ChannelView{}, peerIDInvalidErr()
}
input := &tg.InputChannel{ChannelID: ref.ID}
if ref.CheckAccessHash {
input.AccessHash = ref.AccessHash
}
userID, view, err := r.channelView(ctx, input)
if err != nil {
return 0, domain.ChannelView{}, err
}
if requireAdmin && view.Self.Role != domain.ChannelRoleCreator && view.Self.Role != domain.ChannelRoleAdmin {
return 0, domain.ChannelView{}, tgerr400("CHAT_ADMIN_REQUIRED")
}
return userID, view, nil
}
func premiumBoostChannelRef(peer tg.InputPeerClass) (channelInputRef, bool) {
switch p := peer.(type) {
case *tg.InputPeerChannel:
return channelInputRef{
ID: p.ChannelID,
AccessHash: p.AccessHash,
CheckAccessHash: p.AccessHash != 0,
}, p.ChannelID > 0
case *tg.InputPeerChannelFromMessage:
return channelInputRef{ID: p.ChannelID}, p.ChannelID > 0
case *tg.InputPeerChat:
return channelInputRef{ID: p.ChatID}, p.ChatID > 0
default:
return channelInputRef{}, false
}
}
func emptyPremiumBoostsStatus() *tg.PremiumBoostsStatus {
return &tg.PremiumBoostsStatus{
Level: 0,
CurrentLevelBoosts: 0,
Boosts: 0,
BoostURL: "",
}
}
func emptyPremiumBoostsList() *tg.PremiumBoostsList {
return &tg.PremiumBoostsList{
Count: 0,
Boosts: []tg.Boost{},
Users: []tg.UserClass{},
}
}
func emptyPremiumMyBoosts() *tg.PremiumMyBoosts {
return &tg.PremiumMyBoosts{
MyBoosts: []tg.MyBoost{},
Chats: []tg.ChatClass{},
Users: []tg.UserClass{},
}
}