2023-02-22 16:23:38 +03:00
|
|
|
|
package tg
|
|
|
|
|
|
|
|
|
|
import (
|
2023-08-02 20:11:58 +03:00
|
|
|
|
"fmt"
|
2023-03-27 21:05:17 +03:00
|
|
|
|
"io"
|
2023-02-22 16:23:38 +03:00
|
|
|
|
"log"
|
2023-03-27 21:05:17 +03:00
|
|
|
|
"os"
|
2023-08-12 11:52:51 +03:00
|
|
|
|
"strconv"
|
2023-08-03 14:49:51 +03:00
|
|
|
|
"strings"
|
2023-08-06 11:26:48 +03:00
|
|
|
|
"time"
|
2023-02-22 16:23:38 +03:00
|
|
|
|
|
|
|
|
|
"git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/database"
|
|
|
|
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
2023-08-02 20:11:58 +03:00
|
|
|
|
"github.com/joho/godotenv"
|
2023-02-22 16:23:38 +03:00
|
|
|
|
"xorm.io/xorm"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Bot struct {
|
2023-08-30 08:42:27 +03:00
|
|
|
|
TG *tgbotapi.BotAPI
|
|
|
|
|
DB *xorm.Engine
|
|
|
|
|
TestUser int64
|
|
|
|
|
HelpTxt string
|
|
|
|
|
Week int
|
|
|
|
|
WkPath string
|
|
|
|
|
Debug *log.Logger
|
|
|
|
|
Updates *tgbotapi.UpdatesChannel
|
2023-02-22 16:23:38 +03:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-02 20:11:58 +03:00
|
|
|
|
var env_keys = []string{
|
|
|
|
|
"TELEGRAM_APITOKEN",
|
2023-08-03 10:27:36 +03:00
|
|
|
|
"TELEGRAM_TEST_USER",
|
2023-08-10 11:01:47 +03:00
|
|
|
|
"WK_PATH",
|
|
|
|
|
"MYSQL_USER",
|
|
|
|
|
"MYSQL_PASS",
|
|
|
|
|
"MYSQL_DB",
|
|
|
|
|
"START_WEEK",
|
2023-08-02 20:11:58 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func CheckEnv() error {
|
|
|
|
|
if err := godotenv.Load(); err != nil {
|
|
|
|
|
log.Print("No .env file found")
|
|
|
|
|
}
|
|
|
|
|
for _, key := range env_keys {
|
|
|
|
|
if _, exists := os.LookupEnv(key); !exists {
|
|
|
|
|
return fmt.Errorf("lost env key: %s", key)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Полная инициализация бота со стороны Telegram и БД
|
2023-08-05 12:40:24 +03:00
|
|
|
|
func InitBot(files database.LogFiles, db database.DB, token string) (*Bot, error) {
|
2023-08-02 20:11:58 +03:00
|
|
|
|
var bot Bot
|
2023-08-05 12:40:24 +03:00
|
|
|
|
engine, err := database.Connect(db, files.DBLogFile)
|
2023-08-02 20:11:58 +03:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2023-08-02 21:22:36 +03:00
|
|
|
|
//defer engine.Close()
|
2023-08-02 20:11:58 +03:00
|
|
|
|
bot.DB = engine
|
|
|
|
|
|
2023-02-22 16:23:38 +03:00
|
|
|
|
bot.TG, err = tgbotapi.NewBotAPI(token)
|
|
|
|
|
if err != nil {
|
2023-08-02 20:11:58 +03:00
|
|
|
|
return nil, err
|
2023-02-22 16:23:38 +03:00
|
|
|
|
}
|
|
|
|
|
bot.TG.Debug = true
|
2023-08-02 20:11:58 +03:00
|
|
|
|
//logger := log.New(io.MultiWriter(os.Stdout, database.CreateLog("tg")), "", log.LstdFlags)
|
2023-08-05 12:40:24 +03:00
|
|
|
|
logger := log.New(files.TgLogFile, "", log.LstdFlags)
|
|
|
|
|
err = tgbotapi.SetLogger(logger)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2023-08-02 20:11:58 +03:00
|
|
|
|
bot.GetUpdates()
|
2023-02-22 16:23:38 +03:00
|
|
|
|
|
|
|
|
|
log.Printf("Authorized on account %s", bot.TG.Self.UserName)
|
2023-08-05 12:40:24 +03:00
|
|
|
|
bot.Debug = log.New(io.MultiWriter(os.Stderr, files.DebugFile), "", log.LstdFlags)
|
2023-08-02 20:11:58 +03:00
|
|
|
|
|
|
|
|
|
return &bot, nil
|
2023-02-22 16:23:38 +03:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-02 20:11:58 +03:00
|
|
|
|
func (bot *Bot) GetUpdates() {
|
2023-02-22 16:23:38 +03:00
|
|
|
|
u := tgbotapi.NewUpdate(0)
|
|
|
|
|
u.Timeout = 60
|
|
|
|
|
|
|
|
|
|
updates := bot.TG.GetUpdatesChan(u)
|
2023-08-02 20:11:58 +03:00
|
|
|
|
bot.Updates = &updates
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Получение данных о пользователе из БД и создание нового при необходимости
|
|
|
|
|
func InitUser(db *xorm.Engine, user *tgbotapi.User) (*database.TgUser, error) {
|
|
|
|
|
id := user.ID
|
|
|
|
|
name := user.FirstName + " " + user.LastName
|
|
|
|
|
|
|
|
|
|
var users []database.TgUser
|
|
|
|
|
err := db.Find(&users, &database.TgUser{TgId: id})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var tg_user database.TgUser
|
|
|
|
|
if len(users) == 0 {
|
|
|
|
|
l9id, err := database.GenerateID(db)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
user := database.User{
|
|
|
|
|
L9Id: l9id,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tg_user = database.TgUser{
|
|
|
|
|
L9Id: l9id,
|
|
|
|
|
Name: name,
|
|
|
|
|
TgId: id,
|
2023-08-03 10:27:36 +03:00
|
|
|
|
PosTag: database.NotStarted,
|
2023-08-02 20:11:58 +03:00
|
|
|
|
}
|
|
|
|
|
_, err = db.Insert(user, tg_user)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
tg_user = users[0]
|
|
|
|
|
}
|
|
|
|
|
return &tg_user, nil
|
2023-02-22 16:23:38 +03:00
|
|
|
|
}
|
2023-08-02 21:22:36 +03:00
|
|
|
|
|
2023-08-06 11:26:48 +03:00
|
|
|
|
func (bot *Bot) HandleUpdate(update tgbotapi.Update, now ...time.Time) (tgbotapi.Message, error) {
|
2023-08-03 14:49:51 +03:00
|
|
|
|
nilMsg := tgbotapi.Message{}
|
2023-08-02 21:22:36 +03:00
|
|
|
|
if update.Message != nil {
|
|
|
|
|
msg := update.Message
|
|
|
|
|
user, err := InitUser(bot.DB, msg.From)
|
|
|
|
|
if err != nil {
|
2023-08-03 14:49:51 +03:00
|
|
|
|
return nilMsg, err
|
2023-08-02 21:22:36 +03:00
|
|
|
|
}
|
|
|
|
|
bot.Debug.Printf("Message [%d] <%s> %s", user.L9Id, user.Name, msg.Text)
|
2023-08-30 08:42:27 +03:00
|
|
|
|
if strings.Contains(msg.Text, "/help") {
|
|
|
|
|
msg := tgbotapi.NewMessage(user.TgId, bot.HelpTxt)
|
|
|
|
|
return bot.TG.Send(msg)
|
|
|
|
|
}
|
2023-08-03 12:13:09 +03:00
|
|
|
|
switch user.PosTag {
|
|
|
|
|
case database.NotStarted:
|
2023-08-03 10:27:36 +03:00
|
|
|
|
err = bot.Start(user)
|
2023-08-03 12:13:09 +03:00
|
|
|
|
case database.Ready:
|
2023-08-06 12:40:23 +03:00
|
|
|
|
if len(now) == 0 {
|
2023-08-07 15:20:39 +03:00
|
|
|
|
now = append(now, msg.Time())
|
2023-08-06 12:40:23 +03:00
|
|
|
|
}
|
2023-08-07 21:18:44 +03:00
|
|
|
|
if msg.Text == "Моё расписание" {
|
|
|
|
|
return bot.GetPersonal(now[0], user)
|
2023-08-11 21:20:09 +03:00
|
|
|
|
} else if msg.Text == "Настройки" {
|
|
|
|
|
return bot.GetOptions(user)
|
2023-08-30 08:42:27 +03:00
|
|
|
|
} else if strings.Contains(msg.Text, "/keyboard") {
|
|
|
|
|
options := database.ShedulesInUser{
|
|
|
|
|
L9Id: user.L9Id,
|
|
|
|
|
}
|
|
|
|
|
if _, err := bot.DB.Get(&options); err != nil {
|
|
|
|
|
return nilMsg, err
|
|
|
|
|
}
|
|
|
|
|
msg := tgbotapi.NewMessage(user.TgId, "Клавиатура выдана")
|
|
|
|
|
msg.ReplyMarkup = GeneralKeyboard(options.UID != 0)
|
|
|
|
|
return bot.TG.Send(msg)
|
|
|
|
|
} else if strings.Contains(msg.Text, "/scream") && user.TgId == bot.TestUser {
|
|
|
|
|
var users []database.TgUser
|
|
|
|
|
if err := bot.DB.Where("tgid > 0").Find(&users); err != nil {
|
|
|
|
|
return nilMsg, err
|
|
|
|
|
}
|
|
|
|
|
msg := tgbotapi.NewMessage(
|
|
|
|
|
0,
|
|
|
|
|
strings.TrimPrefix(msg.Text, "/scream"),
|
|
|
|
|
)
|
|
|
|
|
for _, u := range users {
|
|
|
|
|
msg.ChatID = u.TgId
|
|
|
|
|
if _, err := bot.TG.Send(msg); err != nil {
|
|
|
|
|
if !strings.Contains(err.Error(), "blocked by user") {
|
|
|
|
|
bot.Debug.Println(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
msg.ChatID = bot.TestUser
|
|
|
|
|
msg.Text = "Сообщения отправлены"
|
|
|
|
|
return bot.TG.Send(msg)
|
2023-08-07 21:18:44 +03:00
|
|
|
|
}
|
|
|
|
|
return bot.Find(now[0], user, msg.Text)
|
|
|
|
|
case database.Add:
|
2023-08-06 12:40:23 +03:00
|
|
|
|
return bot.Find(now[0], user, msg.Text)
|
2023-08-12 11:52:51 +03:00
|
|
|
|
case database.Set:
|
|
|
|
|
return bot.SetFirstTime(msg, user)
|
2023-08-12 12:53:13 +03:00
|
|
|
|
case database.Delete:
|
|
|
|
|
return bot.DeleteGroup(user, msg.Text)
|
|
|
|
|
|
2023-08-03 12:39:59 +03:00
|
|
|
|
default:
|
2023-08-06 11:26:48 +03:00
|
|
|
|
return bot.Etc(user)
|
2023-08-03 12:13:09 +03:00
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
2023-08-03 14:49:51 +03:00
|
|
|
|
return nilMsg, err
|
2023-08-03 10:27:36 +03:00
|
|
|
|
}
|
2023-08-02 21:22:36 +03:00
|
|
|
|
}
|
2023-08-03 12:39:59 +03:00
|
|
|
|
if update.CallbackQuery != nil {
|
|
|
|
|
query := update.CallbackQuery
|
|
|
|
|
user, err := InitUser(bot.DB, query.From)
|
|
|
|
|
if err != nil {
|
2023-08-03 14:49:51 +03:00
|
|
|
|
return nilMsg, err
|
2023-08-03 12:39:59 +03:00
|
|
|
|
}
|
|
|
|
|
bot.Debug.Printf("Callback [%d] <%s> %s", user.L9Id, user.Name, query.Data)
|
2023-08-03 15:57:27 +03:00
|
|
|
|
if query.Data == "cancel" {
|
|
|
|
|
return nilMsg, bot.Cancel(user, query)
|
|
|
|
|
}
|
2023-08-13 14:26:04 +03:00
|
|
|
|
if user.PosTag == database.NotStarted {
|
2023-08-03 13:00:42 +03:00
|
|
|
|
err = bot.Start(user)
|
2023-08-13 14:26:04 +03:00
|
|
|
|
} else if user.PosTag == database.Ready || user.PosTag == database.Add {
|
2023-08-11 21:20:09 +03:00
|
|
|
|
if strings.Contains(query.Data, "sh") {
|
2023-08-06 11:26:48 +03:00
|
|
|
|
err = bot.HandleSummary(user, query, now...)
|
2023-08-11 21:20:09 +03:00
|
|
|
|
} else if strings.Contains(query.Data, "opt") {
|
|
|
|
|
err = bot.HandleOptions(user, query)
|
|
|
|
|
} else {
|
|
|
|
|
err = bot.GetShedule(user, query, now...)
|
2023-08-03 14:49:51 +03:00
|
|
|
|
}
|
2023-08-13 14:26:04 +03:00
|
|
|
|
} else {
|
2023-08-06 11:26:48 +03:00
|
|
|
|
return bot.Etc(user)
|
2023-08-03 13:00:42 +03:00
|
|
|
|
}
|
2023-08-13 14:26:04 +03:00
|
|
|
|
|
2023-08-03 13:00:42 +03:00
|
|
|
|
if err != nil {
|
2023-08-03 14:49:51 +03:00
|
|
|
|
return nilMsg, err
|
2023-08-03 13:00:42 +03:00
|
|
|
|
}
|
2023-08-13 15:13:58 +03:00
|
|
|
|
/*if query.ID != "" {
|
2023-08-06 11:26:48 +03:00
|
|
|
|
callback := tgbotapi.NewCallback(query.ID, query.Data)
|
|
|
|
|
_, err = bot.TG.Request(callback)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nilMsg, err
|
|
|
|
|
}
|
2023-08-13 15:13:58 +03:00
|
|
|
|
}*/
|
2023-08-03 12:39:59 +03:00
|
|
|
|
}
|
2023-08-03 14:49:51 +03:00
|
|
|
|
return nilMsg, nil
|
2023-08-02 21:22:36 +03:00
|
|
|
|
}
|
2023-08-12 11:52:51 +03:00
|
|
|
|
|
2023-08-12 12:53:13 +03:00
|
|
|
|
func (bot *Bot) DeleteGroup(user *database.TgUser, text string) (tgbotapi.Message, error) {
|
|
|
|
|
nilMsg := tgbotapi.Message{}
|
|
|
|
|
user.PosTag = database.Ready
|
|
|
|
|
if _, err := bot.DB.ID(user.L9Id).Update(user); err != nil {
|
|
|
|
|
return nilMsg, err
|
|
|
|
|
}
|
|
|
|
|
var msg tgbotapi.MessageConfig
|
|
|
|
|
if strings.ToLower(text) == "да" {
|
|
|
|
|
userInfo := database.ShedulesInUser{
|
|
|
|
|
L9Id: user.L9Id,
|
|
|
|
|
}
|
|
|
|
|
if _, err := bot.DB.Delete(&userInfo); err != nil {
|
|
|
|
|
return nilMsg, err
|
|
|
|
|
}
|
2023-08-30 08:42:27 +03:00
|
|
|
|
files := database.File{
|
|
|
|
|
TgId: user.L9Id,
|
|
|
|
|
IsPersonal: true,
|
|
|
|
|
}
|
|
|
|
|
if _, err := bot.DB.UseBool("IsPersonal").Delete(&files); err != nil {
|
|
|
|
|
return nilMsg, err
|
|
|
|
|
}
|
2023-08-12 12:53:13 +03:00
|
|
|
|
msg = tgbotapi.NewMessage(user.TgId, "Группа отключена")
|
|
|
|
|
msg.ReplyMarkup = GeneralKeyboard(false)
|
|
|
|
|
} else {
|
|
|
|
|
msg = tgbotapi.NewMessage(user.TgId, "Действие отменено")
|
|
|
|
|
}
|
|
|
|
|
return bot.TG.Send(msg)
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-12 11:52:51 +03:00
|
|
|
|
func (bot *Bot) SetFirstTime(msg *tgbotapi.Message, user *database.TgUser) (tgbotapi.Message, error) {
|
|
|
|
|
nilMsg := tgbotapi.Message{}
|
|
|
|
|
t, err := strconv.Atoi(msg.Text)
|
|
|
|
|
if err != nil {
|
|
|
|
|
msg := tgbotapi.NewMessage(
|
|
|
|
|
user.TgId,
|
|
|
|
|
"Ой, время соообщения о начале занятий введено как-то неверно ):",
|
|
|
|
|
)
|
|
|
|
|
return bot.TG.Send(msg)
|
|
|
|
|
}
|
|
|
|
|
userInfo := database.ShedulesInUser{
|
|
|
|
|
L9Id: user.L9Id,
|
|
|
|
|
}
|
|
|
|
|
if _, err := bot.DB.Get(&userInfo); err != nil {
|
|
|
|
|
return nilMsg, err
|
|
|
|
|
}
|
|
|
|
|
if t <= 10 {
|
|
|
|
|
msg := tgbotapi.NewMessage(
|
|
|
|
|
user.TgId,
|
|
|
|
|
"Ой, установлено слишком малое время. Попробуй ввести большее время",
|
|
|
|
|
)
|
|
|
|
|
return bot.TG.Send(msg)
|
|
|
|
|
} else if t > 240 {
|
|
|
|
|
msg := tgbotapi.NewMessage(
|
|
|
|
|
user.TgId,
|
|
|
|
|
"Ой, установлено слишком большое время. Попробуй ввести меньшее время",
|
|
|
|
|
)
|
|
|
|
|
return bot.TG.Send(msg)
|
|
|
|
|
}
|
|
|
|
|
userInfo.FirstTime = t / 5 * 5
|
|
|
|
|
if _, err := bot.DB.ID(userInfo.UID).Update(userInfo); err != nil {
|
|
|
|
|
return nilMsg, err
|
|
|
|
|
}
|
|
|
|
|
user.PosTag = database.Ready
|
|
|
|
|
if _, err := bot.DB.ID(user.L9Id).Update(user); err != nil {
|
|
|
|
|
return nilMsg, err
|
|
|
|
|
}
|
|
|
|
|
return bot.GetOptions(user)
|
|
|
|
|
}
|