Compare commits
4 commits
c0re100
...
fresh-tdli
Author | SHA1 | Date | |
---|---|---|---|
47da331806 | |||
063c3471b0 | |||
ff46ac12bc | |||
c54167dc40 |
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
||||||
TAG := v1.8.0
|
TAG := v1.8.14
|
||||||
|
|
||||||
schema-update:
|
schema-update:
|
||||||
curl https://raw.githubusercontent.com/tdlib/td/${TAG}/td/generate/scheme/td_api.tl 2>/dev/null > ./data/td_api.tl
|
curl https://raw.githubusercontent.com/tdlib/td/${TAG}/td/generate/scheme/td_api.tl 2>/dev/null > ./data/td_api.tl
|
||||||
|
|
15
README.md
15
README.md
|
@ -1,11 +1,13 @@
|
||||||
# go-tdlib
|
# go-tdlib
|
||||||
|
|
||||||
Go wrapper for [TDLib (Telegram Database Library)](https://github.com/tdlib/td) with full support of TDLib v1.8.0
|
Go wrapper for [TDLib (Telegram Database Library)](https://github.com/tdlib/td) with full support of TDLib v1.8.14
|
||||||
|
|
||||||
## TDLib installation
|
## TDLib installation
|
||||||
|
|
||||||
Use [TDLib build instructions](https://tdlib.github.io/td/build.html) with checkmarked `Install built TDLib to /usr/local instead of placing the files to td/tdlib`.
|
Use [TDLib build instructions](https://tdlib.github.io/td/build.html) with checkmarked `Install built TDLib to /usr/local instead of placing the files to td/tdlib`.
|
||||||
|
|
||||||
|
### Note: Compatible with TDLib v1.8.14 only!
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
Build with environment variables:
|
Build with environment variables:
|
||||||
|
@ -135,6 +137,17 @@ tdlibClient, err := client.NewClient(authorizer, proxy)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
[Example application](https://github.com/zelenin/go-tdlib/tree/master/example)
|
||||||
|
|
||||||
|
```
|
||||||
|
cd example
|
||||||
|
docker build --network host --build-arg TD_TAG=v1.8.14 --tag tdlib-test .
|
||||||
|
docker run --rm -it -e "API_ID=00000" -e "API_HASH=abcdef0123456789" tdlib-test ash
|
||||||
|
./app
|
||||||
|
```
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
* WIP. Library API can be changed in the future
|
* WIP. Library API can be changed in the future
|
||||||
|
|
|
@ -8,6 +8,42 @@ import (
|
||||||
|
|
||||||
var ErrNotSupportedAuthorizationState = errors.New("not supported state")
|
var ErrNotSupportedAuthorizationState = errors.New("not supported state")
|
||||||
|
|
||||||
|
// Contains parameters for TDLib initialization
|
||||||
|
type TdlibParameters struct {
|
||||||
|
// Pass true to use Telegram test environment instead of the production environment
|
||||||
|
UseTestDc bool `json:"use_test_dc"`
|
||||||
|
// The path to the directory for the persistent database; if empty, the current working directory will be used
|
||||||
|
DatabaseDirectory string `json:"database_directory"`
|
||||||
|
// The path to the directory for storing files; if empty, database_directory will be used
|
||||||
|
FilesDirectory string `json:"files_directory"`
|
||||||
|
// Encryption key for the database. If the encryption key is invalid, then an error with code 401 will be returned
|
||||||
|
DatabaseEncryptionKey []byte `json:"database_encryption_key"`
|
||||||
|
// Pass true to keep information about downloaded and uploaded files between application restarts
|
||||||
|
UseFileDatabase bool `json:"use_file_database"`
|
||||||
|
// Pass true to keep cache of users, basic groups, supergroups, channels and secret chats between restarts. Implies use_file_database
|
||||||
|
UseChatInfoDatabase bool `json:"use_chat_info_database"`
|
||||||
|
// Pass true to keep cache of chats and messages between restarts. Implies use_chat_info_database
|
||||||
|
UseMessageDatabase bool `json:"use_message_database"`
|
||||||
|
// Pass true to enable support for secret chats
|
||||||
|
UseSecretChats bool `json:"use_secret_chats"`
|
||||||
|
// Application identifier for Telegram API access, which can be obtained at https://my.telegram.org
|
||||||
|
ApiId int32 `json:"api_id"`
|
||||||
|
// Application identifier hash for Telegram API access, which can be obtained at https://my.telegram.org
|
||||||
|
ApiHash string `json:"api_hash"`
|
||||||
|
// IETF language tag of the user's operating system language; must be non-empty
|
||||||
|
SystemLanguageCode string `json:"system_language_code"`
|
||||||
|
// Model of the device the application is being run on; must be non-empty
|
||||||
|
DeviceModel string `json:"device_model"`
|
||||||
|
// Version of the operating system the application is being run on. If empty, the version is automatically detected by TDLib
|
||||||
|
SystemVersion string `json:"system_version"`
|
||||||
|
// Application version; must be non-empty
|
||||||
|
ApplicationVersion string `json:"application_version"`
|
||||||
|
// Pass true to automatically delete old files in background
|
||||||
|
EnableStorageOptimizer bool `json:"enable_storage_optimizer"`
|
||||||
|
// Pass true to ignore original file names for downloaded files. Otherwise, downloaded files are saved under names as close as possible to the original name
|
||||||
|
IgnoreFileNames bool `json:"ignore_file_names"`
|
||||||
|
}
|
||||||
|
|
||||||
type AuthorizationStateHandler interface {
|
type AuthorizationStateHandler interface {
|
||||||
Handle(client *Client, state AuthorizationState) error
|
Handle(client *Client, state AuthorizationState) error
|
||||||
Close()
|
Close()
|
||||||
|
@ -65,15 +101,27 @@ func (stateHandler *clientAuthorizer) Handle(client *Client, state Authorization
|
||||||
|
|
||||||
switch state.AuthorizationStateType() {
|
switch state.AuthorizationStateType() {
|
||||||
case TypeAuthorizationStateWaitTdlibParameters:
|
case TypeAuthorizationStateWaitTdlibParameters:
|
||||||
|
p := <-stateHandler.TdlibParameters
|
||||||
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
||||||
Parameters: <-stateHandler.TdlibParameters,
|
UseTestDc: p.UseTestDc,
|
||||||
|
DatabaseDirectory: p.DatabaseDirectory,
|
||||||
|
FilesDirectory: p.FilesDirectory,
|
||||||
|
DatabaseEncryptionKey: p.DatabaseEncryptionKey,
|
||||||
|
UseFileDatabase: p.UseFileDatabase,
|
||||||
|
UseChatInfoDatabase: p.UseChatInfoDatabase,
|
||||||
|
UseMessageDatabase: p.UseMessageDatabase,
|
||||||
|
UseSecretChats: p.UseSecretChats,
|
||||||
|
ApiId: p.ApiId,
|
||||||
|
ApiHash: p.ApiHash,
|
||||||
|
SystemLanguageCode: p.SystemLanguageCode,
|
||||||
|
DeviceModel: p.DeviceModel,
|
||||||
|
SystemVersion: p.SystemVersion,
|
||||||
|
ApplicationVersion: p.ApplicationVersion,
|
||||||
|
EnableStorageOptimizer: p.EnableStorageOptimizer,
|
||||||
|
IgnoreFileNames: p.IgnoreFileNames,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitEncryptionKey:
|
|
||||||
_, err := client.CheckDatabaseEncryptionKey(&CheckDatabaseEncryptionKeyRequest{})
|
|
||||||
return err
|
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitPhoneNumber:
|
case TypeAuthorizationStateWaitPhoneNumber:
|
||||||
_, err := client.SetAuthenticationPhoneNumber(&SetAuthenticationPhoneNumberRequest{
|
_, err := client.SetAuthenticationPhoneNumber(&SetAuthenticationPhoneNumberRequest{
|
||||||
PhoneNumber: <-stateHandler.PhoneNumber,
|
PhoneNumber: <-stateHandler.PhoneNumber,
|
||||||
|
@ -85,12 +133,21 @@ func (stateHandler *clientAuthorizer) Handle(client *Client, state Authorization
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
|
case TypeAuthorizationStateWaitEmailAddress:
|
||||||
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
|
case TypeAuthorizationStateWaitEmailCode:
|
||||||
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitCode:
|
case TypeAuthorizationStateWaitCode:
|
||||||
_, err := client.CheckAuthenticationCode(&CheckAuthenticationCodeRequest{
|
_, err := client.CheckAuthenticationCode(&CheckAuthenticationCodeRequest{
|
||||||
Code: <-stateHandler.Code,
|
Code: <-stateHandler.Code,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
|
case TypeAuthorizationStateWaitOtherDeviceConfirmation:
|
||||||
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitRegistration:
|
case TypeAuthorizationStateWaitRegistration:
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
|
@ -140,6 +197,12 @@ func CliInteractor(clientAuthorizer *clientAuthorizer) {
|
||||||
|
|
||||||
clientAuthorizer.PhoneNumber <- phoneNumber
|
clientAuthorizer.PhoneNumber <- phoneNumber
|
||||||
|
|
||||||
|
case TypeAuthorizationStateWaitEmailAddress:
|
||||||
|
return
|
||||||
|
|
||||||
|
case TypeAuthorizationStateWaitEmailCode:
|
||||||
|
return
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitCode:
|
case TypeAuthorizationStateWaitCode:
|
||||||
var code string
|
var code string
|
||||||
|
|
||||||
|
@ -148,6 +211,12 @@ func CliInteractor(clientAuthorizer *clientAuthorizer) {
|
||||||
|
|
||||||
clientAuthorizer.Code <- code
|
clientAuthorizer.Code <- code
|
||||||
|
|
||||||
|
case TypeAuthorizationStateWaitOtherDeviceConfirmation:
|
||||||
|
return
|
||||||
|
|
||||||
|
case TypeAuthorizationStateWaitRegistration:
|
||||||
|
return
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitPassword:
|
case TypeAuthorizationStateWaitPassword:
|
||||||
fmt.Println("Enter password: ")
|
fmt.Println("Enter password: ")
|
||||||
var password string
|
var password string
|
||||||
|
@ -185,15 +254,27 @@ func (stateHandler *botAuthorizer) Handle(client *Client, state AuthorizationSta
|
||||||
|
|
||||||
switch state.AuthorizationStateType() {
|
switch state.AuthorizationStateType() {
|
||||||
case TypeAuthorizationStateWaitTdlibParameters:
|
case TypeAuthorizationStateWaitTdlibParameters:
|
||||||
|
p := <-stateHandler.TdlibParameters
|
||||||
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
||||||
Parameters: <-stateHandler.TdlibParameters,
|
UseTestDc: p.UseTestDc,
|
||||||
|
DatabaseDirectory: p.DatabaseDirectory,
|
||||||
|
FilesDirectory: p.FilesDirectory,
|
||||||
|
DatabaseEncryptionKey: p.DatabaseEncryptionKey,
|
||||||
|
UseFileDatabase: p.UseFileDatabase,
|
||||||
|
UseChatInfoDatabase: p.UseChatInfoDatabase,
|
||||||
|
UseMessageDatabase: p.UseMessageDatabase,
|
||||||
|
UseSecretChats: p.UseSecretChats,
|
||||||
|
ApiId: p.ApiId,
|
||||||
|
ApiHash: p.ApiHash,
|
||||||
|
SystemLanguageCode: p.SystemLanguageCode,
|
||||||
|
DeviceModel: p.DeviceModel,
|
||||||
|
SystemVersion: p.SystemVersion,
|
||||||
|
ApplicationVersion: p.ApplicationVersion,
|
||||||
|
EnableStorageOptimizer: p.EnableStorageOptimizer,
|
||||||
|
IgnoreFileNames: p.IgnoreFileNames,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitEncryptionKey:
|
|
||||||
_, err := client.CheckDatabaseEncryptionKey(&CheckDatabaseEncryptionKeyRequest{})
|
|
||||||
return err
|
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitPhoneNumber:
|
case TypeAuthorizationStateWaitPhoneNumber:
|
||||||
_, err := client.CheckAuthenticationBotToken(&CheckAuthenticationBotTokenRequest{
|
_, err := client.CheckAuthenticationBotToken(&CheckAuthenticationBotTokenRequest{
|
||||||
Token: <-stateHandler.Token,
|
Token: <-stateHandler.Token,
|
||||||
|
|
5071
client/function.go
5071
client/function.go
File diff suppressed because it is too large
Load diff
|
@ -2,6 +2,7 @@ package client
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <td/telegram/td_json_client.h>
|
#include <td/telegram/td_json_client.h>
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
@ -83,7 +84,8 @@ func (instance *tdlib) receive(timeout time.Duration) (*Response, error) {
|
||||||
return nil, errors.New("update receiving timeout")
|
return nil, errors.New("update receiving timeout")
|
||||||
}
|
}
|
||||||
|
|
||||||
data := []byte(C.GoString(result))
|
resultLen := C.strlen(result)
|
||||||
|
data := C.GoBytes(unsafe.Pointer(result), C.int(resultLen))
|
||||||
|
|
||||||
var resp Response
|
var resp Response
|
||||||
|
|
||||||
|
@ -107,7 +109,8 @@ func Execute(req Request) (*Response, error) {
|
||||||
return nil, errors.New("request can't be parsed")
|
return nil, errors.New("request can't be parsed")
|
||||||
}
|
}
|
||||||
|
|
||||||
data = []byte(C.GoString(result))
|
resultLen := C.strlen(result)
|
||||||
|
data = C.GoBytes(unsafe.Pointer(result), C.int(resultLen))
|
||||||
|
|
||||||
var resp Response
|
var resp Response
|
||||||
|
|
||||||
|
|
12267
client/type.go
12267
client/type.go
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
8909
data/td_api.json
8909
data/td_api.json
File diff suppressed because it is too large
Load diff
4474
data/td_api.tl
4474
data/td_api.tl
File diff suppressed because it is too large
Load diff
85
example/Dockerfile
Normal file
85
example/Dockerfile
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
FROM alpine:3.17 as tdlib-builder
|
||||||
|
|
||||||
|
ENV LANG en_US.UTF-8
|
||||||
|
ENV TZ UTC
|
||||||
|
|
||||||
|
ARG TD_TAG
|
||||||
|
|
||||||
|
RUN apk update && \
|
||||||
|
apk upgrade && \
|
||||||
|
apk add --update \
|
||||||
|
build-base \
|
||||||
|
ca-certificates \
|
||||||
|
ccache \
|
||||||
|
cmake \
|
||||||
|
git \
|
||||||
|
gperf \
|
||||||
|
linux-headers \
|
||||||
|
openssl-dev \
|
||||||
|
php \
|
||||||
|
php-ctype \
|
||||||
|
readline-dev \
|
||||||
|
zlib-dev && \
|
||||||
|
git clone -b "${TD_TAG}" "https://github.com/tdlib/td.git" /src && \
|
||||||
|
mkdir /src/build && \
|
||||||
|
cd /src/build && \
|
||||||
|
cmake \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_INSTALL_PREFIX:PATH=/usr/local \
|
||||||
|
.. && \
|
||||||
|
cmake --build . --target prepare_cross_compiling && \
|
||||||
|
cd .. && \
|
||||||
|
php SplitSource.php && \
|
||||||
|
cd build && \
|
||||||
|
cmake --build . --target install && \
|
||||||
|
ls -lah /usr/local
|
||||||
|
|
||||||
|
|
||||||
|
FROM golang:1.20.2-alpine3.17 as go-builder
|
||||||
|
|
||||||
|
ENV LANG en_US.UTF-8
|
||||||
|
ENV TZ UTC
|
||||||
|
|
||||||
|
RUN set -eux && \
|
||||||
|
apk update && \
|
||||||
|
apk upgrade && \
|
||||||
|
apk add \
|
||||||
|
bash \
|
||||||
|
build-base \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
git \
|
||||||
|
linux-headers \
|
||||||
|
openssl-dev \
|
||||||
|
zlib-dev
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY --from=tdlib-builder /usr/local/include/td /usr/local/include/td/
|
||||||
|
COPY --from=tdlib-builder /usr/local/lib/libtd* /usr/local/lib/
|
||||||
|
COPY . /src
|
||||||
|
|
||||||
|
RUN go build \
|
||||||
|
-a \
|
||||||
|
-trimpath \
|
||||||
|
-ldflags "-s -w" \
|
||||||
|
-o app \
|
||||||
|
"./demo.go" && \
|
||||||
|
ls -lah
|
||||||
|
|
||||||
|
|
||||||
|
FROM alpine:3.17
|
||||||
|
|
||||||
|
ENV LANG en_US.UTF-8
|
||||||
|
ENV TZ UTC
|
||||||
|
|
||||||
|
RUN apk upgrade --no-cache && \
|
||||||
|
apk add --no-cache \
|
||||||
|
ca-certificates \
|
||||||
|
libstdc++
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=go-builder /src/app .
|
||||||
|
|
||||||
|
CMD ["./app"]
|
83
example/demo.go
Normal file
83
example/demo.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/zelenin/go-tdlib/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
authorizer := client.ClientAuthorizer()
|
||||||
|
go client.CliInteractor(authorizer)
|
||||||
|
|
||||||
|
var (
|
||||||
|
apiIdRaw = os.Getenv("API_ID")
|
||||||
|
apiHash = os.Getenv("API_HASH")
|
||||||
|
)
|
||||||
|
|
||||||
|
apiId64, err := strconv.ParseInt(apiIdRaw, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("strconv.Atoi error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
apiId := int32(apiId64)
|
||||||
|
|
||||||
|
authorizer.TdlibParameters <- &client.TdlibParameters{
|
||||||
|
UseTestDc: false,
|
||||||
|
DatabaseDirectory: filepath.Join(".tdlib", "database"),
|
||||||
|
FilesDirectory: filepath.Join(".tdlib", "files"),
|
||||||
|
UseFileDatabase: true,
|
||||||
|
UseChatInfoDatabase: true,
|
||||||
|
UseMessageDatabase: true,
|
||||||
|
UseSecretChats: false,
|
||||||
|
ApiId: apiId,
|
||||||
|
ApiHash: apiHash,
|
||||||
|
SystemLanguageCode: "en",
|
||||||
|
DeviceModel: "Server",
|
||||||
|
SystemVersion: "1.0.0",
|
||||||
|
ApplicationVersion: "1.0.0",
|
||||||
|
EnableStorageOptimizer: true,
|
||||||
|
IgnoreFileNames: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.SetLogVerbosityLevel(&client.SetLogVerbosityLevelRequest{
|
||||||
|
NewVerbosityLevel: 1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("SetLogVerbosityLevel error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tdlibClient, err := client.NewClient(authorizer)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("NewClient error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
optionValue, err := tdlibClient.GetOption(&client.GetOptionRequest{
|
||||||
|
Name: "version",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("GetOption error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("TDLib version: %s", optionValue.(*client.OptionValueString).Value)
|
||||||
|
|
||||||
|
me, err := tdlibClient.GetMe()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("GetMe error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Me: %s %s [%s]", me.FirstName, me.LastName, me.Username)
|
||||||
|
|
||||||
|
ch := make(chan os.Signal, 2)
|
||||||
|
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
||||||
|
go func() {
|
||||||
|
<-ch
|
||||||
|
tdlibClient.Stop()
|
||||||
|
os.Exit(1)
|
||||||
|
}()
|
||||||
|
}
|
5
example/go.mod
Normal file
5
example/go.mod
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module go-tdlib-demo
|
||||||
|
|
||||||
|
go 1.20
|
||||||
|
|
||||||
|
require github.com/zelenin/go-tdlib v0.6.0 // indirect
|
2
example/go.sum
Normal file
2
example/go.sum
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
github.com/zelenin/go-tdlib v0.6.0 h1:dmdaPYcluNPiVuagM7D2FPT/nLYftTmqeKndz30vSDM=
|
||||||
|
github.com/zelenin/go-tdlib v0.6.0/go.mod h1:Xs8fXbk5n7VaPyrSs9DP7QYoBScWYsjX+lUcWmx1DIU=
|
Loading…
Reference in a new issue