mirror of
https://github.com/Arman92/go-tdlib.git
synced 2024-09-12 19:00:38 +02:00
Stable work, added some examples
This commit is contained in:
parent
e6e7359fec
commit
d393342cb0
8 changed files with 21224 additions and 247 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -22,3 +22,8 @@
|
|||
|
||||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||
.glide/
|
||||
|
||||
tdlib-db
|
||||
tdlib-files
|
||||
|
||||
errors.txt
|
68
examples/authorization/basicAuthorization.go
Normal file
68
examples/authorization/basicAuthorization.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"tg-tdlib/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")
|
||||
}
|
||||
|
||||
}
|
78
examples/customEvents/getCustomEvents.go
Normal file
78
examples/customEvents/getCustomEvents.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"tg-tdlib/tdlib"
|
||||
"time"
|
||||
)
|
||||
|
||||
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,
|
||||
})
|
||||
|
||||
// Handle Ctrl+C
|
||||
ch := make(chan os.Signal, 2)
|
||||
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-ch
|
||||
client.DestroyInstance()
|
||||
os.Exit(1)
|
||||
}()
|
||||
|
||||
// Wait while we get AuthorizationReady!
|
||||
currentState, _ := client.Authorize()
|
||||
for ; currentState.GetAuthorizationStateEnum() != tdlib.AuthorizationStateReadyType; currentState, _ = client.Authorize() {
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
}
|
||||
|
||||
go func() {
|
||||
// Create an filter function which will be used to filter out unwanted tdlib messages
|
||||
eventFilter := func(msg *tdlib.TdMessage) bool {
|
||||
updateMsg := (*msg).(*tdlib.UpdateNewMessage)
|
||||
// For example, we want incomming messages from user with below id:
|
||||
if updateMsg.Message.SenderUserID == 41507975 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Here we can add a receiver to retreive any message type we want
|
||||
// We like to get UpdateNewMessage events and with a specific FilterFunc
|
||||
receiver := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, eventFilter, 5)
|
||||
for newMsg := range receiver.Chan {
|
||||
fmt.Println(newMsg)
|
||||
updateMsg := (newMsg).(*tdlib.UpdateNewMessage)
|
||||
// We assume the message content is simple text: (should be more sophosticated for general use)
|
||||
msgText := updateMsg.Message.Content.(*tdlib.MessageText)
|
||||
fmt.Println("MsgText: ", msgText.Text)
|
||||
fmt.Print("\n\n")
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
// Just fetch updates so the Updates channel won't cause the main routine to get blocked
|
||||
for update := range client.RawUpdates {
|
||||
_ = update
|
||||
}
|
||||
|
||||
}
|
78
examples/getChats/getChats.go
Normal file
78
examples/getChats/getChats.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"tg-tdlib/tdlib"
|
||||
"time"
|
||||
)
|
||||
|
||||
var allChats []tdlib.Chat
|
||||
|
||||
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,
|
||||
})
|
||||
|
||||
// Handle Ctrl+C , Gracefully exit and shutdown tdlib
|
||||
ch := make(chan os.Signal, 2)
|
||||
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-ch
|
||||
client.DestroyInstance()
|
||||
os.Exit(1)
|
||||
}()
|
||||
|
||||
// Wait while we get AuthorizationReady!
|
||||
currentState, _ := client.Authorize()
|
||||
for ; currentState.GetAuthorizationStateEnum() != tdlib.AuthorizationStateReadyType; currentState, _ = client.Authorize() {
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
}
|
||||
|
||||
// Main loop
|
||||
go func() {
|
||||
// Just fetch updates so the Updates channel won't cause the main routine to get blocked
|
||||
for update := range client.RawUpdates {
|
||||
_ = update
|
||||
}
|
||||
}()
|
||||
|
||||
// Get chats
|
||||
// see https://stackoverflow.com/questions/37782348/how-to-use-getchats-in-tdlib
|
||||
chats, err := client.GetChats(math.MaxInt64, 0, 100)
|
||||
allChats = make([]tdlib.Chat, 0, 1)
|
||||
if err != nil {
|
||||
fmt.Printf("Error getting chats, err: %v\n", err)
|
||||
} else {
|
||||
for _, chatID := range chats.ChatIDs {
|
||||
chat, err := client.GetChat(chatID)
|
||||
if err == nil {
|
||||
fmt.Println("Got chat info: ", *chat)
|
||||
allChats = append(allChats, *chat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
138
main.go
138
main.go
|
@ -1,22 +1,23 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"tg-tdlib/tdjson"
|
||||
"tg-tdlib/types"
|
||||
"tg-tdlib/tdlib"
|
||||
"time"
|
||||
)
|
||||
|
||||
var allChats []tdlib.Chat
|
||||
|
||||
func main() {
|
||||
tdjson.SetLogVerbosityLevel(1)
|
||||
tdjson.SetFilePath("./errors.txt")
|
||||
tdlib.SetLogVerbosityLevel(1)
|
||||
tdlib.SetFilePath("./errors.txt")
|
||||
|
||||
// Create new instance of client
|
||||
client := tdjson.NewClient(tdjson.TdlibConfig{
|
||||
client := tdlib.NewClient(tdlib.Config{
|
||||
APIID: "187786",
|
||||
APIHash: "e782045df67ba48e441ccb105da8fc85",
|
||||
SystemLanguageCode: "en",
|
||||
|
@ -27,8 +28,8 @@ func main() {
|
|||
UseFileDatabase: true,
|
||||
UseChatInfoDatabase: true,
|
||||
UseTestDataCenter: false,
|
||||
DatabaseDirectory: "tdlib-db",
|
||||
FileDirectory: "tdlib-files",
|
||||
DatabaseDirectory: "./tdlib-db",
|
||||
FileDirectory: "./tdlib-files",
|
||||
IgnoreFileNames: false,
|
||||
})
|
||||
|
||||
|
@ -37,93 +38,88 @@ func main() {
|
|||
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-ch
|
||||
client.Destroy()
|
||||
client.DestroyInstance()
|
||||
os.Exit(1)
|
||||
}()
|
||||
|
||||
for {
|
||||
currentState, _ := client.Authorize()
|
||||
if currentState == tdjson.AuthorizationStateWaitPhoneNumber {
|
||||
if currentState.GetAuthorizationStateEnum() == tdlib.AuthorizationStateWaitPhoneNumberType {
|
||||
fmt.Print("Enter phone: ")
|
||||
var number string
|
||||
fmt.Scanln(&number)
|
||||
client.SendPhoneNumber(number)
|
||||
} else if currentState == tdjson.AuthorizationStateWaitCode {
|
||||
_, 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)
|
||||
client.SendAuthCode(code)
|
||||
} else if currentState == tdjson.AuthorizationStateWaitPassword {
|
||||
_, 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)
|
||||
client.SendAuthPassword(password)
|
||||
} else if currentState == tdjson.AuthorizationStateReady {
|
||||
_, 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
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
for {
|
||||
res, err := client.SendAndCatch(tdjson.Update{
|
||||
"@type": "getAuthorizationState",
|
||||
})
|
||||
fmt.Println(res)
|
||||
fmt.Println(err)
|
||||
|
||||
result, err := client.SendAndCatchBytes(tdjson.Update{
|
||||
"@type": "getChats",
|
||||
"offset_order": 9223372036854775807,
|
||||
"offset_chat_id": 0,
|
||||
"limit": 200,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
panic("Fuck")
|
||||
eventFilter := func(msg *tdlib.TdMessage) bool {
|
||||
updateMsg := (*msg).(*tdlib.UpdateNewMessage)
|
||||
if updateMsg.Message.SenderUserID == 41507975 {
|
||||
return true
|
||||
}
|
||||
|
||||
chatIDs := types.Chats{}
|
||||
json.Unmarshal(result, &chatIDs)
|
||||
|
||||
var chats []types.Chat
|
||||
chats = make([]types.Chat, 0, 1)
|
||||
|
||||
for _, chatID := range chatIDs.ChatIDs {
|
||||
result, err = client.SendAndCatchBytes(tdjson.Update{
|
||||
"@type": "getChat",
|
||||
"chat_id": chatID,
|
||||
})
|
||||
|
||||
var update tdjson.Update
|
||||
json.Unmarshal(result, &update)
|
||||
fmt.Println(update)
|
||||
|
||||
var chat types.Chat
|
||||
json.Unmarshal(result, &chat)
|
||||
chats = append(chats, chat)
|
||||
}
|
||||
|
||||
result, err = client.SendAndCatchBytes(tdjson.Update{
|
||||
"@type": "getChatMember",
|
||||
"chat_id": -1001178287687,
|
||||
"user_id": 41507975,
|
||||
})
|
||||
|
||||
var update tdjson.Update
|
||||
json.Unmarshal(result, &update)
|
||||
fmt.Println(update)
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
return false
|
||||
}
|
||||
|
||||
receiver := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, eventFilter, 5)
|
||||
for newMsg := range receiver.Chan {
|
||||
fmt.Println(newMsg)
|
||||
updateMsg := (newMsg).(*tdlib.UpdateNewMessage)
|
||||
msgText := updateMsg.Message.Content.(*tdlib.MessageText)
|
||||
fmt.Println("MsgText: ", msgText.Text)
|
||||
fmt.Print("\n\n")
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
// Main loop
|
||||
for update := range client.Updates {
|
||||
// Show all updates
|
||||
fmt.Println(update)
|
||||
fmt.Print("\n\n")
|
||||
go func() {
|
||||
for update := range client.RawUpdates {
|
||||
// Show all updates
|
||||
// fmt.Println(update.Data)
|
||||
// fmt.Print("\n\n")
|
||||
_ = update
|
||||
}
|
||||
}()
|
||||
|
||||
// see https://stackoverflow.com/questions/37782348/how-to-use-getchats-in-tdlib
|
||||
chats, err := client.GetChats(math.MaxInt64, 0, 100)
|
||||
allChats = make([]tdlib.Chat, 0, 1)
|
||||
if err != nil {
|
||||
fmt.Printf("Error getting chats, err: %v\n", err)
|
||||
} else {
|
||||
for _, chatID := range chats.ChatIDs {
|
||||
chat, err := client.GetChat(chatID)
|
||||
if err == nil {
|
||||
fmt.Println("Got chat info: ", *chat)
|
||||
allChats = append(allChats, *chat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
|
6425
tdlib/methods.go
Executable file
6425
tdlib/methods.go
Executable file
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
|||
package tdjson
|
||||
package tdlib
|
||||
|
||||
//#cgo linux CFLAGS: -I/usr/local/include
|
||||
//#cgo windows CFLAGS: -IC:/src/td -IC:/src/td/build
|
||||
|
@ -12,41 +12,43 @@ import "C"
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Update is used to unmarshal recieved json strings into
|
||||
type Update = map[string]interface{}
|
||||
// UpdateData alias for use in UpdateMsg
|
||||
type UpdateData map[string]interface{}
|
||||
|
||||
// AuthorizationState is used to indicate Authorization State
|
||||
type AuthorizationState uint8
|
||||
// UpdateMsg is used to unmarshal recieved json strings into
|
||||
type UpdateMsg struct {
|
||||
Data UpdateData
|
||||
Raw []byte
|
||||
}
|
||||
|
||||
// AuthorizationStates
|
||||
const (
|
||||
AuthorizationStateClosed = iota
|
||||
AuthorizationStateClosing
|
||||
AuthorizationStateLoggingOut
|
||||
AuthorizationStateReady
|
||||
AuthorizationStateWaitCode
|
||||
AuthorizationStateWaitEncryptionKey
|
||||
AuthorizationStateWaitPassword
|
||||
AuthorizationStateWaitPhoneNumber
|
||||
AuthorizationStateWaitTdlibParameters
|
||||
)
|
||||
// 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
|
||||
Updates chan Update
|
||||
waiters sync.Map
|
||||
rawWaiters sync.Map
|
||||
Client unsafe.Pointer
|
||||
RawUpdates chan UpdateMsg
|
||||
receivers []EventReceiver
|
||||
waiters sync.Map
|
||||
receiverLock *sync.Mutex
|
||||
}
|
||||
|
||||
// TdlibConfig holds tdlibParameters
|
||||
type TdlibConfig struct {
|
||||
// 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.
|
||||
|
@ -67,56 +69,69 @@ type TdlibConfig struct {
|
|||
|
||||
// NewClient Creates a new instance of TDLib.
|
||||
// Has two public fields:
|
||||
// Client itself and Updates channel
|
||||
func NewClient(config TdlibConfig) *Client {
|
||||
// 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.Updates = make(chan Update, 100)
|
||||
client.RawUpdates = make(chan UpdateMsg, 100)
|
||||
client.receivers = make([]EventReceiver, 0, 1)
|
||||
client.receiverLock = &sync.Mutex{}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
// get update
|
||||
updateBytes := client.Receive(10)
|
||||
var update Update
|
||||
json.Unmarshal(updateBytes, &update)
|
||||
var updateData UpdateData
|
||||
json.Unmarshal(updateBytes, &updateData)
|
||||
|
||||
// does new update has @extra field?
|
||||
if extra, hasExtra := update["@extra"].(string); hasExtra {
|
||||
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 Update) <- update
|
||||
waiter.(chan UpdateMsg) <- UpdateMsg{Data: updateData, Raw: updateBytes}
|
||||
|
||||
// trying to prevent memory leak
|
||||
close(waiter.(chan Update))
|
||||
}
|
||||
|
||||
// trying to load update with this salt
|
||||
if rawWaiter, found := client.rawWaiters.Load(extra); found {
|
||||
// found? send it to rawWaiter channel
|
||||
rawWaiter.(chan []byte) <- updateBytes
|
||||
|
||||
// trying to prevent memory leak
|
||||
close(rawWaiter.(chan []byte))
|
||||
close(waiter.(chan UpdateMsg))
|
||||
}
|
||||
} else {
|
||||
// does new updates has @type field?
|
||||
if _, hasType := update["@type"]; hasType {
|
||||
if msgType, hasType := updateData["@type"]; hasType {
|
||||
// if yes, send it in main channel
|
||||
client.Updates <- update
|
||||
client.RawUpdates <- UpdateMsg{Data: updateData, Raw: updateBytes}
|
||||
|
||||
client.receiverLock.Lock()
|
||||
for _, receiver := range client.receivers {
|
||||
if msgType == receiver.Instance.MessageType() {
|
||||
err := json.Unmarshal(updateBytes, &receiver.Instance)
|
||||
if err != nil {
|
||||
fmt.Printf("Error unmarhaling to type %v", err)
|
||||
}
|
||||
if receiver.FilterFunc(&receiver.Instance) {
|
||||
receiver.Chan <- receiver.Instance
|
||||
}
|
||||
}
|
||||
}
|
||||
client.receiverLock.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
client.Send(Update{
|
||||
client.Send(UpdateData{
|
||||
"@type": "setTdlibParameters",
|
||||
"parameters": Update{
|
||||
"parameters": UpdateData{
|
||||
"@type": "tdlibParameters",
|
||||
"use_test_dc": config.UseTestDataCenter,
|
||||
"database_directory": config.DatabaseDirectory,
|
||||
"files_directory": config.FileDirectory,
|
||||
"use_file_database": config.UseFileDatabase,
|
||||
"use_chat_info_database": config.UseChatInfoDatabase,
|
||||
"use_message_database": config.UseMessageDatabase,
|
||||
"use_secret_chats": config.UseSecretChats,
|
||||
"api_id": config.APIID,
|
||||
"api_hash": config.APIHash,
|
||||
"system_language_code": config.SystemLanguageCode,
|
||||
|
@ -124,64 +139,79 @@ func NewClient(config TdlibConfig) *Client {
|
|||
"system_version": config.SystemVersion,
|
||||
"application_version": config.ApplicationVersion,
|
||||
"enable_storage_optimizer": config.EnableStorageOptimizer,
|
||||
"ignore_file_names": config.IgnoreFileNames,
|
||||
},
|
||||
})
|
||||
|
||||
return &client
|
||||
}
|
||||
|
||||
// Destroy Destroys the TDLib client instance.
|
||||
// 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 (c *Client) Destroy() {
|
||||
C.td_json_client_destroy(c.Client)
|
||||
func (client *Client) DestroyInstance() {
|
||||
C.td_json_client_destroy(client.Client)
|
||||
}
|
||||
|
||||
// Send Sends request to the TDLib client.
|
||||
// You can provide string or Update.
|
||||
func (c *Client) Send(jsonQuery interface{}) {
|
||||
// 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 Update:
|
||||
jsonBytes, _ := json.Marshal(jsonQuery.(Update))
|
||||
case UpdateData:
|
||||
jsonBytes, _ := json.Marshal(jsonQuery.(UpdateData))
|
||||
fmt.Println("Sending: ", string(jsonBytes))
|
||||
query = C.CString(string(jsonBytes))
|
||||
}
|
||||
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
C.td_json_client_send(c.Client, 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 Update.
|
||||
func (c *Client) Receive(timeout float64) []byte {
|
||||
result := C.td_json_client_receive(c.Client, C.double(timeout))
|
||||
// You can provide string or UpdateData.
|
||||
func (client *Client) Receive(timeout float64) []byte {
|
||||
result := C.td_json_client_receive(client.Client, C.double(timeout))
|
||||
|
||||
// var update Update
|
||||
// json.Unmarshal([]byte(C.GoString(result)), &update)
|
||||
return []byte(C.GoString(result))
|
||||
}
|
||||
|
||||
// Execute Synchronously executes TDLib request.
|
||||
// Only a few requests can be executed synchronously.
|
||||
func (c *Client) Execute(jsonQuery interface{}) Update {
|
||||
func (client *Client) Execute(jsonQuery interface{}) UpdateMsg {
|
||||
var query *C.char
|
||||
|
||||
switch jsonQuery.(type) {
|
||||
case string:
|
||||
query = C.CString(jsonQuery.(string))
|
||||
case Update:
|
||||
jsonBytes, _ := json.Marshal(jsonQuery.(Update))
|
||||
case UpdateData:
|
||||
jsonBytes, _ := json.Marshal(jsonQuery.(UpdateData))
|
||||
query = C.CString(string(jsonBytes))
|
||||
}
|
||||
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
result := C.td_json_client_execute(c.Client, query)
|
||||
result := C.td_json_client_execute(client.Client, query)
|
||||
|
||||
var update Update
|
||||
var update UpdateData
|
||||
json.Unmarshal([]byte(C.GoString(result)), &update)
|
||||
return 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.
|
||||
|
@ -201,16 +231,16 @@ func SetLogVerbosityLevel(level int) {
|
|||
}
|
||||
|
||||
// SendAndCatch Sends request to the TDLib client and catches the result in updates channel.
|
||||
// You can provide string or Update.
|
||||
func (c *Client) SendAndCatch(jsonQuery interface{}) (Update, error) {
|
||||
var update Update
|
||||
// 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 Update:
|
||||
update = jsonQuery.(Update)
|
||||
case UpdateData:
|
||||
update = jsonQuery.(UpdateData)
|
||||
}
|
||||
|
||||
// letters for generating random string
|
||||
|
@ -227,11 +257,11 @@ func (c *Client) SendAndCatch(jsonQuery interface{}) (Update, error) {
|
|||
update["@extra"] = randomString
|
||||
|
||||
// create waiter chan and save it in Waiters
|
||||
waiter := make(chan Update, 1)
|
||||
c.waiters.Store(randomString, waiter)
|
||||
waiter := make(chan UpdateMsg, 1)
|
||||
client.waiters.Store(randomString, waiter)
|
||||
|
||||
// send it through already implemented method
|
||||
c.Send(update)
|
||||
client.Send(update)
|
||||
|
||||
select {
|
||||
// wait response from main loop in NewClient()
|
||||
|
@ -239,138 +269,62 @@ func (c *Client) SendAndCatch(jsonQuery interface{}) (Update, error) {
|
|||
return response, nil
|
||||
// or timeout
|
||||
case <-time.After(10 * time.Second):
|
||||
c.waiters.Delete(randomString)
|
||||
return Update{}, errors.New("timeout")
|
||||
}
|
||||
}
|
||||
|
||||
// SendAndCatchBytes Sends request to the TDLib client and catches the result (bytes) in updates channel.
|
||||
// You can provide string or Update.
|
||||
func (c *Client) SendAndCatchBytes(jsonQuery interface{}) ([]byte, error) {
|
||||
var update Update
|
||||
|
||||
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 Update:
|
||||
update = jsonQuery.(Update)
|
||||
}
|
||||
|
||||
// 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 []byte, 1)
|
||||
c.rawWaiters.Store(randomString, waiter)
|
||||
|
||||
// send it through already implemented method
|
||||
c.Send(update)
|
||||
|
||||
select {
|
||||
// wait response from main loop in NewClient()
|
||||
case response := <-waiter:
|
||||
return response, nil
|
||||
// or timeout
|
||||
case <-time.After(10 * time.Second):
|
||||
c.rawWaiters.Delete(randomString)
|
||||
return nil, errors.New("timeout")
|
||||
}
|
||||
}
|
||||
|
||||
// GetAuthorizationState returns authorization state
|
||||
func (c *Client) GetAuthorizationState() (AuthorizationState, error) {
|
||||
res, err := c.SendAndCatch(Update{
|
||||
"@type": "getAuthorizationState",
|
||||
})
|
||||
|
||||
switch res["@type"].(string) {
|
||||
case "authorizationStateClosed":
|
||||
return AuthorizationStateClosed, err
|
||||
case "authorizationStateClosing":
|
||||
return AuthorizationStateClosing, err
|
||||
case "authorizationStateLoggingOut":
|
||||
return AuthorizationStateLoggingOut, err
|
||||
case "authorizationStateReady":
|
||||
return AuthorizationStateReady, err
|
||||
case "authorizationStateWaitCode":
|
||||
return AuthorizationStateWaitCode, err
|
||||
case "authorizationStateWaitEncryptionKey":
|
||||
return AuthorizationStateWaitEncryptionKey, err
|
||||
case "authorizationStateWaitPassword":
|
||||
return AuthorizationStateWaitPassword, err
|
||||
case "authorizationStateWaitPhoneNumber":
|
||||
return AuthorizationStateWaitPhoneNumber, err
|
||||
case "authorizationStateWaitTdlibParameters":
|
||||
return AuthorizationStateWaitTdlibParameters, err
|
||||
default:
|
||||
return AuthorizationStateClosed, err
|
||||
client.waiters.Delete(randomString)
|
||||
return UpdateMsg{}, errors.New("timeout")
|
||||
}
|
||||
}
|
||||
|
||||
// Authorize is used to authorize the users
|
||||
func (c *Client) Authorize() (AuthorizationState, error) {
|
||||
if state, _ := c.GetAuthorizationState(); state == AuthorizationStateWaitEncryptionKey {
|
||||
_, err := c.SendAndCatch(Update{
|
||||
"@type": "checkDatabaseEncryptionKey",
|
||||
})
|
||||
func (client *Client) Authorize() (AuthorizationState, error) {
|
||||
state, err := client.GetAuthorizationState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return AuthorizationStateClosed, err
|
||||
if state.GetAuthorizationStateEnum() == AuthorizationStateWaitEncryptionKeyType {
|
||||
ok, err := client.CheckDatabaseEncryptionKey(nil)
|
||||
|
||||
if ok == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return c.GetAuthorizationState()
|
||||
authState, err := client.GetAuthorizationState()
|
||||
return authState, err
|
||||
}
|
||||
|
||||
// SendPhoneNumber sends phone number to tdlib
|
||||
func (c *Client) SendPhoneNumber(phoneNumber string) (AuthorizationState, error) {
|
||||
_, err := c.SendAndCatch(Update{
|
||||
"@type": "setAuthenticationPhoneNumber",
|
||||
"phone_number": phoneNumber,
|
||||
})
|
||||
func (client *Client) SendPhoneNumber(phoneNumber string) (AuthorizationState, error) {
|
||||
_, err := client.SetAuthenticationPhoneNumber(phoneNumber, false, false)
|
||||
|
||||
if err != nil {
|
||||
return AuthorizationStateClosed, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.GetAuthorizationState()
|
||||
authState, err := client.GetAuthorizationState()
|
||||
return authState, err
|
||||
}
|
||||
|
||||
// SendAuthCode sends auth code to tdlib
|
||||
func (c *Client) SendAuthCode(code string) (AuthorizationState, error) {
|
||||
_, err := c.SendAndCatch(Update{
|
||||
"@type": "checkAuthenticationCode",
|
||||
"code": code,
|
||||
})
|
||||
func (client *Client) SendAuthCode(code string) (AuthorizationState, error) {
|
||||
_, err := client.CheckAuthenticationCode(code, "", "")
|
||||
|
||||
if err != nil {
|
||||
return AuthorizationStateClosed, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.GetAuthorizationState()
|
||||
authState, err := client.GetAuthorizationState()
|
||||
return authState, err
|
||||
}
|
||||
|
||||
// SendAuthPassword sends two-step verification password (user defined)to tdlib
|
||||
func (c *Client) SendAuthPassword(password string) (AuthorizationState, error) {
|
||||
_, err := c.SendAndCatch(Update{
|
||||
"@type": "checkAuthenticationPassword",
|
||||
"password": password,
|
||||
})
|
||||
func (client *Client) SendAuthPassword(password string) (AuthorizationState, error) {
|
||||
_, err := client.CheckAuthenticationPassword(password)
|
||||
|
||||
if err != nil {
|
||||
return AuthorizationStateClosed, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.GetAuthorizationState()
|
||||
authState, err := client.GetAuthorizationState()
|
||||
return authState, err
|
||||
}
|
14373
tdlib/types.go
Executable file
14373
tdlib/types.go
Executable file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue