[WIP] Handle leaving chat for users, parse message more thoroughly in public chats.
Add parser for users that left channel Add semi-stub (partial) censor functionality Add bot name cut-out in public chat Add sending functionality for public chats
This commit is contained in:
@@ -34,7 +34,7 @@ func parseConfig(path string) (myConfig, error) {
|
||||
|
||||
// Исходя из документации, hjson какбы умеет парсить "кривой" json, но парсит его в map-ку.
|
||||
// Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку
|
||||
// сериализуем в json, а потом json преврщааем в стркутурку. Не очень эффективно, но он и не часто требуется.
|
||||
// сериализуем в json, а потом json превращааем в структурку. Не очень эффективно, но он и не часто требуется.
|
||||
var (
|
||||
sampleConfig myConfig
|
||||
tmp map[string]interface{}
|
||||
|
||||
@@ -19,7 +19,7 @@ var forwardMax int64 = 5
|
||||
var redisClient *redis.Client
|
||||
var subscriber *redis.PubSub
|
||||
|
||||
// Main context
|
||||
// Main context.
|
||||
var ctx = context.Background()
|
||||
|
||||
// Ставится в true, если мы получили сигнал на выключение
|
||||
|
||||
6
main.go
6
main.go
@@ -86,7 +86,7 @@ func main() {
|
||||
log.SetOutput(logfile)
|
||||
}
|
||||
|
||||
// Инициализируем redis-клиента
|
||||
// Инициализируем redis-клиента.
|
||||
redisClient = redis.NewClient(&redis.Options{
|
||||
Addr: fmt.Sprintf("%s:%d", config.Redis.Server, config.Redis.Port),
|
||||
})
|
||||
@@ -95,8 +95,6 @@ func main() {
|
||||
subscriber = redisClient.Subscribe(ctx, config.Redis.MyChannel)
|
||||
redisMsgChan := subscriber.Channel()
|
||||
|
||||
// telego init here
|
||||
|
||||
// Самое время поставить траппер сигналов.
|
||||
signal.Notify(sigChan,
|
||||
syscall.SIGINT,
|
||||
@@ -106,7 +104,7 @@ func main() {
|
||||
go sigHandler()
|
||||
go telega(config)
|
||||
|
||||
// Обработчик событий от редиски
|
||||
// Обработчик событий от редиски.
|
||||
for msg := range redisMsgChan {
|
||||
if shutdown {
|
||||
continue
|
||||
|
||||
309
msg-parsers.go
309
msg-parsers.go
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/NicoNex/echotron/v3"
|
||||
@@ -12,7 +13,7 @@ import (
|
||||
|
||||
// telego msg parser
|
||||
|
||||
// redisMsgParser парсит json-чики прилетевшие из REDIS-ки, причём, json-чики должны быть относительно валидными.
|
||||
// redisMsgParser парсит json-чики прилетевшие из REDIS-ки, причём json-чики должны быть относительно валидными.
|
||||
func redisMsgParser(msg string) {
|
||||
if shutdown {
|
||||
// Если мы завершаем работу программы, то нам ничего обрабатывать не надо.
|
||||
@@ -120,20 +121,36 @@ func telegramMsgParser(msg *echotron.Update) {
|
||||
}
|
||||
|
||||
// Сообщение о том, что этот чятик изменился, например превратился в супергруппу.
|
||||
if msg.Message.MigrateFromChatID < 0 && msg.Message.MigrateToChatID < 0 {
|
||||
// TODO: поддержать миграцию настроек чата га новый chatId.
|
||||
if (msg.Message.MigrateFromChatID < 0) && (msg.Message.MigrateToChatID < 0) {
|
||||
// TODO: поддержать миграцию настроек чата на новый chatId.
|
||||
// TODO: подумать, что можно сделать с настройками бэкэндов. Кажись, ничего, но надо глянуть.
|
||||
}
|
||||
|
||||
// Люди пришли в чят.
|
||||
if msg.Message.NewChatMembers != nil {
|
||||
// TODO: проверить, надо ли приветсвовать, выбрать одну из приветственных фраз, потянуть время, типа, мы пишем
|
||||
// текст и поприветсвовать вновьприбывшего
|
||||
// TODO: проверить, надо ли приветствовать, выбрать одну из приветственных фраз, потянуть время, типа, мы пишем
|
||||
// текст и поприветствовать вновь прибывшего.
|
||||
}
|
||||
|
||||
// Человек ушёл из чата.
|
||||
if msg.Message.LeftChatMember != nil {
|
||||
// TODO: проверить, надо ли прощаться с ушедшим участником чата и попрощаться, если надо
|
||||
if GetSetting(fmt.Sprintf("%d", msg.Message.Chat.ID), "GoodbyeMsg") == "1" {
|
||||
user := ConstructUserFirstLastName(msg.Message.From)
|
||||
|
||||
goodbye := fmt.Sprintf("Прощаемся с %s", user)
|
||||
|
||||
opts := echotron.MessageOptions{DisableNotification: true, ParseMode: "MarkdownV2"}
|
||||
|
||||
if msg.Message.ThreadID != 0 {
|
||||
opts.MessageThreadID = int64(msg.Message.ThreadID)
|
||||
}
|
||||
|
||||
if res, err := tg.SendMessage(goodbye, msg.Message.Chat.ID, &opts); err != nil {
|
||||
log.Errorf("Unable to send message to telegram api: %s", err)
|
||||
} else if !res.Ok {
|
||||
log.Errorf("Unable to send message to telegram api: %s", res.Description)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -145,11 +162,14 @@ func telegramMsgParser(msg *echotron.Update) {
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Unable to get info about myself, %s", err)
|
||||
|
||||
errorOccured = true
|
||||
}
|
||||
|
||||
// Типа, при некоторых обстоятельствах, мы можем получить более внятное сообщение. Но это надо проверять.
|
||||
if !me.Ok {
|
||||
log.Errorf("Unable to get info about myself: %d %s", me.ErrorCode, me.Description)
|
||||
|
||||
errorOccured = true
|
||||
}
|
||||
|
||||
@@ -164,12 +184,11 @@ func telegramMsgParser(msg *echotron.Update) {
|
||||
return
|
||||
}
|
||||
|
||||
// handle private messages
|
||||
// Считаем, что приватное сообщение всегда нуждается в ответе, иначе, зачем писать боту?
|
||||
rmsg.Misc.Answer = 1
|
||||
// если фраза является командой - засылаем её в парсер команд
|
||||
|
||||
// Засылаем фразу в misc-канал (в роутер)
|
||||
rmsg.Chatid = fmt.Sprintf("%d", msg.ChatID())
|
||||
// Засылаем фразу в misc-канал (в роутер).
|
||||
rmsg.Chatid = fmt.Sprintf("%d", msg.Message.Chat.ID)
|
||||
rmsg.Userid = fmt.Sprintf("%d", msg.Message.From.ID)
|
||||
rmsg.Message = msg.Message.Text
|
||||
rmsg.Mode = "private"
|
||||
@@ -177,9 +196,10 @@ func telegramMsgParser(msg *echotron.Update) {
|
||||
rmsg.From = "telegram"
|
||||
rmsg.Misc.Csign = config.Csign
|
||||
rmsg.Misc.Fwdcnt = 1
|
||||
rmsg.Misc.Botnick = me.Result.Username
|
||||
rmsg.Misc.Username = ""
|
||||
rmsg.Misc.Botnick = ConstructPartialUserUsername(me.Result)
|
||||
rmsg.Misc.Username = ConstructPartialUserUsername(msg.Message.From)
|
||||
rmsg.Misc.GoodMorning = 0
|
||||
|
||||
// TODO: детектить нужно ли форматировать ответ. Для этого фактически надо парсить простые команды, как минимум.
|
||||
rmsg.Misc.Msgformat = 0
|
||||
|
||||
@@ -191,7 +211,7 @@ func telegramMsgParser(msg *echotron.Update) {
|
||||
return
|
||||
}
|
||||
|
||||
// Заталкиваем наш json в редиску
|
||||
// Заталкиваем наш 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 {
|
||||
@@ -199,14 +219,136 @@ func telegramMsgParser(msg *echotron.Update) {
|
||||
}
|
||||
|
||||
case "group", "supergroup":
|
||||
// handle public (super)group messages
|
||||
// Здесь работает цензор, если он включён.
|
||||
// Здесь же, если человек ответил на авто-приветствие, это надо обнаруживать и пропускать.
|
||||
// Здесь же, если фраза менее 3-х букв, просто игнорируем её
|
||||
// Здесь же, если фраза является командой - засылаем её в парсер команд
|
||||
// Обрабатываем сообщения для групп и супергрупп. По сути это примерно одинаковые вещи/сущности.
|
||||
|
||||
// Цензор удаляет сообщения из чятика, если они "неправильные" - от имени других каналов, аудиосообщения,
|
||||
// содержат картинки, видео аудио итп, это настраивается через команду !admin censor.
|
||||
if GetSetting(fmt.Sprintf("%d", msg.Message.Chat.ID), "censor") == "1" {
|
||||
// Если цензор отработал, больше делать нечего, сообщения уже нету.
|
||||
if Censor(msg) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Если фраза менее 3-х букв, просто игнорируем её.
|
||||
if len(msg.Message.Text) <= 3 {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: если человек ответил на авто-приветствие, это надо обнаруживать и пропускать.
|
||||
|
||||
// Если фраза является командой - засылаем её в парсер команд.
|
||||
if msg.Message.Text[0:len(config.Csign)] == config.Csign {
|
||||
if err := cmdParser(msg.Message.Text); err != nil {
|
||||
log.Errorf(
|
||||
"Unable to parse message from telegram api as a command. Message was: %s, error: %s",
|
||||
msg.Message.Text,
|
||||
err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Здесь же, если фраза обращена к боту (ник или имя), выставляем флажок, что надо ответить
|
||||
// Здесь же, пытаемся убрать из фразы ник или имя бота
|
||||
// Засылаем фразу в misc-канал (в роутер)
|
||||
quotedBotUsername := regexp.QuoteMeta(me.Result.Username)
|
||||
quotedBotFirstName := regexp.QuoteMeta(me.Result.FirstName)
|
||||
quotedBotLastName := regexp.QuoteMeta(me.Result.LastName)
|
||||
|
||||
if messageContainsBotUsername, err := regexp.MatchString(quotedBotUsername, msg.Message.Text); err != nil {
|
||||
log.Errorf("An error occured while matching message with bot username: %s", err)
|
||||
|
||||
return
|
||||
} else if messageContainsBotUsername {
|
||||
rmsg.Misc.Answer = 1
|
||||
m := regexp.MustCompile(quotedBotUsername)
|
||||
msg.Message.Text = m.ReplaceAllString(msg.Message.Text, "")
|
||||
}
|
||||
|
||||
// TODO: обращение может содержать знаки препинания, пробелы перед, пробелы после. Надо бы это поддержать.
|
||||
switch {
|
||||
// Если у на есть и имя и фамилия бота, то попробуем их слепить вместе, через "1 и более" пробел и вырезать
|
||||
// полученное из входящей фразы.
|
||||
case quotedBotFirstName != "" && quotedBotLastName != "":
|
||||
messageContainsBotName, err := regexp.MatchString(
|
||||
quotedBotFirstName+"[[:space:]]+"+quotedBotLastName,
|
||||
msg.Message.Text,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("An error occured while matching message with bot firstname and lastname: %s", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if messageContainsBotName {
|
||||
rmsg.Misc.Answer = 1
|
||||
m := regexp.MustCompile(quotedBotFirstName + "[[:space:]]+" + quotedBotLastName)
|
||||
msg.Message.Text = m.ReplaceAllString(msg.Message.Text, "")
|
||||
}
|
||||
// Если у нас есть только имя, то попробуем его вырезать из входящей фразы.
|
||||
case quotedBotFirstName != "":
|
||||
messageContainsBotName, err := regexp.MatchString(quotedBotFirstName, msg.Message.Text)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("An error occured while matching message with bot firstname: %s", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if messageContainsBotName {
|
||||
rmsg.Misc.Answer = 1
|
||||
m := regexp.MustCompile(quotedBotFirstName)
|
||||
msg.Message.Text = m.ReplaceAllString(msg.Message.Text, "")
|
||||
}
|
||||
// Если у нас есть только фамилия, то попробуем его вырезать из входящей фразы.
|
||||
case quotedBotLastName != "":
|
||||
messageContainsBotName, err := regexp.MatchString(quotedBotLastName, msg.Message.Text)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("An error occured while matching message with bot lastname: %s", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if messageContainsBotName {
|
||||
rmsg.Misc.Answer = 1
|
||||
m := regexp.MustCompile(quotedBotLastName)
|
||||
msg.Message.Text = m.ReplaceAllString(msg.Message.Text, "")
|
||||
}
|
||||
}
|
||||
|
||||
// Засылаем фразу в misc-канал (в роутер).
|
||||
rmsg.Chatid = fmt.Sprintf("%d", msg.Message.Chat.ID)
|
||||
rmsg.Userid = fmt.Sprintf("%d", msg.Message.From.ID)
|
||||
rmsg.Message = msg.Message.Text
|
||||
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(msg.Message.From)
|
||||
|
||||
rmsg.Misc.GoodMorning = 0
|
||||
|
||||
// TODO: детектить нужно ли форматировать ответ. Для этого фактически надо парсить простые команды, как минимум.
|
||||
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))
|
||||
}
|
||||
|
||||
case "channel":
|
||||
// Тут мы ничего сделать не можем.
|
||||
} //nolint:wsl
|
||||
@@ -218,4 +360,131 @@ func cmdParser(cmd string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Censor парсит сообщения в поисках непотребных данных и если он их находит, то сообщение удаляется.
|
||||
// Непотребными могут быть аудиосообщения, аудиофайлы, видеосообщения, сообщения от имени других каналов итп.
|
||||
// Это могут настроить админы чятика через команду !admin censor.
|
||||
// TODO: Реализовать censor-а.
|
||||
func Censor(msg *echotron.Update) bool {
|
||||
result := false
|
||||
|
||||
if GetSetting(fmt.Sprintf("%d", msg.ChatID()), "VoiceMsg") == "1" {
|
||||
result = true
|
||||
|
||||
if res, err := tg.DeleteMessage(msg.ChatID(), msg.Message.ID); err != nil {
|
||||
chat := ConstructFullChatName(msg.Message.SenderChat)
|
||||
user := ConstructFullUserName(msg.Message.From)
|
||||
|
||||
log.Errorf("Unable to delete message %d in chat %s from %s via telegram api: %s", msg.Message.ID, chat, user, err)
|
||||
} else if !res.Ok {
|
||||
chat := ConstructFullChatName(msg.Message.SenderChat)
|
||||
user := ConstructFullUserName(msg.Message.From)
|
||||
|
||||
log.Errorf("Unable to delete message %d in chat %s from %s via telegram api: %s", msg.ID, chat, user, res.Description)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// ConstructFullUserName выковыривает из сообщения полный username, в формате @username FirstName LastName (id)
|
||||
func ConstructFullUserName(u *echotron.User) string {
|
||||
user := fmt.Sprintf("(%d)", u.ID)
|
||||
|
||||
if u.LastName != "" {
|
||||
user = fmt.Sprintf("%s %s", u.LastName, user)
|
||||
}
|
||||
|
||||
if u.FirstName != "" {
|
||||
user = fmt.Sprintf("%s %s", u.FirstName, user)
|
||||
}
|
||||
|
||||
if u.Username != "" {
|
||||
user = fmt.Sprintf("@%s %s", u.Username, user)
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
// ConstructFullChatName выковыривает из сообщения полный username чата, в формате @username FirstName LastName (id)
|
||||
func ConstructFullChatName(c *echotron.Chat) string {
|
||||
chat := fmt.Sprintf("(%d)", c.ID)
|
||||
|
||||
if c.LastName != "" {
|
||||
chat = fmt.Sprintf("%s %s", c.LastName, chat)
|
||||
}
|
||||
|
||||
if c.FirstName != "" {
|
||||
chat = fmt.Sprintf("%s %s", c.FirstName, chat)
|
||||
}
|
||||
|
||||
if c.Username != "" {
|
||||
chat = fmt.Sprintf("@%s %s", c.Username, chat)
|
||||
}
|
||||
|
||||
return chat
|
||||
}
|
||||
|
||||
// ConstructPartialUserUsername пытается найти и вытащить username, если такового нет, вытаскивает First/Last Name, если
|
||||
// такового нет, то возвращает ID.
|
||||
func ConstructPartialUserUsername(u *echotron.User) string {
|
||||
switch {
|
||||
case u.Username != "":
|
||||
return fmt.Sprintf("@%s", u.Username)
|
||||
|
||||
case u.FirstName != "" && u.LastName != "":
|
||||
return fmt.Sprintf("%s %s", u.FirstName, u.LastName)
|
||||
|
||||
case u.FirstName != "":
|
||||
return u.FirstName
|
||||
|
||||
case u.LastName != "":
|
||||
return u.LastName
|
||||
|
||||
default:
|
||||
return fmt.Sprintf("%d", u.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// ConstructPartialUserUsername пытается найти и вытащить username, если такового нет, вытаскивает First/Last Name, если
|
||||
// такового нет, то возвращает ID.
|
||||
func ConstructPartialChatUsername(c *echotron.Chat) string {
|
||||
switch {
|
||||
case c.Username != "":
|
||||
return fmt.Sprintf("@%s", c.Username)
|
||||
|
||||
case c.FirstName != "" && c.LastName != "":
|
||||
return fmt.Sprintf("%s %s", c.FirstName, c.LastName)
|
||||
|
||||
case c.FirstName != "":
|
||||
return c.FirstName
|
||||
|
||||
case c.LastName != "":
|
||||
return c.LastName
|
||||
|
||||
default:
|
||||
return fmt.Sprintf("%d", c.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// ConstructUserFirstLastName Пытается найти и вытащить first name и last name пользователя, если не получается, то
|
||||
// вначале пытается фоллбэчиться на first name, потом на last name, потом на username.
|
||||
func ConstructUserFirstLastName(u *echotron.User) string {
|
||||
var user string
|
||||
|
||||
switch {
|
||||
case u.FirstName != "" && u.LastName != "":
|
||||
user = fmt.Sprintf("%s %s", u.FirstName, u.LastName)
|
||||
case u.FirstName != "":
|
||||
user = u.FirstName
|
||||
case u.LastName != "":
|
||||
user = u.LastName
|
||||
case u.Username != "":
|
||||
user = fmt.Sprintf("@%s", u.Username)
|
||||
default:
|
||||
user = fmt.Sprintf("%d", u.ID)
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -21,7 +21,7 @@ func StoreKV(db *pebble.DB, key string, value string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// FetchV достаёт значение по ключу
|
||||
// FetchV достаёт значение по ключу.
|
||||
func FetchV(db *pebble.DB, key string) (string, error) {
|
||||
var kArray = []byte(key)
|
||||
|
||||
@@ -41,7 +41,7 @@ func FetchV(db *pebble.DB, key string) (string, error) {
|
||||
}
|
||||
|
||||
// getSetting достаёт настройку из БД с настройками.
|
||||
func getSetting(chatID string, setting string) string {
|
||||
func GetSetting(chatID string, setting string) string {
|
||||
var err error
|
||||
|
||||
chatHash := sha256.Sum256([]byte(chatID))
|
||||
@@ -52,7 +52,7 @@ func getSetting(chatID string, setting string) string {
|
||||
var options pebble.Options
|
||||
// По дефолту ограничение ставится на мегабайты данных, а не на количество файлов, поэтому с дефолтными
|
||||
// настройками порождается огромное количество файлов. Умолчальное ограничение на количество файлов - 500 штук,
|
||||
// что нас не устраивает, поэтому немного снизим эту цифру до более приемлемых значений
|
||||
// что нас не устраивает, поэтому немного снизим эту цифру до более приемлемых значений.
|
||||
options.L0CompactionFileThreshold = 8
|
||||
settingsDB[database], err = pebble.Open(config.DataDir+"/"+database, &options)
|
||||
|
||||
@@ -64,7 +64,7 @@ func getSetting(chatID string, setting string) string {
|
||||
|
||||
value, err := FetchV(settingsDB[database], setting)
|
||||
|
||||
// Если из базы ничего не вынулось, по каким-то причинам, то просто вернём пустую строку
|
||||
// Если из базы ничего не вынулось, по каким-то причинам, то просто вернём пустую строку.
|
||||
if err != nil {
|
||||
if errors.Is(err, pebble.ErrNotFound) {
|
||||
log.Debugf("Unable to get value for %s: no record found in db %s", setting, database)
|
||||
@@ -82,18 +82,18 @@ func getSetting(chatID string, setting string) string {
|
||||
return value
|
||||
}
|
||||
|
||||
// saveSetting сохраняет настройку в БД с настройками
|
||||
func saveSetting(chatID string, setting string, value string) error {
|
||||
// saveSetting сохраняет настройку в БД с настройками.
|
||||
func GaveSetting(chatID string, setting string, value string) error {
|
||||
var chatHash = sha256.Sum256([]byte(chatID))
|
||||
var database = fmt.Sprintf("settings_db/%x", chatHash)
|
||||
var err error
|
||||
|
||||
// Если БД не открыта, откроем её
|
||||
// Если БД не открыта, откроем её.
|
||||
if _, ok := settingsDB[database]; !ok {
|
||||
var options pebble.Options
|
||||
// По дефолту ограничение ставится на мегабайты данных, а не на количество файлов, поэтому с дефолтными
|
||||
// настройками порождается огромное количество файлов. Умолчальное ограничение на количество файлов - 500 штук,
|
||||
// что нас не устраивает, поэтому немного снизим эту цифру до более приемлемых значений
|
||||
// что нас не устраивает, поэтому немного снизим эту цифру до более приемлемых значений.
|
||||
options.L0CompactionFileThreshold = 8
|
||||
|
||||
settingsDB[database], err = pebble.Open(config.DataDir+"/"+database, &options)
|
||||
|
||||
12
util.go
12
util.go
@@ -32,12 +32,12 @@ func readConfig() {
|
||||
for _, location := range locations {
|
||||
fileInfo, err := os.Stat(location)
|
||||
|
||||
// Предполагаем, что файла либо нет, либо мы не можем его прочитать, второе надо бы логгировать, но пока забьём
|
||||
// Предполагаем, что файла либо нет, либо мы не можем его прочитать, второе надо бы логгировать, но пока забьём.
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Конфиг-файл длинноват для конфига, попробуем следующего кандидата
|
||||
// Конфиг-файл длинноват для конфига, попробуем следующего кандидата.
|
||||
if fileInfo.Size() > 65535 {
|
||||
log.Warnf("Config file %s is too long for config, skipping", location)
|
||||
|
||||
@@ -46,7 +46,7 @@ func readConfig() {
|
||||
|
||||
buf, err := os.ReadFile(location)
|
||||
|
||||
// Не удалось прочитать, попробуем следующего кандидата
|
||||
// Не удалось прочитать, попробуем следующего кандидата.
|
||||
if err != nil {
|
||||
log.Warnf("Skip reading config file %s: %s", location, err)
|
||||
|
||||
@@ -63,7 +63,7 @@ func readConfig() {
|
||||
|
||||
err = hjson.Unmarshal(buf, &tmp)
|
||||
|
||||
// Не удалось распарсить - попробуем следующего кандидата
|
||||
// Не удалось распарсить - попробуем следующего кандидата.
|
||||
if err != nil {
|
||||
log.Warnf("Skip parsing config file %s: %s", location, err)
|
||||
|
||||
@@ -72,7 +72,7 @@ func readConfig() {
|
||||
|
||||
tmpjson, err := json.Marshal(tmp)
|
||||
|
||||
// Не удалось преобразовать map-ку в json
|
||||
// Не удалось преобразовать map-ку в json.
|
||||
if err != nil {
|
||||
log.Warnf("Skip parsing config file %s: %s", location, err)
|
||||
|
||||
@@ -154,7 +154,7 @@ func sigHandler() {
|
||||
case syscall.SIGQUIT:
|
||||
log.Infoln("Got SIGQUIT, quitting")
|
||||
|
||||
// Заходим на новую итерацию, если у нас "неинтересный" сигнал
|
||||
// Заходим на новую итерацию, если у нас "неинтересный" сигнал.
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user