package service import ( "errors" "fmt" "github.com/gofiber/fiber/v2" "github.com/rs/xid" "path/filepath" "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model" "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/pj_errors" "penahub.gitlab.yandexcloud.net/backend/quiz/core/clients/telegram" "penahub.gitlab.yandexcloud.net/backend/tdlib/client" "strconv" ) type Message struct { Type string `json:"type"` Data string `json:"data"` } func (s *Service) GetPoolTgAccounts(ctx *fiber.Ctx) error { allAccounts, err := s.dal.TgRepo.GetAllTgAccounts(ctx.Context()) if err != nil { switch { case errors.Is(err, pj_errors.ErrNotFound): return ctx.Status(fiber.StatusNotFound).SendString("not found") default: return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } } return ctx.Status(fiber.StatusOK).JSON(allAccounts) } func (s *Service) AddingTgAccount(ctx *fiber.Ctx) error { var req telegram.AuthTgUserReq if err := ctx.BodyParser(&req); err != nil { return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data") } allAccounts, err := s.dal.TgRepo.GetAllTgAccounts(ctx.Context()) if err != nil && !errors.Is(err, pj_errors.ErrNotFound) { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } if !errors.Is(err, pj_errors.ErrNotFound) { for _, account := range allAccounts { if account.ApiID == req.ApiID && account.ApiHash == req.ApiHash && account.Status == model.ActiveTg { return ctx.Status(fiber.StatusConflict).SendString("this account already exist and active") } } } authorizer := client.ClientAuthorizerr() authorizer.TdlibParameters <- &client.SetTdlibParametersRequest{ UseTestDc: false, DatabaseDirectory: filepath.Join(".tdlib", "database"), FilesDirectory: filepath.Join(".tdlib", "files"), UseFileDatabase: false, UseChatInfoDatabase: false, UseMessageDatabase: false, UseSecretChats: false, ApiId: req.ApiID, ApiHash: req.ApiHash, SystemLanguageCode: "en", DeviceModel: "Server", SystemVersion: "1.0.0", ApplicationVersion: "1.0.0", } _, err = client.SetLogVerbosityLevel(&client.SetLogVerbosityLevelRequest{ NewVerbosityLevel: 1, }) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } 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 ctx.Status(fiber.StatusInternalServerError).SendString(goErr.Error()) } for { state, ok := <-authorizer.State if !ok { return ctx.Status(fiber.StatusOK).SendString("state chan is close auth maybe ok") } fmt.Println("currnet state:", state) switch state.AuthorizationStateType() { case client.TypeAuthorizationStateWaitPhoneNumber: authorizer.PhoneNumber <- req.PhoneNumber case client.TypeAuthorizationStateWaitCode: signature := xid.New() s.telegramClient.AddedToMap(telegram.WaitingClient{ TdLibClient: tdlibClient, PreviousReq: req, Authorizer: authorizer, }, signature.String()) return ctx.Status(fiber.StatusOK).JSON(fiber.Map{"signature": signature.String()}) case client.TypeAuthorizationStateLoggingOut, client.TypeAuthorizationStateClosing, client.TypeAuthorizationStateClosed: return ctx.Status(fiber.StatusForbidden).SendString(fmt.Sprintf("auth failed, last state is %s", state)) } } } func (s *Service) SettingTgCode(ctx *fiber.Ctx) error { var req struct { Code string `json:"code"` Signature string `json:"signature"` } if err := ctx.BodyParser(&req); err != nil { return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data") } data, ok := s.telegramClient.GetFromMap(req.Signature) if !ok { return ctx.Status(fiber.StatusBadRequest).SendString("Invalid id, don't have data") } data.Authorizer.Code <- req.Code for { state, ok := <-data.Authorizer.State if !ok { return ctx.Status(fiber.StatusOK).SendString("state chan is close auth maybe ok") } fmt.Println("currnet state:", state) switch state.AuthorizationStateType() { case client.TypeAuthorizationStateReady: id, err := s.telegramClient.SaveTgAccount(ctx.Context(), data.TdLibClient, model.TgAccount{ ApiID: data.PreviousReq.ApiID, ApiHash: data.PreviousReq.ApiHash, PhoneNumber: data.PreviousReq.PhoneNumber, Status: model.ActiveTg, Password: data.PreviousReq.Password, }) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } return ctx.Status(fiber.StatusOK).JSON(fiber.Map{"id": id}) case client.TypeAuthorizationStateWaitPassword: data.Authorizer.Password <- data.PreviousReq.Password case client.TypeAuthorizationStateLoggingOut, client.TypeAuthorizationStateClosing, client.TypeAuthorizationStateClosed: return ctx.Status(fiber.StatusForbidden).SendString(fmt.Sprintf("auth failed, last state is %s", state)) } } } func (s *Service) DeleteTgAccountByID(ctx *fiber.Ctx) error { id, err := strconv.ParseInt(ctx.Params("id"), 10, 64) if err != nil { return ctx.Status(fiber.StatusBadRequest).SendString("invalid id format") } err = s.dal.TgRepo.SoftDeleteTgAccount(ctx.Context(), id) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } return ctx.SendStatus(fiber.StatusOK) }