core/internal/clients/telegram/tg.go

247 lines
7.4 KiB
Go
Raw Normal View History

2024-06-25 14:37:26 +00:00
package telegram
import (
2024-06-30 18:02:23 +00:00
"context"
"errors"
2024-06-25 14:37:26 +00:00
"fmt"
"path/filepath"
2024-06-30 18:02:23 +00:00
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal"
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model"
2024-07-01 13:21:15 +00:00
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/pj_errors"
2024-06-30 18:02:23 +00:00
"penahub.gitlab.yandexcloud.net/backend/tdlib/client"
"sync"
"time"
2024-06-25 14:37:26 +00:00
)
type TelegramClient struct {
2024-06-30 18:02:23 +00:00
repo *dal.DAL
2024-07-01 13:02:26 +00:00
TgClients map[int64]*client.Client
2024-06-30 18:02:23 +00:00
WaitingClients map[string]WaitingClient
mu sync.Mutex
2024-06-30 18:02:23 +00:00
}
2024-06-25 14:37:26 +00:00
2024-06-30 18:02:23 +00:00
type WaitingClient struct {
PreviousReq AuthTgUserReq
Authorizer *client.ClientAuthorizer
}
2024-06-27 09:24:23 +00:00
func NewTelegramClient(ctx context.Context, repo *dal.DAL) (*TelegramClient, error) {
tgClient := &TelegramClient{
2024-06-30 18:02:23 +00:00
repo: repo,
2024-07-01 13:02:26 +00:00
TgClients: make(map[int64]*client.Client),
2024-06-30 18:02:23 +00:00
WaitingClients: make(map[string]WaitingClient),
}
allTgAccounts, err := repo.TgRepo.GetAllTgAccounts(ctx)
if err != nil {
2024-07-01 13:21:15 +00:00
if errors.Is(err, pj_errors.ErrNotFound) {
return tgClient, nil
}
return nil, err
}
for _, account := range allTgAccounts {
2024-07-01 13:02:26 +00:00
if account.Status == model.ActiveTg {
authorizer := client.ClientAuthorizerr()
authorizer.TdlibParameters <- &client.SetTdlibParametersRequest{
UseTestDc: false,
DatabaseDirectory: filepath.Join(".tdlib", "database"),
FilesDirectory: filepath.Join(".tdlib", "files"),
UseFileDatabase: true,
UseChatInfoDatabase: true,
UseMessageDatabase: true,
UseSecretChats: true,
2024-07-01 13:02:26 +00:00
ApiId: account.ApiID,
ApiHash: account.ApiHash,
SystemLanguageCode: "en",
DeviceModel: "Server",
SystemVersion: "1.0.0",
ApplicationVersion: "1.0.0",
}
2024-07-01 13:02:26 +00:00
_, err := client.SetLogVerbosityLevel(&client.SetLogVerbosityLevelRequest{
NewVerbosityLevel: 1,
})
if err != nil {
return nil, err
}
2024-07-01 13:02:26 +00:00
var tdlibClient *client.Client
var goErr error
go func() {
tdlibClient, goErr = client.NewClient(authorizer)
if goErr != nil {
fmt.Println("new client failed", err)
return
}
fmt.Println("i am down")
}()
if goErr != nil {
return nil, goErr
}
2024-07-01 13:02:26 +00:00
for {
state, ok := <-authorizer.State
if !ok {
break
}
fmt.Println("currnet state:", state)
switch state.AuthorizationStateType() {
case client.TypeAuthorizationStateWaitPhoneNumber:
authorizer.PhoneNumber <- account.PhoneNumber
case client.TypeAuthorizationStateWaitCode:
err := tgClient.repo.TgRepo.UpdateStatusTg(ctx, account.ID, model.InactiveTg)
if err != nil {
return nil, err
}
case client.TypeAuthorizationStateLoggingOut, client.TypeAuthorizationStateClosing, client.TypeAuthorizationStateClosed:
err := tgClient.repo.TgRepo.UpdateStatusTg(ctx, account.ID, model.InactiveTg)
if err != nil {
return nil, err
}
case client.TypeAuthorizationStateReady:
// костыль так как в либе тож костыль стоит пока там ьд обновиться будет ниловый всегда клиент
time.Sleep(3 * time.Second)
me, err := tdlibClient.GetMe()
if err != nil {
return nil, err
}
fmt.Printf("Me: %s %s [%v]", me.FirstName, me.LastName, me.Usernames)
tgClient.mu.Lock()
tgClient.TgClients[account.ID] = tdlibClient
tgClient.mu.Unlock()
break
case client.TypeAuthorizationStateWaitPassword:
authorizer.Password <- account.Password
}
}
}
}
return tgClient, nil
2024-06-30 18:02:23 +00:00
}
2024-06-25 14:37:26 +00:00
2024-06-30 18:02:23 +00:00
type AuthTgUserReq struct {
ApiID int32 `json:"api_id"`
ApiHash string `json:"api_hash"`
PhoneNumber string `json:"phone_number"`
Password string `json:"password"`
}
func (tg *TelegramClient) AddedToMap(data WaitingClient, id string) {
fmt.Println("AddedToMap")
tg.mu.Lock()
defer tg.mu.Unlock()
2024-06-30 18:02:23 +00:00
tg.WaitingClients[id] = data
}
func (tg *TelegramClient) GetFromMap(id string) (WaitingClient, bool) {
fmt.Println("GetFromMap")
tg.mu.Lock()
defer tg.mu.Unlock()
2024-06-30 18:02:23 +00:00
if data, ok := tg.WaitingClients[id]; ok {
2024-07-01 13:21:15 +00:00
delete(tg.WaitingClients, id)
2024-06-30 18:02:23 +00:00
return data, true
2024-06-25 14:37:26 +00:00
}
2024-06-30 18:02:23 +00:00
return WaitingClient{}, false
}
func (tg *TelegramClient) SaveTgAccount(appID int32, appHash string, tdLibClient *client.Client) {
account, err := tg.repo.TgRepo.SearchIDByAppIDanAppHash(context.Background(), appID, appHash)
if err != nil {
fmt.Println("err SaveTgAccount", err)
return
}
if account.Status == model.ActiveTg {
tg.mu.Lock()
defer tg.mu.Unlock()
tg.TgClients[account.ID] = tdLibClient
}
2024-06-25 14:37:26 +00:00
}
2024-07-05 07:49:42 +00:00
func (tg *TelegramClient) CreateChannel(channelName string, botID int64) (string, int64, error) {
tg.mu.Lock()
defer tg.mu.Unlock()
2024-07-05 07:49:42 +00:00
if len(tg.TgClients) == 0 {
return "", 0, errors.New("no active Telegram clients")
}
2024-07-05 07:49:42 +00:00
var lastError error
var inviteLink string
var channelId int64
for _, activeClient := range tg.TgClients {
// todo пока не понимаю это какой то рандом? в один день бот норм находится в другой уже не находится хотя абсолютно с точки зрения тг кода этой функции и бота не менялось
2024-07-05 07:49:42 +00:00
_, err := activeClient.GetUser(&client.GetUserRequest{
UserId: botID,
})
if err != nil {
lastError = fmt.Errorf("not found this bot, make privacy off: %v", err)
continue
}
2024-07-05 07:49:42 +00:00
// todo нужно поймать ошибку, при которой либо бан либо медленный редим включается для того чтобы прервать
// исполнение клиента текущего аккаунта и дать задачу следующему пока поймал 1 раз и не запомнил больше не получается
channel, err := activeClient.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{
2024-07-10 11:46:45 +00:00
Title: channelName,
IsChannel: true,
2024-07-05 07:49:42 +00:00
Description: "private channel",
})
if err != nil {
lastError = fmt.Errorf("failed to create channel: %s", err.Error())
continue
}
2024-07-05 07:49:42 +00:00
_, err = activeClient.SetChatMemberStatus(&client.SetChatMemberStatusRequest{
ChatId: channel.Id,
MemberId: &client.MessageSenderUser{UserId: botID},
Status: &client.ChatMemberStatusAdministrator{
CustomTitle: "bot",
Rights: &client.ChatAdministratorRights{
CanManageChat: true,
CanChangeInfo: true,
CanPostMessages: true,
CanEditMessages: true,
CanDeleteMessages: true,
CanInviteUsers: true,
CanRestrictMembers: true,
CanPinMessages: true,
CanManageTopics: true,
CanPromoteMembers: true,
CanManageVideoChats: true,
CanPostStories: true,
CanEditStories: true,
CanDeleteStories: true,
2024-07-05 07:49:42 +00:00
},
},
2024-07-05 07:49:42 +00:00
})
if err != nil {
lastError = fmt.Errorf("failed to make bot admin: %s", err.Error())
continue
}
2024-07-05 07:49:42 +00:00
inviteLinkResp, err := activeClient.CreateChatInviteLink(&client.CreateChatInviteLinkRequest{
ChatId: channel.Id,
Name: channelName,
ExpirationDate: 0,
MemberLimit: 0,
CreatesJoinRequest: false,
})
if err != nil {
lastError = fmt.Errorf("failed to get invite link: %s", err.Error())
continue
}
2024-07-05 07:49:42 +00:00
_, err = activeClient.LeaveChat(&client.LeaveChatRequest{
ChatId: channel.Id,
})
if err != nil {
lastError = fmt.Errorf("failed to leave the channel: %s", err.Error())
continue
}
inviteLink = inviteLinkResp.InviteLink
channelId = channel.Id
return inviteLink, channelId, nil
}
2024-07-05 07:49:42 +00:00
return "", 0, lastError
2024-06-25 14:37:26 +00:00
}