Исправления нюансов, выявленных в ходе тестирования

main v0.5
losyash 2023-08-30 09:42:27 +04:00
parent 19d4e2c27d
commit a9aea7b3d9
11 changed files with 132 additions and 32 deletions

5
.gitignore vendored
View File

@ -9,4 +9,7 @@ shedules
*.env
.vscode
*.html
*.pdf
*.pdf
help.txt
main
wkhtmltoimage

25
main.go
View File

@ -1,6 +1,7 @@
package main
import (
"io"
"log"
"os"
"strconv"
@ -13,13 +14,18 @@ import (
)
func main() {
ssau_parser.HeadURL = "http://127.0.0.1:5000/prod"
ssau_parser.HeadURL = "https://ssau.ru"
if err := tg.CheckEnv(); err != nil {
log.Fatal(err)
}
logs := database.OpenLogs()
defer logs.CloseAll()
//bot := new(tg.Bot)
log.SetOutput(io.MultiWriter(os.Stderr, logs.ErrorFile))
help, err := os.ReadFile("help.txt")
if err != nil {
log.Fatal(err)
}
// bot.Debug = log.New(io.MultiWriter(os.Stderr, database.CreateLog("messages")), "", log.LstdFlags)
bot, err := tg.InitBot(
logs,
@ -37,7 +43,12 @@ func main() {
if err != nil {
log.Fatal(err)
}
bot.TestUser, err = strconv.ParseInt(os.Getenv("TELEGRAM_TEST_USER"), 0, 64)
if err != nil {
log.Fatal(err)
}
bot.WkPath = os.Getenv("WK_PATH")
bot.HelpTxt = string(help)
//now, _ := time.Parse("2006-01-02 15:04 -07", "2023-02-07 07:00 +04")
now := time.Now()
next := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), (now.Minute() + 1), 0, 0, now.Location())
@ -45,21 +56,20 @@ func main() {
log.Println("Waiting...")
time.Sleep(next.Sub(now))
mailTicker := time.NewTicker(1 * time.Minute)
sheduleTicker := time.NewTicker(1 * time.Minute)
sheduleTicker := time.NewTicker(30 * time.Minute)
log.Println("Started")
defer mailTicker.Stop()
defer sheduleTicker.Stop()
for {
select {
case update := <-*bot.Updates:
now = time.Now().Add(-6 * 30 * 24 * time.Hour)
now = time.Now()
_, err := bot.HandleUpdate(update, now)
if err != nil {
log.Println(err)
}
case <-mailTicker.C:
now = time.Now().Add(-6 * 30 * 24 * time.Hour)
//now = now.Add(5 * time.Minute)
now = time.Now()
log.Println(now)
notes, err := notify.CheckNext(bot.DB, now)
if err != nil {
@ -68,9 +78,8 @@ func main() {
notify.FirstMailing(bot, now)
notify.Mailing(bot, notes, now)
notify.ClearTemp(bot, now)
//return
case <-sheduleTicker.C:
now = time.Now().Add(-6 * 30 * 24 * time.Hour)
now = time.Now()
if now.Hour() > 8 && now.Hour() < 20 {
log.Println("check changes")
notify.CheckShedules(bot, now)

View File

@ -21,6 +21,7 @@ type DB struct {
type LogFiles struct {
DebugFile *os.File
ErrorFile *os.File
TgLogFile *os.File
DBLogFile *os.File
}
@ -28,6 +29,7 @@ type LogFiles struct {
func OpenLogs() (files LogFiles) {
return LogFiles{
DebugFile: CreateLog("messages"),
ErrorFile: CreateLog("error"),
TgLogFile: CreateLog("tg"),
DBLogFile: CreateLog("sql"),
}
@ -35,6 +37,7 @@ func OpenLogs() (files LogFiles) {
func (files *LogFiles) CloseAll() {
files.DebugFile.Close()
files.ErrorFile.Close()
files.TgLogFile.Close()
files.DBLogFile.Close()
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"log"
"strconv"
"strings"
"time"
"git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/database"
@ -85,7 +86,7 @@ func CheckNext(db *xorm.Engine, now time.Time) ([]Notify, error) {
var next_lesson database.Lesson
if _, err := db.
Where(
"groupid = ? and begin >= ?",
"groupid = ? and begin > ?",
l.GroupId, l.Begin.Format("2006-01-02 15:04:05"),
).
Asc("begin").
@ -219,9 +220,18 @@ func Mailing(bot *tg.Bot, notes []Notify, now time.Time) {
msg.ParseMode = tgbotapi.ModeHTML
m, err := bot.TG.Send(msg)
if err != nil {
log.Println(err)
// Удаление пользователя, заблокировавшего бота
if !strings.Contains(err.Error(), "blocked by user") {
bot.DB.Delete(&user)
bot.DB.Delete(&database.ShedulesInUser{L9Id: user.L9Id})
bot.DB.Delete(&database.User{L9Id: user.L9Id})
continue
} else {
log.Println(err)
}
} else {
AddTemp(m, tempTime, bot)
}
AddTemp(m, tempTime, bot)
} else {
if err = bot.GetWeekSummary(
note.Lesson.Begin,
@ -229,9 +239,10 @@ func Mailing(bot *tg.Bot, notes []Notify, now time.Time) {
database.ShedulesInUser{},
0,
true,
"На этой неделе больше ничего нет\n\nВыше расписание на следующую неделю",
"На этой неделе больше ничего нет\n\nНа фото расписание на следующую неделю",
); err != nil {
log.Println(err)
continue
}
}
ids = append(ids, user.TgId)
@ -271,7 +282,7 @@ func ClearTemp(bot *tg.Bot, now time.Time) {
var firstMailQuery = `SELECT t.tgId, l.lessonId, u.firsttime
FROM ShedulesInUser u
JOIN (SELECT lessonid, groupid, type, min(begin) as begin FROM Lesson WHERE date(begin) = date('%s') GROUP BY lessonid, groupid, type, begin) l
JOIN (SELECT lessonid, groupid, type, min(begin) as begin FROM Lesson WHERE date(begin) = date('%s') GROUP BY groupid) l
ON '%s' = DATE_SUB(l.Begin, INTERVAL u.firsttime MINUTE) AND u.sheduleid = l.groupid
JOIN TgUser t ON u.L9ID = t.L9ID
WHERE u.first = true AND (l.type != "mil" OR (l.type = "mil" AND u.military = true));`
@ -309,6 +320,7 @@ func FirstMailing(bot *tg.Bot, now time.Time) {
msg, err := bot.TG.Send(mail)
if err != nil {
log.Println(err)
continue
}
AddTemp(msg, lesson.Begin.Add(15*time.Minute), bot)
}

View File

@ -160,7 +160,7 @@ func (sh *WeekShedule) Parse(p Page, uncover bool) error {
return nil
}
var types = [4]string{"lect", "lab", "pract", "other"}
var types = []string{"lect", "lab", "pract", "other", "exam", "cons", "kurs"}
// Парсинг занятия
func ParseLesson(s *goquery.Selection, isGroup bool, sheduleId int64) []Lesson {

View File

@ -16,13 +16,14 @@ import (
)
type Bot struct {
TG *tgbotapi.BotAPI
DB *xorm.Engine
// TG_user database.TgUser
Week int
WkPath string
Debug *log.Logger
Updates *tgbotapi.UpdatesChannel
TG *tgbotapi.BotAPI
DB *xorm.Engine
TestUser int64
HelpTxt string
Week int
WkPath string
Debug *log.Logger
Updates *tgbotapi.UpdatesChannel
}
var env_keys = []string{
@ -131,6 +132,10 @@ func (bot *Bot) HandleUpdate(update tgbotapi.Update, now ...time.Time) (tgbotapi
return nilMsg, err
}
bot.Debug.Printf("Message [%d] <%s> %s", user.L9Id, user.Name, msg.Text)
if strings.Contains(msg.Text, "/help") {
msg := tgbotapi.NewMessage(user.TgId, bot.HelpTxt)
return bot.TG.Send(msg)
}
switch user.PosTag {
case database.NotStarted:
err = bot.Start(user)
@ -142,6 +147,36 @@ func (bot *Bot) HandleUpdate(update tgbotapi.Update, now ...time.Time) (tgbotapi
return bot.GetPersonal(now[0], user)
} else if msg.Text == "Настройки" {
return bot.GetOptions(user)
} 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)
}
return bot.Find(now[0], user, msg.Text)
case database.Add:
@ -210,6 +245,13 @@ func (bot *Bot) DeleteGroup(user *database.TgUser, text string) (tgbotapi.Messag
if _, err := bot.DB.Delete(&userInfo); err != nil {
return nilMsg, err
}
files := database.File{
TgId: user.L9Id,
IsPersonal: true,
}
if _, err := bot.DB.UseBool("IsPersonal").Delete(&files); err != nil {
return nilMsg, err
}
msg = tgbotapi.NewMessage(user.TgId, "Группа отключена")
msg.ReplyMarkup = GeneralKeyboard(false)
} else {

View File

@ -22,7 +22,12 @@ func (bot *Bot) Start(user *database.TgUser) error {
msg := tgbotapi.NewMessage(
user.TgId,
`Привет! У меня можно посмотреть в удобном формате <b>ближайшие пары</b>, расписание <b>по дням</b> и даже <b>по неделям</b>!
Просто напиши мне <b>номер группы</b> или <b>фамилию преподавателя</b>`)
Просто напиши мне <b>номер группы</b> или <b>фамилию преподавателя</b>
Также можно получать уведомления о своих занятиях по кнопке <b>Моё расписание</b>👇
Внимание! Бот ещё находится на стадии испытаний, поэтому могут возникать ошибки в его работе.
Рекомендуется сверять настоящее расписание и обо всех ошибках сообщать по контакам в /help`)
msg.ParseMode = tgbotapi.ModeHTML
msg.ReplyMarkup = GeneralKeyboard(false)
_, err = bot.TG.Send(msg)
@ -135,7 +140,9 @@ func (bot *Bot) Find(now time.Time, user *database.TgUser, query string) (tgbota
msg := tgbotapi.NewMessage(
user.TgId,
"Расписание успешно подключено!\n"+
"Теперь его можно открыть по кнопке <b>Моё расписание</b>👇",
"Теперь можно смотреть свои занятия по кнопке <b>Моё расписание</b>👇\n\n"+
"Также ты будешь получать уведомления о занятиях, "+
"которыми можно управлять в панели <b>Настройки</b>\n",
)
msg.ParseMode = tgbotapi.ModeHTML
msg.ReplyMarkup = GeneralKeyboard(true)
@ -234,7 +241,7 @@ func (bot *Bot) GetShedule(user *database.TgUser, query *tgbotapi.CallbackQuery,
if _, err = bot.DB.ID(user.L9Id).Update(user); err != nil {
return err
}
_, err = bot.GetPersonal(now[0], user)
_, err = bot.GetPersonal(now[0], user, *query.Message)
}
return err
}

View File

@ -19,6 +19,13 @@ func (bot *Bot) GetOptions(user *database.TgUser) (tgbotapi.Message, error) {
if _, err := bot.DB.Get(&options); err != nil {
return nilMsg, err
}
// Если кто-то хитрожопый нажал на кнопку без подключенной группы
if options.UID == 0 {
msg := tgbotapi.NewMessage(user.TgId, "У тебя пока не подключено ни одной группы\nНажми на кнопку <b>Моё расписание</b>")
msg.ParseMode = tgbotapi.ModeHTML
msg.ReplyMarkup = GeneralKeyboard(false)
return bot.TG.Send(msg)
}
markup := OptMarkup(options)
msg := tgbotapi.NewMessage(user.TgId, optStr)
msg.ReplyMarkup = markup

View File

@ -16,7 +16,7 @@ import (
func (bot *Bot) GetPersonal(now time.Time, user *database.TgUser, editMsg ...tgbotapi.Message) (tgbotapi.Message, error) {
var shedules []database.ShedulesInUser
bot.DB.ID(user.L9Id).Find(&shedules)
bot.DB.Where("l9id = ?", user.L9Id).Find(&shedules)
if len(shedules) == 0 {
user.PosTag = database.Add
@ -131,8 +131,12 @@ func (bot *Bot) GetSummary(
return bot.EditOrSend(user.TgId, str, "", markup, editMsg...)
} else {
msg := tgbotapi.NewMessage(user.TgId, "Ой! Занятий не обнаружено ):")
return bot.TG.Send(msg)
return bot.EditOrSend(
user.TgId,
"Ой! Занятий не обнаружено ):",
"",
tgbotapi.InlineKeyboardMarkup{},
editMsg...)
}
}
@ -319,7 +323,17 @@ func GroupPairs(lessons []database.Lesson) [][]database.Lesson {
return shedule
}
var Icons = map[string]string{"lect": "📗", "pract": "📕", "lab": "📘", "other": "📙", "mil": "🫡", "window": "🏝"}
var Icons = map[string]string{
"lect": "📗 Лекция ",
"pract": "📕 Практика ",
"lab": "📘 Лаба ",
"other": "📙 Прочее ",
"mil": "🫡",
"window": "🏝",
"exam": "💀 Экзамен",
"cons": "🗨 Консультация",
"kurs": "🤯 Курсовая",
}
// Конвертация занятий с текст
func PairToStr(pair []database.Lesson, db *xorm.Engine, isGroup bool) (string, error) {

View File

@ -140,6 +140,7 @@ func GenerateButtonTail(sheduleId int64, dt int, isGroup bool) string {
}
// Отправка сообщения или его редактирование, если в editMsg указано сообщение
// TODO: Обрабатывать старые сообщения, которые уже нельзя редактировать (message can't be deleted for everyone)
func (bot *Bot) EditOrSend(
id int64,
str string,
@ -229,6 +230,8 @@ func (bot *Bot) EditOrSend(
msg := tgbotapi.NewMessage(id, str)
if len(markup.InlineKeyboard) != 0 {
msg.ReplyMarkup = &markup
} else {
msg.ReplyMarkup = GeneralKeyboard(false)
}
msg.ParseMode = tgbotapi.ModeHTML
return bot.TG.Send(msg)

View File

@ -245,14 +245,14 @@ func (bot *Bot) CreateWeekImg(
}
input := fmt.Sprintf("./%s/week_%d.html", path, week-bot.Week)
output := fmt.Sprintf("./%s/week_%d.png", path, week-bot.Week)
output := fmt.Sprintf("./%s/week_%d.jpg", path, week-bot.Week)
f, _ := os.Create(input)
defer f.Close()
f.WriteString(html)
cmd := exec.CommandContext(context.Background(), bot.WkPath, []string{
"--width",
"1280",
"1600",
input,
output,
}...)
@ -339,7 +339,7 @@ const head = `<html lang="ru">
</head>
<style>
.note div,.rasp div{background-color:#f0f8ff;padding:10px;text-align:center;border-radius:10px}.note,th.head,th.time{font-family:monospace}.subj div #text,.subj p{display:none}html{font-size:1.5rem}body{background:#dc14bd}table{table-layout:fixed;width:100%;border-spacing:5px 5px}.note div{margin:10px 0}.head p,.subj p,hr{margin:0}.rasp div{transition:.3s}th.head{background-color:#0ff;border-radius:10px;padding:5px;font-size:1.05rem}th.subj,th.time{background-color:#f0f8ff;padding:10px;border-radius:10px}th.time{font-size:1.1rem}.subj h2,.subj p{font-size:.85rem}th.subj:not(.lab,.lect,.pract,.other){background-color:#a9a9a9}.subj div{border-radius:10px;padding:5px}.subj p{font-family:monospace;color:#f0f8ff}.subj h2,.subj h3,.subj h5{font-family:monospace;text-align:left;margin:5px}.subj h3{font-size:.65rem}.subj h5{font-size:.7rem;font-weight:400}.lect div{background-color:#7fff00}.pract div{background-color:#dc143c}.lab div{background-color:#8a2be2}.other div{background-color:#ff8c00}.mil div{background-color:#ff8c00}.window div{background-color:blue}
.subj div,th.head,th.subj,th.time{border-radius:10px}.note,.subj p,th.head,th.time{font-family:monospace}.note div,.rasp div{background-color:#f0f8ff;padding:10px;text-align:center;border-radius:10px}.subj div #text,.subj p{display:none}html{font-size:1.5rem}body{background:#dc14bd}table{table-layout:fixed;width:100%;border-spacing:5px 5px}.note div{margin:10px 0}.head p,.subj p,hr{margin:0}.rasp div{transition:.3s}th.head{background-color:#0ff;padding:5px;font-size:1.05rem}th.subj,th.time{background-color:#f0f8ff;padding:10px}th.time{font-size:1.1rem}.subj h2,.subj p{font-size:.85rem}th.subj:not(.lab,.lect,.pract,.other){background-color:#a9a9a9}.subj div{padding:5px}.subj p{color:#f0f8ff}.subj h2,.subj h3,.subj h5{font-family:monospace;text-align:left;margin:5px}.subj h3{font-size:.65rem}.subj h5{font-size:.7rem;font-weight:400}.lect div{background-color:#7fff00}.pract div{background-color:#dc143c}.lab div{background-color:#8a2be2}.mil div,.other div{background-color:#ff8c00}.window div{background-color:#00f}.cons div{background-color:green}.exam div{background-color:purple}.kurs div{background-color:orange}
</style>
<body>