2018-08-30 14:55:42 +00:00
package client
import (
2018-10-23 12:38:10 +00:00
"errors"
"fmt"
"time"
2018-08-30 14:55:42 +00:00
)
var ErrNotSupportedAuthorizationState = errors . New ( "not supported state" )
2023-11-11 17:31:19 +00:00
// 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" `
}
2018-08-30 14:55:42 +00:00
type AuthorizationStateHandler interface {
2018-10-23 12:38:10 +00:00
Handle ( client * Client , state AuthorizationState ) error
2018-10-24 14:54:34 +00:00
Close ( )
2018-08-30 14:55:42 +00:00
}
func Authorize ( client * Client , authorizationStateHandler AuthorizationStateHandler ) error {
2018-10-24 14:54:34 +00:00
defer authorizationStateHandler . Close ( )
2019-12-30 15:52:13 +00:00
var authorizationError error
2018-10-23 12:38:10 +00:00
for {
state , err := client . GetAuthorizationState ( )
if err != nil {
return err
}
2019-12-30 15:52:13 +00:00
if state . AuthorizationStateType ( ) == TypeAuthorizationStateClosed {
return authorizationError
2018-10-23 12:38:10 +00:00
}
if state . AuthorizationStateType ( ) == TypeAuthorizationStateReady {
// dirty hack for db flush after authorization
time . Sleep ( 1 * time . Second )
return nil
}
2019-12-30 15:52:13 +00:00
err = authorizationStateHandler . Handle ( client , state )
if err != nil {
authorizationError = err
client . Close ( )
}
2018-10-23 12:38:10 +00:00
}
2018-08-30 14:55:42 +00:00
}
type clientAuthorizer struct {
2018-10-23 12:38:10 +00:00
TdlibParameters chan * TdlibParameters
PhoneNumber chan string
Code chan string
State chan AuthorizationState
2018-10-23 16:45:57 +00:00
Password chan string
2018-08-30 14:55:42 +00:00
}
func ClientAuthorizer ( ) * clientAuthorizer {
2018-10-23 12:38:10 +00:00
return & clientAuthorizer {
TdlibParameters : make ( chan * TdlibParameters , 1 ) ,
PhoneNumber : make ( chan string , 1 ) ,
Code : make ( chan string , 1 ) ,
State : make ( chan AuthorizationState , 10 ) ,
2018-10-23 16:45:57 +00:00
Password : make ( chan string , 1 ) ,
2018-10-23 12:38:10 +00:00
}
2018-08-30 14:55:42 +00:00
}
func ( stateHandler * clientAuthorizer ) Handle ( client * Client , state AuthorizationState ) error {
2018-10-23 12:38:10 +00:00
stateHandler . State <- state
switch state . AuthorizationStateType ( ) {
case TypeAuthorizationStateWaitTdlibParameters :
2023-11-11 17:31:19 +00:00
p := <- stateHandler . TdlibParameters
2018-10-23 12:38:10 +00:00
_ , err := client . SetTdlibParameters ( & SetTdlibParametersRequest {
2023-11-11 17:31:19 +00:00
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 ,
2018-10-23 12:38:10 +00:00
} )
return err
case TypeAuthorizationStateWaitPhoneNumber :
_ , err := client . SetAuthenticationPhoneNumber ( & SetAuthenticationPhoneNumberRequest {
2019-09-10 12:36:54 +00:00
PhoneNumber : <- stateHandler . PhoneNumber ,
Settings : & PhoneNumberAuthenticationSettings {
AllowFlashCall : false ,
IsCurrentPhoneNumber : false ,
AllowSmsRetrieverApi : false ,
} ,
2018-10-23 12:38:10 +00:00
} )
return err
2023-11-11 17:31:19 +00:00
case TypeAuthorizationStateWaitEmailAddress :
return ErrNotSupportedAuthorizationState
case TypeAuthorizationStateWaitEmailCode :
return ErrNotSupportedAuthorizationState
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateWaitCode :
_ , err := client . CheckAuthenticationCode ( & CheckAuthenticationCodeRequest {
2019-09-10 12:36:54 +00:00
Code : <- stateHandler . Code ,
2018-10-23 12:38:10 +00:00
} )
return err
2023-11-11 17:31:19 +00:00
case TypeAuthorizationStateWaitOtherDeviceConfirmation :
return ErrNotSupportedAuthorizationState
2019-09-10 12:36:54 +00:00
case TypeAuthorizationStateWaitRegistration :
return ErrNotSupportedAuthorizationState
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateWaitPassword :
2018-10-23 16:45:57 +00:00
_ , err := client . CheckAuthenticationPassword ( & CheckAuthenticationPasswordRequest {
Password : <- stateHandler . Password ,
} )
return err
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateReady :
return nil
case TypeAuthorizationStateLoggingOut :
return ErrNotSupportedAuthorizationState
case TypeAuthorizationStateClosing :
2019-12-30 15:52:13 +00:00
return nil
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateClosed :
2019-12-30 15:52:13 +00:00
return nil
2018-10-23 12:38:10 +00:00
}
return ErrNotSupportedAuthorizationState
2018-08-30 14:55:42 +00:00
}
2018-10-24 14:54:34 +00:00
func ( stateHandler * clientAuthorizer ) Close ( ) {
close ( stateHandler . TdlibParameters )
close ( stateHandler . PhoneNumber )
close ( stateHandler . Code )
close ( stateHandler . State )
close ( stateHandler . Password )
}
2018-10-10 13:35:28 +00:00
func CliInteractor ( clientAuthorizer * clientAuthorizer ) {
2018-10-23 12:38:10 +00:00
for {
select {
2018-10-25 12:20:19 +00:00
case state , ok := <- clientAuthorizer . State :
if ! ok {
return
}
2018-10-23 12:38:10 +00:00
switch state . AuthorizationStateType ( ) {
case TypeAuthorizationStateWaitPhoneNumber :
fmt . Println ( "Enter phone number: " )
var phoneNumber string
fmt . Scanln ( & phoneNumber )
clientAuthorizer . PhoneNumber <- phoneNumber
2023-11-11 17:31:19 +00:00
case TypeAuthorizationStateWaitEmailAddress :
return
case TypeAuthorizationStateWaitEmailCode :
return
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateWaitCode :
var code string
fmt . Println ( "Enter code: " )
fmt . Scanln ( & code )
clientAuthorizer . Code <- code
2023-11-11 17:31:19 +00:00
case TypeAuthorizationStateWaitOtherDeviceConfirmation :
return
case TypeAuthorizationStateWaitRegistration :
return
2018-10-23 16:45:57 +00:00
case TypeAuthorizationStateWaitPassword :
fmt . Println ( "Enter password: " )
var password string
fmt . Scanln ( & password )
clientAuthorizer . Password <- password
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateReady :
return
}
}
}
2018-08-30 14:55:42 +00:00
}
type botAuthorizer struct {
2018-10-23 12:38:10 +00:00
TdlibParameters chan * TdlibParameters
Token chan string
State chan AuthorizationState
2018-08-30 14:55:42 +00:00
}
func BotAuthorizer ( token string ) * botAuthorizer {
2018-10-23 12:38:10 +00:00
botAuthorizer := & botAuthorizer {
TdlibParameters : make ( chan * TdlibParameters , 1 ) ,
Token : make ( chan string , 1 ) ,
State : make ( chan AuthorizationState , 10 ) ,
}
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
botAuthorizer . Token <- token
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
return botAuthorizer
2018-08-30 14:55:42 +00:00
}
func ( stateHandler * botAuthorizer ) Handle ( client * Client , state AuthorizationState ) error {
2018-10-23 12:38:10 +00:00
stateHandler . State <- state
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
switch state . AuthorizationStateType ( ) {
case TypeAuthorizationStateWaitTdlibParameters :
2023-11-11 17:31:19 +00:00
p := <- stateHandler . TdlibParameters
2018-10-23 12:38:10 +00:00
_ , err := client . SetTdlibParameters ( & SetTdlibParametersRequest {
2023-11-11 17:31:19 +00:00
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 ,
2018-10-23 12:38:10 +00:00
} )
return err
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateWaitPhoneNumber :
_ , err := client . CheckAuthenticationBotToken ( & CheckAuthenticationBotTokenRequest {
Token : <- stateHandler . Token ,
} )
return err
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateWaitCode :
return ErrNotSupportedAuthorizationState
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateWaitPassword :
return ErrNotSupportedAuthorizationState
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateReady :
return nil
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateLoggingOut :
return ErrNotSupportedAuthorizationState
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateClosing :
return ErrNotSupportedAuthorizationState
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
case TypeAuthorizationStateClosed :
return ErrNotSupportedAuthorizationState
}
2018-08-30 14:55:42 +00:00
2018-10-23 12:38:10 +00:00
return ErrNotSupportedAuthorizationState
2018-08-30 14:55:42 +00:00
}
2018-10-24 14:54:34 +00:00
func ( stateHandler * botAuthorizer ) Close ( ) {
close ( stateHandler . TdlibParameters )
close ( stateHandler . Token )
close ( stateHandler . State )
}