diff --git a/internal/db/models/user.go b/internal/db/models/user.go index cc4b90f..ed78cfa 100644 --- a/internal/db/models/user.go +++ b/internal/db/models/user.go @@ -18,15 +18,17 @@ func (r UserRole) String() string { } type User struct { - ID int `json:"id" pg:",pk,default:gen_random_uuid()"` - Name string `json:"name" pg:",notnull"` - TelegramID int64 `json:"telegram_id" pg:",notnull,unique"` - TelegramNickname string `json:"telegram_nickname" pg:",notnull,unique"` - DiscordID int `json:"discord_id"` - Role UserRole `json:"role" pg:"type:UserRole,notnull,default:'guest'"` - Proposals []Proposal `json:"proposals" pg:"rel:has-many,fk:user_id"` - BackersID []int64 `json:"backers_id" pg:",array"` - NominatorID int `json:"nominator_id"` - TempProposal Proposal `json:"temp_proposal"` - TelegramState TelegramState `json:"telegram_state"` + ID int `json:"id" pg:",pk,default:gen_random_uuid()"` + Name string `json:"name" pg:",notnull"` + TelegramID int64 `json:"telegram_id" pg:",notnull,unique"` + TelegramNickname string `json:"telegram_nickname" pg:",notnull,unique"` + DiscordID int `json:"discord_id"` + Role UserRole `json:"role" pg:"type:UserRole,notnull,default:'guest'"` + Proposals []Proposal `json:"proposals" pg:"rel:has-many,fk:user_id"` + BackersID []int64 `json:"backers_id" pg:",array"` + NominatorID int `json:"nominator_id"` + MembersChatInviteLink string `json:"members_chat_invite_link"` + SeedersChatInviteLink string `json:"seeders_chat_invite_link"` + TempProposal Proposal `json:"temp_proposal"` + TelegramState TelegramState `json:"telegram_state"` } diff --git a/internal/db/repositories/proposal_repository.go b/internal/db/repositories/proposal_repository.go index 1bfef0e..45b8c60 100644 --- a/internal/db/repositories/proposal_repository.go +++ b/internal/db/repositories/proposal_repository.go @@ -17,6 +17,7 @@ type ProposalRepository interface { Delete(request *models.Proposal) error GetOneByID(id int64) (*models.Proposal, error) GetManyByNomineeNickname(nomineeNickName string) ([]*models.Proposal, error) + GetApprovedByNomineeNickname(nomineeNickName string) (*models.Proposal, error) GetManyByStatus(status ...models.ProposalStatus) ([]*models.Proposal, error) } @@ -93,6 +94,21 @@ func (r *proposalRepository) GetManyByNomineeNickname(nomineeNickName string) ([ return proposals, err } +func (r *proposalRepository) GetApprovedByNomineeNickname(nomineeNickName string) (*models.Proposal, error) { + proposals := make([]*models.Proposal, 0) + + err := r.db.Model(&proposals). + Where("nominee_telegram_nickname = ? AND status = ?", nomineeNickName, models.ProposalStatusApproved). + OrderExpr("created_at ASC"). + Select() + + if len(proposals) == 0 { + return nil, errors.New("proposal not found") + } + + return proposals[len(proposals)-1], err +} + func (r *proposalRepository) GetManyByStatus(status ...models.ProposalStatus) ([]*models.Proposal, error) { proposals := make([]*models.Proposal, 0) diff --git a/internal/tg_bot/commands/access_governance_bot/start.go b/internal/tg_bot/commands/access_governance_bot/start.go index 2cca461..1e49379 100644 --- a/internal/tg_bot/commands/access_governance_bot/start.go +++ b/internal/tg_bot/commands/access_governance_bot/start.go @@ -47,8 +47,8 @@ func (c *startCommand) Handle(command, arguments string, user *models.User, bot ` messages = append(messages, tgbotapi.NewMessage(chatID, text)) - if user.Role == models.UserRoleSeeder && user.DiscordID == 0 { - message := c.createInstructionMessageForSeeder(bot, chatID, user.TelegramNickname) + if user.Role == models.UserRoleSeeder { + message := c.createInstructionMessageForSeeder(bot, chatID, user) if message == nil { return []tgbotapi.Chattable{tgbot.DefaultErrorMessage(chatID)} @@ -60,11 +60,25 @@ func (c *startCommand) Handle(command, arguments string, user *models.User, bot return messages } -func (c *startCommand) createInstructionMessageForSeeder(bot *tgbotapi.BotAPI, chatID int64, nomineeTelegramNickname string) tgbotapi.Chattable { - membersChatInviteLink, err := tgbot.CreateChatInviteLink(bot, c.config.App.MembersChatID, "Shmit16", nomineeTelegramNickname) - if err != nil { - c.logger.Errorf("could not create members chat invite link: %v", err) - return nil +func (c *startCommand) createInstructionMessageForSeeder(bot *tgbotapi.BotAPI, chatID int64, user *models.User) tgbotapi.Chattable { + membersChatInviteLink := user.MembersChatInviteLink + + if membersChatInviteLink == "" { + inviteLink, err := tgbot.CreateChatInviteLink(bot, c.config.App.MembersChatID, "Shmit16", user.TelegramNickname) + if err != nil { + c.logger.Errorf("could not create members chat invite link: %v", err) + return nil + } + + if inviteLink != "" { + membersChatInviteLink = inviteLink + user.MembersChatInviteLink = inviteLink + + _, err = c.userRepository.Update(user) + if err != nil { + c.logger.Errorw("failed to update user", "error", err) + } + } } messageText := fmt.Sprintf("Обязательно убедись, что ты вступил в нашу группу: %s", membersChatInviteLink) diff --git a/internal/tg_bot/handlers/access_governance_bot/command_handler.go b/internal/tg_bot/handlers/access_governance_bot/command_handler.go index 5fb1357..8358054 100644 --- a/internal/tg_bot/handlers/access_governance_bot/command_handler.go +++ b/internal/tg_bot/handlers/access_governance_bot/command_handler.go @@ -58,15 +58,15 @@ func (h *accessGovernanceBotCommandHandler) Handle(bot *tgbotapi.BotAPI, update if message != nil { chatID = message.Chat.ID telegramUser = message.From + + if len(message.NewChatMembers) > 0 { + return h.handleNewChatMembers(bot, message) + } } else if callbackQuery != nil { chatID = callbackQuery.Message.Chat.ID telegramUser = callbackQuery.From } - if len(message.NewChatMembers) > 0 { - return h.handleNewChatMembers(bot, message) - } - if telegramUser.ID != chatID { h.logger.Infow("received message", "message", message) return []tgbotapi.Chattable{} @@ -89,8 +89,13 @@ func (h *accessGovernanceBotCommandHandler) Handle(bot *tgbotapi.BotAPI, update } if callbackQuery != nil { - h.logger.Infow("received callback query", "callback_query", callbackQuery) - return h.tryToHandleQueryCallback(callbackQuery.Data, h.commands, user, bot, chatID) + if user.TelegramState.LastCommand != "" { + h.logger.Infow("received subcommand", "subcommand", callbackQuery.Data) + return h.tryToHandleSubCommand(user.TelegramState.LastCommand, callbackQuery.Data, h.commands, user, bot, chatID) + } else { + h.logger.Infow("received callback query", "callback_query", callbackQuery) + return h.tryToHandleQueryCallback(callbackQuery.Data, h.commands, user, bot, chatID) + } } h.logger.Warn("received unknown message") @@ -241,7 +246,23 @@ func (h *accessGovernanceBotCommandHandler) handleNewChatMembers(bot *tgbotapi.B continue } - user.TelegramID = newChatMember.ID + if user.TelegramID != 0 { + user.TelegramID = newChatMember.ID + } + + if user.Role == models.UserRoleGuest { + proposal, err := h.proposalRepository.GetApprovedByNomineeNickname(user.TelegramNickname) + if err != nil { + h.logger.Errorw("failed to get proposal", "error", err) + continue + } + + if proposal.NomineeRole == models.NomineeRoleSeeder { + user.Role = models.UserRoleSeeder + } else { + user.Role = models.UserRoleMember + } + } _, err = h.userRepository.Update(user) if err != nil { @@ -250,10 +271,24 @@ func (h *accessGovernanceBotCommandHandler) handleNewChatMembers(bot *tgbotapi.B } if user.Role == models.UserRoleSeeder { - seedersChatInviteLink, err := tgbot.CreateChatInviteLink(bot, h.config.App.SeedersChatID, "Shmit16", user.TelegramNickname) - if err != nil { - h.logger.Errorf("could not create seeders chat invite link: %v", err) - return nil + seedersChatInviteLink := user.SeedersChatInviteLink + + if seedersChatInviteLink == "" { + inviteLink, err := tgbot.CreateChatInviteLink(bot, h.config.App.SeedersChatID, "Shmit16", user.TelegramNickname) + if err != nil { + h.logger.Errorf("could not create seeders chat invite link: %v", err) + continue + } + + if inviteLink != "" { + seedersChatInviteLink = inviteLink + user.SeedersChatInviteLink = inviteLink + + _, err = h.userRepository.Update(user) + if err != nil { + h.logger.Errorw("failed to update user", "error", err) + } + } } text := fmt.Sprintf(` diff --git a/migrations/1_users.up.sql b/migrations/1_users.up.sql index 669d7c4..c8a99ba 100644 --- a/migrations/1_users.up.sql +++ b/migrations/1_users.up.sql @@ -10,5 +10,7 @@ CREATE TABLE IF NOT EXISTS users ( backers_id VARCHAR[] NOT NULL DEFAULT '{}'::VARCHAR[], nominator_id INTEGER, temp_proposal JSONB, - telegram_state JSONB + telegram_state JSONB, + members_chat_invite_link VARCHAR, + seeders_chat_invite_link VARCHAR );