teldrive/utils/tgclient.go

168 lines
3.1 KiB
Go
Raw Normal View History

2023-08-07 03:32:46 +08:00
package utils
import (
"context"
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"time"
"github.com/gotd/contrib/bg"
"github.com/gotd/contrib/middleware/ratelimit"
2023-08-12 19:21:42 +08:00
"github.com/gotd/td/session"
2023-08-07 03:32:46 +08:00
"github.com/gotd/td/telegram"
"github.com/pkg/errors"
"go.uber.org/zap"
"golang.org/x/time/rate"
)
type Client struct {
Tg *telegram.Client
Token string
Workload int
}
var clients map[int]*Client
2023-08-12 19:21:42 +08:00
func getBotClient(appID int, appHash, clientName, sessionDir string) *telegram.Client {
2023-08-07 03:32:46 +08:00
sessionStorage := &telegram.FileSessionStorage{
Path: filepath.Join(sessionDir, clientName+".json"),
}
options := telegram.Options{
SessionStorage: sessionStorage,
Middlewares: []telegram.Middleware{
ratelimit.New(rate.Every(time.Millisecond*100), 5),
},
2023-08-12 19:21:42 +08:00
NoUpdates: true,
2023-08-07 03:32:46 +08:00
}
client := telegram.NewClient(appID, appHash, options)
return client
}
2023-08-12 19:21:42 +08:00
func startClient(ctx context.Context, client *Client) (bg.StopFunc, error) {
2023-08-07 03:32:46 +08:00
stop, err := bg.Connect(client.Tg)
if err != nil {
return nil, errors.Wrap(err, "failed to start client")
}
tguser, err := client.Tg.Self(ctx)
if err != nil {
if _, err := client.Tg.Auth().Bot(ctx, client.Token); err != nil {
return nil, err
}
tguser, _ = client.Tg.Self(ctx)
}
2023-08-12 19:21:42 +08:00
Logger.Info("started Client", zap.String("user", tguser.Username))
2023-08-07 03:32:46 +08:00
return stop, nil
}
2023-08-12 19:21:42 +08:00
func StartBotTgClients() {
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
clients = make(map[int]*Client)
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
if config.MultiClient {
sessionDir := "sessions"
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
if err := os.MkdirAll(sessionDir, 0700); err != nil {
return
}
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
var keysToSort []string
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
for _, e := range os.Environ() {
if strings.HasPrefix(e, "MULTI_TOKEN") {
if i := strings.Index(e, "="); i >= 0 {
keysToSort = append(keysToSort, e[:i])
}
}
}
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
sort.Strings(keysToSort)
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
for idx, key := range keysToSort {
client := getBotClient(config.AppId, config.AppHash, fmt.Sprintf("client%d", idx), sessionDir)
clients[idx] = &Client{Tg: client, Token: os.Getenv(key)}
}
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
ctx := context.Background()
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
for _, client := range clients {
go startClient(ctx, client)
2023-08-07 03:32:46 +08:00
}
}
2023-08-12 19:21:42 +08:00
}
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
func GetAuthClient(sessionStr string, userId int) (*Client, error) {
2023-08-07 03:32:46 +08:00
2023-08-12 19:21:42 +08:00
if client, ok := clients[userId]; ok {
return client, nil
2023-08-07 03:32:46 +08:00
}
ctx := context.Background()
2023-08-12 19:21:42 +08:00
data, err := session.TelethonSession(sessionStr)
if err != nil {
return nil, err
}
var (
storage = new(session.StorageMemory)
loader = session.Loader{Storage: storage}
)
if err := loader.Save(ctx, data); err != nil {
return nil, err
2023-08-07 03:32:46 +08:00
}
2023-08-12 19:21:42 +08:00
client := telegram.NewClient(config.AppId, config.AppHash, telegram.Options{
SessionStorage: storage,
Middlewares: []telegram.Middleware{
ratelimit.New(rate.Every(time.Millisecond*100), 5),
},
NoUpdates: true,
})
_, err = bg.Connect(client)
if err != nil {
return nil, err
}
tguser, err := client.Self(ctx)
if err != nil {
return nil, err
}
Logger.Info("started Client", zap.String("user", tguser.Username))
tgClient := &Client{Tg: client}
clients[int(tguser.GetID())] = tgClient
return tgClient, nil
2023-08-07 03:32:46 +08:00
}
2023-08-12 19:21:42 +08:00
func GetBotClient() *Client {
2023-08-07 03:32:46 +08:00
smallest := clients[0]
for _, client := range clients {
if client.Workload < smallest.Workload {
smallest = client
}
}
return smallest
}