move gotd fork into repo. (#111)

- update to latest telegram layer
- remove some references to fields in tg.Entities that don't exist in
the schema
- originally added here:
https://github.com/beeper/td/commit/820929062a2ba0104397bc01235ab58a9cff780e
  - referenced here
-
https://github.com/mautrix/telegramgo/commit/124f0967ed195b5a380c9bd02e170ada9710dde3
-
https://github.com/mautrix/telegramgo/commit/4205047aab2e0639217148b5d125bfaab668bd8e
This commit is contained in:
Adam Van Ymeren
2025-06-27 20:03:37 -07:00
committed by GitHub
parent 0952df0244
commit 7a04f298d2
19264 changed files with 1539697 additions and 84 deletions
+96
View File
@@ -0,0 +1,96 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.interfaceConfig*/ -}}
{{ define "box" }}{{ $f := .Interface }}
// Decode{{ $f.Func }} implements binary de-serialization for {{ $f.Name }}.
func Decode{{ $f.Func }} (buf *bin.Buffer) ({{ $f.Name }}, error) {
id, err := buf.PeekID()
if err != nil {
return nil, err
}
switch id {
{{- range $c := $f.Constructors }}
case {{ $c.Name }}TypeID:
// Decoding {{ $c.RawType }}.
v := {{ $c.Name }}{}
if err := v.Decode(buf); err != nil {
return nil, fmt.Errorf("unable to decode {{ $f.Name }}: %w", err)
}
return &v, nil
{{- end }}
default:
return nil, fmt.Errorf("unable to decode {{ $f.Name }}: %w", bin.NewUnexpectedID(id))
}
}
{{- if $.Config.Flags.TDLibJSON }}
// DecodeTDLibJSON{{ $f.Func }} implements binary de-serialization for {{ $f.Name }}.
func DecodeTDLibJSON{{ $f.Func }} (buf tdjson.Decoder) ({{ $f.Name }}, error) {
id, err := buf.FindTypeID()
if err != nil {
return nil, err
}
switch id {
{{- range $c := $f.Constructors }}
case "{{ $c.RawName }}":
// Decoding {{ $c.RawType }}.
v := {{ $c.Name }}{}
if err := v.DecodeTDLibJSON(buf); err != nil {
return nil, fmt.Errorf("unable to decode {{ $f.Name }}: %w", err)
}
return &v, nil
{{- end }}
default:
return nil, fmt.Errorf("unable to decode {{ $f.Name }}: %w", tdjson.NewUnexpectedID(id))
}
}
{{- end }}
// {{ $f.Func }} boxes the {{ $f.Name }} providing a helper.
type {{ $f.Func }}Box struct {
{{ $f.BaseName }} {{ $f.Name }}
}
// Decode implements bin.Decoder for {{ $f.Func }}Box.
func (b *{{ $f.Func }}Box) Decode(buf *bin.Buffer) error {
if b == nil {
return fmt.Errorf("unable to decode {{ $f.Func }}Box to nil")
}
v, err := Decode{{ $f.Func }}(buf)
if err != nil {
return fmt.Errorf("unable to decode boxed value: %w", err)
}
b.{{ $f.BaseName }} = v
return nil
}
// Encode implements bin.Encode for {{ $f.Func }}Box.
func (b *{{ $f.Func }}Box) Encode(buf *bin.Buffer) error {
if b == nil || b.{{ $f.BaseName }} == nil {
return fmt.Errorf("unable to encode {{ $f.Name }} as nil")
}
return b.{{ $f.BaseName }}.Encode(buf)
}
{{- if $.Config.Flags.TDLibJSON }}
// DecodeTDLibJSON implements bin.Decoder for {{ $f.Func }}Box.
func (b *{{ $f.Func }}Box) DecodeTDLibJSON(buf tdjson.Decoder) error {
if b == nil {
return fmt.Errorf("unable to decode {{ $f.Func }}Box to nil")
}
v, err := DecodeTDLibJSON{{ $f.Func }}(buf)
if err != nil {
return fmt.Errorf("unable to decode boxed value: %w", err)
}
b.{{ $f.BaseName }} = v
return nil
}
// EncodeTDLibJSON implements bin.Encode for {{ $f.Func }}Box.
func (b *{{ $f.Func }}Box) EncodeTDLibJSON(buf tdjson.Encoder) error {
if b == nil || b.{{ $f.BaseName }} == nil {
return fmt.Errorf("unable to encode {{ $f.Name }} as nil")
}
return b.{{ $f.BaseName }}.EncodeTDLibJSON(buf)
}
{{- end }}
{{ end }}
+27
View File
@@ -0,0 +1,27 @@
{{ define "client" }}
{{ $pkg := $.Package }}
{{ template "header" $ }}
// Invoker can invoke raw MTProto rpc calls.
type Invoker interface {
Invoke(ctx context.Context, input bin.Encoder, output bin.Decoder) error
}
// Client implement methods for calling functions from TL schema via Invoker.
type Client struct {
rpc Invoker
}
// Invoker returns Invoker used by this client.
func (c *Client) Invoker() Invoker {
return c.rpc
}
// NewClient creates new Client.
func NewClient(invoker Invoker) *Client {
return &Client{
rpc: invoker,
}
}
{{ end }}
+101
View File
@@ -0,0 +1,101 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
{{ define "decode" }}{{ $s := . }}
// Decode implements bin.Decoder.
func ({{ $s.Receiver }} *{{ $s.Name }}) Decode({{ $s.BufArg }} *bin.Buffer) error {
if {{ $s.Receiver }} == nil {
return fmt.Errorf("can't decode {{ $s.RawType }} to nil")
}
{{ if not $s.Vector -}}
if err := {{ $s.BufArg }}.ConsumeID({{ $s.Name }}TypeID); err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: %w", err)
}
{{- end }}
return {{ $s.Receiver }}.DecodeBare({{ $s.BufArg }})
}
// DecodeBare implements bin.BareDecoder.
func ({{ $s.Receiver }} *{{ $s.Name }}) DecodeBare({{ $s.BufArg }} *bin.Buffer) error {
if {{ $s.Receiver }} == nil {
return fmt.Errorf("can't decode {{ $s.RawType }} to nil")
}
{{- range $f := $s.Fields }}
{{- if $f.ConditionalBool }}
{{ $s.Receiver }}.{{ $f.Name }} = {{ $s.Receiver }}.{{ $f.ConditionalField }}.Has({{ $f.ConditionalIndex }})
{{- else }}
{{- if $f.Conditional}}
if {{ $s.Receiver }}.{{ $f.ConditionalField }}.Has({{ $f.ConditionalIndex }}) {
{{- else}}
{
{{- end }}
{{- if $f.Vector }}
headerLen, err := {{ if $f.BareVector }}{{ $s.BufArg }}.Int(){{ else }}{{ $s.BufArg }}.VectorHeader(){{ end }}
if err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
if headerLen > 0 {
{{ $s.Receiver }}.{{ $f.Name }} = make({{ template "print_type" $f }}, 0, headerLen % bin.PreallocateLimit)
}
for idx := 0; idx < headerLen; idx++ {
{{- if $f.DoubleVector }}
innerLen, err := {{ $s.BufArg }}.VectorHeader()
if err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
var row []{{ $f.Type }}
if innerLen > 0 {
row = make([]{{ $f.Type }}, 0, innerLen % bin.PreallocateLimit)
}
for innerIndex := 0; innerIndex < innerLen; innerLen++ {
{{- end }}
{{- if $f.Interface }}
value, err := Decode{{ $f.InterfaceFunc }}({{ $s.BufArg }})
if err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- else if $f.Encoder }}
var value {{ $f.Type }}
if err := value.Decode{{ if and $f.BareEncoder $f.BareVector }}Bare{{ end }}({{ $s.BufArg }}); err != nil {
return fmt.Errorf("unable to decode{{ if and $f.BareEncoder $f.BareVector }} bare{{ end }} {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- else}}
value, err := {{ $s.BufArg }}.{{ $f.Func }}()
if err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- end }}
{{- if $f.DoubleVector }}
row = append(row, value)
}
{{ $s.Receiver }}.{{ $f.Name }} = append({{ $s.Receiver }}.{{ $f.Name }}, row)
{{- else }}
{{ $s.Receiver }}.{{ $f.Name }} = append({{ $s.Receiver }}.{{ $f.Name }}, value)
{{- end }}
}
{{- else }}
{{- if $f.Interface }}
value, err := Decode{{ $f.InterfaceFunc }}({{ $s.BufArg }})
if err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{ $s.Receiver }}.{{ $f.Name }} = value
{{- else if $f.Encoder }}
if err := {{ $s.Receiver }}.{{ $f.Name }}.Decode({{ $s.BufArg }}); err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- else }}
value, err := {{ $s.BufArg }}.{{ $f.Func }}()
if err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{ $s.Receiver }}.{{ $f.Name }} = value
{{- end }}
{{- end }}
}
{{- end }}
{{- end }}
return nil
}
{{ end }}
+85
View File
@@ -0,0 +1,85 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
{{ define "decode_tdlib_json" }}{{ $s := . }}
// DecodeTDLibJSON implements tdjson.TDLibDecoder.
func ({{ $s.Receiver }} *{{ $s.Name }}) DecodeTDLibJSON({{ $s.BufArg }} tdjson.Decoder) error {
if {{ $s.Receiver }} == nil {
return fmt.Errorf("can't decode {{ $s.RawType }} to nil")
}
return {{ $s.BufArg }}.Obj(func({{ $s.BufArg }} tdjson.Decoder, key []byte) error {
switch string(key) {
case tdjson.TypeField:
if err := {{ $s.BufArg }}.ConsumeID("{{ $s.RawName }}"); err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: %w", err)
}
{{- range $f := $s.Fields }}
case "{{ $f.RawName }}":
{{- if or $f.ConditionalBool $f.Conditional }}
{{ $s.Receiver }}.{{ $f.ConditionalField }}.Set({{ $f.ConditionalIndex }})
{{- end }}
{{- if $f.Vector }}
if err := {{ $s.BufArg }}.Arr(func({{ $s.BufArg }} tdjson.Decoder) error {
{{- if $f.DoubleVector }}
var row []{{ $f.Type }}
if err := {{ $s.BufArg }}.Arr(func({{ $s.BufArg }} tdjson.Decoder) error {
{{- end }}
{{- if $f.Interface }}
value, err := DecodeTDLibJSON{{ $f.InterfaceFunc }}({{ $s.BufArg }})
if err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- else if $f.Encoder }}
var value {{ $f.Type }}
if err := value.DecodeTDLibJSON({{ $s.BufArg }}); err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- else}}
value, err := {{ $s.BufArg }}.{{ $f.Func }}()
if err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- end }}
{{- if $f.DoubleVector }}
row = append(row, value)
return nil
}); err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{ $s.Receiver }}.{{ $f.Name }} = append({{ $s.Receiver }}.{{ $f.Name }}, row)
{{- else }}
{{ $s.Receiver }}.{{ $f.Name }} = append({{ $s.Receiver }}.{{ $f.Name }}, value)
{{- end }}
return nil
}); err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- else }}
{{- if $f.Interface }}
value, err := DecodeTDLibJSON{{ $f.InterfaceFunc }}({{ $s.BufArg }})
if err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{ $s.Receiver }}.{{ $f.Name }} = value
{{- else if $f.Encoder }}
{{- if not (eq $f.Type "bin.Fields") }}
if err := {{ $s.Receiver }}.{{ $f.Name }}.DecodeTDLibJSON({{ $s.BufArg }}); err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- end }}
{{- else }}
value, err := {{ $s.BufArg }}.{{ $f.Func }}()
if err != nil {
return fmt.Errorf("unable to decode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{ $s.Receiver }}.{{ $f.Name }} = value
{{- end }}
{{- end }}
{{- end }}
default:
return {{ $s.BufArg }}.Skip()
}
return nil
})
}
{{ end }}
+71
View File
@@ -0,0 +1,71 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
{{ define "encode" }}{{ $s := . }}
// Encode implements bin.Encoder.
func ({{ $s.Receiver }} *{{ $s.Name }}) Encode({{ $s.BufArg }} *bin.Buffer) error {
if {{ $s.Receiver }} == nil {
return fmt.Errorf("can't encode {{ $s.RawType }} as nil")
}
{{ if not $s.Vector -}}
{{ $s.BufArg }}.PutID({{ $s.Name }}TypeID)
{{- end }}
return {{ $s.Receiver }}.EncodeBare({{ $s.BufArg }})
}
// EncodeBare implements bin.BareEncoder.
func ({{ $s.Receiver }} *{{ $s.Name }}) EncodeBare({{ $s.BufArg }} *bin.Buffer) error {
if {{ $s.Receiver }} == nil {
return fmt.Errorf("can't encode {{ $s.RawType }} as nil")
}
{{- if hasFlags $s }}
{{ $s.Receiver }}.SetFlags()
{{- end }}
{{- range $f := $s.Fields }}
{{- if not $f.ConditionalBool }}
{{- if $f.Conditional }}
if {{ $s.Receiver }}.{{ $f.ConditionalField }}.Has({{ $f.ConditionalIndex }}) {
{{- end }}
{{- if $f.Vector }}
{{ if not $f.BareVector }}{{ $s.BufArg }}.PutVectorHeader(len({{ $s.Receiver }}.{{ $f.Name }})){{ else }}{{ $s.BufArg }}.PutInt(len({{ $s.Receiver }}.{{ $f.Name }})){{- end }}
for {{ if $f.Encoder }}idx{{ else }}_{{ end }}, {{- if $f.DoubleVector }}row{{else}}v{{end}} := range {{ $s.Receiver }}.{{ $f.Name }} {
{{- if $f.DoubleVector }}
{{ $s.BufArg }}.PutVectorHeader(len(row))
for _, v := range row {
{{- end }}
{{- if $f.Encoder }}
{{- if $f.Interface }}
if v == nil {
return fmt.Errorf("unable to encode {{ $s.RawType }}: field {{ $f.RawName }} element with index %d is nil", idx)
}
{{- end}}
if err := v.Encode{{ if and $f.BareEncoder $f.BareVector }}Bare{{ end }}({{ $s.BufArg }}); err != nil {
return fmt.Errorf("unable to encode{{ if and $f.BareEncoder $f.BareVector }} bare{{ end }} {{ $s.RawType }}: field {{ $f.RawName }} element with index %d: %w", idx, err)
}
{{- else }}
{{ $s.BufArg }}.Put{{ $f.Func }}(v)
{{- end }}
{{- if $f.DoubleVector }}
}
{{- end }}
}
{{- else }}
{{- if $f.Encoder }}
{{- if $f.Interface }}
if {{ $s.Receiver }}.{{ $f.Name }} == nil {
return fmt.Errorf("unable to encode {{ $s.RawType }}: field {{ $f.RawName }} is nil")
}
{{- end}}
if err := {{ $s.Receiver }}.{{ $f.Name }}.Encode({{ $s.BufArg }}); err != nil {
return fmt.Errorf("unable to encode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- else }}
{{ $s.BufArg }}.Put{{ $f.Func }}({{ $s.Receiver }}.{{ $f.Name }})
{{- end }}
{{- end }}
{{- if $f.Conditional }}
}
{{- end }}
{{- end }}
{{- end }}
return nil
}
{{ end }}
+75
View File
@@ -0,0 +1,75 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
{{ define "encode_tdlib_json" }}{{ $s := . }}
// EncodeTDLibJSON implements tdjson.TDLibEncoder.
func ({{ $s.Receiver }} *{{ $s.Name }}) EncodeTDLibJSON({{ $s.BufArg }} tdjson.Encoder) error {
if {{ $s.Receiver }} == nil {
return fmt.Errorf("can't encode {{ $s.RawType }} as nil")
}
{{ $s.BufArg }}.ObjStart()
{{ $s.BufArg }}.PutID("{{ $s.RawName }}")
{{ $s.BufArg }}.Comma()
{{- if hasFlags $s }}
{{ $s.Receiver }}.SetFlags()
{{- end }}
{{- range $i, $f := $s.Fields }}
{{- if not $f.ConditionalBool }}
{{- if $f.Conditional }}
if {{ $s.Receiver }}.{{ $f.ConditionalField }}.Has({{ $f.ConditionalIndex }}) {
{{- end }}
{{ $s.BufArg }}.FieldStart("{{ $f.RawName }}")
{{- if $f.Vector }}
{{ $s.BufArg }}.ArrStart()
for {{ if $f.Encoder }}idx{{ else }}_{{ end }}, {{- if $f.DoubleVector }}row{{else}}v{{end}} := range {{ $s.Receiver }}.{{ $f.Name }} {
{{- if $f.DoubleVector }}
{{ $s.BufArg }}.ArrStart()
for _, v := range row {
{{- end }}
{{- if $f.Encoder }}
{{- if $f.Interface }}
if v == nil {
return fmt.Errorf("unable to encode {{ $s.RawType }}: field {{ $f.RawName }} element with index %d is nil", idx)
}
{{- end }}
if err := v.EncodeTDLibJSON({{ $s.BufArg }}); err != nil {
return fmt.Errorf("unable to encode {{ $s.RawType }}: field {{ $f.RawName }} element with index %d: %w", idx, err)
}
{{- else }}
{{ $s.BufArg }}.Put{{ $f.Func }}(v)
{{- end }}
{{ $s.BufArg }}.Comma()
{{- if $f.DoubleVector }}
}
{{ $s.BufArg }}.StripComma()
{{ $s.BufArg }}.ArrEnd()
{{ $s.BufArg }}.Comma()
{{- end }}
}
{{ $s.BufArg }}.StripComma()
{{ $s.BufArg }}.ArrEnd()
{{- else }}
{{- if $f.Encoder }}
{{- if $f.Interface }}
if {{ $s.Receiver }}.{{ $f.Name }} == nil {
return fmt.Errorf("unable to encode {{ $s.RawType }}: field {{ $f.RawName }} is nil")
}
{{- end }}
{{- if not (eq $f.Type "bin.Fields") }}
if err := {{ $s.Receiver }}.{{ $f.Name }}.EncodeTDLibJSON({{ $s.BufArg }}); err != nil {
return fmt.Errorf("unable to encode {{ $s.RawType }}: field {{ $f.RawName }}: %w", err)
}
{{- end }}
{{- else }}
{{ $s.BufArg }}.Put{{ $f.Func }}({{ $s.Receiver }}.{{ $f.Name }})
{{- end }}
{{- end }}
{{- if $f.Conditional }}
}
{{- end }}
{{- end }}
{{ $s.BufArg }}.Comma()
{{- end }}
{{ $s.BufArg }}.StripComma()
{{ $s.BufArg }}.ObjEnd()
return nil
}
{{ end }}
+21
View File
@@ -0,0 +1,21 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.config*/ -}}
{{ define "errors" }}
{{ $pkg := $.Package }}
{{ template "header" $ }}
// Telegram API error types.
const (
{{- range $s := $.Errors }}
Err{{ $s.Name }} = "{{ $s.Type }}"
{{- end }}
)
{{- range $s := $.Errors }}
// Is{{ $s.Name }} reports whether err is {{ $s.Type }}.
func Is{{ $s.Name }}(err error) bool {
return tgerr.Is(err, Err{{ $s.Name }})
}
{{ end }}
{{ end }}
+48
View File
@@ -0,0 +1,48 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structConfig*/ -}}
{{ define "field_mapping" }}{{- $s := .Struct -}}
{{- range $f := $s.Fields }}{{ if and (not $f.DoubleSlice) (ne ($f.Type) ("bin.Fields")) }}
{{ if not $f.Slice }}
{{- $mappings := index ($.Config.Mappings) ($f.Type) -}}
{{- range $mapping := $mappings }}{{- if (not $mapping.Constructor) }}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.constructorMapping*/ -}}
// Get{{ $f.Name }}As{{ $mapping.MapperName }} returns mapped value of {{ $f.Name }} {{ if $f.Conditional }}
{{- if not ($f.ConditionalBool) }}conditional field and
// boolean which is true if field was set.
{{- else }}conditional field.
{{- end }}
{{- else }}field.
{{- end }}
func ({{ $s.Receiver }} *{{ $s.Name }}) Get{{ $f.Name }}As{{ $mapping.MapperName }}() ({{ template "print_mapper_type" $mapping }}, bool) {
{{- if $f.Conditional }}
if value, ok := {{ $s.Receiver }}.Get{{ $f.Name }}(); ok {
return value.As{{ $mapping.MapperName }}()
}
return nil, false
{{- else }}
return {{ $s.Receiver }}.{{ $f.Name }}.As{{ $mapping.MapperName }}()
{{- end }}
}
{{- end }}{{- end }}
{{- else }}
{{- if $f.Interface }}
// Map{{ $f.Name }} returns field {{ $f.Name }} wrapped in {{ template "slice_field_name" $f }} helper.
func ({{ $s.Receiver }} *{{ $s.Name }}) Map{{ $f.Name }}() (value {{ template "slice_field_name" $f }}{{ if $f.Conditional }}, ok bool{{ end }}) {
{{- if $f.Conditional }}
if !{{ $s.Receiver }}.{{ $f.ConditionalField }}.Has({{ $f.ConditionalIndex }}) {
return value, false
}
return {{ template "slice_field_name" $f }}({{ $s.Receiver }}.{{ $f.Name }}), true
{{- else }}
return {{ template "slice_field_name" $f }}({{ $s.Receiver }}.{{ $f.Name }})
{{- end }}
}
{{- end }}
{{- end }}
{{- end }}{{- end }}
{{ end }}
+20
View File
@@ -0,0 +1,20 @@
{{ define "fill_from" }}{{ $s := . }}{{ if $s.Fields }}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
// FillFrom fills {{ $s.Name }} from given interface.
func ({{ $s.Receiver }} *{{ $s.Name }}) FillFrom(from interface{
{{- range $f := $s.Fields }}{{ if ne ($f.Type) ("bin.Fields") }}
{{ template "getter_func_type" $f }}
{{- end }}{{- end }}
}) {
{{- range $f := $s.Fields }}{{ if ne ($f.Type) ("bin.Fields") }}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.fieldDef*/ -}}
{{- if and ($f.Conditional) (not $f.ConditionalBool) }}
if val, ok := from.Get{{ $f.Name }}(); ok {
{{ $s.Receiver }}.{{ $f.Name }} = val
}
{{ else }}
{{ $s.Receiver }}.{{ $f.Name }} = from.Get{{ $f.Name }}()
{{- end }}
{{- end }}{{- end }}
}
{{ end }}{{ end }}
+48
View File
@@ -0,0 +1,48 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
{{ define "getset" }}{{ $s := . }}
{{- range $f := $s.Fields }}{{ if ne ($f.Type) ("bin.Fields") }}
{{ if $f.Conditional }}
// Set{{ $f.Name }} sets value of {{ $f.Name }} conditional field.
func ({{ $s.Receiver }} *{{ $s.Name }}) Set{{ $f.Name }}(value {{ template "print_type" $f }}) {
{{- if $f.ConditionalBool }}
if value {
{{ $s.Receiver }}.{{ $f.ConditionalField }}.Set({{ $f.ConditionalIndex }})
{{ $s.Receiver }}.{{ $f.Name }} = true
} else {
{{ $s.Receiver }}.{{ $f.ConditionalField }}.Unset({{ $f.ConditionalIndex }})
{{ $s.Receiver }}.{{ $f.Name }} = false
}
{{- else }}
{{ $s.Receiver }}.{{ $f.ConditionalField }}.Set({{ $f.ConditionalIndex }})
{{ $s.Receiver }}.{{ $f.Name }} = value
{{- end }}
}
{{- end }}
// Get{{ $f.Name }} returns value of {{ $f.Name }} {{ if $f.Conditional }}
{{- if not ($f.ConditionalBool) }}conditional field and
// boolean which is true if field was set.
{{- else }}conditional field.
{{- end }}
{{- else }}field.
{{- end }}
func ({{ $s.Receiver }} *{{ $s.Name }}) {{ template "getter_func_type" $f }} {
if {{ $s.Receiver }} == nil {
return
}
{{- if $f.Conditional }}{{ if not ($f.ConditionalBool) }}
if !{{ $s.Receiver }}.{{ $f.ConditionalField }}.Has({{ $f.ConditionalIndex }}) {
return value, false
}
return {{ $s.Receiver }}.{{ $f.Name }}, true
{{- else }}
return {{ $s.Receiver }}.{{ $f.ConditionalField }}.Has({{ $f.ConditionalIndex }})
{{- end }}
{{- else }}
return {{ $s.Receiver }}.{{ $f.Name }}
{{- end }}
}
{{- end }}{{- end }}
{{ end }}
+93
View File
@@ -0,0 +1,93 @@
{{ define "handlers" }}
{{ $pkg := $.Package }}
{{ template "header" $ }}
type handler = func(context.Context, Entities, UpdateClass) error
type UpdateDispatcher struct {
handlers map[uint32]handler
}
func NewUpdateDispatcher() UpdateDispatcher {
return UpdateDispatcher{
handlers: map[uint32]handler{},
}
}
type Entities struct {
Short bool
Users map[int64]*User
Chats map[int64]*Chat
Channels map[int64]*Channel
}
func (u *Entities) short() {
u.Short = true
u.Users = make(map[int64]*User, 0)
u.Chats = make(map[int64]*Chat, 0)
u.Channels = make(map[int64]*Channel, 0)
}
// Handle implements UpdateDispatcher.
func (u UpdateDispatcher) Handle(ctx context.Context, updates UpdatesClass) error {
var (
e Entities
upds []UpdateClass
)
switch u := updates.(type) {
case *Updates:
upds = u.Updates
e.Users = u.MapUsers().NotEmptyToMap()
chats := u.MapChats()
e.Chats = chats.ChatToMap()
e.Channels = chats.ChannelToMap()
case *UpdatesCombined:
upds = u.Updates
e.Users = u.MapUsers().NotEmptyToMap()
chats := u.MapChats()
e.Chats = chats.ChatToMap()
e.Channels = chats.ChannelToMap()
case *UpdateShort:
upds = []UpdateClass{u.Update}
e.short()
default:
// *UpdateShortMessage
// *UpdateShortChatMessage
// *UpdateShortSentMessage
// *UpdatesTooLong
return nil
}
var err error
for _, update := range upds {
multierr.AppendInto(&err, u.dispatch(ctx, e, update))
}
return err
}
func (u UpdateDispatcher) dispatch(ctx context.Context, e Entities, update UpdateClass) error {
if update == nil {
return nil
}
typeID := update.TypeID()
handler, ok := u.handlers[typeID]
if !ok {
return nil
}
return handler(ctx, e, update)
}
{{- range $s := $.Structs }}{{ if eq $s.Interface "UpdateClass" }}
{{ $eventName := trimPrefix $s.Name "Update"}}
// {{ $eventName }}Handler is a {{ $eventName }} event handler.
type {{ $eventName }}Handler func(ctx context.Context, e Entities, update *{{ $s.Name }}) error
// On{{ $eventName }} sets {{ $eventName }} handler.
func (u UpdateDispatcher) On{{ $eventName }}(handler {{ $eventName }}Handler) {
u.handlers[{{ $s.Name }}TypeID] = func(ctx context.Context, e Entities, update UpdateClass) error {
return handler(ctx, e, update.(*{{ $s.Name }}))
}
}
{{- end }}{{ end }}
{{ end }}
+36
View File
@@ -0,0 +1,36 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.config*/ -}}
{{ define "header" }}
// Code generated by gotdgen, DO NOT EDIT.
package {{ $.Package }}
import (
"context"
"errors"
"fmt"
"sort"
"strings"
"go.uber.org/multierr"
"go.mau.fi/mautrix-telegram/pkg/gotd/bin"
"go.mau.fi/mautrix-telegram/pkg/gotd/tdjson"
"go.mau.fi/mautrix-telegram/pkg/gotd/tdp"
"go.mau.fi/mautrix-telegram/pkg/gotd/tgerr"
)
// No-op definition for keeping imports.
var (
_ = bin.Buffer{}
_ = context.Background()
_ = fmt.Stringer(nil)
_ = strings.Builder{}
_ = errors.Is
_ = multierr.AppendInto
_ = sort.Ints
_ = tdp.Format
_ = tgerr.Error{}
_ = tdjson.Encoder{}
)
{{ end }}
+58
View File
@@ -0,0 +1,58 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.interfaceConfig*/ -}}
{{ define "interface" }}{{ $f := .Interface }}
// {{ $f.Name }}Name is schema name of {{ $f.Name }}.
const {{ $f.Name }}Name = "{{ $f.RawType }}"
// {{ $f.Name }} represents {{ $f.RawType }} generic type.
//
{{- if $f.URL }}
// See {{ $f.URL }} for reference.
//
{{- end }}
// Example:
// g, err := {{ $.Config.Package }}.Decode{{ $f.Func }}(buf)
// if err != nil {
// panic(err)
// }
// switch v := g.(type) {
{{ range $c := $f.Constructors -}}
// case *{{ $.Config.Package }}.{{ $c.Name }}: // {{ $c.RawType }}
{{ end -}}
// default: panic(v)
// }
type {{ $f.Name }} interface {
{{ template "class_interface_header" $f }}
{{ if $.Config.Flags.TDLibJSON }}
EncodeTDLibJSON(b tdjson.Encoder) error
DecodeTDLibJSON(b tdjson.Decoder) error
{{- end }}
{{ range $field := $f.SharedFields.Common -}}
{{- template "print_comment" $field.Comment }}
{{- if $field.Links }}
{{- template "print_links" $field.Links }}
{{- end }}
{{ if $.Config.Flags.GetSet }}{{ template "getter_func_type" $field -}}{{ end }}
{{- if and ($.Config.Flags.Mapping) (not $field.DoubleSlice) }}
{{- if not $field.Slice }}
{{- $mappings := index ($.Config.Mappings) ($field.Type) -}}
{{- range $mapping := $mappings -}}
{{- template "print_comment" $field.Comment }}
Get{{ $field.Name }}As{{ $mapping.MapperName }}() ({{ template "print_mapper_type" $mapping }}, bool)
{{- end }}
{{ else }}{{- if $field.Interface }}
{{- template "print_comment" $field.Comment }}
Map{{ $field.Name }}() (value {{ template "slice_field_name" $field }}{{ if $field.Conditional }}, ok bool{{ end }})
{{- end }}{{- end }}
{{- end }}
{{- end }}
{{ range $mapping := $f.Mappings -}}{{- if and ($.Config.Flags.Mapping) (not $mapping.Constructor) -}}
// As{{ $mapping.MapperName }} tries to map {{ $f.Name }} to {{ $mapping.Name }}.
{{ template "mapper_func_type" $mapping }}
{{ end }}{{ end }}
}
{{ end }}
@@ -0,0 +1,56 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.interfaceDef*/ -}}
{{ define "interface_mapping" }}{{ $f := . }}
{{ range $mapping := $f.Mappings -}}
{{- if not ($mapping.Concrete) }}
// {{ $mapping.Name }} represents {{ $mapping.MapperName }} subset of {{ $f.Name }}.
type {{ $mapping.Name }} interface {
{{ template "class_interface_header" $f }}
{{ range $field := index ($f.SharedFields) ($mapping.MapperName) -}}{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.fieldDef*/ -}}
{{- template "print_comment" $field.Comment }}
{{- if $field.Links }}
{{- template "print_links" $field.Links }}
{{- end }}
{{ template "getter_func_type" $field}}
{{ end }}
}
{{- end }}
{{ range $s := $f.Constructors -}}{{- if or (not $mapping.Constructor) (eq ($s.Name) ($mapping.Constructor)) }}
// As{{ $mapping.MapperName }} tries to map {{ $s.Name }} to {{ $mapping.Name }}.
func ({{ $s.Receiver }} *{{ $s.Name }}) {{ template "mapper_func_type" $mapping }} {
{{- if not ($mapping.Concrete) }}
value, ok := ({{ $f.Name }}({{ $s.Receiver }})).({{ $mapping.Name }})
return value, ok
{{- else }}{{- if $mapping.Fields }}
value := new({{ $mapping.Name }})
{{- range $pair := $mapping.Fields -}}
{{- if and ($pair.L.Conditional) (not $pair.L.ConditionalBool) }}
if fieldValue, ok := {{ $s.Receiver }}.Get{{ $pair.L.Name }}(); ok {
{{- if $pair.R.Conditional }}
value.Set{{ $pair.R.Name }}(fieldValue)
{{- else }}
value.{{ $pair.R.Name }} = fieldValue
{{- end }}
}
{{ else }}
{{- if $pair.R.Conditional -}}
value.Set{{ $pair.R.Name }}({{ $s.Receiver }}.Get{{ $pair.L.Name }}())
{{- else }}
value.{{ $pair.R.Name }} = {{ $s.Receiver }}.Get{{ $pair.L.Name }}()
{{- end }}
{{- end }}
{{- end }}
return value
{{- else }}
{{- if eq ($s.Name) ($mapping.Name) }} return {{ $s.Receiver }}, true
{{- else }} return nil, false {{ end }}
{{- end }}{{- end }}
}
{{ end }}{{ end }}
{{ end }}
{{ end }}
@@ -0,0 +1,94 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.interfaceDef*/ -}}
{{ define "interface_slice" }}{{ $f := . }}
{{ template "slice" $f }}
{{ range $field := sortableFields ($f.SharedFields.Common) }}
{{ template "slice_sort_by" concat ($f) ($field) }}
{{ end }}
{{ range $s := $f.Constructors }}{{ if $s.Fields }}
{{ range $field := mapCollectableFields ($f.SharedFields.Common) }}
{{ template "slice_collect_to_map" concat ($f) ($field) ($s.Name) }}
{{ end }}
// As{{ $s.Name }} returns copy with only {{ $s.Name }} constructors.
func (s {{ template "slice_name" $f }}) As{{ $s.Name }}() (to {{ template "slice_name" $s }}) {
for _, elem := range s {
value, ok := elem.(*{{ $s.Name }})
if !ok {
continue
}
to = append(to, *value)
}
return to
}
{{- end }}{{- end }}
{{ range $mapping := $f.Mappings }}{{- if (not $mapping.Constructor) }}
{{- range $field := mapCollectableFields (index ($f.SharedFields) ($mapping.MapperName)) }}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.fieldDef*/ -}}
// Fill{{ $mapping.MapperName }}Map fills only {{ $mapping.MapperName }} constructors to given map.
func (s {{ template "slice_name" $f }}) Fill{{ $mapping.MapperName }}{{ template "map_collector_name" $field }}Map(to map[{{ $field.Type }}]{{ template "print_mapper_type" $mapping }}) {
for _, elem := range s {
value, ok := elem.As{{ $mapping.MapperName }}()
if !ok {
continue
}
to[value.Get{{ $field.Name }}()] = value
}
}
// {{ $mapping.MapperName }}ToMap collects only {{ $mapping.MapperName }} constructors to map.
func (s {{ template "slice_name" $f }}) {{ $mapping.MapperName }}To{{ template "map_collector_name" $field }}Map() map[{{ $field.Type }}]{{ template "print_mapper_type" $mapping }} {
r := make(map[{{ $field.Type }}]{{ template "print_mapper_type" $mapping }}, len(s))
s.Fill{{ $mapping.MapperName }}{{ template "map_collector_name" $field }}Map(r)
return r
}
{{ end }}
// AppendOnly{{ $mapping.MapperName }} appends only {{ $mapping.MapperName }} constructors to
// given slice.
func (s {{ template "slice_name" $f }}) AppendOnly{{ $mapping.MapperName }}(to []{{ template "print_mapper_type" $mapping }}) []{{ template "print_mapper_type" $mapping }} {
for _, elem := range s {
value, ok := elem.As{{ $mapping.MapperName }}()
if !ok {
continue
}
to = append(to, value)
}
return to
}
// As{{ $mapping.MapperName }} returns copy with only {{ $mapping.MapperName }} constructors.
func (s {{ template "slice_name" $f }}) As{{ $mapping.MapperName }}() (to []{{ template "print_mapper_type" $mapping }}) {
return s.AppendOnly{{ $mapping.MapperName }}(to)
}
{{- range $method := concat ("First") ("Last") }}
// {{ $method }}As{{ $mapping.MapperName }} returns {{ lower $method }} element of slice (if exists).
func (s {{ template "slice_name" $f }}) {{ $method }}As{{ $mapping.MapperName }}() (v {{ template "print_mapper_type" $mapping }}, ok bool) {
value, ok := s.{{ $method }}()
if !ok {
return
}
return value.As{{ $mapping.MapperName }}()
}
{{- end }}
{{- range $method := concat ("PopFirst") ("Pop") }}
// {{ $method }}As{{ $mapping.MapperName }} returns element of slice (if exists).
func (s *{{ template "slice_name" $f }}) {{ $method }}As{{ $mapping.MapperName }}() (v {{ template "print_mapper_type" $mapping }}, ok bool) {
value, ok := s.{{ $method }}()
if !ok {
return
}
return value.As{{ $mapping.MapperName }}()
}
{{ end }}
{{- end }}{{- end }}
{{- end }}
+31
View File
@@ -0,0 +1,31 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.config*/ -}}
{{ define "main" }}
{{ $pkg := $.Package }}
{{ template "header" $ }}
{{ range $s := $.Structs }}
{{ template "struct" $s }}
{{ template "zero_derive" $s }}
{{ template "string_derive" $s }}
{{ if $.Flags.Mapping }}{{ template "fill_from" $s }}{{ end }}
{{ template "type_info" $s }}
{{ template "set_flags" $s }}
{{ template "encode" $s }}
{{ template "decode" $s }}
{{- if $.Flags.TDLibJSON }}
{{ template "encode_tdlib_json" $s }}
{{ template "decode_tdlib_json" $s }}
{{- end }}
{{ if $.Flags.GetSet }}{{ template "getset" $s }}{{ end }}
{{ if $.Flags.Mapping }}{{ template "field_mapping" newStructConfig ($s) ($) }}{{ end }}
{{ if $.Flags.Client }}{{ template "method" $s }}{{ end }}
{{ end }}
{{ range $f := $.Interfaces }}
{{ template "interface" newInterfaceConfig ($f) ($) }}
{{ if $.Flags.Mapping }}{{ template "interface_mapping" $f }}{{ end }}
{{ template "box" newInterfaceConfig ($f) ($) }}
{{ end }}
{{- end }}
+62
View File
@@ -0,0 +1,62 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
{{ define "method" }}{{- $s := . -}}{{ if $s.Method }}
// {{ $s.Method }} invokes method {{ $s.RawType }} returning error if any.
{{- if $s.Docs }}
{{- range $d := $s.Docs }}
// {{ trim $d }}
{{- end }}
{{- end }}
{{- if $s.Links }}
{{- template "print_links" $s.Links }}
{{- end }}
{{- if $s.Errors }}
{{- template "print_errors" $s.Errors }}
{{- end }}
{{- if $s.URL }}
//
// See {{ $s.URL }} for reference.
{{- end }}
{{- if $s.BotCanUse }}
// Can be used by bots.
{{- end }}
{{- if $s.Result }}
{{- if $s.ResultSingular }}
func (c *Client) {{ $s.Method }}({{ template "request_params" $s }}) ({{ if not $s.ResultVector }}*{{ $s.Result }}{{ else }}{{ template "slice_result_name" $s }}{{ end }}, error) {
var result {{ $s.Result }}
{{ template "pack_request" $s }}
if err := c.rpc.Invoke(ctx, request, &result); err != nil {
return nil, err
}
{{- if $s.ResultVector }}
return {{ template "slice_result_name" $s }}(result.Elems), nil
{{- else }}
return &result, nil
{{- end }}
}
{{- else }}
func (c *Client) {{ $s.Method }}({{ template "request_params" $s }}) ({{if ne $s.Result "BoolClass"}}{{ $s.Result }}{{ else }}bool{{ end }}, error) {
var result {{ $s.ResultFunc }}Box
{{ template "pack_request" $s }}
if err := c.rpc.Invoke(ctx, request, &result); err != nil {
{{- if ne $s.Result "BoolClass" }}return nil, err{{- else }}return false, err{{- end }}
}
{{- if ne $s.Result "BoolClass" }}
return result.{{ $s.ResultBaseName }}, nil
{{- else }}
_, ok := result.{{ $s.ResultBaseName }}.(*BoolTrue)
return ok, nil
{{- end }}
}
{{- end }}
{{- else }}
func (c *Client) {{ $s.Method }}({{ template "request_params" $s }}) error {
var ok Ok
{{ template "pack_request" $s }}
if err := c.rpc.Invoke(ctx, request, &ok); err != nil {
return err
}
return nil
}
{{- end }}
{{ end }}{{ end }}
+51
View File
@@ -0,0 +1,51 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.config*/ -}}
{{ define "registry" }}
{{ $pkg := $.Package }}
{{ template "header" $ }}
{{- if $.Layer }}
// Layer version of schema.
const Layer = {{ $.Layer }}
{{- end }}
// TypesMap returns mapping from type ids to TL type names.
func TypesMap() map[uint32]string {
return map[uint32]string {
{{- range $elem := $.Registry }}
{{ $elem.Name }}TypeID: "{{ $elem.Raw }}",
{{- end }}
}
}
// NamesMap returns mapping from type names to TL type ids.
func NamesMap() map[string]uint32 {
return map[string]uint32 {
{{- range $elem := $.Registry }}
"{{ trimSuffix (trimSuffix ($elem.Raw) ($elem.HexID)) ("#") }}": {{ $elem.Name }}TypeID,
{{- end }}
}
}
// TypesConstructorMap maps type ids to constructors.
func TypesConstructorMap() map[uint32]func() bin.Object {
return map[uint32]func() bin.Object {
{{- range $elem := $.Registry }}
{{ $elem.Name }}TypeID: func() bin.Object { return &{{ $elem.Name }}{} },
{{- end }}
}
}
// ClassConstructorsMap maps class schema name to constructors type ids.
func ClassConstructorsMap() map[string][]uint32 {
return map[string][]uint32 {
{{- range $elem := $.Interfaces }}
{{ $elem.Name }}Name: {
{{- range $c := $elem.Constructors }}
{{ $c.Name }}TypeID,
{{- end }}
},
{{- end }}
}
}
{{ end }}
+102
View File
@@ -0,0 +1,102 @@
{{ define "server" }}
{{ $pkg := $.Package }}
{{ template "header" $ }}
type ServerDispatcher struct{
fallback func(ctx context.Context, b *bin.Buffer) (bin.Encoder, error)
handlers map[uint32]func(ctx context.Context, b *bin.Buffer) (bin.Encoder, error)
}
func NewServerDispatcher(fallback func(ctx context.Context, b *bin.Buffer) (bin.Encoder, error)) *ServerDispatcher {
return &ServerDispatcher{
fallback: fallback,
handlers: map[uint32]func(context.Context, *bin.Buffer) (bin.Encoder, error){},
}
}
func (s *ServerDispatcher) Handle(ctx context.Context, b *bin.Buffer) (bin.Encoder, error) {
id, err := b.PeekID()
if err != nil{
return nil, err
}
f, ok := s.handlers[id]
if !ok {
return s.fallback(ctx, b)
}
return f(ctx, b)
}
{{ range $s:= $.Structs }}{{- if notEmpty $s.Method }}
{{- if $s.Result }}
{{- if $s.ResultSingular }}
func (s *ServerDispatcher) On{{ $s.Method }}(f func({{ template "request_params" $s }}) ({{ if not $s.ResultVector }}*{{ $s.Result }}{{ else }}{{ template "slice_result_name" $s }}{{ end }}, error)) {
handler := func(ctx context.Context, b *bin.Buffer) (bin.Encoder, error) {
var request {{ $s.Name }}
if err := request.Decode(b); err != nil{
return nil, err
}
response, err := f({{- template "unpack_request" $s }})
if err != nil{
return nil, err
}
{{- if $s.ResultVector }}
return &{{ $s.Result }}{Elems: response}, nil
{{- else }}
return response, nil
{{- end }}
}
s.handlers[{{ $s.Name }}TypeID] = handler
}
{{- else }}
func (s *ServerDispatcher) On{{ $s.Method }}(f func({{ template "request_params" $s }}) ({{if ne $s.Result "BoolClass"}}{{ $s.Result }}{{ else }}bool{{ end }}, error)) {
handler := func(ctx context.Context, b *bin.Buffer) (bin.Encoder, error) {
var request {{ $s.Name }}
if err := request.Decode(b); err != nil{
return nil, err
}
response, err := f({{- template "unpack_request" $s }})
if err != nil{
return nil, err
}
{{- if ne $s.Result "BoolClass" }}
return &{{ $s.ResultFunc }}Box{ {{ $s.ResultBaseName }}: response }, nil
{{- else }}
if response {
return &{{ $s.ResultFunc }}Box{ {{ $s.ResultBaseName }}: &BoolTrue{} }, nil
}
return &{{ $s.ResultFunc }}Box{ {{ $s.ResultBaseName }}: &BoolFalse{} }, nil
{{- end }}
}
s.handlers[{{ $s.Name }}TypeID] = handler
}
{{- end }}
{{- else }}
func (s *ServerDispatcher) On{{ $s.Method }}(f func({{ template "request_params" $s }}) error) {
handler := func(ctx context.Context, b *bin.Buffer) (bin.Encoder, error) {
var request {{ $s.Name }}
if err := request.Decode(b); err != nil{
return nil, err
}
if err := f({{- template "unpack_request" $s }}); err != nil{
return nil, err
}
return &Ok{}, nil
}
s.handlers[{{ $s.Name }}TypeID] = handler
}
{{- end }}
{{ end }}
{{- end }}
{{- end }}
+15
View File
@@ -0,0 +1,15 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
{{ define "set_flags" }}{{ $s := . }}
{{- if hasFlags $s }}
// SetFlags sets flags for non-zero fields.
func ({{ $s.Receiver }} *{{ $s.Name }}) SetFlags() {
{{- range $f := $s.Fields }}
{{- if $f.Conditional }}
if !({{ $s.Receiver }}.{{template "compare_zero" $f}}) {
{{ $s.Receiver }}.{{ $f.ConditionalField }}.Set({{ $f.ConditionalIndex }})
}
{{- end }}
{{- end }}
}
{{- end }}
{{ end }}
+148
View File
@@ -0,0 +1,148 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.config*/ -}}
{{ define "slices" }}
//go:build !no_gotd_slices
// +build !no_gotd_slices
{{ $pkg := $.Package }}
{{ template "header" $ }}
{{- range $f := $.Interfaces }}
{{ template "interface_slice" $f }}
{{- range $s := $.Structs }}{{- if generateSliceHelper ($s) -}}
{{ template "struct_slice" $s }}
{{- end }}{{- end }}
{{ end }}
{{ end }}
{{ define "slice_sort_by" }}{{ $args := . -}}
{{ $f := index ($args) (0) -}}
{{ $field := index ($args) (1) -}}
// SortBy{{ $field.Name }} sorts slice of {{ $f.Name }} by {{ $field.Name }}.
func (s {{ template "slice_name" $f }}) SortBy{{ $field.Name }}() {{ template "slice_name" $f }} {
return s.Sort(func(a, b {{ $f.Name }}) bool {
return a.Get{{ $field.Name }}() < b.Get{{ $field.Name }}()
})
}
// SortStableBy{{ $field.Name }} sorts slice of {{ $f.Name }} by {{ $field.Name }}.
func (s {{ template "slice_name" $f }}) SortStableBy{{ $field.Name }}() {{ template "slice_name" $f }} {
return s.SortStable(func(a, b {{ $f.Name }}) bool {
return a.Get{{ $field.Name }}() < b.Get{{ $field.Name }}()
})
}
{{ end }}
{{ define "slice_collect_to_map" }}{{ $args := . -}}
{{ $f := index ($args) (0) -}}
{{ $field := index ($args) (1) -}}
{{ $name := index ($args) (2) -}}
// Fill{{ $name }}Map fills only {{ $name }} constructors to given map.
func (s {{ template "slice_name" $f }}) Fill{{ $name }}{{ template "map_collector_name" $field }}Map(to map[{{ $field.Type }}]*{{ $name }} ) {
for _, elem := range s {
value, ok := elem.(*{{ $name }})
if !ok {
continue
}
to[value.Get{{ $field.Name }}()] = value
}
}
// {{ $name }}ToMap collects only {{ $name }} constructors to map.
func (s {{ template "slice_name" $f }}) {{ $name }}To{{ template "map_collector_name" $field }}Map() map[{{ $field.Type }}]*{{ $name }} {
r := make(map[{{ $field.Type }}]*{{ $name }}, len(s))
s.Fill{{ $name }}Map(r)
return r
}
{{ end }}
{{ define "slice_name" }}{{ $.Name }}Array{{ end }}
{{ define "slice_field_name" }}{{ $.Type }}Array{{ end }}
{{ define "slice_result_name" }}{{ if $.Interface }}{{ $.ResultFunc }}Array{{ else }}[]{{ $.ResultFunc }}{{ end }}{{ end }}
{{ define "slice" }}{{ $f := . }}
// {{ template "slice_name" $f }} is adapter for slice of {{ $f.Name }}.
type {{ template "slice_name" $f }} []{{ $f.Name }}
// Sort sorts slice of {{ $f.Name }}.
func (s {{ template "slice_name" $f }}) Sort(less func(a, b {{ $f.Name }}) bool) {{ template "slice_name" $f }} {
sort.Slice(s, func(i, j int) bool {
return less(s[i], s[j])
})
return s
}
// SortStable sorts slice of {{ $f.Name }}.
func (s {{ template "slice_name" $f }}) SortStable(less func(a, b {{ $f.Name }}) bool) {{ template "slice_name" $f }} {
sort.SliceStable(s, func(i, j int) bool {
return less(s[i], s[j])
})
return s
}
// Retain filters in-place slice of {{ $f.Name }}.
func (s {{ template "slice_name" $f }}) Retain(keep func(x {{ $f.Name }}) bool) {{ template "slice_name" $f }} {
n := 0
for _, x := range s {
if keep(x) {
s[n] = x
n++
}
}
s = s[:n]
return s
}
// First returns first element of slice (if exists).
func (s {{ template "slice_name" $f }}) First() (v {{ $f.Name }}, ok bool) {
if len(s) < 1 {
return
}
return s[0], true
}
// Last returns last element of slice (if exists).
func (s {{ template "slice_name" $f }}) Last() (v {{ $f.Name }}, ok bool) {
if len(s) < 1 {
return
}
return s[len(s)-1], true
}
// PopFirst returns first element of slice (if exists) and deletes it.
func (s *{{ template "slice_name" $f }}) PopFirst() (v {{ $f.Name }}, ok bool) {
if s == nil || len(*s) < 1 {
return
}
a := *s
v = a[0]
// Delete by index from SliceTricks.
copy(a[0:], a[1:])
var zero {{ $f.Name }}
a[len(a)-1] = zero
a = a[:len(a)-1]
*s = a
return v, true
}
// Pop returns last element of slice (if exists) and deletes it.
func (s *{{ template "slice_name" $f }}) Pop() (v {{ $f.Name }}, ok bool) {
if s == nil || len(*s) < 1 {
return
}
a := *s
v = a[len(a)-1]
a = a[:len(a)-1]
*s = a
return v, true
}
{{ end }}
+10
View File
@@ -0,0 +1,10 @@
{{define "string_derive" }}{{ $s := $ }}
// String implements fmt.Stringer.
func ({{ $s.Receiver }} *{{ $s.Name }}) String() string {
if {{ $s.Receiver }} == nil {
return "{{ $.Name }}(nil)"
}
type Alias {{ $s.Name }}
return fmt.Sprintf("{{ $s.Name }}%+v", Alias(*{{ $s.Receiver }}))
}
{{- end }}
+46
View File
@@ -0,0 +1,46 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
{{ define "struct" }}{{ $s := . }}
// {{ $s.Comment }}
{{- if $s.Docs }}
{{- template "print_comment" $s.Docs }}
{{- end }}
{{- if $s.Links }}
{{- template "print_links" $s.Links }}
{{- end }}
{{- if $s.URL }}
//
// See {{ $s.URL }} for reference.
{{- end }}
type {{ $s.Name }} struct {
{{- range $f := $s.Fields }}
{{- template "print_comment" $f.Comment }}
{{- if $f.Links}}
{{- template "print_links" $f.Links }}
{{- end }}
{{- if and ($f.Conditional) (not $f.ConditionalBool) }}
//
// Use Set{{ $f.Name }} and Get{{ $f.Name }} helpers.
{{- end }}
{{ $f.Name }} {{ template "print_type" $f }}
{{- end }}
}
// {{ $s.Name }}TypeID is TL type id of {{ $s.Name }}.
const {{ $s.Name }}TypeID = {{ if not $s.Vector }}0x{{ $s.HexID }}{{- else -}}bin.TypeVector{{- end }}
{{ if $s.Interface }}
// construct implements constructor of {{ $s.Interface }}.
func ({{ $s.Receiver }} {{ $s.Name }}) construct() {{ $s.Interface }} { return &{{ $s.Receiver }} }
{{ end }}
// Ensuring interfaces in compile-time for {{ $s.Name }}.
var (
_ bin.Encoder = &{{ $s.Name }}{}
_ bin.Decoder = &{{ $s.Name }}{}
_ bin.BareEncoder = &{{ $s.Name }}{}
_ bin.BareDecoder = &{{ $s.Name }}{}
{{ if $s.Interface }}
_ {{ $s.Interface }} = &{{ $s.Name }}{}
{{ end }}
)
{{ end }}
+23
View File
@@ -0,0 +1,23 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
{{ define "struct_slice" }}{{ $f := . }}
{{ template "slice" $f }}
{{ range $field := sortableFields ($f.Fields) }}
{{ template "slice_sort_by" concat ($f) ($field) }}
{{ end }}
{{ range $field := mapCollectableFields ($f.Fields) }}
// FillMap fills constructors to given map.
func (s {{ template "slice_name" $f }}) Fill{{ template "map_collector_name" $field }}Map(to map[{{ $field.Type }}]{{ $f.Name }} ) {
for _, value := range s {
to[value.Get{{ $field.Name }}()] = value
}
}
// ToMap collects constructors to map.
func (s {{ template "slice_name" $f }}) To{{ template "map_collector_name" $field }}Map() map[{{ $field.Type }}]{{ $f.Name }} {
r := make(map[{{ $field.Type }}]{{ $f.Name }}, len(s))
s.Fill{{ template "map_collector_name" $field }}Map(r)
return r
}
{{ end }}
{{ end }}
+40
View File
@@ -0,0 +1,40 @@
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
{{ define "type_info" }}{{ $s := . }}
// TypeID returns type id in TL schema.
//
// See https://core.telegram.org/mtproto/TL-tl#remarks.
func (*{{ $s.Name }}) TypeID() uint32 {
return {{ $s.Name }}TypeID
}
// TypeName returns name of type in TL schema.
func (*{{ $s.Name }}) TypeName() string {
return "{{ $s.RawName }}"
}
// TypeInfo returns info about TL type.
func ({{ $s.Receiver }} *{{ $s.Name }}) TypeInfo() tdp.Type {
typ := tdp.Type{
Name: "{{ $s.RawName }}",
ID: {{ $s.Name }}TypeID,
}
if {{ $s.Receiver }} == nil {
typ.Null = true
return typ
}
typ.Fields = []tdp.Field{
{{- range $f := $s.Fields }}
{{- if ne ($f.Type) ("bin.Fields") }}
{
Name: "{{ $f.Name }}",
SchemaName: "{{ $f.RawName }}",
{{- if $f.Conditional }}
Null: !{{ $s.Receiver }}.{{ $f.ConditionalField }}.Has({{ $f.ConditionalIndex }}),
{{- end }}
},
{{- end }}
{{- end }}
}
return typ
}
{{ end }}
@@ -0,0 +1,72 @@
{{ define "updates_classifier" }}
{{ $pkg := $.Package }}
{{ template "header" $ }}
func IsPtsUpdate(u UpdateClass) (pts, ptsCount int, ok bool) {
switch u := u.(type) {
{{- range $s := $.Structs }}{{ if and (eq $s.Interface "UpdateClass")
(hasField $s.Fields "Pts" "int")
(not (contains $s.Name "Channel")) }}
{{- $ptsCount := or (and (hasField $s.Fields "PtsCount" "int") "u.PtsCount") "0" }}
case *{{ $s.Name }}:
return u.Pts, {{ $ptsCount }}, true
{{- end }}{{ end }}
}
return
}
func IsQtsUpdate(u UpdateClass) (qts int, ok bool) {
switch u := u.(type) {
{{- range $s := $.Structs }}{{ if and (eq $s.Interface "UpdateClass") (hasField $s.Fields "Qts" "int") }}
case *{{ $s.Name }}:
return u.Qts, true
{{- end }}{{ end }}
}
return
}
func IsChannelPtsUpdate(u UpdateClass) (channelID int64, pts, ptsCount int, ok bool, err error) {
switch u := u.(type) {
{{- range $s := $.Structs }}{{ if and (eq $s.Interface "UpdateClass")
(hasField $s.Fields "Pts" "int")
(contains $s.Name "Channel") }}
{{- $ptsCount := or (and (hasField $s.Fields "PtsCount" "int") "u.PtsCount") "0" }}
case *{{ $s.Name }}:
{{- if (hasField $s.Fields "ChannelID" "int64") }}
return u.ChannelID, u.Pts, {{ $ptsCount }}, true, nil
{{- else }}
channelID, err = extractChannelID(u.Message)
return channelID, u.Pts, {{ $ptsCount }}, true, err
{{- end }}{{ end }}{{ end }}
}
return
}
func extractChannelID(msg MessageClass) (int64, error) {
switch msg := msg.(type) {
{{- range $s := $.Structs }}{{ if eq $s.Interface "MessageClass" }}
case *{{ $s.Name }}:
{{- range $field := $s.Fields }}{{ if eq $field.Name "PeerID" }}
{{- if (optionalField $s $field) }}
peer, ok := msg.GetPeerID()
if !ok {
return 0, errors.New("{{ $s.Name }} have no peerID field")
}
{{- else }}
peer := msg.PeerID
{{ end }}{{ end }}{{ end }}
if c, ok := peer.(*PeerChannel); ok {
return c.ChannelID, nil
}
return 0, errors.New("unexpected peer type")
{{- end }}{{ end }}
default:
return 0, errors.New("unexpected MessageClass type")
}
}
{{ end }}
+88
View File
@@ -0,0 +1,88 @@
{{ define "request_params" }}ctx context.Context{{- if .UnpackParameters }}{{- if .Fields }}
{{- range $f := .Fields }}, {{ lowerGo $f.Name }} {{ template "print_type" $f }}{{- end }}
{{- end }}
{{- else }}, request *{{ .Name }}{{- end }}
{{- end }}
{{ define "pack_request" }}{{- if .UnpackParameters }}
request := &{{ $.Name }}{
{{- range $f := $.Fields }}
{{ $f.Name }}: {{ lowerGo $f.Name }},
{{- end }}
}
{{- end }}{{- end }}
{{ define "unpack_request" }}ctx{{- if .UnpackParameters }}{{- if .Fields }}
{{- range $f := $.Fields }}, request.{{ $f.Name }}
{{- end }}{{- end }}
{{- else }}, &request{{- end }}
{{- end }}
{{ define "print_type" }}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.fieldDef*/ -}}
{{- if $.DoubleSlice }}[][]{{ $.Type }}
{{- else if $.Slice }}[]{{ $.Type }}
{{- else }}{{ $.Type }}
{{- end }}{{- end }}
{{ define "getter_func_type" }}{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.fieldDef*/ -}}
Get{{$.Name}}() (value {{ template "print_type" $ }}{{ if and ($.Conditional) (not $.ConditionalBool) }}, ok bool{{ end }})
{{- end }}
{{ define "print_mapper_type" }}{{ $mapping := . -}}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.constructorMapping*/ -}}
{{- if not ($mapping.Concrete) }}{{ $mapping.Name }}{{- else }}*{{ $mapping.Name }}{{- end -}}
{{ end }}
{{ define "mapper_func_type" }}{{ $mapping := . -}}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.constructorMapping*/ -}}
{{- if $mapping.Fields }}As{{ $mapping.MapperName }}() {{ template "print_mapper_type" $mapping }}
{{- else }}As{{ $mapping.MapperName }}() ({{ template "print_mapper_type" $mapping }}, bool)
{{- end }}{{- end }}
{{ define "print_links" }}
//
// Links:
{{- range $i, $link := . }}
// {{ add $i 1 }}) {{ $link }}
{{- end }}
{{- end }}
{{ define "print_comment" }}
{{- range $line := . }}
// {{ trim $line }}
{{- end }}
{{- end }}
{{ define "print_errors" }}
//
// Possible errors:
{{- range $err := . }}
// {{ $err.Code }} {{ $err.Type }}: {{ $err.Description }}
{{- end }}
{{- end }}
{{ define "class_interface_header" }}{{ $f := . }}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.interfaceDef*/ -}}
bin.Encoder
bin.Decoder
bin.BareEncoder
bin.BareDecoder
construct() {{ $f.Name }}
// TypeID returns type id in TL schema.
//
// See https://core.telegram.org/mtproto/TL-tl#remarks.
TypeID() uint32
// TypeName returns name of type in TL schema.
TypeName() string
// String implements fmt.Stringer.
String() string
// Zero returns true if current object has a zero value.
Zero() bool
{{- end }}
{{ define "map_collector_name" }}{{ $field := . }}{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.fieldDef*/ -}}
{{ if ne ($field.Name) ("ID") }}{{ $field.Name }}{{ end }}
{{- end }}
+30
View File
@@ -0,0 +1,30 @@
{{ define "zero_derive" }}{{ $s := . }}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.structDef*/ -}}
func ({{ $s.Receiver }} *{{ $s.Name }}) Zero() bool {
if {{ $s.Receiver }} == nil {
return true
}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.fieldDef*/ -}}
{{- range $f := $s.Fields }}{{- if ne ($f.Name) ($f.ConditionalField) }}
if !({{ $s.Receiver }}.{{template "compare_zero" $f}}) {
return false
}
{{- end }}{{- end }}
return true
}
{{- end -}}
{{ define "compare_zero" }}
{{- /*gotype: go.mau.fi/mautrix-telegram/pkg/gotd/gen.fieldDef*/ -}}
{{- .Name -}}
{{- if or (.Slice) (.DoubleSlice) -}} == nil
{{- else if eq (.Type) ("bin.Int128") -}} == bin.Int128{}
{{- else if eq (.Type) ("bin.Int256") -}} == bin.Int256{}
{{- else if or (hasPrefix (.Type) ("int")) (hasPrefix (.Type) ("float")) }} == 0
{{- else if eq (.Type) ("string") -}} == ""
{{- else if eq (.Type) ("bool") -}} == false
{{- else if eq (.Type) ("bin.Object") }} == nil
{{- else if hasSuffix (.Type) ("Class") }} == nil
{{- else -}}.Zero()
{{- end -}}{{- end }}