Skip to content
This repository has been archived by the owner on Sep 13, 2019. It is now read-only.

Commit

Permalink
Merge pull request #4 from shelomentsevd/master
Browse files Browse the repository at this point in the history
Options pattern for flexible configuration
  • Loading branch information
savely-krasovsky authored Mar 13, 2018
2 parents aa49115 + 2b85205 commit c344b34
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 22 deletions.
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,26 @@ func main() {
tdjson.SetLogVerbosityLevel(1)
tdjson.SetFilePath("./errors.txt")

var params []tdjson.Option = []tdjson.Option{
tdjson.WithMessageDatabase(),
tdjson.WithStorageOptimizer(),
}

// Get API_ID and API_HASH from env vars
apiId := os.Getenv("API_ID")
if apiId == "" {
log.Fatal("API_ID env variable not specified")
}
params = append(params, tdjson.WithID(apiId))

apiHash := os.Getenv("API_HASH")
if apiHash == "" {
log.Fatal("API_HASH env variable not specified")
}
params = append(params, tdjson.WithHash(apiHash))

// Create new instance of client
client := tdjson.NewClient()
client := tdjson.NewClient(params...)

// Handle Ctrl+C
ch := make(chan os.Signal, 2)
Expand All @@ -65,7 +73,7 @@ func main() {
// Authorization block
if update["@type"].(string) == "updateAuthorizationState" {
if authorizationState, ok := update["authorization_state"].(tdjson.Update)["@type"].(string); ok {
res, err := client.Auth(authorizationState, apiId, apiHash)
res, err := client.Auth(authorizationState)
if err != nil {
log.Println(err)
}
Expand All @@ -74,5 +82,4 @@ func main() {
}
}
}

```
156 changes: 156 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package tdjson

// The Telegram test environment will be used instead of the production environment
func WithTestDC() Option {
return func(options *options) {
options.useTestDC = true
}
}

// The path to the directory for the persistent database; if empty, the current working directory will be used
func WithDatabaseDir(path string) Option {
return func(options *options) {
options.databaseDirectory = path
}
}

// The path to the directory for storing files; if empty, database_directory will be used
func WithFilesDir(path string) Option {
return func(options *options) {
options.filesDirectory = path
}
}

// If set to true, information about downloaded and uploaded files will be saved between application restarts
func WithFileDatabase() Option {
return func(options *options) {
options.useFileDatabase = true
}
}

// If set to true, the library will maintain a cache of users, basic groups, supergroups, channels and secret chats. Implies use WithFileDatabase()
func WithChatInfoDatabase() Option {
return func(options *options) {
options.useChatInfoDatabase = true
}
}

// If set to true, the library will maintain a cache of chats and messages. Implies use WithChatInfoDatabase()
func WithMessageDatabase() Option {
return func(options *options) {
options.useMessageDatabase = true
}
}

// If set to true, support for secret chats will be enabled
func WithSecretChats() Option {
return func(options *options) {
options.useSecretChats = true
}
}

// Application identifier for Telegram API access, which can be obtained at https://my.telegram.org
func WithID(id string) Option {
return func(options *options) {
options.apiID = id
}
}

// Application identifier hash for Telegram API access, which can be obtained at https://my.telegram.org
func WithHash(hash string) Option {
return func(options *options) {
options.apiHash = hash
}
}

// IETF language tag of the user's operating system language
func WithSystemLanguage(lang string) Option {
return func(options *options) {
options.systemLanguageCode = lang
}
}

// Model of the device the application is being run on
func WithDeviceModel(model string) Option {
return func(options *options) {
options.deviceModel = model
}
}

// Version of the operating system the application is being run on
func WithSystemVersion(system string) Option {
return func(options *options) {
options.systemVersion = system
}
}

// Application version
func WithApplicationVersion(version string) Option {
return func(options *options) {
options.applicationVersion = version
}
}

// If set to true, old files will automatically be deleted
func WithStorageOptimizer() Option {
return func(options *options) {
options.enableStorageOptimizer = true
}
}

// 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
func WithIgnoreFileNames() Option {
return func(options *options) {
options.ignoreFileNames = true
}
}

// Sets phone number for authorization
func WithPhone(phone string) Option {
return func(options *options) {
options.phone = phone
}
}

// Changes parameters which will be used during execution Auth method with state authorizationStateWaitTdlibParameters.
type Option func(*options)

type options struct {
useTestDC bool
databaseDirectory string
filesDirectory string
useFileDatabase bool
useChatInfoDatabase bool
useMessageDatabase bool
useSecretChats bool
apiID string
apiHash string
systemLanguageCode string
deviceModel string
systemVersion string
applicationVersion string
enableStorageOptimizer bool
ignoreFileNames bool
phone string
}

func (o options) toTdlibParameters() Update {
return Update{
"@type": "tdlibParameters",
"use_test_dc": o.useTestDC,
"database_directory": o.databaseDirectory,
"files_directory": o.filesDirectory,
"use_file_database": o.useFileDatabase,
"use_chat_info_database": o.useChatInfoDatabase,
"use_message_database": o.useMessageDatabase,
"use_secret_chats": o.useSecretChats,
"api_id": o.apiID,
"api_hash": o.apiHash,
"system_language_code": o.systemLanguageCode,
"device_model": o.deviceModel,
"system_version": o.systemVersion,
"application_version": o.applicationVersion,
"enable_storage_optimizer": o.enableStorageOptimizer,
"ignore_file_names": o.ignoreFileNames,
}
}
45 changes: 26 additions & 19 deletions tdjson.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,31 @@ import (
type Update = map[string]interface{}

type Client struct {
Client unsafe.Pointer
Updates chan Update
waiters sync.Map
Client unsafe.Pointer
Updates chan Update
waiters sync.Map
parameters *options
}

// Creates a new instance of TDLib.
// Has two public fields:
// Client itself and Updates channel
func NewClient() *Client {
func NewClient(params ...Option) *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.parameters = &options{
systemLanguageCode: "en",
systemVersion: "Unknown",
applicationVersion: "1.0",
deviceModel: "Unknown",
}

for _, option := range params {
option(client.parameters)
}

go func() {
for {
Expand Down Expand Up @@ -183,22 +194,12 @@ func (c *Client) SendAndCatch(jsonQuery interface{}) (Update, error) {
}

// Method for interactive authorizations process, just provide it authorization state from updates and api credentials.
func (c *Client) Auth(authorizationState string, apiId string, apiHash string) (Update, error) {
func (c *Client) Auth(authorizationState string) (Update, error) {
switch authorizationState {
case "authorizationStateWaitTdlibParameters":
res, err := c.SendAndCatch(Update{
"@type": "setTdlibParameters",
"parameters": Update{
"@type": "tdlibParameters",
"use_message_database": true,
"api_id": apiId,
"api_hash": apiHash,
"system_language_code": "en",
"device_model": "Server",
"system_version": "Unknown",
"application_version": "1.0",
"enable_storage_optimizer": true,
},
"@type": "setTdlibParameters",
"parameters": c.parameters.toTdlibParameters(),
})
if err != nil {
return nil, err
Expand All @@ -213,9 +214,14 @@ func (c *Client) Auth(authorizationState string, apiId string, apiHash string) (
}
return res, nil
case "authorizationStateWaitPhoneNumber":
fmt.Print("Enter phone: ")
var number string
fmt.Scanln(&number)
if c.parameters.phone == "" {
fmt.Print("Enter phone: ")
fmt.Scanln(&number)
c.parameters.phone = number
} else {
number = c.parameters.phone
}

res, err := c.SendAndCatch(Update{
"@type": "setAuthenticationPhoneNumber",
Expand All @@ -226,6 +232,7 @@ func (c *Client) Auth(authorizationState string, apiId string, apiHash string) (
}
return res, nil
case "authorizationStateWaitCode":
fmt.Println("Phone number: ", c.parameters.phone)
fmt.Print("Enter code: ")
var code string
fmt.Scanln(&code)
Expand Down

0 comments on commit c344b34

Please sign in to comment.