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 \
|
-functionFile function.go \
|
||||||
-typeFile type.go \
|
-typeFile type.go \
|
||||||
-unmarshalerFile unmarshaler.go
|
-unmarshalerFile unmarshaler.go
|
||||||
|
go fmt ./client
|
||||||
|
|
|
@ -1,214 +1,214 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotSupportedAuthorizationState = errors.New("not supported state")
|
var ErrNotSupportedAuthorizationState = errors.New("not supported state")
|
||||||
|
|
||||||
type AuthorizationStateHandler interface {
|
type AuthorizationStateHandler interface {
|
||||||
Handle(client *Client, state AuthorizationState) error
|
Handle(client *Client, state AuthorizationState) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func Authorize(client *Client, authorizationStateHandler AuthorizationStateHandler) error {
|
func Authorize(client *Client, authorizationStateHandler AuthorizationStateHandler) error {
|
||||||
for {
|
for {
|
||||||
state, err := client.GetAuthorizationState()
|
state, err := client.GetAuthorizationState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = authorizationStateHandler.Handle(client, state)
|
err = authorizationStateHandler.Handle(client, state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.AuthorizationStateType() == TypeAuthorizationStateReady {
|
if state.AuthorizationStateType() == TypeAuthorizationStateReady {
|
||||||
// dirty hack for db flush after authorization
|
// dirty hack for db flush after authorization
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientAuthorizer struct {
|
type clientAuthorizer struct {
|
||||||
TdlibParameters chan *TdlibParameters
|
TdlibParameters chan *TdlibParameters
|
||||||
PhoneNumber chan string
|
PhoneNumber chan string
|
||||||
Code chan string
|
Code chan string
|
||||||
State chan AuthorizationState
|
State chan AuthorizationState
|
||||||
FirstName chan string
|
FirstName chan string
|
||||||
LastName chan string
|
LastName chan string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ClientAuthorizer() *clientAuthorizer {
|
func ClientAuthorizer() *clientAuthorizer {
|
||||||
return &clientAuthorizer{
|
return &clientAuthorizer{
|
||||||
TdlibParameters: make(chan *TdlibParameters, 1),
|
TdlibParameters: make(chan *TdlibParameters, 1),
|
||||||
PhoneNumber: make(chan string, 1),
|
PhoneNumber: make(chan string, 1),
|
||||||
Code: make(chan string, 1),
|
Code: make(chan string, 1),
|
||||||
State: make(chan AuthorizationState, 10),
|
State: make(chan AuthorizationState, 10),
|
||||||
FirstName: make(chan string, 1),
|
FirstName: make(chan string, 1),
|
||||||
LastName: make(chan string, 1),
|
LastName: make(chan string, 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stateHandler *clientAuthorizer) Handle(client *Client, state AuthorizationState) error {
|
func (stateHandler *clientAuthorizer) Handle(client *Client, state AuthorizationState) error {
|
||||||
stateHandler.State <- state
|
stateHandler.State <- state
|
||||||
|
|
||||||
switch state.AuthorizationStateType() {
|
switch state.AuthorizationStateType() {
|
||||||
case TypeAuthorizationStateWaitTdlibParameters:
|
case TypeAuthorizationStateWaitTdlibParameters:
|
||||||
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
||||||
Parameters: <-stateHandler.TdlibParameters,
|
Parameters: <-stateHandler.TdlibParameters,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitEncryptionKey:
|
case TypeAuthorizationStateWaitEncryptionKey:
|
||||||
_, err := client.CheckDatabaseEncryptionKey(&CheckDatabaseEncryptionKeyRequest{})
|
_, err := client.CheckDatabaseEncryptionKey(&CheckDatabaseEncryptionKeyRequest{})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitPhoneNumber:
|
case TypeAuthorizationStateWaitPhoneNumber:
|
||||||
_, err := client.SetAuthenticationPhoneNumber(&SetAuthenticationPhoneNumberRequest{
|
_, err := client.SetAuthenticationPhoneNumber(&SetAuthenticationPhoneNumberRequest{
|
||||||
PhoneNumber: <-stateHandler.PhoneNumber,
|
PhoneNumber: <-stateHandler.PhoneNumber,
|
||||||
AllowFlashCall: false,
|
AllowFlashCall: false,
|
||||||
IsCurrentPhoneNumber: false,
|
IsCurrentPhoneNumber: false,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitCode:
|
case TypeAuthorizationStateWaitCode:
|
||||||
_, err := client.CheckAuthenticationCode(&CheckAuthenticationCodeRequest{
|
_, err := client.CheckAuthenticationCode(&CheckAuthenticationCodeRequest{
|
||||||
Code: <-stateHandler.Code,
|
Code: <-stateHandler.Code,
|
||||||
FirstName: <-stateHandler.FirstName,
|
FirstName: <-stateHandler.FirstName,
|
||||||
LastName: <-stateHandler.LastName,
|
LastName: <-stateHandler.LastName,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitPassword:
|
case TypeAuthorizationStateWaitPassword:
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
case TypeAuthorizationStateReady:
|
case TypeAuthorizationStateReady:
|
||||||
close(stateHandler.TdlibParameters)
|
close(stateHandler.TdlibParameters)
|
||||||
close(stateHandler.PhoneNumber)
|
close(stateHandler.PhoneNumber)
|
||||||
close(stateHandler.Code)
|
close(stateHandler.Code)
|
||||||
close(stateHandler.State)
|
close(stateHandler.State)
|
||||||
close(stateHandler.FirstName)
|
close(stateHandler.FirstName)
|
||||||
close(stateHandler.LastName)
|
close(stateHandler.LastName)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case TypeAuthorizationStateLoggingOut:
|
case TypeAuthorizationStateLoggingOut:
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
case TypeAuthorizationStateClosing:
|
case TypeAuthorizationStateClosing:
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
case TypeAuthorizationStateClosed:
|
case TypeAuthorizationStateClosed:
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
}
|
}
|
||||||
|
|
||||||
func CliInteractor(clientAuthorizer *clientAuthorizer) {
|
func CliInteractor(clientAuthorizer *clientAuthorizer) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case state := <-clientAuthorizer.State:
|
case state := <-clientAuthorizer.State:
|
||||||
switch state.AuthorizationStateType() {
|
switch state.AuthorizationStateType() {
|
||||||
case TypeAuthorizationStateWaitPhoneNumber:
|
case TypeAuthorizationStateWaitPhoneNumber:
|
||||||
fmt.Println("Enter phone number: ")
|
fmt.Println("Enter phone number: ")
|
||||||
var phoneNumber string
|
var phoneNumber string
|
||||||
fmt.Scanln(&phoneNumber)
|
fmt.Scanln(&phoneNumber)
|
||||||
|
|
||||||
clientAuthorizer.PhoneNumber <- phoneNumber
|
clientAuthorizer.PhoneNumber <- phoneNumber
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitCode:
|
case TypeAuthorizationStateWaitCode:
|
||||||
var code string
|
var code string
|
||||||
var firstName string
|
var firstName string
|
||||||
var lastName string
|
var lastName string
|
||||||
|
|
||||||
fmt.Println("Enter code: ")
|
fmt.Println("Enter code: ")
|
||||||
fmt.Scanln(&code)
|
fmt.Scanln(&code)
|
||||||
|
|
||||||
if !state.(*AuthorizationStateWaitCode).IsRegistered {
|
if !state.(*AuthorizationStateWaitCode).IsRegistered {
|
||||||
fmt.Println("Phone number is not registered.")
|
fmt.Println("Phone number is not registered.")
|
||||||
|
|
||||||
fmt.Println("Enter first name: ")
|
fmt.Println("Enter first name: ")
|
||||||
fmt.Scanln(&firstName)
|
fmt.Scanln(&firstName)
|
||||||
|
|
||||||
fmt.Println("Enter last name: ")
|
fmt.Println("Enter last name: ")
|
||||||
fmt.Scanln(&lastName)
|
fmt.Scanln(&lastName)
|
||||||
}
|
}
|
||||||
|
|
||||||
clientAuthorizer.Code <- code
|
clientAuthorizer.Code <- code
|
||||||
clientAuthorizer.FirstName <- firstName
|
clientAuthorizer.FirstName <- firstName
|
||||||
clientAuthorizer.LastName <- lastName
|
clientAuthorizer.LastName <- lastName
|
||||||
|
|
||||||
case TypeAuthorizationStateReady:
|
case TypeAuthorizationStateReady:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type botAuthorizer struct {
|
type botAuthorizer struct {
|
||||||
TdlibParameters chan *TdlibParameters
|
TdlibParameters chan *TdlibParameters
|
||||||
Token chan string
|
Token chan string
|
||||||
State chan AuthorizationState
|
State chan AuthorizationState
|
||||||
}
|
}
|
||||||
|
|
||||||
func BotAuthorizer(token string) *botAuthorizer {
|
func BotAuthorizer(token string) *botAuthorizer {
|
||||||
botAuthorizer := &botAuthorizer{
|
botAuthorizer := &botAuthorizer{
|
||||||
TdlibParameters: make(chan *TdlibParameters, 1),
|
TdlibParameters: make(chan *TdlibParameters, 1),
|
||||||
Token: make(chan string, 1),
|
Token: make(chan string, 1),
|
||||||
State: make(chan AuthorizationState, 10),
|
State: make(chan AuthorizationState, 10),
|
||||||
}
|
}
|
||||||
|
|
||||||
botAuthorizer.Token <- token
|
botAuthorizer.Token <- token
|
||||||
|
|
||||||
return botAuthorizer
|
return botAuthorizer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stateHandler *botAuthorizer) Handle(client *Client, state AuthorizationState) error {
|
func (stateHandler *botAuthorizer) Handle(client *Client, state AuthorizationState) error {
|
||||||
stateHandler.State <- state
|
stateHandler.State <- state
|
||||||
|
|
||||||
switch state.AuthorizationStateType() {
|
switch state.AuthorizationStateType() {
|
||||||
case TypeAuthorizationStateWaitTdlibParameters:
|
case TypeAuthorizationStateWaitTdlibParameters:
|
||||||
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
_, err := client.SetTdlibParameters(&SetTdlibParametersRequest{
|
||||||
Parameters: <-stateHandler.TdlibParameters,
|
Parameters: <-stateHandler.TdlibParameters,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitEncryptionKey:
|
case TypeAuthorizationStateWaitEncryptionKey:
|
||||||
_, err := client.CheckDatabaseEncryptionKey(&CheckDatabaseEncryptionKeyRequest{})
|
_, err := client.CheckDatabaseEncryptionKey(&CheckDatabaseEncryptionKeyRequest{})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitPhoneNumber:
|
case TypeAuthorizationStateWaitPhoneNumber:
|
||||||
_, err := client.CheckAuthenticationBotToken(&CheckAuthenticationBotTokenRequest{
|
_, err := client.CheckAuthenticationBotToken(&CheckAuthenticationBotTokenRequest{
|
||||||
Token: <-stateHandler.Token,
|
Token: <-stateHandler.Token,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitCode:
|
case TypeAuthorizationStateWaitCode:
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
case TypeAuthorizationStateWaitPassword:
|
case TypeAuthorizationStateWaitPassword:
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
case TypeAuthorizationStateReady:
|
case TypeAuthorizationStateReady:
|
||||||
close(stateHandler.TdlibParameters)
|
close(stateHandler.TdlibParameters)
|
||||||
close(stateHandler.Token)
|
close(stateHandler.Token)
|
||||||
close(stateHandler.State)
|
close(stateHandler.State)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case TypeAuthorizationStateLoggingOut:
|
case TypeAuthorizationStateLoggingOut:
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
case TypeAuthorizationStateClosing:
|
case TypeAuthorizationStateClosing:
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
|
|
||||||
case TypeAuthorizationStateClosed:
|
case TypeAuthorizationStateClosed:
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrNotSupportedAuthorizationState
|
return ErrNotSupportedAuthorizationState
|
||||||
}
|
}
|
||||||
|
|
190
client/client.go
190
client/client.go
|
@ -1,145 +1,145 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
jsonClient *JsonClient
|
jsonClient *JsonClient
|
||||||
extraGenerator ExtraGenerator
|
extraGenerator ExtraGenerator
|
||||||
catcher chan *Response
|
catcher chan *Response
|
||||||
listenerStore *listenerStore
|
listenerStore *listenerStore
|
||||||
catchersStore *sync.Map
|
catchersStore *sync.Map
|
||||||
updatesTimeout time.Duration
|
updatesTimeout time.Duration
|
||||||
catchTimeout time.Duration
|
catchTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type Option func(*Client)
|
type Option func(*Client)
|
||||||
|
|
||||||
func WithExtraGenerator(extraGenerator ExtraGenerator) Option {
|
func WithExtraGenerator(extraGenerator ExtraGenerator) Option {
|
||||||
return func(client *Client) {
|
return func(client *Client) {
|
||||||
client.extraGenerator = extraGenerator
|
client.extraGenerator = extraGenerator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithCatchTimeout(timeout time.Duration) Option {
|
func WithCatchTimeout(timeout time.Duration) Option {
|
||||||
return func(client *Client) {
|
return func(client *Client) {
|
||||||
client.catchTimeout = timeout
|
client.catchTimeout = timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithUpdatesTimeout(timeout time.Duration) Option {
|
func WithUpdatesTimeout(timeout time.Duration) Option {
|
||||||
return func(client *Client) {
|
return func(client *Client) {
|
||||||
client.updatesTimeout = timeout
|
client.updatesTimeout = timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(authorizationStateHandler AuthorizationStateHandler, options ...Option) (*Client, error) {
|
func NewClient(authorizationStateHandler AuthorizationStateHandler, options ...Option) (*Client, error) {
|
||||||
catchersListener := make(chan *Response, 1000)
|
catchersListener := make(chan *Response, 1000)
|
||||||
|
|
||||||
client := &Client{
|
client := &Client{
|
||||||
jsonClient: NewJsonClient(),
|
jsonClient: NewJsonClient(),
|
||||||
catcher: catchersListener,
|
catcher: catchersListener,
|
||||||
listenerStore: newListenerStore(),
|
listenerStore: newListenerStore(),
|
||||||
catchersStore: &sync.Map{},
|
catchersStore: &sync.Map{},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
option(client)
|
option(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.extraGenerator == nil {
|
if client.extraGenerator == nil {
|
||||||
client.extraGenerator = UuidV4Generator()
|
client.extraGenerator = UuidV4Generator()
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.catchTimeout == 0 {
|
if client.catchTimeout == 0 {
|
||||||
client.catchTimeout = 60 * time.Second
|
client.catchTimeout = 60 * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.updatesTimeout == 0 {
|
if client.updatesTimeout == 0 {
|
||||||
client.updatesTimeout = 60 * time.Second
|
client.updatesTimeout = 60 * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
go client.receive()
|
go client.receive()
|
||||||
go client.catch(catchersListener)
|
go client.catch(catchersListener)
|
||||||
|
|
||||||
err := Authorize(client, authorizationStateHandler)
|
err := Authorize(client, authorizationStateHandler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) receive() {
|
func (client *Client) receive() {
|
||||||
for {
|
for {
|
||||||
resp, err := client.jsonClient.Receive(client.updatesTimeout)
|
resp, err := client.jsonClient.Receive(client.updatesTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
client.catcher <- resp
|
client.catcher <- resp
|
||||||
|
|
||||||
typ, err := UnmarshalType(resp.Data)
|
typ, err := UnmarshalType(resp.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
needGc := false
|
needGc := false
|
||||||
for _, listener := range client.listenerStore.Listeners() {
|
for _, listener := range client.listenerStore.Listeners() {
|
||||||
if listener.IsActive() {
|
if listener.IsActive() {
|
||||||
listener.Updates <- typ
|
listener.Updates <- typ
|
||||||
} else {
|
} else {
|
||||||
needGc = true
|
needGc = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if needGc {
|
if needGc {
|
||||||
client.listenerStore.gc()
|
client.listenerStore.gc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) catch(updates chan *Response) {
|
func (client *Client) catch(updates chan *Response) {
|
||||||
for update := range updates {
|
for update := range updates {
|
||||||
if update.Extra != "" {
|
if update.Extra != "" {
|
||||||
value, ok := client.catchersStore.Load(update.Extra)
|
value, ok := client.catchersStore.Load(update.Extra)
|
||||||
if ok {
|
if ok {
|
||||||
value.(chan *Response) <- update
|
value.(chan *Response) <- update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) Send(req Request) (*Response, error) {
|
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() {
|
defer func() {
|
||||||
close(catcher)
|
close(catcher)
|
||||||
client.catchersStore.Delete(req.Extra)
|
client.catchersStore.Delete(req.Extra)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
client.jsonClient.Send(req)
|
client.jsonClient.Send(req)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case response := <-catcher:
|
case response := <-catcher:
|
||||||
return response, nil
|
return response, nil
|
||||||
|
|
||||||
case <-time.After(client.catchTimeout):
|
case <-time.After(client.catchTimeout):
|
||||||
return nil, errors.New("response catching timeout")
|
return nil, errors.New("response catching timeout")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) GetListener() *Listener {
|
func (client *Client) GetListener() *Listener {
|
||||||
listener := &Listener{
|
listener := &Listener{
|
||||||
isActive: true,
|
isActive: true,
|
||||||
Updates: make(chan Type, 1000),
|
Updates: make(chan Type, 1000),
|
||||||
}
|
}
|
||||||
client.listenerStore.Add(listener)
|
client.listenerStore.Add(listener)
|
||||||
|
|
||||||
return listener
|
return listener
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ExtraGenerator func() string
|
type ExtraGenerator func() string
|
||||||
|
|
||||||
func UuidV4Generator() ExtraGenerator {
|
func UuidV4Generator() ExtraGenerator {
|
||||||
return func() string {
|
return func() string {
|
||||||
var uuid [16]byte
|
var uuid [16]byte
|
||||||
rand.Read(uuid[:])
|
rand.Read(uuid[:])
|
||||||
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | 0x40
|
uuid[6] = (uuid[6] & 0x0f) | 0x40
|
||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80
|
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
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newListenerStore() *listenerStore {
|
func newListenerStore() *listenerStore {
|
||||||
return &listenerStore{
|
return &listenerStore{
|
||||||
listeners: []*Listener{},
|
listeners: []*Listener{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type listenerStore struct {
|
type listenerStore struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
listeners []*Listener
|
listeners []*Listener
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *listenerStore) Add(listener *Listener) {
|
func (store *listenerStore) Add(listener *Listener) {
|
||||||
store.Lock()
|
store.Lock()
|
||||||
defer store.Unlock()
|
defer store.Unlock()
|
||||||
|
|
||||||
store.listeners = append(store.listeners, listener)
|
store.listeners = append(store.listeners, listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *listenerStore) Listeners() []*Listener {
|
func (store *listenerStore) Listeners() []*Listener {
|
||||||
store.Lock()
|
store.Lock()
|
||||||
defer store.Unlock()
|
defer store.Unlock()
|
||||||
|
|
||||||
return store.listeners
|
return store.listeners
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *listenerStore) gc() {
|
func (store *listenerStore) gc() {
|
||||||
store.Lock()
|
store.Lock()
|
||||||
defer store.Unlock()
|
defer store.Unlock()
|
||||||
|
|
||||||
oldListeners := store.listeners
|
oldListeners := store.listeners
|
||||||
|
|
||||||
store.listeners = []*Listener{}
|
store.listeners = []*Listener{}
|
||||||
|
|
||||||
for _, listener := range oldListeners {
|
for _, listener := range oldListeners {
|
||||||
if listener.IsActive() {
|
if listener.IsActive() {
|
||||||
store.listeners = append(store.listeners, listener)
|
store.listeners = append(store.listeners, listener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
isActive bool
|
isActive bool
|
||||||
Updates chan Type
|
Updates chan Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listener *Listener) Close() {
|
func (listener *Listener) Close() {
|
||||||
listener.mu.Lock()
|
listener.mu.Lock()
|
||||||
defer listener.mu.Unlock()
|
defer listener.mu.Unlock()
|
||||||
|
|
||||||
listener.isActive = false
|
listener.isActive = false
|
||||||
close(listener.Updates)
|
close(listener.Updates)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listener *Listener) IsActive() bool {
|
func (listener *Listener) IsActive() bool {
|
||||||
listener.mu.Lock()
|
listener.mu.Lock()
|
||||||
defer listener.mu.Unlock()
|
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 "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type JsonClient struct {
|
type JsonClient struct {
|
||||||
jsonClient unsafe.Pointer
|
jsonClient unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJsonClient() *JsonClient {
|
func NewJsonClient() *JsonClient {
|
||||||
return &JsonClient{
|
return &JsonClient{
|
||||||
jsonClient: C.td_json_client_create(),
|
jsonClient: C.td_json_client_create(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends request to the TDLib client. May be called from any thread.
|
// Sends request to the TDLib client. May be called from any thread.
|
||||||
func (jsonClient *JsonClient) Send(req Request) {
|
func (jsonClient *JsonClient) Send(req Request) {
|
||||||
data, _ := json.Marshal(req)
|
data, _ := json.Marshal(req)
|
||||||
|
|
||||||
query := C.CString(string(data))
|
query := C.CString(string(data))
|
||||||
defer C.free(unsafe.Pointer(query))
|
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
|
// 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
|
// 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.
|
// in the same thread, so it can't be used after that.
|
||||||
func (jsonClient *JsonClient) Receive(timeout time.Duration) (*Response, error) {
|
func (jsonClient *JsonClient) Receive(timeout time.Duration) (*Response, error) {
|
||||||
result := C.td_json_client_receive(jsonClient.jsonClient, C.double(float64(timeout)/float64(time.Second)))
|
result := C.td_json_client_receive(jsonClient.jsonClient, C.double(float64(timeout)/float64(time.Second)))
|
||||||
if result == nil {
|
if result == nil {
|
||||||
return nil, errors.New("update receiving timeout")
|
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)
|
err := json.Unmarshal(data, &resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// 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
|
// 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.
|
// in the same thread, so it can't be used after that.
|
||||||
func (jsonClient *JsonClient) Execute(req Request) (*Response, error) {
|
func (jsonClient *JsonClient) Execute(req Request) (*Response, error) {
|
||||||
data, _ := json.Marshal(req)
|
data, _ := json.Marshal(req)
|
||||||
|
|
||||||
query := C.CString(string(data))
|
query := C.CString(string(data))
|
||||||
defer C.free(unsafe.Pointer(query))
|
defer C.free(unsafe.Pointer(query))
|
||||||
|
|
||||||
result := C.td_json_client_execute(jsonClient.jsonClient, query)
|
result := C.td_json_client_execute(jsonClient.jsonClient, query)
|
||||||
if result == nil {
|
if result == nil {
|
||||||
return nil, errors.New("request can't be parsed")
|
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)
|
err := json.Unmarshal(data, &resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// Destroys the TDLib client instance. After this is called the client instance shouldn't be used anymore.
|
||||||
func (jsonClient *JsonClient) DestroyInstance() {
|
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.
|
// 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.
|
// By default TDLib writes logs to stderr or an OS specific log.
|
||||||
// Use this method to write the log to a file instead.
|
// Use this method to write the log to a file instead.
|
||||||
func SetLogFilePath(filePath string) {
|
func SetLogFilePath(filePath string) {
|
||||||
query := C.CString(filePath)
|
query := C.CString(filePath)
|
||||||
defer C.free(unsafe.Pointer(query))
|
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.
|
// 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.
|
// Unused if log is not written to a file. Defaults to 10 MB.
|
||||||
func SetLogMaxFileSize(maxFileSize int64) {
|
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.
|
// Sets the verbosity level of the internal logging of TDLib.
|
||||||
// By default the TDLib uses a log verbosity level of 5
|
// By default the TDLib uses a log verbosity level of 5
|
||||||
func SetLogVerbosityLevel(newVerbosityLevel int) {
|
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 meta struct {
|
||||||
Type string `json:"@type"`
|
Type string `json:"@type"`
|
||||||
Extra string `json:"@extra"`
|
Extra string `json:"@extra"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
meta
|
meta
|
||||||
Data map[string]interface{}
|
Data map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (req Request) MarshalJSON() ([]byte, error) {
|
func (req Request) MarshalJSON() ([]byte, error) {
|
||||||
req.Data["@type"] = req.Type
|
req.Data["@type"] = req.Type
|
||||||
req.Data["@extra"] = req.Extra
|
req.Data["@extra"] = req.Extra
|
||||||
|
|
||||||
return json.Marshal(req.Data)
|
return json.Marshal(req.Data)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Response struct {
|
type Response struct {
|
||||||
meta
|
meta
|
||||||
Data json.RawMessage
|
Data json.RawMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseError struct {
|
type ResponseError struct {
|
||||||
Err *Error
|
Err *Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (responseError ResponseError) Error() string {
|
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 {
|
func buildResponseError(data json.RawMessage) error {
|
||||||
respErr, err := UnmarshalError(data)
|
respErr, err := UnmarshalError(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseError{
|
return ResponseError{
|
||||||
Err: respErr,
|
Err: respErr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JsonInt64 alias for int64, in order to deal with json big number problem
|
// JsonInt64 alias for int64, in order to deal with json big number problem
|
||||||
|
@ -162,22 +162,22 @@ type JsonInt64 int64
|
||||||
|
|
||||||
// MarshalJSON marshals to json
|
// MarshalJSON marshals to json
|
||||||
func (jsonInt64 *JsonInt64) MarshalJSON() ([]byte, error) {
|
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
|
// UnmarshalJSON unmarshals from json
|
||||||
func (jsonInt64 *JsonInt64) UnmarshalJSON(data []byte) error {
|
func (jsonInt64 *JsonInt64) UnmarshalJSON(data []byte) error {
|
||||||
jsonBigInt, err := strconv.ParseInt(string(data[1:len(data)-1]), 10, 64)
|
jsonBigInt, err := strconv.ParseInt(string(data[1:len(data)-1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
*jsonInt64 = JsonInt64(jsonBigInt)
|
*jsonInt64 = JsonInt64(jsonBigInt)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Type interface {
|
type Type interface {
|
||||||
GetType() string
|
GetType() string
|
||||||
GetClass() 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