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

247 lines
7.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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))
}
}