go fmt formatted codegen
This commit is contained in:
parent
3709d1ca57
commit
e292b9559e
1
Makefile
1
Makefile
|
@ -16,3 +16,4 @@ generate-code:
|
|||
-functionFile function.go \
|
||||
-typeFile type.go \
|
||||
-unmarshalerFile unmarshaler.go
|
||||
go fmt ./client
|
||||
|
|
|
@ -1,214 +1,214 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
var ErrNotSupportedAuthorizationState = errors.New("not supported state")
|
||||
|
||||
type AuthorizationStateHandler interface {
|
||||
Handle(client *Client, state AuthorizationState) error
|
||||
Handle(client *Client, state AuthorizationState) error
|
||||
}
|
||||
|
||||
func Authorize(client *Client, authorizationStateHandler AuthorizationStateHandler) error {
|
||||
for {
|
||||
state, err := client.GetAuthorizationState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
state, err := client.GetAuthorizationState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = authorizationStateHandler.Handle(client, state)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = authorizationStateHandler.Handle(client, state)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if state.AuthorizationStateType() == TypeAuthorizationStateReady {
|
||||
// dirty hack for db flush after authorization
|
||||
time.Sleep(1 * time.Second)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if state.AuthorizationStateType() == TypeAuthorizationStateReady {
|
||||
// dirty hack for db flush after authorization
|
||||
time.Sleep(1 * time.Second)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type clientAuthorizer struct {
|
||||
TdlibParameters chan *TdlibParameters
|
||||
PhoneNumber chan string
|
||||
Code chan string
|
||||
State chan AuthorizationState
|
||||
FirstName chan string
|
||||
LastName chan string
|
||||
TdlibParameters chan *TdlibParameters
|
||||
PhoneNumber chan string
|
||||
Code chan string
|
||||
State chan AuthorizationState
|
||||
FirstName chan string
|
||||
LastName chan string
|
||||
}
|
||||
|
||||
func ClientAuthorizer() *clientAuthorizer {
|
||||
return &clientAuthorizer{
|
||||
TdlibParameters: make(chan *TdlibParameters, 1),
|
||||
PhoneNumber: make(chan string, 1),
|
||||
Code: make(chan string, 1),
|
||||
State: make(chan AuthorizationState, 10),
|
||||
FirstName: make(chan string, 1),
|
||||
LastName: make(chan string, 1),
|
||||
}
|
||||
return &clientAuthorizer{
|
||||
TdlibParameters: make(chan *TdlibParameters, 1),
|
||||
PhoneNumber: make(chan string, 1),
|
||||
Code: make(chan string, 1),
|
||||
State: make(chan AuthorizationState, 10),
|
||||
FirstName: make(chan string, 1),
|
||||
LastName: make(chan string, 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (stateHandler *clientAuthorizer) Handle(client *Client, state AuthorizationState) error {
|
||||
stateHandler.State <- state
|
||||
stateHandler.State <- state
|
||||
|
||||
switch state.AuthorizationStateType() {
|
||||
case TypeAuthorizationStateWaitTdlibParameters:
|
||||
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
||||
Parameters: <-stateHandler.TdlibParameters,
|
||||
})
|
||||
return err
|
||||
switch state.AuthorizationStateType() {
|
||||
case TypeAuthorizationStateWaitTdlibParameters:
|
||||
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
||||
Parameters: <-stateHandler.TdlibParameters,
|
||||
})
|
||||
return err
|
||||
|
||||
case TypeAuthorizationStateWaitEncryptionKey:
|
||||
_, err := client.CheckDatabaseEncryptionKey(&CheckDatabaseEncryptionKeyRequest{})
|
||||
return err
|
||||
case TypeAuthorizationStateWaitEncryptionKey:
|
||||
_, err := client.CheckDatabaseEncryptionKey(&CheckDatabaseEncryptionKeyRequest{})
|
||||
return err
|
||||
|
||||
case TypeAuthorizationStateWaitPhoneNumber:
|
||||
_, err := client.SetAuthenticationPhoneNumber(&SetAuthenticationPhoneNumberRequest{
|
||||
PhoneNumber: <-stateHandler.PhoneNumber,
|
||||
AllowFlashCall: false,
|
||||
IsCurrentPhoneNumber: false,
|
||||
})
|
||||
return err
|
||||
case TypeAuthorizationStateWaitPhoneNumber:
|
||||
_, err := client.SetAuthenticationPhoneNumber(&SetAuthenticationPhoneNumberRequest{
|
||||
PhoneNumber: <-stateHandler.PhoneNumber,
|
||||
AllowFlashCall: false,
|
||||
IsCurrentPhoneNumber: false,
|
||||
})
|
||||
return err
|
||||
|
||||
case TypeAuthorizationStateWaitCode:
|
||||
_, err := client.CheckAuthenticationCode(&CheckAuthenticationCodeRequest{
|
||||
Code: <-stateHandler.Code,
|
||||
FirstName: <-stateHandler.FirstName,
|
||||
LastName: <-stateHandler.LastName,
|
||||
})
|
||||
return err
|
||||
case TypeAuthorizationStateWaitCode:
|
||||
_, err := client.CheckAuthenticationCode(&CheckAuthenticationCodeRequest{
|
||||
Code: <-stateHandler.Code,
|
||||
FirstName: <-stateHandler.FirstName,
|
||||
LastName: <-stateHandler.LastName,
|
||||
})
|
||||
return err
|
||||
|
||||
case TypeAuthorizationStateWaitPassword:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
case TypeAuthorizationStateWaitPassword:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
|
||||
case TypeAuthorizationStateReady:
|
||||
close(stateHandler.TdlibParameters)
|
||||
close(stateHandler.PhoneNumber)
|
||||
close(stateHandler.Code)
|
||||
close(stateHandler.State)
|
||||
close(stateHandler.FirstName)
|
||||
close(stateHandler.LastName)
|
||||
case TypeAuthorizationStateReady:
|
||||
close(stateHandler.TdlibParameters)
|
||||
close(stateHandler.PhoneNumber)
|
||||
close(stateHandler.Code)
|
||||
close(stateHandler.State)
|
||||
close(stateHandler.FirstName)
|
||||
close(stateHandler.LastName)
|
||||
|
||||
return nil
|
||||
return nil
|
||||
|
||||
case TypeAuthorizationStateLoggingOut:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
case TypeAuthorizationStateLoggingOut:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
|
||||
case TypeAuthorizationStateClosing:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
case TypeAuthorizationStateClosing:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
|
||||
case TypeAuthorizationStateClosed:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
}
|
||||
case TypeAuthorizationStateClosed:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
}
|
||||
|
||||
return ErrNotSupportedAuthorizationState
|
||||
return ErrNotSupportedAuthorizationState
|
||||
}
|
||||
|
||||
func CliInteractor(clientAuthorizer *clientAuthorizer) {
|
||||
for {
|
||||
select {
|
||||
case state := <-clientAuthorizer.State:
|
||||
switch state.AuthorizationStateType() {
|
||||
case TypeAuthorizationStateWaitPhoneNumber:
|
||||
fmt.Println("Enter phone number: ")
|
||||
var phoneNumber string
|
||||
fmt.Scanln(&phoneNumber)
|
||||
for {
|
||||
select {
|
||||
case state := <-clientAuthorizer.State:
|
||||
switch state.AuthorizationStateType() {
|
||||
case TypeAuthorizationStateWaitPhoneNumber:
|
||||
fmt.Println("Enter phone number: ")
|
||||
var phoneNumber string
|
||||
fmt.Scanln(&phoneNumber)
|
||||
|
||||
clientAuthorizer.PhoneNumber <- phoneNumber
|
||||
clientAuthorizer.PhoneNumber <- phoneNumber
|
||||
|
||||
case TypeAuthorizationStateWaitCode:
|
||||
var code string
|
||||
var firstName string
|
||||
var lastName string
|
||||
case TypeAuthorizationStateWaitCode:
|
||||
var code string
|
||||
var firstName string
|
||||
var lastName string
|
||||
|
||||
fmt.Println("Enter code: ")
|
||||
fmt.Scanln(&code)
|
||||
fmt.Println("Enter code: ")
|
||||
fmt.Scanln(&code)
|
||||
|
||||
if !state.(*AuthorizationStateWaitCode).IsRegistered {
|
||||
fmt.Println("Phone number is not registered.")
|
||||
if !state.(*AuthorizationStateWaitCode).IsRegistered {
|
||||
fmt.Println("Phone number is not registered.")
|
||||
|
||||
fmt.Println("Enter first name: ")
|
||||
fmt.Scanln(&firstName)
|
||||
fmt.Println("Enter first name: ")
|
||||
fmt.Scanln(&firstName)
|
||||
|
||||
fmt.Println("Enter last name: ")
|
||||
fmt.Scanln(&lastName)
|
||||
}
|
||||
fmt.Println("Enter last name: ")
|
||||
fmt.Scanln(&lastName)
|
||||
}
|
||||
|
||||
clientAuthorizer.Code <- code
|
||||
clientAuthorizer.FirstName <- firstName
|
||||
clientAuthorizer.LastName <- lastName
|
||||
clientAuthorizer.Code <- code
|
||||
clientAuthorizer.FirstName <- firstName
|
||||
clientAuthorizer.LastName <- lastName
|
||||
|
||||
case TypeAuthorizationStateReady:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
case TypeAuthorizationStateReady:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type botAuthorizer struct {
|
||||
TdlibParameters chan *TdlibParameters
|
||||
Token chan string
|
||||
State chan AuthorizationState
|
||||
TdlibParameters chan *TdlibParameters
|
||||
Token chan string
|
||||
State chan AuthorizationState
|
||||
}
|
||||
|
||||
func BotAuthorizer(token string) *botAuthorizer {
|
||||
botAuthorizer := &botAuthorizer{
|
||||
TdlibParameters: make(chan *TdlibParameters, 1),
|
||||
Token: make(chan string, 1),
|
||||
State: make(chan AuthorizationState, 10),
|
||||
}
|
||||
botAuthorizer := &botAuthorizer{
|
||||
TdlibParameters: make(chan *TdlibParameters, 1),
|
||||
Token: make(chan string, 1),
|
||||
State: make(chan AuthorizationState, 10),
|
||||
}
|
||||
|
||||
botAuthorizer.Token <- token
|
||||
botAuthorizer.Token <- token
|
||||
|
||||
return botAuthorizer
|
||||
return botAuthorizer
|
||||
}
|
||||
|
||||
func (stateHandler *botAuthorizer) Handle(client *Client, state AuthorizationState) error {
|
||||
stateHandler.State <- state
|
||||
stateHandler.State <- state
|
||||
|
||||
switch state.AuthorizationStateType() {
|
||||
case TypeAuthorizationStateWaitTdlibParameters:
|
||||
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
||||
Parameters: <-stateHandler.TdlibParameters,
|
||||
})
|
||||
return err
|
||||
switch state.AuthorizationStateType() {
|
||||
case TypeAuthorizationStateWaitTdlibParameters:
|
||||
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
||||
Parameters: <-stateHandler.TdlibParameters,
|
||||
})
|
||||
return err
|
||||
|
||||
case TypeAuthorizationStateWaitEncryptionKey:
|
||||
_, err := client.CheckDatabaseEncryptionKey(&CheckDatabaseEncryptionKeyRequest{})
|
||||
return err
|
||||
case TypeAuthorizationStateWaitEncryptionKey:
|
||||
_, err := client.CheckDatabaseEncryptionKey(&CheckDatabaseEncryptionKeyRequest{})
|
||||
return err
|
||||
|
||||
case TypeAuthorizationStateWaitPhoneNumber:
|
||||
_, err := client.CheckAuthenticationBotToken(&CheckAuthenticationBotTokenRequest{
|
||||
Token: <-stateHandler.Token,
|
||||
})
|
||||
return err
|
||||
case TypeAuthorizationStateWaitPhoneNumber:
|
||||
_, err := client.CheckAuthenticationBotToken(&CheckAuthenticationBotTokenRequest{
|
||||
Token: <-stateHandler.Token,
|
||||
})
|
||||
return err
|
||||
|
||||
case TypeAuthorizationStateWaitCode:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
case TypeAuthorizationStateWaitCode:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
|
||||
case TypeAuthorizationStateWaitPassword:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
case TypeAuthorizationStateWaitPassword:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
|
||||
case TypeAuthorizationStateReady:
|
||||
close(stateHandler.TdlibParameters)
|
||||
close(stateHandler.Token)
|
||||
close(stateHandler.State)
|
||||
case TypeAuthorizationStateReady:
|
||||
close(stateHandler.TdlibParameters)
|
||||
close(stateHandler.Token)
|
||||
close(stateHandler.State)
|
||||
|
||||
return nil
|
||||
return nil
|
||||
|
||||
case TypeAuthorizationStateLoggingOut:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
case TypeAuthorizationStateLoggingOut:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
|
||||
case TypeAuthorizationStateClosing:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
case TypeAuthorizationStateClosing:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
|
||||
case TypeAuthorizationStateClosed:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
}
|
||||
case TypeAuthorizationStateClosed:
|
||||
return ErrNotSupportedAuthorizationState
|
||||
}
|
||||
|
||||
return ErrNotSupportedAuthorizationState
|
||||
return ErrNotSupportedAuthorizationState
|
||||
}
|
||||
|
|
190
client/client.go
190
client/client.go
|
@ -1,145 +1,145 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
jsonClient *JsonClient
|
||||
extraGenerator ExtraGenerator
|
||||
catcher chan *Response
|
||||
listenerStore *listenerStore
|
||||
catchersStore *sync.Map
|
||||
updatesTimeout time.Duration
|
||||
catchTimeout time.Duration
|
||||
jsonClient *JsonClient
|
||||
extraGenerator ExtraGenerator
|
||||
catcher chan *Response
|
||||
listenerStore *listenerStore
|
||||
catchersStore *sync.Map
|
||||
updatesTimeout time.Duration
|
||||
catchTimeout time.Duration
|
||||
}
|
||||
|
||||
type Option func(*Client)
|
||||
|
||||
func WithExtraGenerator(extraGenerator ExtraGenerator) Option {
|
||||
return func(client *Client) {
|
||||
client.extraGenerator = extraGenerator
|
||||
}
|
||||
return func(client *Client) {
|
||||
client.extraGenerator = extraGenerator
|
||||
}
|
||||
}
|
||||
|
||||
func WithCatchTimeout(timeout time.Duration) Option {
|
||||
return func(client *Client) {
|
||||
client.catchTimeout = timeout
|
||||
}
|
||||
return func(client *Client) {
|
||||
client.catchTimeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
func WithUpdatesTimeout(timeout time.Duration) Option {
|
||||
return func(client *Client) {
|
||||
client.updatesTimeout = timeout
|
||||
}
|
||||
return func(client *Client) {
|
||||
client.updatesTimeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
func NewClient(authorizationStateHandler AuthorizationStateHandler, options ...Option) (*Client, error) {
|
||||
catchersListener := make(chan *Response, 1000)
|
||||
catchersListener := make(chan *Response, 1000)
|
||||
|
||||
client := &Client{
|
||||
jsonClient: NewJsonClient(),
|
||||
catcher: catchersListener,
|
||||
listenerStore: newListenerStore(),
|
||||
catchersStore: &sync.Map{},
|
||||
}
|
||||
client := &Client{
|
||||
jsonClient: NewJsonClient(),
|
||||
catcher: catchersListener,
|
||||
listenerStore: newListenerStore(),
|
||||
catchersStore: &sync.Map{},
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(client)
|
||||
}
|
||||
for _, option := range options {
|
||||
option(client)
|
||||
}
|
||||
|
||||
if client.extraGenerator == nil {
|
||||
client.extraGenerator = UuidV4Generator()
|
||||
}
|
||||
if client.extraGenerator == nil {
|
||||
client.extraGenerator = UuidV4Generator()
|
||||
}
|
||||
|
||||
if client.catchTimeout == 0 {
|
||||
client.catchTimeout = 60 * time.Second
|
||||
}
|
||||
if client.catchTimeout == 0 {
|
||||
client.catchTimeout = 60 * time.Second
|
||||
}
|
||||
|
||||
if client.updatesTimeout == 0 {
|
||||
client.updatesTimeout = 60 * time.Second
|
||||
}
|
||||
if client.updatesTimeout == 0 {
|
||||
client.updatesTimeout = 60 * time.Second
|
||||
}
|
||||
|
||||
go client.receive()
|
||||
go client.catch(catchersListener)
|
||||
go client.receive()
|
||||
go client.catch(catchersListener)
|
||||
|
||||
err := Authorize(client, authorizationStateHandler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err := Authorize(client, authorizationStateHandler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (client *Client) receive() {
|
||||
for {
|
||||
resp, err := client.jsonClient.Receive(client.updatesTimeout)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
client.catcher <- resp
|
||||
for {
|
||||
resp, err := client.jsonClient.Receive(client.updatesTimeout)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
client.catcher <- resp
|
||||
|
||||
typ, err := UnmarshalType(resp.Data)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
typ, err := UnmarshalType(resp.Data)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
needGc := false
|
||||
for _, listener := range client.listenerStore.Listeners() {
|
||||
if listener.IsActive() {
|
||||
listener.Updates <- typ
|
||||
} else {
|
||||
needGc = true
|
||||
}
|
||||
}
|
||||
if needGc {
|
||||
client.listenerStore.gc()
|
||||
}
|
||||
}
|
||||
needGc := false
|
||||
for _, listener := range client.listenerStore.Listeners() {
|
||||
if listener.IsActive() {
|
||||
listener.Updates <- typ
|
||||
} else {
|
||||
needGc = true
|
||||
}
|
||||
}
|
||||
if needGc {
|
||||
client.listenerStore.gc()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) catch(updates chan *Response) {
|
||||
for update := range updates {
|
||||
if update.Extra != "" {
|
||||
value, ok := client.catchersStore.Load(update.Extra)
|
||||
if ok {
|
||||
value.(chan *Response) <- update
|
||||
}
|
||||
}
|
||||
}
|
||||
for update := range updates {
|
||||
if update.Extra != "" {
|
||||
value, ok := client.catchersStore.Load(update.Extra)
|
||||
if ok {
|
||||
value.(chan *Response) <- update
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) Send(req Request) (*Response, error) {
|
||||
req.Extra = client.extraGenerator()
|
||||
req.Extra = client.extraGenerator()
|
||||
|
||||
catcher := make(chan *Response, 1)
|
||||
catcher := make(chan *Response, 1)
|
||||
|
||||
client.catchersStore.Store(req.Extra, catcher)
|
||||
client.catchersStore.Store(req.Extra, catcher)
|
||||
|
||||
defer func() {
|
||||
close(catcher)
|
||||
client.catchersStore.Delete(req.Extra)
|
||||
}()
|
||||
defer func() {
|
||||
close(catcher)
|
||||
client.catchersStore.Delete(req.Extra)
|
||||
}()
|
||||
|
||||
client.jsonClient.Send(req)
|
||||
client.jsonClient.Send(req)
|
||||
|
||||
select {
|
||||
case response := <-catcher:
|
||||
return response, nil
|
||||
select {
|
||||
case response := <-catcher:
|
||||
return response, nil
|
||||
|
||||
case <-time.After(client.catchTimeout):
|
||||
return nil, errors.New("response catching timeout")
|
||||
}
|
||||
case <-time.After(client.catchTimeout):
|
||||
return nil, errors.New("response catching timeout")
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) GetListener() *Listener {
|
||||
listener := &Listener{
|
||||
isActive: true,
|
||||
Updates: make(chan Type, 1000),
|
||||
}
|
||||
client.listenerStore.Add(listener)
|
||||
listener := &Listener{
|
||||
isActive: true,
|
||||
Updates: make(chan Type, 1000),
|
||||
}
|
||||
client.listenerStore.Add(listener)
|
||||
|
||||
return listener
|
||||
return listener
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
type ExtraGenerator func() string
|
||||
|
||||
func UuidV4Generator() ExtraGenerator {
|
||||
return func() string {
|
||||
var uuid [16]byte
|
||||
rand.Read(uuid[:])
|
||||
return func() string {
|
||||
var uuid [16]byte
|
||||
rand.Read(uuid[:])
|
||||
|
||||
uuid[6] = (uuid[6] & 0x0f) | 0x40
|
||||
uuid[8] = (uuid[8] & 0x3f) | 0x80
|
||||
uuid[6] = (uuid[6] & 0x0f) | 0x40
|
||||
uuid[8] = (uuid[8] & 0x3f) | 0x80
|
||||
|
||||
return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x", uuid[:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])
|
||||
}
|
||||
return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x", uuid[:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])
|
||||
}
|
||||
}
|
||||
|
|
12068
client/function.go
12068
client/function.go
File diff suppressed because it is too large
Load diff
|
@ -1,66 +1,66 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func newListenerStore() *listenerStore {
|
||||
return &listenerStore{
|
||||
listeners: []*Listener{},
|
||||
}
|
||||
return &listenerStore{
|
||||
listeners: []*Listener{},
|
||||
}
|
||||
}
|
||||
|
||||
type listenerStore struct {
|
||||
sync.Mutex
|
||||
listeners []*Listener
|
||||
sync.Mutex
|
||||
listeners []*Listener
|
||||
}
|
||||
|
||||
func (store *listenerStore) Add(listener *Listener) {
|
||||
store.Lock()
|
||||
defer store.Unlock()
|
||||
store.Lock()
|
||||
defer store.Unlock()
|
||||
|
||||
store.listeners = append(store.listeners, listener)
|
||||
store.listeners = append(store.listeners, listener)
|
||||
}
|
||||
|
||||
func (store *listenerStore) Listeners() []*Listener {
|
||||
store.Lock()
|
||||
defer store.Unlock()
|
||||
store.Lock()
|
||||
defer store.Unlock()
|
||||
|
||||
return store.listeners
|
||||
return store.listeners
|
||||
}
|
||||
|
||||
func (store *listenerStore) gc() {
|
||||
store.Lock()
|
||||
defer store.Unlock()
|
||||
store.Lock()
|
||||
defer store.Unlock()
|
||||
|
||||
oldListeners := store.listeners
|
||||
oldListeners := store.listeners
|
||||
|
||||
store.listeners = []*Listener{}
|
||||
store.listeners = []*Listener{}
|
||||
|
||||
for _, listener := range oldListeners {
|
||||
if listener.IsActive() {
|
||||
store.listeners = append(store.listeners, listener)
|
||||
}
|
||||
}
|
||||
for _, listener := range oldListeners {
|
||||
if listener.IsActive() {
|
||||
store.listeners = append(store.listeners, listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Listener struct {
|
||||
mu sync.Mutex
|
||||
isActive bool
|
||||
Updates chan Type
|
||||
mu sync.Mutex
|
||||
isActive bool
|
||||
Updates chan Type
|
||||
}
|
||||
|
||||
func (listener *Listener) Close() {
|
||||
listener.mu.Lock()
|
||||
defer listener.mu.Unlock()
|
||||
listener.mu.Lock()
|
||||
defer listener.mu.Unlock()
|
||||
|
||||
listener.isActive = false
|
||||
close(listener.Updates)
|
||||
listener.isActive = false
|
||||
close(listener.Updates)
|
||||
}
|
||||
|
||||
func (listener *Listener) IsActive() bool {
|
||||
listener.mu.Lock()
|
||||
defer listener.mu.Unlock()
|
||||
listener.mu.Lock()
|
||||
defer listener.mu.Unlock()
|
||||
|
||||
return listener.isActive
|
||||
return listener.isActive
|
||||
}
|
||||
|
|
148
client/tdlib.go
148
client/tdlib.go
|
@ -8,32 +8,32 @@ package client
|
|||
import "C"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
"unsafe"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type JsonClient struct {
|
||||
jsonClient unsafe.Pointer
|
||||
jsonClient unsafe.Pointer
|
||||
}
|
||||
|
||||
func NewJsonClient() *JsonClient {
|
||||
return &JsonClient{
|
||||
jsonClient: C.td_json_client_create(),
|
||||
}
|
||||
return &JsonClient{
|
||||
jsonClient: C.td_json_client_create(),
|
||||
}
|
||||
}
|
||||
|
||||
// Sends request to the TDLib client. May be called from any thread.
|
||||
func (jsonClient *JsonClient) Send(req Request) {
|
||||
data, _ := json.Marshal(req)
|
||||
data, _ := json.Marshal(req)
|
||||
|
||||
query := C.CString(string(data))
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
query := C.CString(string(data))
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
|
||||
C.td_json_client_send(jsonClient.jsonClient, query)
|
||||
C.td_json_client_send(jsonClient.jsonClient, query)
|
||||
}
|
||||
|
||||
// Receives incoming updates and request responses from the TDLib client. May be called from any thread, but
|
||||
|
@ -41,23 +41,23 @@ func (jsonClient *JsonClient) Send(req Request) {
|
|||
// Returned pointer will be deallocated by TDLib during next call to td_json_client_receive or td_json_client_execute
|
||||
// in the same thread, so it can't be used after that.
|
||||
func (jsonClient *JsonClient) Receive(timeout time.Duration) (*Response, error) {
|
||||
result := C.td_json_client_receive(jsonClient.jsonClient, C.double(float64(timeout)/float64(time.Second)))
|
||||
if result == nil {
|
||||
return nil, errors.New("update receiving timeout")
|
||||
}
|
||||
result := C.td_json_client_receive(jsonClient.jsonClient, C.double(float64(timeout)/float64(time.Second)))
|
||||
if result == nil {
|
||||
return nil, errors.New("update receiving timeout")
|
||||
}
|
||||
|
||||
data := []byte(C.GoString(result))
|
||||
data := []byte(C.GoString(result))
|
||||
|
||||
var resp Response
|
||||
var resp Response
|
||||
|
||||
err := json.Unmarshal(data, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err := json.Unmarshal(data, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Data = data
|
||||
resp.Data = data
|
||||
|
||||
return &resp, nil
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// Synchronously executes TDLib request. May be called from any thread.
|
||||
|
@ -65,96 +65,96 @@ func (jsonClient *JsonClient) Receive(timeout time.Duration) (*Response, error)
|
|||
// Returned pointer will be deallocated by TDLib during next call to td_json_client_receive or td_json_client_execute
|
||||
// in the same thread, so it can't be used after that.
|
||||
func (jsonClient *JsonClient) Execute(req Request) (*Response, error) {
|
||||
data, _ := json.Marshal(req)
|
||||
data, _ := json.Marshal(req)
|
||||
|
||||
query := C.CString(string(data))
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
query := C.CString(string(data))
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
|
||||
result := C.td_json_client_execute(jsonClient.jsonClient, query)
|
||||
if result == nil {
|
||||
return nil, errors.New("request can't be parsed")
|
||||
}
|
||||
result := C.td_json_client_execute(jsonClient.jsonClient, query)
|
||||
if result == nil {
|
||||
return nil, errors.New("request can't be parsed")
|
||||
}
|
||||
|
||||
data = []byte(C.GoString(result))
|
||||
data = []byte(C.GoString(result))
|
||||
|
||||
var resp Response
|
||||
var resp Response
|
||||
|
||||
err := json.Unmarshal(data, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err := json.Unmarshal(data, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Data = data
|
||||
resp.Data = data
|
||||
|
||||
return &resp, nil
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// Destroys the TDLib client instance. After this is called the client instance shouldn't be used anymore.
|
||||
func (jsonClient *JsonClient) DestroyInstance() {
|
||||
C.td_json_client_destroy(jsonClient.jsonClient)
|
||||
C.td_json_client_destroy(jsonClient.jsonClient)
|
||||
}
|
||||
|
||||
// Sets the path to the file 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 SetLogFilePath(filePath string) {
|
||||
query := C.CString(filePath)
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
query := C.CString(filePath)
|
||||
defer C.free(unsafe.Pointer(query))
|
||||
|
||||
C.td_set_log_file_path(query)
|
||||
C.td_set_log_file_path(query)
|
||||
}
|
||||
|
||||
// Sets maximum size of the file to where the internal TDLib log is written before the file will be auto-rotated.
|
||||
// Unused if log is not written to a file. Defaults to 10 MB.
|
||||
func SetLogMaxFileSize(maxFileSize int64) {
|
||||
C.td_set_log_max_file_size(C.longlong(maxFileSize))
|
||||
C.td_set_log_max_file_size(C.longlong(maxFileSize))
|
||||
}
|
||||
|
||||
// Sets the verbosity level of the internal logging of TDLib.
|
||||
// By default the TDLib uses a log verbosity level of 5
|
||||
func SetLogVerbosityLevel(newVerbosityLevel int) {
|
||||
C.td_set_log_verbosity_level(C.int(newVerbosityLevel))
|
||||
C.td_set_log_verbosity_level(C.int(newVerbosityLevel))
|
||||
}
|
||||
|
||||
type meta struct {
|
||||
Type string `json:"@type"`
|
||||
Extra string `json:"@extra"`
|
||||
Type string `json:"@type"`
|
||||
Extra string `json:"@extra"`
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
meta
|
||||
Data map[string]interface{}
|
||||
meta
|
||||
Data map[string]interface{}
|
||||
}
|
||||
|
||||
func (req Request) MarshalJSON() ([]byte, error) {
|
||||
req.Data["@type"] = req.Type
|
||||
req.Data["@extra"] = req.Extra
|
||||
req.Data["@type"] = req.Type
|
||||
req.Data["@extra"] = req.Extra
|
||||
|
||||
return json.Marshal(req.Data)
|
||||
return json.Marshal(req.Data)
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
meta
|
||||
Data json.RawMessage
|
||||
meta
|
||||
Data json.RawMessage
|
||||
}
|
||||
|
||||
type ResponseError struct {
|
||||
Err *Error
|
||||
Err *Error
|
||||
}
|
||||
|
||||
func (responseError ResponseError) Error() string {
|
||||
return fmt.Sprintf("%d %s", responseError.Err.Code, responseError.Err.Message)
|
||||
return fmt.Sprintf("%d %s", responseError.Err.Code, responseError.Err.Message)
|
||||
}
|
||||
|
||||
func buildResponseError(data json.RawMessage) error {
|
||||
respErr, err := UnmarshalError(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
respErr, err := UnmarshalError(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ResponseError{
|
||||
Err: respErr,
|
||||
}
|
||||
return ResponseError{
|
||||
Err: respErr,
|
||||
}
|
||||
}
|
||||
|
||||
// JsonInt64 alias for int64, in order to deal with json big number problem
|
||||
|
@ -162,22 +162,22 @@ type JsonInt64 int64
|
|||
|
||||
// MarshalJSON marshals to json
|
||||
func (jsonInt64 *JsonInt64) MarshalJSON() ([]byte, error) {
|
||||
return []byte(strconv.FormatInt(int64(*jsonInt64), 10)), nil
|
||||
return []byte(strconv.FormatInt(int64(*jsonInt64), 10)), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from json
|
||||
func (jsonInt64 *JsonInt64) UnmarshalJSON(data []byte) error {
|
||||
jsonBigInt, err := strconv.ParseInt(string(data[1:len(data)-1]), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
jsonBigInt, err := strconv.ParseInt(string(data[1:len(data)-1]), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*jsonInt64 = JsonInt64(jsonBigInt)
|
||||
*jsonInt64 = JsonInt64(jsonBigInt)
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
type Type interface {
|
||||
GetType() string
|
||||
GetClass() string
|
||||
GetType() string
|
||||
GetClass() string
|
||||
}
|
||||
|
|
18437
client/type.go
18437
client/type.go
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue