package telegramimport ()var (tdlibToTelegramMapmap[string]stringtdlibToTelegramMapOncesync.Once)// buildTDLibToTelegramMap builds reverse mapping from TDLib method names// (e.g., "sendMessage") to Telegram API names (e.g., "messages.sendMessage").func () map[string]string {tdlibToTelegramMapOnce.Do(func() { := tg.NamesMap()tdlibToTelegramMap = make(map[string]string)// Build reverse mapping: for each entry in NamesMap that looks like a method request, // create mapping from TDLib name (without namespace) to full namefor := range {// Only process method requests (they contain a dot and end with "Request" conceptually) // In NamesMap, request methods are stored as "namespace.methodName"if !strings.Contains(, ".") {continue }// Extract method name without namespace := strings.SplitN(, ".", 2)iflen() != 2 {continue } := [1]// Skip result types and constructors (they don't have "Request" in their name pattern) // Request methods in NamesMap are like "messages.sendMessage", "auth.sendCode", etc. // We want to map "sendMessage" -> "messages.sendMessage" // Skip types that are clearly not methods (like "auth.authorization", "messages.messages")ifstrings.HasSuffix(, "TypeID") ||strings.HasSuffix(, "Class") {continue }// Check if the type ID corresponds to a Request type by checking the constructors map // Request types in NamesMap map to RequestTypeID constants // We'll include it in the mapping - if it's not a request, it will fail later during invocation // This is simpler than trying to detect all request types upfronttdlibToTelegramMap[] = } })returntdlibToTelegramMap}// InvokeRawJSON invokes MTProto method using pure TDLib JSON format.// It accepts JSON with @type field in TDLib format (e.g., "sendMessage")// and returns JSON response in TDLib format.//// The JSON structure, keys and values exactly match TDLib standard JSON.// For example, use "sendMessage" not "messages.sendMessage" in @type field.func ( *Client) ( context.Context, string) ( string, error) {// Parse JSON to extract @type := jx.DecodeStr() := tdjson.Decoder{Decoder: } , := .FindTypeID()if != nil {return"", errors.Wrap(, "find @type field") }// Map TDLib method name to Telegram API name := buildTDLibToTelegramMap() , := []if ! {// Try direct lookup in case it's already in full format := tg.NamesMap()if , := []; { = } else {return"", errors.Errorf("unknown method: %q", ) } }// Lookup type ID := tg.NamesMap() , := []if ! {return"", errors.Errorf("type not found: %q", ) }// Create instance := tg.TypesConstructorMap() , := []if ! {return"", errors.Errorf("constructor not found for type: %q (id: 0x%x)", , ) } := ()if == nil {return"", errors.Errorf("failed to create instance for type: %q", ) }// Check if instance supports TDLib JSON decoding , := .(tdjson.TDLibDecoder)if ! {return"", errors.Errorf("type %q does not support TDLib JSON decoding", ) }// Decode JSON into instance (create new decoder for full decode) := jx.DecodeStr() := tdjson.Decoder{Decoder: }if := .DecodeTDLibJSON(); != nil {return"", errors.Wrapf(, "decode TDLib JSON for %q", ) }// Ensure instance implements bin.Encoder , := .(bin.Encoder)if ! {return"", errors.Errorf("type %q does not implement bin.Encoder", ) }// Invoke via existing Invoke method with a decoder that can handle any response type := &rawJSONResponseDecoder{}if := .Invoke(, , ); != nil {// Check if it's an RPC error and convert to TDLib JSON error formatif , := tgerr.As(); {returnencodeTDLibError(), nil }return"", errors.Wrap(, "invoke") } := .resultif == nil {return"", errors.New("empty response") }// Encode response to TDLib JSON , := .(tdjson.TDLibEncoder)if ! {return"", errors.Errorf("response type does not support TDLib JSON encoding") }varjx.Writer := tdjson.Encoder{Writer: &}if := .EncodeTDLibJSON(); != nil {return"", errors.Wrap(, "encode response to TDLib JSON") }return .String(), nil}// rawJSONResponseDecoder is a decoder that can decode any response type// and store it as bin.Object for later JSON encoding.typerawJSONResponseDecoderstruct {resultbin.Object}func ( *rawJSONResponseDecoder) ( *bin.Buffer) error {// Peek at the type ID to determine what to decode , := .PeekID()if != nil {returnerrors.Wrap(, "peek response type ID") }// Use TypesConstructorMap to create appropriate instance := tg.TypesConstructorMap() , := []if ! {returnerrors.Errorf("unknown response type: 0x%x", ) } := ()if == nil {returnerrors.Errorf("failed to create response instance for type: 0x%x", ) }// Decode into instance , := .(bin.Decoder)if ! {returnerrors.Errorf("response type does not implement bin.Decoder") }if := .Decode(); != nil {returnerrors.Wrap(, "decode response") }// Store as bin.Objectif , := .(bin.Object); { .result = } else {returnerrors.New("response is not a bin.Object") }returnnil}// encodeTDLibError encodes tgerr.Error to TDLib JSON error format.func ( *tgerr.Error) string {// TDLib error format: {"@type":"error","code":420,"message":"FLOOD_WAIT_3"}varjx.Writer .ObjStart() .FieldStart("@type") .Str("error") .Comma() .FieldStart("code") .Int(.Code) .Comma() .FieldStart("message") .Str(.Message) .ObjEnd()return .String()}
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.