owpengram-server/internal/rpc/help.go

132 lines
5.3 KiB
Go
Raw 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"
"time"
"github.com/gotd/td/tg"
androidcompat "telesrv/internal/compat/android"
ioscompat "telesrv/internal/compat/ios"
"telesrv/internal/compat/tdesktop"
)
// registerHelp 注册 help.* RPC handlerDC 配置、最近 DC
func (r *Router) registerHelp(d *tg.ServerDispatcher) {
d.OnHelpGetConfig(func(ctx context.Context) (*tg.Config, error) {
return tdesktop.BuildConfig(r.cfg.DC, r.cfg.IP, r.cfg.Port, r.clock.Now(), r.cfg.PublicBaseURL), nil
})
d.OnHelpGetNearestDC(func(ctx context.Context) (*tg.NearestDC, error) {
return tdesktop.NearestDC(r.cfg.DC), nil
})
d.OnHelpGetInviteText(func(ctx context.Context) (*tg.HelpInviteText, error) {
return &tg.HelpInviteText{Message: "Join me on Telegram."}, nil
})
d.OnHelpGetAppUpdate(func(ctx context.Context, source string) (tg.HelpAppUpdateClass, error) {
if _, _, err := r.currentUserID(ctx); err != nil {
return nil, internalErr()
}
return ioscompat.NoAppUpdate(), nil
})
d.OnHelpGetAppConfig(func(ctx context.Context, hash int) (tg.HelpAppConfigClass, error) {
if r.deps.Help == nil {
return tdesktop.AppConfig(hash), nil
}
cfg, notModified, err := r.deps.Help.GetAppConfig(ctx, hash)
if err != nil {
return nil, internalErr()
}
if notModified {
return &tg.HelpAppConfigNotModified{}, nil
}
return &tg.HelpAppConfig{Hash: cfg.Hash, Config: tgJSONValue(cfg.JSON)}, nil
})
d.OnHelpGetCountriesList(func(ctx context.Context, req *tg.HelpGetCountriesListRequest) (tg.HelpCountriesListClass, error) {
if r.deps.Help == nil {
return tdesktop.CountriesList(req.Hash), nil
}
list, notModified, err := r.deps.Help.GetCountries(ctx, req.LangCode, req.Hash)
if err != nil {
return nil, internalErr()
}
if notModified {
return &tg.HelpCountriesListNotModified{}, nil
}
return tgCountriesList(list), nil
})
d.OnHelpGetTimezonesList(func(ctx context.Context, hash int) (tg.HelpTimezonesListClass, error) {
return tdesktop.TimezonesList(hash), nil
})
d.OnHelpGetPeerColors(func(ctx context.Context, hash int) (tg.HelpPeerColorsClass, error) {
return tdesktop.PeerColors(hash), nil
})
d.OnHelpGetPeerProfileColors(func(ctx context.Context, hash int) (tg.HelpPeerColorsClass, error) {
return tdesktop.PeerProfileColors(hash), nil
})
d.OnHelpGetPromoData(func(ctx context.Context) (tg.HelpPromoDataClass, error) {
return tdesktop.PromoData(r.clock.Now()), nil
})
d.OnHelpGetTermsOfServiceUpdate(func(ctx context.Context) (tg.HelpTermsOfServiceUpdateClass, error) {
return tdesktop.TermsOfServiceUpdate(r.clock.Now()), nil
})
// 客户端遇到无法识别的 tg:// 深链时会查询 help.getDeepLinkInfo。telesrv 不维护
// “需更新 App”的特殊深链提示库对所有 path 返回 deepLinkInfoEmpty——这是规范的
// “无特殊信息”应答DrKLO 仅在收到非空 deepLinkInfo 时才弹“请更新 App”弹窗
// LaunchActivity.java:5175收到 Empty 则静默放行按普通链接处理。此前未注册
// handler 会落 fallback 返回 500 NOT_IMPLEMENTED污染日志且非正确协议行为
d.OnHelpGetDeepLinkInfo(func(ctx context.Context, path string) (tg.HelpDeepLinkInfoClass, error) {
return &tg.HelpDeepLinkInfoEmpty{}, nil
})
d.OnHelpDismissSuggestion(r.onHelpDismissSuggestion)
d.OnHelpGetPremiumPromo(r.onHelpGetPremiumPromo)
}
// onHelpDismissSuggestion 为 DrKLO 改号成功后的 suggestion 清理提供有界兼容。
// Android 会先把 suggestion 从本地状态删除,再发送该 RPC且 generic 500 会被
// 连接层持续重试。当前 server 不发布 pending suggestions故非空 dismissal
// 无需持久化,幂等 BoolTrue 即为完整的当前边界语义。
func (r *Router) onHelpDismissSuggestion(ctx context.Context, req *tg.HelpDismissSuggestionRequest) (bool, error) {
userID, found, err := r.currentUserID(ctx)
if err != nil {
return false, internalErr()
}
if !found {
return false, authKeyUnregisteredErr()
}
if r.userIsBot(ctx, userID) {
return false, botMethodInvalidErr()
}
if req == nil {
return false, nil
}
return androidcompat.DismissSuggestion(req.Suggestion), nil
}
// onHelpGetPremiumPromo 返回最小真实的 Premium 状态页数据:状态文案按 viewer
// 的会员有效期生成videos/period_options 留空——购买入口已被 appConfig
// premium_purchase_blocked=true 关闭,订阅价格 UI 不会消费这些字段TDesktop
// 空 period_options 仅隐藏价格按钮DrKLO 回退到无价文案,均不报错)。
// 六个字段全是 TL 必填项,空值也必须给出空集合而非缺失。
func (r *Router) onHelpGetPremiumPromo(ctx context.Context) (*tg.HelpPremiumPromo, error) {
promo := &tg.HelpPremiumPromo{
StatusText: "Telegram Premium is not active on this account.",
StatusEntities: []tg.MessageEntityClass{},
VideoSections: []string{},
Videos: []tg.DocumentClass{},
PeriodOptions: []tg.PremiumSubscriptionOption{},
Users: []tg.UserClass{},
}
userID, _, err := r.currentUserID(ctx)
if err != nil || r.deps.Users == nil {
return promo, nil
}
u, err := r.deps.Users.Self(ctx, userID)
if err != nil {
return promo, nil
}
if u.PremiumActiveAt(r.clock.Now().Unix()) {
until := time.Unix(int64(u.PremiumUntil), 0)
promo.StatusText = "Telegram Premium is active until " + until.Format("2006-01-02") + "."
}
return promo, nil
}