owpengram-server/internal/rpc/account_themes_compat.go

183 lines
4.9 KiB
Go

package rpc
import (
"context"
"github.com/gotd/td/bin"
"github.com/gotd/td/tg"
)
// DrKLO 12.8.1(Layer 227)发出的 theme 方法构造器比 gotd v0.158 的 schema 更新:
// gotd 的 ServerDispatcher 按构造器 id 匹配,这些「新」id 匹配不上而落到 fallback。
// 字段语义与 gotd 请求结构相同(仅 createTheme/updateTheme 的 settings 在线为单个对象、
// gotd 为 Vector;getTheme 多一个被忽略的 document_id),故这里按 DrKLO 字段序手动解码、
// 复用现有 handler。uploadTheme(0x1c3db333)/saveTheme(0xf257106c) 构造器与 gotd 一致,
// 无需 compat。
const (
legacyCreateThemeID = 0x8432c21f
legacyUpdateThemeID = 0x5cb367d5
legacyInstallThemeID = 0x7ae43737
legacyGetThemeID = 0x8d9d742b
)
// tryLegacyThemeRPC 在 fallback 中尝试处理 DrKLO 的新版 theme 构造器。
// handled=false 表示不是这些构造器,调用方继续原 fallback 流程。
func (r *Router) tryLegacyThemeRPC(ctx context.Context, b *bin.Buffer) (enc bin.Encoder, handled bool, err error) {
id, perr := b.PeekID()
if perr != nil {
return nil, false, nil
}
switch id {
case legacyCreateThemeID:
enc, err = r.legacyCreateTheme(ctx, b)
case legacyUpdateThemeID:
enc, err = r.legacyUpdateTheme(ctx, b)
case legacyInstallThemeID:
enc, err = r.legacyInstallTheme(ctx, b)
case legacyGetThemeID:
enc, err = r.legacyGetTheme(ctx, b)
default:
return nil, false, nil
}
return enc, true, err
}
func boolEncoder(v bool) bin.Encoder {
if v {
return &tg.BoolTrue{}
}
return &tg.BoolFalse{}
}
func (r *Router) legacyCreateTheme(ctx context.Context, b *bin.Buffer) (bin.Encoder, error) {
if _, err := b.ID(); err != nil {
return nil, inputConstructorInvalidErr()
}
flags, err := b.Int32()
if err != nil {
return nil, inputConstructorInvalidErr()
}
slug, err := b.String()
if err != nil {
return nil, inputConstructorInvalidErr()
}
title, err := b.String()
if err != nil {
return nil, inputConstructorInvalidErr()
}
req := &tg.AccountCreateThemeRequest{Slug: slug, Title: title}
if flags&(1<<2) != 0 {
doc, err := tg.DecodeInputDocument(b)
if err != nil {
return nil, inputConstructorInvalidErr()
}
req.SetDocument(doc)
}
if flags&(1<<3) != 0 {
var s tg.InputThemeSettings
if err := s.Decode(b); err != nil {
return nil, inputConstructorInvalidErr()
}
req.SetSettings([]tg.InputThemeSettings{s})
}
return r.onAccountCreateTheme(ctx, req)
}
func (r *Router) legacyUpdateTheme(ctx context.Context, b *bin.Buffer) (bin.Encoder, error) {
if _, err := b.ID(); err != nil {
return nil, inputConstructorInvalidErr()
}
flags, err := b.Int32()
if err != nil {
return nil, inputConstructorInvalidErr()
}
format, err := b.String()
if err != nil {
return nil, inputConstructorInvalidErr()
}
theme, err := tg.DecodeInputTheme(b)
if err != nil {
return nil, inputConstructorInvalidErr()
}
req := &tg.AccountUpdateThemeRequest{Format: format, Theme: theme}
if flags&(1<<0) != 0 {
slug, err := b.String()
if err != nil {
return nil, inputConstructorInvalidErr()
}
req.SetSlug(slug)
}
if flags&(1<<1) != 0 {
title, err := b.String()
if err != nil {
return nil, inputConstructorInvalidErr()
}
req.SetTitle(title)
}
if flags&(1<<2) != 0 {
doc, err := tg.DecodeInputDocument(b)
if err != nil {
return nil, inputConstructorInvalidErr()
}
req.SetDocument(doc)
}
if flags&(1<<3) != 0 {
var s tg.InputThemeSettings
if err := s.Decode(b); err != nil {
return nil, inputConstructorInvalidErr()
}
req.SetSettings([]tg.InputThemeSettings{s})
}
return r.onAccountUpdateTheme(ctx, req)
}
func (r *Router) legacyInstallTheme(ctx context.Context, b *bin.Buffer) (bin.Encoder, error) {
if _, err := b.ID(); err != nil {
return nil, inputConstructorInvalidErr()
}
flags, err := b.Int32()
if err != nil {
return nil, inputConstructorInvalidErr()
}
req := &tg.AccountInstallThemeRequest{}
if flags&(1<<0) != 0 {
req.SetDark(true)
}
// bit1 同时门控 format 与 theme(DrKLO 布局)。
if flags&(1<<1) != 0 {
format, err := b.String()
if err != nil {
return nil, inputConstructorInvalidErr()
}
theme, err := tg.DecodeInputTheme(b)
if err != nil {
return nil, inputConstructorInvalidErr()
}
req.SetFormat(format)
req.SetTheme(theme)
}
ok, err := r.onAccountInstallTheme(ctx, req)
if err != nil {
return nil, err
}
return boolEncoder(ok), nil
}
func (r *Router) legacyGetTheme(ctx context.Context, b *bin.Buffer) (bin.Encoder, error) {
if _, err := b.ID(); err != nil {
return nil, inputConstructorInvalidErr()
}
format, err := b.String()
if err != nil {
return nil, inputConstructorInvalidErr()
}
theme, err := tg.DecodeInputTheme(b)
if err != nil {
return nil, inputConstructorInvalidErr()
}
if _, err := b.Long(); err != nil { // document_id:被服务端忽略
return nil, inputConstructorInvalidErr()
}
req := &tg.AccountGetThemeRequest{Format: format, Theme: theme}
return r.onAccountGetTheme(ctx, req)
}