aboutsummaryrefslogblamecommitdiff
path: root/telegram/client.go
blob: e9acd202fcb13adb380dd86e9f21c13a64e3fadd (plain) (tree)
1
2
3
4
5
6
7
8
9


                
                               
                      

                       
              
              

                                                    
                                                         
                                                            
 
                                            
                       


                                    






                         










                                          





                                                               

                                                               

                                    
                                                    

                                  
 



                                      
                                   


                                               
 


                                                    


                                      

                                   

 
                         
                                     
                                                
                                     
                                     
                                     

 
                                        
                                                                                                                                  


                                                                                              
                                                                      






                                                                                  
 
                                                                       
                       
                                                                  

         




                                                          
                                                       

                                 

                                                                          





                                                                           
                                      










                                                                         
                       
                                             



                                                       
                                                         


                                                  
                                                                

                                                        


                                                                      

              
package telegram

import (
	"github.com/pkg/errors"
	"hash/maphash"
	"path/filepath"
	"strconv"
	"sync"
	"time"

	"dev.narayana.im/narayana/telegabber/config"
	"dev.narayana.im/narayana/telegabber/persistence"
	"dev.narayana.im/narayana/telegabber/telegram/cache"

	"github.com/zelenin/go-tdlib/client"
	"gosrc.io/xmpp"
)

var logConstants = map[string]int32{
	":fatal":   0,
	":error":   1,
	":warn":    2,
	":info":    3,
	":debug":   4,
	":verbose": 5,
	":all":     1023,
}

func stringToLogConstant(c string) int32 {
	level, ok := logConstants[c]
	if !ok {
		level = 0
	}

	return level
}

// DelayedStatus describes an online status expiring on timeout
type DelayedStatus struct {
	TimestampOnline  int64
	TimestampExpired int64
}

// Client stores the metadata for lazily invoked TDlib instance
type Client struct {
	client     *client.Client
	authorizer *clientAuthorizer
	parameters *client.SetTdlibParametersRequest
	options    []client.Option
	me         *client.User

	xmpp      *xmpp.Component
	jid       string
	Session   *persistence.Session
	resources map[string]bool
	outbox    map[string]string
	content   *config.TelegramContentConfig
	cache     *cache.Cache
	online    bool

	DelayedStatuses     map[int64]*DelayedStatus
	DelayedStatusesLock sync.Mutex

	lastMsgHashes map[int64]uint64
	msgHashSeed   maphash.Seed

	locks           clientLocks
	SendMessageLock sync.Mutex
}

type clientLocks struct {
	authorizationReady sync.Mutex
	chatMessageLocks   map[int64]*sync.Mutex
	resourcesLock      sync.Mutex
	outboxLock         sync.Mutex
	lastMsgHashesLock  sync.Mutex
}

// NewClient instantiates a Telegram App
func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component, session *persistence.Session) (*Client, error) {
	var options []client.Option

	options = append(options, client.WithLogVerbosity(&client.SetLogVerbosityLevelRequest{
		NewVerbosityLevel: stringToLogConstant(conf.Loglevel),
	}))

	if conf.Tdlib.Client.CatchTimeout != 0 {
		options = append(options, client.WithCatchTimeout(
			time.Duration(conf.Tdlib.Client.CatchTimeout)*time.Second,
		))
	}

	apiID, err := strconv.ParseInt(conf.Tdlib.Client.APIID, 10, 32)
	if err != nil {
		return &Client{}, errors.Wrap(err, "Wrong api_id")
	}

	datadir := conf.Tdlib.Datadir
	if datadir == "" {
		datadir = "./sessions/" // ye olde defaute
	}

	parameters := client.SetTdlibParametersRequest{
		UseTestDc: false,

		DatabaseDirectory: filepath.Join(datadir, jid),
		FilesDirectory:    filepath.Join(datadir, jid, "/files/"),

		UseFileDatabase:     true,
		UseChatInfoDatabase: conf.Tdlib.Client.UseChatInfoDatabase,
		UseMessageDatabase:  true,
		UseSecretChats:      conf.Tdlib.Client.UseSecretChats,

		ApiId:   int32(apiID),
		ApiHash: conf.Tdlib.Client.APIHash,

		SystemLanguageCode: "en",
		DeviceModel:        conf.Tdlib.Client.DeviceModel,
		SystemVersion:      "1.0.0",
		ApplicationVersion: conf.Tdlib.Client.ApplicationVersion,

		EnableStorageOptimizer: true,
		IgnoreFileNames:        false,
	}

	return &Client{
		parameters:      &parameters,
		xmpp:            component,
		jid:             jid,
		Session:         session,
		resources:       make(map[string]bool),
		outbox:          make(map[string]string),
		content:         &conf.Content,
		cache:           cache.NewCache(),
		options:         options,
		DelayedStatuses: make(map[int64]*DelayedStatus),
		lastMsgHashes:   make(map[int64]uint64),
		msgHashSeed:     maphash.MakeSeed(),
		locks: clientLocks{
			chatMessageLocks: make(map[int64]*sync.Mutex),
		},
	}, nil
}