[WIP] Implement good morning message for all willing chats, update TODO.md
This commit is contained in:
3
TODO.md
3
TODO.md
@@ -25,7 +25,7 @@
|
||||
|
||||
1 [V] [V] цензор сообщений определённого типа.
|
||||
|
||||
2 [ ] [V] фортунка каждое утро. (+ добавить время, относительно gmt, когда показывать фортунку). См. п.13.
|
||||
2 [V] [V] фортунка каждое утро. См. п.13.
|
||||
|
||||
3 [V] [V] Приветствие новых участников
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
[V] регулярных компакций базы с настройками.
|
||||
[ ] регулярного обслуживания таблиц с пользователями.
|
||||
|
||||
14. [ ] в функции AppendChatListDB для нового чата добавлять дефолтные значения настроек.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -89,13 +89,20 @@ func main() {
|
||||
go tg.SigHandler()
|
||||
go tg.Telega(tg.Config)
|
||||
|
||||
// Periodically compact/flush pebble dbs.
|
||||
// Периодически обслуживаем базы с настройками чатов.
|
||||
if job, err := scheduler.Every(1).Hours().NotImmediately().Run(tg.TidySettingsDB); err != nil {
|
||||
log.Errorf("Unable to schedule periodic settings db flush: %s", err)
|
||||
} else {
|
||||
tg.PeriodicJobs = append(tg.PeriodicJobs, job)
|
||||
}
|
||||
|
||||
// Отправлем "доброе утро" каждое утро для всех чатов, которые на это подписались.
|
||||
if job, err := scheduler.Every().Day().At("8:10").Run(tg.SendGoodMorning); err != nil {
|
||||
log.Errorf("Unable to schedule send good morning task: %s", err)
|
||||
} else {
|
||||
tg.PeriodicJobs = append(tg.PeriodicJobs, job)
|
||||
}
|
||||
|
||||
// Обработчик событий от редиски.
|
||||
for msg := range redisMsgChan {
|
||||
if tg.Shutdown {
|
||||
|
||||
@@ -35,10 +35,19 @@ var (
|
||||
// settingsDB мапка с открытыми дескрипторами баз с настройками.
|
||||
settingsDB = make(map[string]*pebble.DB)
|
||||
|
||||
// chatListDB объектик *pebble.DB с базой, в которой лежит список чатов.
|
||||
chatListDB *pebble.DB
|
||||
|
||||
// chatListDBName имя базы данных со списком чатов.
|
||||
chatListDBName = "chat_list_db"
|
||||
|
||||
// chatList слайс со списоком чатов.
|
||||
chatList = []string{}
|
||||
|
||||
// tg is var for telegram api.
|
||||
tg echotron.API
|
||||
|
||||
// introduceGreet приветсвенные фразы для новых участников чата.
|
||||
// introduceGreet приветственные фразы для новых участников чата.
|
||||
introduceGreet = [...]string{
|
||||
"Дратути",
|
||||
"Дарована",
|
||||
|
||||
@@ -2,11 +2,14 @@ package tg
|
||||
|
||||
import (
|
||||
"aleesa-telegram-go/internal/log"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
// TidySettingsDB flushes regularly pebble dbs with settings. Remmended action to keeb that db in a good shape.
|
||||
// Meant to be run about hourly or something like that.
|
||||
// TidySettingsDB флашит на диск базу с настройками чатов. Рекомендуется делать это время от времени для поддержания
|
||||
// производительности базы на должном уровне.
|
||||
// Предполагается, что это происходит где-то раз в час, чаще смысла нет.
|
||||
TidySettingsDB = func() {
|
||||
if len(settingsDB) > 0 {
|
||||
for name, db := range settingsDB {
|
||||
@@ -17,6 +20,56 @@ var (
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("Flushing %s", chatListDBName)
|
||||
|
||||
if err := chatListDB.Flush(); err != nil {
|
||||
log.Errorf("Unable to Flush() %s: %s", chatListDBName, err)
|
||||
}
|
||||
}
|
||||
|
||||
// SendGoodMorning отсылает сообщение "с добрым утром" (сейчас - фортунку). Предполагается, что оно прогоняется по
|
||||
// всем желающим чатам раз в сутки, с утра. Утро отсчитывается от настроек локали в системе.
|
||||
SendGoodMorning = func() {
|
||||
for _, chatID := range chatList {
|
||||
if GetSetting(chatID, "FortuneMsg") == "1" {
|
||||
me, err := tg.GetMe()
|
||||
// Засылаем фразу в misc-канал (в роутер).
|
||||
var rmsg rMsg
|
||||
|
||||
rmsg.Chatid = chatID
|
||||
rmsg.Userid = strconv.FormatInt(me.Result.ID, 10)
|
||||
rmsg.Message = "!f"
|
||||
rmsg.Mode = "public"
|
||||
rmsg.Plugin = "telegram"
|
||||
rmsg.From = "telegram"
|
||||
rmsg.Misc.Csign = Config.Csign
|
||||
rmsg.Misc.Fwdcnt = 1
|
||||
|
||||
rmsg.Misc.Botnick = ConstructPartialUserUsername(me.Result)
|
||||
rmsg.Misc.Username = ConstructPartialUserUsername(me.Result)
|
||||
|
||||
rmsg.Misc.GoodMorning = 1
|
||||
// Форматирование нужно только для вывода некоторых ответов на команды, команды мы ловим выше по тексту, так что
|
||||
// смело ставим тут 0.
|
||||
rmsg.Misc.Msgformat = 0
|
||||
|
||||
data, err := json.Marshal(rmsg)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf("Unable to to serialize message for redis: %s", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Заталкиваем наш json в редиску.
|
||||
if err := RedisClient.Publish(Ctx, Config.Redis.Channel, data).Err(); err != nil {
|
||||
log.Warnf("Unable to send data to redis channel %s: %s", Config.Redis.Channel, err)
|
||||
} else {
|
||||
log.Debugf("Sent msg to redis channel %s: %s", Config.Redis.Channel, string(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"slices"
|
||||
|
||||
"aleesa-telegram-go/internal/log"
|
||||
|
||||
@@ -45,6 +46,81 @@ func FetchV(db *pebble.DB, key string) (string, error) {
|
||||
return valueString, err
|
||||
}
|
||||
|
||||
// InitChatListDB открывает для пользования базу со списком чатов.
|
||||
func InitChatListDB() error {
|
||||
var (
|
||||
err error
|
||||
options pebble.Options
|
||||
dbPath = Config.DataDir + "/" + chatListDBName
|
||||
)
|
||||
|
||||
// По дефолту ограничение ставится на мегабайты данных, а не на количество файлов, поэтому с дефолтными
|
||||
// настройками порождается огромное количество файлов. Умолчальное ограничение на количество файлов - 500 штук,
|
||||
// что нас не устраивает, поэтому немного снизим эту цифру до более приемлемых значений.
|
||||
options.L0CompactionFileThreshold = 8
|
||||
chatListDB, err = pebble.Open(dbPath, &options)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to open settings db, %s: %w\n", dbPath, err)
|
||||
}
|
||||
|
||||
// Заполним слайс со списком чатов. Операция нудная.
|
||||
iterator, err := chatListDB.NewIter(&pebble.IterOptions{})
|
||||
|
||||
if !iterator.First() {
|
||||
return errors.New("Unable to iterate slice with chats")
|
||||
}
|
||||
|
||||
// Попробуем извлечь список ключей и заполнить слайс с чатами.
|
||||
for {
|
||||
// Закончили итерировать по списку.
|
||||
if !iterator.Valid() {
|
||||
break
|
||||
}
|
||||
|
||||
// Битая база?
|
||||
if err := iterator.Error(); err != nil {
|
||||
chatList = []string{}
|
||||
|
||||
return fmt.Errorf("Unable to get chat list: %w", err)
|
||||
}
|
||||
|
||||
chatName := iterator.Key()
|
||||
|
||||
if string(chatName) == "" {
|
||||
return errors.New("Got empty chat name when query " + chatListDBName)
|
||||
}
|
||||
|
||||
chatList = append(chatList, string(chatName))
|
||||
|
||||
iterator.Next()
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// AppendChatListDB добавляет чат в список известных боту. Можно добавлять чаты не глядя, дубликатов не добавится.
|
||||
// Bot API нам такую информацию не даёт.
|
||||
func AppendChatListDB(chatID string) error {
|
||||
var err error
|
||||
|
||||
if slices.Contains(chatList, chatID) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = StoreKV(chatListDB, chatID, "{}"); err != nil {
|
||||
return fmt.Errorf("Unable to append %s to %s: %w", chatID, chatListDBName, err)
|
||||
}
|
||||
|
||||
// TODO: fill in defaults!
|
||||
|
||||
// Не забываем актуализировать список чатов.
|
||||
chatList = append(chatList, chatID)
|
||||
slices.Sort(chatList)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetSetting достаёт настройку из БД с настройками.
|
||||
func GetSetting(chatID string, setting string) string {
|
||||
var err error
|
||||
|
||||
@@ -65,6 +65,9 @@ func SigHandler() {
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug("Closing known chat list db")
|
||||
_ = chatListDB.Close()
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ func telegramMsgParser(msg *echotron.Update) {
|
||||
return
|
||||
}
|
||||
|
||||
AppendChatListDB(strconv.FormatInt(msg.ChatID(), 10))
|
||||
|
||||
// Сообщение о том, что этот чятик изменился, например, превратился в супергруппу.
|
||||
if (msg.Message.MigrateFromChatID < 0) && (msg.Message.MigrateToChatID < 0) {
|
||||
// TODO: поддержать миграцию настроек чата на новый chatId.
|
||||
|
||||
Reference in New Issue
Block a user