Files
dickbot/src/controllers/duelController.go
T
2025-09-05 15:32:16 +03:00

247 lines
7.7 KiB
Go

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))
}
}