package controllers import ( "fmt" "log" "math/rand" "strconv" "strings" "time" tele "gopkg.in/telebot.v4" ) // AcceptDuelButtonUnique is the unique identifier for the duel accept button. const AcceptDuelButtonUnique = "accept_duel" type DuelController struct { PlayerOne struct { ID int64 Counter int FName string } PlayerTwo struct { ID int64 Counter int FName string } Summ int Inited bool MatchAccepted bool InitialMessage *tele.Message Bot *tele.Bot DC *DataController } // Controller Init func NewDuel(bot *tele.Bot, dc *DataController) *DuelController { return &DuelController{ Inited: false, Bot: bot, DC: dc, } } // Start Match func (s *DuelController) StartMatch(c tele.Context) error { if s.Inited { return c.Send(fmt.Sprintf("Дуэль уже началась!\nИгрок: %s\nСтавка: %d", s.PlayerOne.FName, s.Summ)) } var text string if strings.Contains(c.Text(), " ") { text = strings.Split(c.Text(), " ")[1] fmt.Println("New match", text) } else { return c.Send("Некоректная команда, используйте /duel <сумма>") } summ, err := strconv.Atoi(text) if err != nil { return c.Send("Некорректная команда, используйте /duel <сумма>") } else { if summ <= 0 { return c.Send("Некорректная сумма, используйте положительное значение!") } else { s.Summ = summ } } s.Inited = true s.PlayerOne.ID = c.Sender().ID s.PlayerOne.FName = c.Sender().FirstName user := s.DC.GetUser(s.PlayerOne.ID) // Assuming GetUser now returns (*User, error) // CRITICAL: Check if the user was found to prevent a panic. if user == nil { s.Inited = false // Reset state since the duel can't start return c.Send("Не удалось найти вас в базе данных. Попробуйте /start.") } if user.DickSize < summ { s.Inited = false return c.Send("У вас недостаточно длинный пенис для состязания!") } // Create an inline keyboard with an "Accept" button markup := &tele.ReplyMarkup{} btnAccept := markup.Data("Принять", AcceptDuelButtonUnique) markup.Inline(markup.Row(btnAccept)) msg, err := s.Bot.Send(c.Chat(), fmt.Sprintf("%s начал дуель, ставка: %d", s.PlayerOne.FName, summ), markup) if err != nil { s.resetDuelState() return err } s.InitialMessage = msg return nil } // Accept Match func (s *DuelController) AcceptMatch(c tele.Context) error { if s.MatchAccepted { return c.Send("Дождитесь окончания дуэли.") } if !s.Inited { return c.Send("Дуэль еще не началась! Дождитесь старта матча или начните новую дуель с помощью /duel <сумма>") } s.PlayerTwo.ID = c.Sender().ID s.PlayerTwo.FName = c.Sender().FirstName user := s.DC.GetUser(s.PlayerTwo.ID) // Assuming GetUser now returns (*User, error) // CRITICAL: Check if the user was found to prevent a panic. if user == nil { // No need to reset state here, the duel is still waiting for a valid player. return c.Send("Не удалось найти вас в базе данных. Попробуйте /start.") } if user.DickSize < s.Summ { return c.Send("У вас недостаточно длинный пенис для состязания!") } if s.PlayerTwo.ID == s.PlayerOne.ID { return c.Send("Вы не можете принять участие в своей же дуэли!") } s.MatchAccepted = true s.Summ *= 2 if s.InitialMessage == nil { log.Println("Error: InitialMessage is nil in AcceptMatch") s.resetDuelState() return c.Send("Произошла ошибка, дуэль отменена. Попробуйте начать заново.") } // Edit the original message to remove the button and show the second player. s.Bot.Edit(s.InitialMessage, fmt.Sprintf("%s начал дуель, ставка: %d\n\n%s принимает участие в дуэли.", s.PlayerOne.FName, s.Summ/2, s.PlayerTwo.FName)) go s.gameProccess(s.InitialMessage) return c.Respond() } // Clear match func (s *DuelController) ClearMatch(c tele.Context) error { if c.Sender().ID == s.PlayerOne.ID { s.resetDuelState() return c.Send(fmt.Sprintf("%s отменил дуель!", c.Sender().FirstName)) } else { return c.Send("Отменить дуель может только инициатор!") } } // resetDuelState clears the current duel's information, making it ready for a new one. func (s *DuelController) resetDuelState() { s.PlayerOne.Counter = 0 s.PlayerTwo.Counter = 0 s.PlayerOne.FName = "" s.PlayerTwo.FName = "" s.PlayerOne.ID = 0 s.PlayerTwo.ID = 0 s.Summ = 0 s.Inited = false s.MatchAccepted = false s.InitialMessage = nil } // Start Game func (s *DuelController) gameProccess(msg *tele.Message) { time.Sleep(time.Second * 3) editedMsg, err := s.Bot.Edit(msg, fmt.Sprintf("Дуэль началась!\nНа кону: %d", s.Summ)) if err != nil { log.Printf("Error sending duel start message: %v", err) s.resetDuelState() // Reset state if we can't even send the message return } s.RoundOne(editedMsg) } // Round One func (s *DuelController) RoundOne(msg *tele.Message) { time.Sleep(time.Second * 3) s.PlayerOne.Counter += rand.Intn(11) + 1 s.PlayerTwo.Counter += rand.Intn(11) + 1 msg, _ = s.Bot.Edit(msg, fmt.Sprintf("Результаты первого раунда\n%s: %d очков.\n%s: %d очков.", s.PlayerOne.FName, s.PlayerOne.Counter, s.PlayerTwo.FName, s.PlayerTwo.Counter), ) s.RoundTwo(msg) } // Round Two func (s *DuelController) RoundTwo(msg *tele.Message) { time.Sleep(time.Second * 3) s.PlayerOne.Counter += rand.Intn(11) + 1 s.PlayerTwo.Counter += rand.Intn(11) + 1 msg, _ = s.Bot.Edit(msg, fmt.Sprintf("Результаты второго раунда\n%s: %d очков.\n%s: %d очков.", s.PlayerOne.FName, s.PlayerOne.Counter, s.PlayerTwo.FName, s.PlayerTwo.Counter), ) s.RoundThree(msg) } // Round Three func (s *DuelController) RoundThree(msg *tele.Message) { time.Sleep(time.Second * 3) s.PlayerOne.Counter += rand.Intn(11) + 1 s.PlayerTwo.Counter += rand.Intn(11) + 1 msg, _ = s.Bot.Edit(msg, fmt.Sprintf("Результаты третьего раунда\n%s: %d очков.\n%s: %d очков.", s.PlayerOne.FName, s.PlayerOne.Counter, s.PlayerTwo.FName, s.PlayerTwo.Counter), ) s.CheckWin(msg) } // Check Win func (s *DuelController) CheckWin(msg *tele.Message) { // Ensure the duel state is reset regardless of how this function exits. defer s.resetDuelState() userOne := s.DC.GetUser(s.PlayerOne.ID) userTwo := s.DC.GetUser(s.PlayerTwo.ID) if userOne == nil || userTwo == nil { log.Println("Error: Could not find one or both duel participants in CheckWin.") s.Bot.Edit(msg, "Произошла ошибка, дуэль отменена.") return } time.Sleep(time.Second * 3) var message string = fmt.Sprintf("Дуэль окончена!\n%s: %d очков.\n%s: %d очков.", s.PlayerOne.FName, s.PlayerOne.Counter, s.PlayerTwo.FName, s.PlayerTwo.Counter) if s.PlayerOne.Counter > s.PlayerTwo.Counter { s.Bot.Edit(msg, fmt.Sprintf("%s\n%s победил!", message, s.PlayerOne.FName)) s.DC.UpdateDick(userOne.ID, userOne.DickSize+(s.Summ/2)) s.DC.UpdateDick(userTwo.ID, userTwo.DickSize-(s.Summ/2)) } else if s.PlayerOne.Counter < s.PlayerTwo.Counter { s.Bot.Edit(msg, fmt.Sprintf("%s\n%s победил!", message, s.PlayerTwo.FName)) s.DC.UpdateDick(userOne.ID, userOne.DickSize-(s.Summ/2)) s.DC.UpdateDick(userTwo.ID, userTwo.DickSize+(s.Summ/2)) } else if s.PlayerOne.Counter == s.PlayerTwo.Counter { s.Bot.Edit(msg, fmt.Sprintf("%s\nНичья!", message)) } }