2023-08-10 21:59:58 +03:00
|
|
|
|
package notify
|
|
|
|
|
|
|
|
|
|
import (
|
2023-08-12 10:28:35 +03:00
|
|
|
|
"fmt"
|
2023-08-10 21:59:58 +03:00
|
|
|
|
"log"
|
2023-08-12 10:28:35 +03:00
|
|
|
|
"strconv"
|
2023-08-30 08:42:27 +03:00
|
|
|
|
"strings"
|
2023-08-10 21:59:58 +03:00
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/database"
|
2023-08-11 17:46:52 +03:00
|
|
|
|
"git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/ssau_parser"
|
2023-08-10 21:59:58 +03:00
|
|
|
|
"git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/tg"
|
|
|
|
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
|
|
|
|
"golang.org/x/exp/slices"
|
|
|
|
|
"xorm.io/xorm"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Next struct {
|
|
|
|
|
Lesson []database.Lesson
|
|
|
|
|
Day []database.Lesson
|
|
|
|
|
Week []database.Lesson
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type NotifyType string
|
|
|
|
|
|
|
|
|
|
const (
|
2023-08-11 17:46:52 +03:00
|
|
|
|
NextLesson NotifyType = "nextnote"
|
|
|
|
|
NextDay NotifyType = "nextday"
|
|
|
|
|
NextWeek NotifyType = "nextweek"
|
2023-08-10 21:59:58 +03:00
|
|
|
|
Changes NotifyType = "changes"
|
|
|
|
|
Military NotifyType = "mil"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Notify struct {
|
|
|
|
|
NotifyType
|
|
|
|
|
IsGroup bool
|
|
|
|
|
SheduleId int64
|
|
|
|
|
Lesson database.Lesson
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Поиск следующей пары, дня, недели
|
|
|
|
|
func CheckNext(db *xorm.Engine, now time.Time) ([]Notify, error) {
|
|
|
|
|
now = now.Truncate(time.Minute)
|
|
|
|
|
var completed []database.Lesson
|
|
|
|
|
if err := db.
|
|
|
|
|
Find(&completed, &database.Lesson{End: now}); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
var nums []int
|
|
|
|
|
for i := range completed {
|
|
|
|
|
new_num := completed[i].NumInShedule + 1
|
|
|
|
|
if !slices.Contains(nums, new_num) {
|
|
|
|
|
nums = append(nums, new_num)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var next []database.Lesson
|
|
|
|
|
if err := db.
|
|
|
|
|
Where("date(`begin`) = ?", now.Format("2006-01-02")).
|
|
|
|
|
In("numinshedule", nums).
|
|
|
|
|
Find(&next); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
var notify []Notify
|
|
|
|
|
for _, n := range next {
|
|
|
|
|
notify = append(notify, Notify{
|
|
|
|
|
NotifyType: NextLesson,
|
|
|
|
|
IsGroup: true,
|
|
|
|
|
SheduleId: n.GroupId,
|
|
|
|
|
Lesson: n,
|
|
|
|
|
})
|
|
|
|
|
if n.TeacherId != 0 {
|
|
|
|
|
notify = append(notify, Notify{
|
|
|
|
|
NotifyType: NextLesson,
|
|
|
|
|
IsGroup: false,
|
|
|
|
|
SheduleId: n.TeacherId,
|
|
|
|
|
Lesson: n,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-11 17:46:52 +03:00
|
|
|
|
// Отсеиваем последние пары дня
|
|
|
|
|
last := ssau_parser.Diff(completed, next)
|
|
|
|
|
|
|
|
|
|
for _, l := range last {
|
|
|
|
|
var next_lesson database.Lesson
|
|
|
|
|
if _, err := db.
|
|
|
|
|
Where(
|
2023-08-30 08:42:27 +03:00
|
|
|
|
"groupid = ? and begin > ?",
|
2023-08-12 10:28:35 +03:00
|
|
|
|
l.GroupId, l.Begin.Format("2006-01-02 15:04:05"),
|
2023-08-11 17:46:52 +03:00
|
|
|
|
).
|
|
|
|
|
Asc("begin").
|
|
|
|
|
Get(&next_lesson); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
// Разделяем, какие пары на этой неделе, какие на следующей
|
|
|
|
|
|
|
|
|
|
_, nl_week := next_lesson.Begin.ISOWeek()
|
|
|
|
|
_, now_week := now.ISOWeek()
|
|
|
|
|
note := Notify{
|
|
|
|
|
IsGroup: true,
|
|
|
|
|
SheduleId: next_lesson.GroupId,
|
|
|
|
|
Lesson: next_lesson,
|
|
|
|
|
}
|
|
|
|
|
if nl_week == now_week {
|
|
|
|
|
note.NotifyType = NextDay
|
|
|
|
|
} else {
|
|
|
|
|
note.NotifyType = NextWeek
|
|
|
|
|
}
|
|
|
|
|
if !slices.Contains(notify, note) {
|
|
|
|
|
notify = append(notify, note)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2023-08-10 21:59:58 +03:00
|
|
|
|
return notify, nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-11 17:46:52 +03:00
|
|
|
|
// Текст уведомления о следующей паре
|
2023-08-10 21:59:58 +03:00
|
|
|
|
func StrNext(db *xorm.Engine, note Notify) (string, error) {
|
2023-08-11 16:17:22 +03:00
|
|
|
|
// TODO: перескакивать окна
|
2023-08-10 21:59:58 +03:00
|
|
|
|
// Подкачиваем группы и подгруппы
|
|
|
|
|
var pair []database.Lesson
|
|
|
|
|
if !note.IsGroup {
|
|
|
|
|
query := database.Lesson{
|
|
|
|
|
Begin: note.Lesson.Begin,
|
|
|
|
|
TeacherId: note.SheduleId,
|
|
|
|
|
}
|
|
|
|
|
if err := db.Find(&pair, query); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
pair = append(pair, note.Lesson)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str := "Следующая пара:\n\n"
|
|
|
|
|
strPair, err := tg.PairToStr(pair, db, note.IsGroup)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
str += strPair
|
|
|
|
|
return str, nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-11 17:46:52 +03:00
|
|
|
|
// Текст уведомления о следующем дне
|
|
|
|
|
func StrNextDay(bot *tg.Bot, note Notify) (string, error) {
|
|
|
|
|
begin := note.Lesson.Begin
|
|
|
|
|
day := time.Date(begin.Year(), begin.Month(), begin.Day(), 0, 0, 0, 0, begin.Location())
|
|
|
|
|
shedules := []database.ShedulesInUser{
|
|
|
|
|
{
|
|
|
|
|
IsGroup: true,
|
|
|
|
|
SheduleId: note.Lesson.GroupId,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
lessons, err := bot.GetLessons(shedules, day)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
if len(lessons) != 0 {
|
|
|
|
|
pairs := tg.GroupPairs(lessons)
|
|
|
|
|
dayStr, err := bot.StrDayShedule(pairs, shedules[0].IsGroup)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
str := "Сегодня больше ничего нет\n"
|
|
|
|
|
str += "Следующие занятия в " + tg.DayStr(day) + ":\n\n" + dayStr
|
|
|
|
|
return str, nil
|
|
|
|
|
}
|
|
|
|
|
return "", nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Рассылка всех уведомлений
|
2023-08-11 16:17:22 +03:00
|
|
|
|
func Mailing(bot *tg.Bot, notes []Notify, now time.Time) {
|
2023-08-10 21:59:58 +03:00
|
|
|
|
var ids []int64
|
|
|
|
|
for _, note := range notes {
|
2023-08-11 17:46:52 +03:00
|
|
|
|
|
|
|
|
|
var users []database.TgUser
|
|
|
|
|
query := database.ShedulesInUser{
|
|
|
|
|
IsGroup: note.IsGroup,
|
|
|
|
|
SheduleId: note.SheduleId,
|
|
|
|
|
}
|
|
|
|
|
var txt string
|
|
|
|
|
var err error
|
2023-08-11 17:52:39 +03:00
|
|
|
|
var tempTime time.Time
|
2023-08-11 17:46:52 +03:00
|
|
|
|
switch note.NotifyType {
|
|
|
|
|
case NextLesson:
|
|
|
|
|
query.NextNote = true
|
|
|
|
|
txt, err = StrNext(bot.DB, note)
|
2023-08-11 17:52:39 +03:00
|
|
|
|
tempTime = note.Lesson.Begin.Add(15 * time.Minute)
|
2023-08-11 17:46:52 +03:00
|
|
|
|
case NextDay:
|
|
|
|
|
query.NextDay = true
|
|
|
|
|
txt, err = StrNextDay(bot, note)
|
2023-08-11 19:39:46 +03:00
|
|
|
|
// TODO: установить время удаления на момент сообщения о начале пар
|
2023-08-11 17:52:39 +03:00
|
|
|
|
tempTime = note.Lesson.Begin.Add(-60 * time.Minute)
|
2023-08-11 17:46:52 +03:00
|
|
|
|
case NextWeek:
|
|
|
|
|
query.NextWeek = true
|
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
2023-08-12 10:28:35 +03:00
|
|
|
|
// TODO: проработать разные подгруппы
|
|
|
|
|
/*var condition string
|
2023-08-11 19:39:46 +03:00
|
|
|
|
if note.Lesson.SubGroup == 0 {
|
|
|
|
|
condition = "subgroup in (?, 1, 2)"
|
|
|
|
|
} else {
|
|
|
|
|
condition = "subgroup in (0, ?)"
|
2023-08-12 10:28:35 +03:00
|
|
|
|
}*/
|
2023-08-11 17:46:52 +03:00
|
|
|
|
if err := bot.DB.
|
|
|
|
|
UseBool(string(note.NotifyType)).
|
|
|
|
|
Table("ShedulesInUser").
|
|
|
|
|
Cols("tgid").
|
2023-08-14 05:48:03 +03:00
|
|
|
|
Join("INNER", "TgUser", "TgUser.l9id = ShedulesInUser.l9id").
|
2023-08-12 10:28:35 +03:00
|
|
|
|
// Where(condition, note.Lesson.SubGroup).
|
2023-08-11 17:46:52 +03:00
|
|
|
|
Find(&users, &query); err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
for _, user := range users {
|
|
|
|
|
if !slices.Contains(ids, user.TgId) {
|
2023-08-11 19:39:46 +03:00
|
|
|
|
if note.NotifyType != NextWeek {
|
|
|
|
|
msg := tgbotapi.NewMessage(user.TgId, txt)
|
|
|
|
|
msg.ParseMode = tgbotapi.ModeHTML
|
|
|
|
|
m, err := bot.TG.Send(msg)
|
|
|
|
|
if err != nil {
|
2023-08-30 08:42:27 +03:00
|
|
|
|
// Удаление пользователя, заблокировавшего бота
|
|
|
|
|
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)
|
2023-08-11 19:39:46 +03:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if err = bot.GetWeekSummary(
|
|
|
|
|
note.Lesson.Begin,
|
|
|
|
|
&user,
|
|
|
|
|
database.ShedulesInUser{},
|
|
|
|
|
0,
|
|
|
|
|
true,
|
2023-08-30 08:42:27 +03:00
|
|
|
|
"На этой неделе больше ничего нет\n\nНа фото расписание на следующую неделю",
|
2023-08-11 19:39:46 +03:00
|
|
|
|
); err != nil {
|
|
|
|
|
log.Println(err)
|
2023-08-30 08:42:27 +03:00
|
|
|
|
continue
|
2023-08-11 19:39:46 +03:00
|
|
|
|
}
|
2023-08-10 21:59:58 +03:00
|
|
|
|
}
|
2023-08-11 17:46:52 +03:00
|
|
|
|
ids = append(ids, user.TgId)
|
2023-08-10 21:59:58 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-11 16:17:22 +03:00
|
|
|
|
|
2023-08-12 10:28:35 +03:00
|
|
|
|
// Добавить сообщение в список временных
|
|
|
|
|
func AddTemp(m tgbotapi.Message, tempTime time.Time, bot *tg.Bot) {
|
|
|
|
|
temp := database.TempMsg{
|
|
|
|
|
TgId: m.Chat.ID,
|
|
|
|
|
MessageId: m.MessageID,
|
|
|
|
|
Destroy: tempTime,
|
|
|
|
|
}
|
|
|
|
|
if _, err := bot.DB.InsertOne(temp); err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-11 16:17:22 +03:00
|
|
|
|
// Удаление временных сообщений
|
|
|
|
|
func ClearTemp(bot *tg.Bot, now time.Time) {
|
|
|
|
|
var temp []database.TempMsg
|
2023-08-12 10:28:35 +03:00
|
|
|
|
if err := bot.DB.Where("destroy <= ?", now.Format("2006-01-02 15:04:05")).Find(&temp); err != nil {
|
2023-08-11 16:17:22 +03:00
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
for _, msg := range temp {
|
|
|
|
|
del := tgbotapi.NewDeleteMessage(msg.TgId, msg.MessageId)
|
|
|
|
|
if _, err := bot.TG.Request(del); err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
if _, err := bot.DB.Delete(&msg); err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-12 10:28:35 +03:00
|
|
|
|
|
|
|
|
|
var firstMailQuery = `SELECT t.tgId, l.lessonId, u.firsttime
|
2023-08-13 15:13:58 +03:00
|
|
|
|
FROM ShedulesInUser u
|
2023-08-30 08:42:27 +03:00
|
|
|
|
JOIN (SELECT lessonid, groupid, type, min(begin) as begin FROM Lesson WHERE date(begin) = date('%s') GROUP BY groupid) l
|
2023-08-14 05:48:03 +03:00
|
|
|
|
ON '%s' = DATE_SUB(l.Begin, INTERVAL u.firsttime MINUTE) AND u.sheduleid = l.groupid
|
|
|
|
|
JOIN TgUser t ON u.L9ID = t.L9ID
|
2023-08-12 12:32:34 +03:00
|
|
|
|
WHERE u.first = true AND (l.type != "mil" OR (l.type = "mil" AND u.military = true));`
|
2023-08-12 10:28:35 +03:00
|
|
|
|
|
|
|
|
|
// Рассылка сообщений о начале занятий
|
|
|
|
|
func FirstMailing(bot *tg.Bot, now time.Time) {
|
|
|
|
|
now = now.Truncate(time.Minute)
|
|
|
|
|
nowStr := now.Format("2006-01-02 15:04:05")
|
|
|
|
|
res, err := bot.DB.Query(fmt.Sprintf(firstMailQuery, nowStr, nowStr))
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
for _, r := range res {
|
|
|
|
|
lid, _ := strconv.ParseInt(string(r["lessonId"]), 0, 64)
|
|
|
|
|
lesson := database.Lesson{LessonId: lid}
|
|
|
|
|
if _, err := bot.DB.Get(&lesson); err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
var str string
|
|
|
|
|
if now.Hour() > 16 {
|
|
|
|
|
str = "Добрый вечер 🌆\n"
|
|
|
|
|
} else if now.Hour() > 11 {
|
|
|
|
|
str = "Добрый день 🌞\n"
|
|
|
|
|
} else {
|
|
|
|
|
str = "Доброе утро 🌅\n"
|
|
|
|
|
}
|
|
|
|
|
str += fmt.Sprintf("Через %s минут начнутся занятия\n\nПервая пара:\n", r["firsttime"])
|
|
|
|
|
pair, err := tg.PairToStr([]database.Lesson{lesson}, bot.DB, true)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
str += pair
|
|
|
|
|
user, _ := strconv.ParseInt(string(r["tgId"]), 0, 64)
|
|
|
|
|
mail := tgbotapi.NewMessage(user, str)
|
|
|
|
|
msg, err := bot.TG.Send(mail)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
2023-08-30 08:42:27 +03:00
|
|
|
|
continue
|
2023-08-12 10:28:35 +03:00
|
|
|
|
}
|
|
|
|
|
AddTemp(msg, lesson.Begin.Add(15*time.Minute), bot)
|
|
|
|
|
}
|
|
|
|
|
}
|