Initial commit
This commit is contained in:
29
vendor/github.com/Arman92/go-tdlib/.gitignore
generated
vendored
Normal file
29
vendor/github.com/Arman92/go-tdlib/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
# Any file without an extension
|
||||
*
|
||||
!*/
|
||||
!*.*
|
||||
|
||||
/.vscode
|
||||
/.git_old
|
||||
|
||||
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||
.glide/
|
||||
|
||||
tdlib-db
|
||||
tdlib-files
|
||||
|
||||
errors.txt
|
124
vendor/github.com/Arman92/go-tdlib/README.md
generated
vendored
Normal file
124
vendor/github.com/Arman92/go-tdlib/README.md
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
# go-tdlib
|
||||
Golang Telegram TdLib JSON bindings
|
||||
|
||||
|
||||
## Introduction
|
||||
Telegram Tdlib is a complete library for creating telegram clients, it laso has a simple tdjson ready-to-use library to ease
|
||||
the integration with different programming languages and platforms.
|
||||
|
||||
**go-tdlib** is a complete tdlib-tdjson binding package to help you create your own Telegram clients.
|
||||
|
||||
**NOTE:** basic tdjson-golang binding is inspired from this package: [go-tdjson](https://github.com/L11R/go-tdjson)
|
||||
|
||||
All the classes and functions declared in [Tdlib TypeLanguage schema](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl)
|
||||
file have been exported using the autogenerate tool [tl-parser](https://github.com/Arman92/go-tl-parser).
|
||||
So you can use every single type and method in Tdlib.
|
||||
|
||||
## Key features:
|
||||
* Autogenerated golang structs and methods of tdlib .tl schema
|
||||
* Custom event receivers defined by user (e.g. get only text messages from a specific user)
|
||||
* Supports all tdjson functions: Send(), Execute(), Receive(), Destroy(), SetFilePath(), SetLogVerbosityLevel()
|
||||
* Supports all tdlib functions and types
|
||||
|
||||
## Installation
|
||||
|
||||
First of all you need to clone the Tdlib repo and build it:
|
||||
```bash
|
||||
git clone git@github.com:tdlib/td.git
|
||||
cd td
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . -- -j5
|
||||
make install
|
||||
|
||||
# -j5 refers to number of your cpu cores + 1 for multi-threaded build.
|
||||
```
|
||||
|
||||
If hit any build errors, refer to [Tdlib build instructions](https://github.com/tdlib/td#building)
|
||||
I'm using static linking against tdlib so it won't require to build the whole tdlib source files.
|
||||
|
||||
## Docker
|
||||
You can use prebuilt tdlib with following Docker image:
|
||||
|
||||
***Windows:***
|
||||
``` shell
|
||||
docker pull mihaildemidoff/tdlib-go
|
||||
```
|
||||
|
||||
## Example
|
||||
Here is a simple example for authorization and fetching updates:
|
||||
```golang
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Arman92/go-tdlib"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tdlib.SetLogVerbosityLevel(1)
|
||||
tdlib.SetFilePath("./errors.txt")
|
||||
|
||||
// Create new instance of client
|
||||
client := tdlib.NewClient(tdlib.Config{
|
||||
APIID: "187786",
|
||||
APIHash: "e782045df67ba48e441ccb105da8fc85",
|
||||
SystemLanguageCode: "en",
|
||||
DeviceModel: "Server",
|
||||
SystemVersion: "1.0.0",
|
||||
ApplicationVersion: "1.0.0",
|
||||
UseMessageDatabase: true,
|
||||
UseFileDatabase: true,
|
||||
UseChatInfoDatabase: true,
|
||||
UseTestDataCenter: false,
|
||||
DatabaseDirectory: "./tdlib-db",
|
||||
FileDirectory: "./tdlib-files",
|
||||
IgnoreFileNames: false,
|
||||
})
|
||||
|
||||
for {
|
||||
currentState, _ := client.Authorize()
|
||||
if currentState.GetAuthorizationStateEnum() == tdlib.AuthorizationStateWaitPhoneNumberType {
|
||||
fmt.Print("Enter phone: ")
|
||||
var number string
|
||||
fmt.Scanln(&number)
|
||||
_, err := client.SendPhoneNumber(number)
|
||||
if err != nil {
|
||||
fmt.Printf("Error sending phone number: %v", err)
|
||||
}
|
||||
} else if currentState.GetAuthorizationStateEnum() == tdlib.AuthorizationStateWaitCodeType {
|
||||
fmt.Print("Enter code: ")
|
||||
var code string
|
||||
fmt.Scanln(&code)
|
||||
_, err := client.SendAuthCode(code)
|
||||
if err != nil {
|
||||
fmt.Printf("Error sending auth code : %v", err)
|
||||
}
|
||||
} else if currentState.GetAuthorizationStateEnum() == tdlib.AuthorizationStateWaitPasswordType {
|
||||
fmt.Print("Enter Password: ")
|
||||
var password string
|
||||
fmt.Scanln(&password)
|
||||
_, err := client.SendAuthPassword(password)
|
||||
if err != nil {
|
||||
fmt.Printf("Error sending auth password: %v", err)
|
||||
}
|
||||
} else if currentState.GetAuthorizationStateEnum() == tdlib.AuthorizationStateReadyType {
|
||||
fmt.Println("Authorization Ready! Let's rock")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Main loop
|
||||
for update := range client.RawUpdates {
|
||||
// Show all updates
|
||||
fmt.Println(update.Data)
|
||||
fmt.Print("\n\n")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
More examples can be found on [examples folder](https://github.com/Arman92/go-tdlib/tree/master/examples)
|
7669
vendor/github.com/Arman92/go-tdlib/methods.go
generated
vendored
Executable file
7669
vendor/github.com/Arman92/go-tdlib/methods.go
generated
vendored
Executable file
File diff suppressed because it is too large
Load Diff
349
vendor/github.com/Arman92/go-tdlib/tdlib.go
generated
vendored
Normal file
349
vendor/github.com/Arman92/go-tdlib/tdlib.go
generated
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
package tdlib
|
||||
|
||||
//#cgo linux CFLAGS: -I/usr/local/include
|
||||
//#cgo darwin CFLAGS: -I/usr/local/include
|
||||
//#cgo windows CFLAGS: -IC:/src/td -IC:/src/td/build
|
||||
//#cgo linux LDFLAGS: -L/usr/local/lib -ltdjson_static -ltdjson_private -ltdclient -ltdcore -ltdactor -ltddb -ltdsqlite -ltdnet -ltdutils -lstdc++ -lssl -lcrypto -ldl -lz -lm
|
||||
//#cgo darwin LDFLAGS: -L/usr/local/lib -L/usr/local/opt/openssl/lib -ltdjson_static -ltdjson_private -ltdclient -ltdcore -ltdactor -ltddb -ltdsqlite -ltdnet -ltdutils -lstdc++ -lssl -lcrypto -ldl -lz -lm
|
||||
//#cgo windows LDFLAGS: -LC:/src/td/build/Debug -ltdjson
|
||||
//#include <stdlib.h>
|
||||
//#include <td/telegram/td_json_client.h>
|
||||
//#include <td/telegram/td_log.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// UpdateData alias for use in UpdateMsg
|
||||
type UpdateData map[string]interface{}
|
||||
|
||||
// UpdateMsg is used to unmarshal recieved json strings into
|
||||
type UpdateMsg struct {
|
||||
Data UpdateData
|
||||
Raw []byte
|
||||
}
|
||||
|
||||
// EventFilterFunc used to filter out unwanted messages in receiver channels
|
||||
type EventFilterFunc func(msg *TdMessage) bool
|
||||
|
||||
// EventReceiver used to retreive updates from tdlib to user
|
||||
type EventReceiver struct {
|
||||
Instance TdMessage
|
||||
Chan chan TdMessage
|
||||
FilterFunc EventFilterFunc
|
||||
}
|
||||
|
||||
// Client is the Telegram TdLib client
|
||||
type Client struct {
|
||||
Client unsafe.Pointer
|
||||
Config Config
|
||||
rawUpdates chan UpdateMsg
|
||||
receivers []EventReceiver
|
||||
waiters sync.Map
|
||||
receiverLock *sync.Mutex
|
||||
}
|
||||
|
||||
// Config holds tdlibParameters
|
||||
type Config struct {
|
||||
APIID string // Application identifier for Telegram API access, which can be obtained at https://my.telegram.org --- must be non-empty..
|
||||
APIHash string // Application identifier hash for Telegram API access, which can be obtained at https://my.telegram.org --- must be non-empty..
|
||||
SystemLanguageCode string // IETF language tag of the user's operating system language; must be non-empty.
|
||||
DeviceModel string // Model of the device the application is being run on; must be non-empty.
|
||||
SystemVersion string // Version of the operating system the application is being run on; must be non-empty.
|
||||
ApplicationVersion string // Application version; must be non-empty.
|
||||
// Optional fields
|
||||
UseTestDataCenter bool // if set to true, the Telegram test environment will be used instead of the production environment.
|
||||
DatabaseDirectory string // The path to the directory for the persistent database; if empty, the current working directory will be used.
|
||||
FileDirectory string // The path to the directory for storing files; if empty, database_directory will be used.
|
||||
UseFileDatabase bool // If set to true, information about downloaded and uploaded files will be saved between application restarts.
|
||||
UseChatInfoDatabase bool // If set to true, the library will maintain a cache of users, basic groups, supergroups, channels and secret chats. Implies use_file_database.
|
||||
UseMessageDatabase bool // If set to true, the library will maintain a cache of chats and messages. Implies use_chat_info_database.
|
||||
UseSecretChats bool // If set to true, support for secret chats will be enabled.
|
||||
EnableStorageOptimizer bool // If set to true, old files will automatically be deleted.
|
||||
IgnoreFileNames bool // If set to true, original file names will be ignored. Otherwise, downloaded files will be saved under names as close as possible to the original name.
|
||||
}
|
||||
|
||||
// NewClient Creates a new instance of TDLib.
|
||||
// Has two public fields:
|
||||
// Client itself and RawUpdates channel
|
||||
func NewClient(config Config) *Client {
|
||||
// Seed rand with time
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
client := Client{Client: C.td_json_client_create()}
|
||||
client.receivers = make([]EventReceiver, 0, 1)
|
||||
client.receiverLock = &sync.Mutex{}
|
||||
client.Config = config
|
||||
|
||||
go func() {
|
||||
for {
|
||||
// get update
|
||||
updateBytes := client.Receive(10)
|
||||
var updateData UpdateData
|
||||
json.Unmarshal(updateBytes, &updateData)
|
||||
|
||||
// does new update has @extra field?
|
||||
if extra, hasExtra := updateData["@extra"].(string); hasExtra {
|
||||
|
||||
// trying to load update with this salt
|
||||
if waiter, found := client.waiters.Load(extra); found {
|
||||
// found? send it to waiter channel
|
||||
waiter.(chan UpdateMsg) <- UpdateMsg{Data: updateData, Raw: updateBytes}
|
||||
|
||||
// trying to prevent memory leak
|
||||
close(waiter.(chan UpdateMsg))
|
||||
}
|
||||
} else {
|
||||
// does new updates has @type field?
|
||||
if msgType, hasType := updateData["@type"]; hasType {
|
||||
|
||||
if client.rawUpdates != nil {
|
||||
// if rawUpdates is initialized, send the update in rawUpdates channel
|
||||
client.rawUpdates <- UpdateMsg{Data: updateData, Raw: updateBytes}
|
||||
}
|
||||
|
||||
client.receiverLock.Lock()
|
||||
for _, receiver := range client.receivers {
|
||||
if msgType == receiver.Instance.MessageType() {
|
||||
var newMsg TdMessage
|
||||
newMsg = reflect.New(reflect.ValueOf(receiver.Instance).Elem().Type()).Interface().(TdMessage)
|
||||
|
||||
err := json.Unmarshal(updateBytes, &newMsg)
|
||||
if err != nil {
|
||||
fmt.Printf("Error unmarhaling to type %v", err)
|
||||
}
|
||||
if receiver.FilterFunc(&newMsg) {
|
||||
receiver.Chan <- newMsg
|
||||
}
|
||||
}
|
||||
}
|
||||
client.receiverLock.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return &client
|
||||
}
|
||||
|
||||
// GetRawUpdatesChannel creates a general channel that fetches every update comming from tdlib
|
||||
func (client *Client) GetRawUpdatesChannel(capacity int) chan UpdateMsg {
|
||||
client.rawUpdates = make(chan UpdateMsg, capacity)
|
||||
return client.rawUpdates
|
||||
}
|
||||
|
||||
// AddEventReceiver adds a new receiver to be subscribed in receiver channels
|
||||
func (client *Client) AddEventReceiver(msgInstance TdMessage, filterFunc EventFilterFunc, channelCapacity int) EventReceiver {
|
||||
receiver := EventReceiver{
|
||||
Instance: msgInstance,
|
||||
Chan: make(chan TdMessage, channelCapacity),
|
||||
FilterFunc: filterFunc,
|
||||
}
|
||||
|
||||
client.receiverLock.Lock()
|
||||
defer client.receiverLock.Unlock()
|
||||
client.receivers = append(client.receivers, receiver)
|
||||
|
||||
return receiver
|
||||
}
|
||||
|
||||
// DestroyInstance Destroys the TDLib client instance.
|
||||
// After this is called the client instance shouldn't be used anymore.
|
||||
func (client *Client) DestroyInstance() {
|
||||
C.td_json_client_destroy(client.Client)
|
||||
}
|
||||
|
||||
// Send Sends request to the TDLib client.
|
||||
// You can provide string or UpdateData.
|
||||
func (client *Client) Send(jsonQuery interface{}) {
|
||||
var query *C.char
|
||||
|
||||
switch jsonQuery.(type) {
|
||||
case string:
|
||||
query = C.CString(jsonQuery.(string))
|
||||
case UpdateData:
|
||||
jsonBytes, _ := json.Marshal(jsonQuery.(UpdateData))
|
||||
query = C.CString(string(jsonBytes))
|
||||
}
|
||||
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
C.td_json_client_send(client.Client, query)
|
||||
}
|
||||
|
||||
// Receive Receives incoming updates and request responses from the TDLib client.
|
||||
// You can provide string or UpdateData.
|
||||
func (client *Client) Receive(timeout float64) []byte {
|
||||
result := C.td_json_client_receive(client.Client, C.double(timeout))
|
||||
|
||||
return []byte(C.GoString(result))
|
||||
}
|
||||
|
||||
// Execute Synchronously executes TDLib request.
|
||||
// Only a few requests can be executed synchronously.
|
||||
func (client *Client) Execute(jsonQuery interface{}) UpdateMsg {
|
||||
var query *C.char
|
||||
|
||||
switch jsonQuery.(type) {
|
||||
case string:
|
||||
query = C.CString(jsonQuery.(string))
|
||||
case UpdateData:
|
||||
jsonBytes, _ := json.Marshal(jsonQuery.(UpdateData))
|
||||
query = C.CString(string(jsonBytes))
|
||||
}
|
||||
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
result := C.td_json_client_execute(client.Client, query)
|
||||
|
||||
var update UpdateData
|
||||
json.Unmarshal([]byte(C.GoString(result)), &update)
|
||||
return UpdateMsg{Data: update, Raw: []byte(C.GoString(result))}
|
||||
}
|
||||
|
||||
// SetFilePath Sets the path to the file to where the internal TDLib log will be written.
|
||||
// By default TDLib writes logs to stderr or an OS specific log.
|
||||
// Use this method to write the log to a file instead.
|
||||
func SetFilePath(path string) {
|
||||
query := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
|
||||
C.td_set_log_file_path(query)
|
||||
}
|
||||
|
||||
// SetLogVerbosityLevel Sets the verbosity level of the internal logging of TDLib.
|
||||
// By default the TDLib uses a verbosity level of 5 for logging.
|
||||
func SetLogVerbosityLevel(level int) {
|
||||
C.td_set_log_verbosity_level(C.int(level))
|
||||
}
|
||||
|
||||
// SendAndCatch Sends request to the TDLib client and catches the result in updates channel.
|
||||
// You can provide string or UpdateData.
|
||||
func (client *Client) SendAndCatch(jsonQuery interface{}) (UpdateMsg, error) {
|
||||
var update UpdateData
|
||||
|
||||
switch jsonQuery.(type) {
|
||||
case string:
|
||||
// unmarshal JSON into map, we don't have @extra field, if user don't set it
|
||||
json.Unmarshal([]byte(jsonQuery.(string)), &update)
|
||||
case UpdateData:
|
||||
update = jsonQuery.(UpdateData)
|
||||
}
|
||||
|
||||
// letters for generating random string
|
||||
letterBytes := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
|
||||
// generate random string for @extra field
|
||||
b := make([]byte, 32)
|
||||
for i := range b {
|
||||
b[i] = letterBytes[rand.Intn(len(letterBytes))]
|
||||
}
|
||||
randomString := string(b)
|
||||
|
||||
// set @extra field
|
||||
update["@extra"] = randomString
|
||||
|
||||
// create waiter chan and save it in Waiters
|
||||
waiter := make(chan UpdateMsg, 1)
|
||||
client.waiters.Store(randomString, waiter)
|
||||
|
||||
// send it through already implemented method
|
||||
client.Send(update)
|
||||
|
||||
select {
|
||||
// wait response from main loop in NewClient()
|
||||
case response := <-waiter:
|
||||
return response, nil
|
||||
// or timeout
|
||||
case <-time.After(10 * time.Second):
|
||||
client.waiters.Delete(randomString)
|
||||
return UpdateMsg{}, errors.New("timeout")
|
||||
}
|
||||
}
|
||||
|
||||
// Authorize is used to authorize the users
|
||||
func (client *Client) Authorize() (AuthorizationState, error) {
|
||||
state, err := client.GetAuthorizationState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if state.GetAuthorizationStateEnum() == AuthorizationStateWaitEncryptionKeyType {
|
||||
ok, err := client.CheckDatabaseEncryptionKey(nil)
|
||||
|
||||
if ok == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if state.GetAuthorizationStateEnum() == AuthorizationStateWaitTdlibParametersType {
|
||||
client.sendTdLibParams()
|
||||
}
|
||||
|
||||
authState, err := client.GetAuthorizationState()
|
||||
return authState, err
|
||||
}
|
||||
|
||||
func (client *Client) sendTdLibParams() {
|
||||
client.Send(UpdateData{
|
||||
"@type": "setTdlibParameters",
|
||||
"parameters": UpdateData{
|
||||
"@type": "tdlibParameters",
|
||||
"use_test_dc": client.Config.UseTestDataCenter,
|
||||
"database_directory": client.Config.DatabaseDirectory,
|
||||
"files_directory": client.Config.FileDirectory,
|
||||
"use_file_database": client.Config.UseFileDatabase,
|
||||
"use_chat_info_database": client.Config.UseChatInfoDatabase,
|
||||
"use_message_database": client.Config.UseMessageDatabase,
|
||||
"use_secret_chats": client.Config.UseSecretChats,
|
||||
"api_id": client.Config.APIID,
|
||||
"api_hash": client.Config.APIHash,
|
||||
"system_language_code": client.Config.SystemLanguageCode,
|
||||
"device_model": client.Config.DeviceModel,
|
||||
"system_version": client.Config.SystemVersion,
|
||||
"application_version": client.Config.ApplicationVersion,
|
||||
"enable_storage_optimizer": client.Config.EnableStorageOptimizer,
|
||||
"ignore_file_names": client.Config.IgnoreFileNames,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// SendPhoneNumber sends phone number to tdlib
|
||||
func (client *Client) SendPhoneNumber(phoneNumber string) (AuthorizationState, error) {
|
||||
_, err := client.SetAuthenticationPhoneNumber(phoneNumber, false, false)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authState, err := client.GetAuthorizationState()
|
||||
return authState, err
|
||||
}
|
||||
|
||||
// SendAuthCode sends auth code to tdlib
|
||||
func (client *Client) SendAuthCode(code string) (AuthorizationState, error) {
|
||||
_, err := client.CheckAuthenticationCode(code, "", "")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authState, err := client.GetAuthorizationState()
|
||||
return authState, err
|
||||
}
|
||||
|
||||
// SendAuthPassword sends two-step verification password (user defined)to tdlib
|
||||
func (client *Client) SendAuthPassword(password string) (AuthorizationState, error) {
|
||||
_, err := client.CheckAuthenticationPassword(password)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authState, err := client.GetAuthorizationState()
|
||||
return authState, err
|
||||
}
|
25335
vendor/github.com/Arman92/go-tdlib/types.go
generated
vendored
Executable file
25335
vendor/github.com/Arman92/go-tdlib/types.go
generated
vendored
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user