mtproto,rpc: support Android legacy startup
(cherry picked from commit 06b6ae2bb2f90bd7cc1d6a8404a82aff507e6821)
This commit is contained in:
parent
6dc42942c8
commit
b435784809
9 changed files with 361 additions and 17 deletions
44
internal/rpc/compat.go
Normal file
44
internal/rpc/compat.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/gotd/td/bin"
|
||||
)
|
||||
|
||||
// dispatchCompat handles explicitly allowlisted legacy TL constructors that are
|
||||
// still emitted by supported clients but are absent from gotd's pinned schema.
|
||||
func (r *Router) dispatchCompat(ctx context.Context, b *bin.Buffer, id uint32) (bin.Encoder, bool, error) {
|
||||
start := time.Now()
|
||||
var (
|
||||
enc bin.Encoder
|
||||
name string
|
||||
err error
|
||||
)
|
||||
|
||||
switch id {
|
||||
case legacyLangpackGetLanguagesTypeID:
|
||||
name = "langpack.getLanguages#800fd57d"
|
||||
enc, err = r.handleLegacyLangpackGetLanguages(ctx, b)
|
||||
default:
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
fields := append([]zap.Field{
|
||||
zap.String("method", name),
|
||||
zap.String("type_id", fmt.Sprintf("%#x", id)),
|
||||
zap.Bool("compat", true),
|
||||
zap.Duration("dur", time.Since(start)),
|
||||
}, r.contextLogFields(ctx)...)
|
||||
if err != nil {
|
||||
fields = append(fields, zap.Error(err))
|
||||
r.log.Info("RPC compat handled", fields...)
|
||||
} else {
|
||||
r.log.Debug("RPC compat handled", fields...)
|
||||
}
|
||||
return enc, true, err
|
||||
}
|
||||
|
|
@ -2,12 +2,19 @@ package rpc
|
|||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/gotd/td/bin"
|
||||
"github.com/gotd/td/tg"
|
||||
)
|
||||
|
||||
const legacyLangpackGetLanguagesTypeID uint32 = 0x800fd57d
|
||||
|
||||
// registerLangpack 注册 langpack.* RPC handler。
|
||||
func (r *Router) registerLangpack(d *tg.ServerDispatcher) {
|
||||
d.OnLangpackGetLanguages(func(ctx context.Context, langPack string) ([]tg.LangPackLanguage, error) {
|
||||
return r.langpackLanguages(ctx, langPack), nil
|
||||
})
|
||||
d.OnLangpackGetLangPack(func(ctx context.Context, req *tg.LangpackGetLangPackRequest) (*tg.LangPackDifference, error) {
|
||||
if r.deps.LangPack == nil {
|
||||
return &tg.LangPackDifference{LangCode: req.LangCode}, nil
|
||||
|
|
@ -39,3 +46,54 @@ func (r *Router) registerLangpack(d *tg.ServerDispatcher) {
|
|||
return tgLangPackStrings(pack.Strings), nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Router) handleLegacyLangpackGetLanguages(ctx context.Context, b *bin.Buffer) (bin.Encoder, error) {
|
||||
if err := b.ConsumeID(legacyLangpackGetLanguagesTypeID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tg.LangPackLanguageVector{Elems: r.langpackLanguages(ctx, "")}, nil
|
||||
}
|
||||
|
||||
func (r *Router) langpackLanguages(ctx context.Context, langPack string) []tg.LangPackLanguage {
|
||||
if langPack == "" {
|
||||
langPack = langPackFromClient(ctx)
|
||||
}
|
||||
_ = langPack
|
||||
return []tg.LangPackLanguage{
|
||||
{
|
||||
Official: true,
|
||||
Name: "English",
|
||||
NativeName: "English",
|
||||
LangCode: "en",
|
||||
PluralCode: "en",
|
||||
StringsCount: 0,
|
||||
TranslatedCount: 0,
|
||||
TranslationsURL: "",
|
||||
},
|
||||
{
|
||||
Official: true,
|
||||
Name: "Chinese (Simplified)",
|
||||
NativeName: "Chinese (Simplified)",
|
||||
LangCode: "zh-hans",
|
||||
PluralCode: "zh",
|
||||
StringsCount: 0,
|
||||
TranslatedCount: 0,
|
||||
TranslationsURL: "",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func langPackFromClient(ctx context.Context) string {
|
||||
info, ok := ClientInfoFrom(ctx)
|
||||
if !ok {
|
||||
return "tdesktop"
|
||||
}
|
||||
if info.LangPack != "" {
|
||||
return info.LangPack
|
||||
}
|
||||
client := strings.ToLower(info.DeviceModel + " " + info.SystemVersion + " " + info.AppVersion)
|
||||
if strings.Contains(client, "android") {
|
||||
return "android"
|
||||
}
|
||||
return "tdesktop"
|
||||
}
|
||||
|
|
|
|||
54
internal/rpc/langpack_compat_test.go
Normal file
54
internal/rpc/langpack_compat_test.go
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"github.com/gotd/td/bin"
|
||||
"github.com/gotd/td/clock"
|
||||
"github.com/gotd/td/tg"
|
||||
)
|
||||
|
||||
func TestLangpackGetLanguagesCurrentAndLegacy(t *testing.T) {
|
||||
r := New(Config{DC: 2, IP: "127.0.0.1", Port: 2398}, Deps{}, zaptest.NewLogger(t), clock.System)
|
||||
|
||||
t.Run("current layer", func(t *testing.T) {
|
||||
var in bin.Buffer
|
||||
if err := (&tg.LangpackGetLanguagesRequest{LangPack: "tdesktop"}).Encode(&in); err != nil {
|
||||
t.Fatalf("encode request: %v", err)
|
||||
}
|
||||
assertLangpackLanguages(t, r, context.Background(), &in)
|
||||
})
|
||||
|
||||
t.Run("legacy android no args", func(t *testing.T) {
|
||||
var in bin.Buffer
|
||||
in.PutID(legacyLangpackGetLanguagesTypeID)
|
||||
ctx := WithClientInfo(context.Background(), ClientInfo{
|
||||
DeviceModel: "Android",
|
||||
AppVersion: "12.7.3",
|
||||
LangCode: "en",
|
||||
})
|
||||
assertLangpackLanguages(t, r, ctx, &in)
|
||||
})
|
||||
}
|
||||
|
||||
func assertLangpackLanguages(t *testing.T, r *Router, ctx context.Context, in *bin.Buffer) {
|
||||
t.Helper()
|
||||
enc, err := r.Dispatch(ctx, [8]byte{}, 0, in)
|
||||
if err != nil {
|
||||
t.Fatalf("dispatch langpack.getLanguages: %v", err)
|
||||
}
|
||||
var out bin.Buffer
|
||||
if err := enc.Encode(&out); err != nil {
|
||||
t.Fatalf("encode response: %v", err)
|
||||
}
|
||||
var langs tg.LangPackLanguageVector
|
||||
if err := langs.Decode(&out); err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if len(langs.Elems) == 0 || langs.Elems[0].LangCode != "en" {
|
||||
t.Fatalf("languages = %+v, want English entry", langs.Elems)
|
||||
}
|
||||
}
|
||||
|
|
@ -306,6 +306,9 @@ func (r *Router) dispatch(ctx context.Context, b *bin.Buffer, depth int) (bin.En
|
|||
return r.dispatch(ctx, &bin.Buffer{Buf: inner.data}, depth+1)
|
||||
|
||||
default:
|
||||
if enc, ok, err := r.dispatchCompat(ctx, b, id); ok {
|
||||
return enc, err
|
||||
}
|
||||
start := time.Now()
|
||||
enc, err := r.dispatcher.Handle(ctx, b)
|
||||
dur := time.Since(start)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue