This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues or pull requests.
l9_stud_bot/modules/tg/bot.go

260 lines
6.3 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 tg
import (
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
"time"
"git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/database"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/joho/godotenv"
"xorm.io/xorm"
)
type Bot struct {
TG *tgbotapi.BotAPI
DB *xorm.Engine
// TG_user database.TgUser
Week int
WkPath string
Debug *log.Logger
Updates *tgbotapi.UpdatesChannel
}
var env_keys = []string{
"TELEGRAM_APITOKEN",
"TELEGRAM_TEST_USER",
"WK_PATH",
"MYSQL_USER",
"MYSQL_PASS",
"MYSQL_DB",
"START_WEEK",
}
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 и БД
func InitBot(files database.LogFiles, db database.DB, token string) (*Bot, error) {
var bot Bot
engine, err := database.Connect(db, files.DBLogFile)
if err != nil {
return nil, err
}
//defer engine.Close()
bot.DB = engine
bot.TG, err = tgbotapi.NewBotAPI(token)
if err != nil {
return nil, err
}
bot.TG.Debug = true
//logger := log.New(io.MultiWriter(os.Stdout, database.CreateLog("tg")), "", log.LstdFlags)
logger := log.New(files.TgLogFile, "", log.LstdFlags)
err = tgbotapi.SetLogger(logger)
if err != nil {
return nil, err
}
bot.GetUpdates()
log.Printf("Authorized on account %s", bot.TG.Self.UserName)
bot.Debug = log.New(io.MultiWriter(os.Stderr, files.DebugFile), "", log.LstdFlags)
return &bot, nil
}
func (bot *Bot) GetUpdates() {
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates := bot.TG.GetUpdatesChan(u)
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,
PosTag: database.NotStarted,
}
_, err = db.Insert(user, tg_user)
if err != nil {
return nil, err
}
} else {
tg_user = users[0]
}
return &tg_user, nil
}
func (bot *Bot) HandleUpdate(update tgbotapi.Update, now ...time.Time) (tgbotapi.Message, error) {
nilMsg := tgbotapi.Message{}
if update.Message != nil {
msg := update.Message
user, err := InitUser(bot.DB, msg.From)
if err != nil {
return nilMsg, err
}
bot.Debug.Printf("Message [%d] <%s> %s", user.L9Id, user.Name, msg.Text)
switch user.PosTag {
case database.NotStarted:
err = bot.Start(user)
case database.Ready:
if len(now) == 0 {
now = append(now, msg.Time())
}
if msg.Text == "Моё расписание" {
return bot.GetPersonal(now[0], user)
} else if msg.Text == "Настройки" {
return bot.GetOptions(user)
}
return bot.Find(now[0], user, msg.Text)
case database.Add:
return bot.Find(now[0], user, msg.Text)
case database.Set:
return bot.SetFirstTime(msg, user)
case database.Delete:
return bot.DeleteGroup(user, msg.Text)
default:
return bot.Etc(user)
}
if err != nil {
return nilMsg, err
}
}
if update.CallbackQuery != nil {
query := update.CallbackQuery
user, err := InitUser(bot.DB, query.From)
if err != nil {
return nilMsg, err
}
bot.Debug.Printf("Callback [%d] <%s> %s", user.L9Id, user.Name, query.Data)
if query.Data == "cancel" {
return nilMsg, bot.Cancel(user, query)
}
switch user.PosTag {
case database.NotStarted:
err = bot.Start(user)
case database.Ready:
if strings.Contains(query.Data, "sh") {
err = bot.HandleSummary(user, query, now...)
} else if strings.Contains(query.Data, "opt") {
err = bot.HandleOptions(user, query)
} else {
err = bot.GetShedule(user, query, now...)
}
default:
return bot.Etc(user)
}
if err != nil {
return nilMsg, err
}
if query.ID != "" {
callback := tgbotapi.NewCallback(query.ID, query.Data)
_, err = bot.TG.Request(callback)
if err != nil {
return nilMsg, err
}
}
}
return nilMsg, nil
}
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
}
msg = tgbotapi.NewMessage(user.TgId, "Группа отключена")
msg.ReplyMarkup = GeneralKeyboard(false)
} else {
msg = tgbotapi.NewMessage(user.TgId, "Действие отменено")
}
return bot.TG.Send(msg)
}
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)
}