0

[WIP] MOAR linter fixes, also move init to tg lib

This commit is contained in:
eleksir
2025-11-09 12:25:51 +03:00
parent bb2425f404
commit ddcc8b1c87
12 changed files with 120 additions and 103 deletions

View File

@@ -1,6 +1,6 @@
Перечень того, что надо реализовать. Перечень того, что надо реализовать.
В качестве основы возьмём https://github.com/NicoNex/echotron В качестве основы возьмём https://github.com/NicoNex/echotron
Для реализации телеграммного фронтэнда нам надо сделать: Для реализации телеграммного фронтэнда нам надо сделать:
* DONE Переделать layout [1/1] * DONE Переделать layout [1/1]

View File

@@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"os" "os"
"os/signal" "os/signal"
"path/filepath"
"syscall" "syscall"
"aleesa-telegram-go/internal/log" "aleesa-telegram-go/internal/log"
@@ -15,48 +14,15 @@ import (
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
) )
// init производит некоторую инициализацию перед запуском main().
func init() {
var (
err error
)
executablePath, err := os.Executable()
if err != nil {
log.Fatalf("Unable to get current executable path: %s", err)
}
configJSONPath := filepath.Dir(executablePath) + "/data/config.json"
locations := []string{
"~/.aleesa-telegram-go.json",
"~/aleesa-telegram-go.json",
"/etc/aleesa-telegram-go.json",
configJSONPath,
}
for _, location := range locations {
tg.Config, err = tg.ParseConfig(location)
if err == nil {
break
}
log.Errorf("Unable to parse config at %s: %s", location, err)
}
if err != nil {
os.Exit(1)
}
}
func main() { func main() {
var ( var (
logfile *os.File logfile *os.File
err error err error
) )
// Найдём и прочитаем конфиг.
tg.ReadConfig()
// Откроем лог и скормим его логгеру. // Откроем лог и скормим его логгеру.
if tg.Config.Log != "" { if tg.Config.Log != "" {
logfile, err = os.OpenFile(tg.Config.Log, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) logfile, err = os.OpenFile(tg.Config.Log, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)

View File

@@ -1,4 +1,5 @@
package settingsmigrator // main Импортирует настройки из файла settings.json в базу с настройками.
package main
import ( import (
"fmt" "fmt"

View File

@@ -21,47 +21,43 @@ func Admin(msg *echotron.Update) (bool, error) {
case c == "admin" || c == "админ": case c == "admin" || c == "админ":
answer = "```\n" answer = "```\n"
answer += fmt.Sprintf("%sadmin censor - показать список состояния типов сообщений\n", Config.Csign) answer += Config.Csign + "admin censor - показать список состояния типов сообщений\n"
answer += fmt.Sprintf("%sадмин ценз - показать список состояния типов сообщений\n", Config.Csign) answer += Config.Csign + "админ ценз - показать список состояния типов сообщений\n"
answer += fmt.Sprintf("%sadmin censor type # - где 1 - вкл, 0 - выкл цензуры для означенного типа сообщений\n", Config.Csign) answer += Config.Csign + "admin censor type # - где 1 - вкл, 0 - выкл цензуры для означенного типа сообщений\n"
answer += fmt.Sprintf("%sадмин ценз тип # - где 1 - вкл, 0 - выкл цензуры для означенного типа сообщений\n", Config.Csign) answer += Config.Csign + "админ ценз тип # - где 1 - вкл, 0 - выкл цензуры для означенного типа сообщений\n"
answer += fmt.Sprintf("%sadmin fortune - показываем ли с утра фортунку для чата\n", Config.Csign) answer += Config.Csign + "admin fortune - показываем ли с утра фортунку для чата\n"
answer += fmt.Sprintf("%sadmin фортунка - показываем ли с утра фортунку для чата\n", Config.Csign) answer += Config.Csign + "admin фортунка - показываем ли с утра фортунку для чата\n"
answer += fmt.Sprintf("%sadmin fortune # - где 1 - вкл, 0 - выкл фортунку с утра\n", Config.Csign) answer += Config.Csign + "admin fortune # - где 1 - вкл, 0 - выкл фортунку с утра\n"
answer += fmt.Sprintf("%sadmin фортунка # - где 1 - вкл, 0 - выкл фортунку с утра\n", Config.Csign) answer += Config.Csign + "admin фортунка # - где 1 - вкл, 0 - выкл фортунку с утра\n"
answer += fmt.Sprintf("%sadmin greet - приветствуем ли новых участников чата\n", Config.Csign) answer += Config.Csign + "admin greet - приветствуем ли новых участников чата\n"
answer += fmt.Sprintf("%sadmin приветствие - приветствуем ли новых участников чата\n", Config.Csign) answer += Config.Csign + "admin приветствие - приветствуем ли новых участников чата\n"
answer += fmt.Sprintf("%sadmin greet # - где 1 - вкл, 0 - выкл приветствия новых участников чата\n", Config.Csign) answer += Config.Csign + "admin greet # - где 1 - вкл, 0 - выкл приветствия новых участников чата\n"
answer += fmt.Sprintf("%sadmin приветствие # - где 1 - вкл, 0 - выкл приветствия новых участников чата\n", Config.Csign) answer += Config.Csign + "admin приветствие # - где 1 - вкл, 0 - выкл приветствия новых участников чата\n"
answer += fmt.Sprintf("%sadmin goodbye - прощаемся ли с ушедшими участниками чата\n", Config.Csign) answer += Config.Csign + "admin goodbye - прощаемся ли с ушедшими участниками чата\n"
answer += fmt.Sprintf("%sadmin прощание - прощаемся ли с ушедшими участниками чата\n", Config.Csign) answer += Config.Csign + "admin прощание - прощаемся ли с ушедшими участниками чата\n"
answer += fmt.Sprintf("%sadmin goodbye # - где 1 - вкл, 0 - выкл прощания с ушедшими участниками чата\n", Config.Csign) answer += Config.Csign + "admin goodbye # - где 1 - вкл, 0 - выкл прощания с ушедшими участниками чата\n"
answer += fmt.Sprintf("%sadmin прощание # - где 1 - вкл, 0 - выкл прощания с ушедшими участниками чата\n", Config.Csign) answer += Config.Csign + "admin прощание # - где 1 - вкл, 0 - выкл прощания с ушедшими участниками чата\n"
answer += fmt.Sprintf("%sadmin oboobs # - где 1 - вкл, 0 - выкл плагина oboobs\n", Config.Csign) answer += Config.Csign + "admin oboobs # - где 1 - вкл, 0 - выкл плагина oboobs\n"
answer += fmt.Sprintf( answer += fmt.Sprintf(
"%sadmin oboobs - показываем ли сисечки по просьбе участников чата (команды %stits, %stities, %sboobs, %sboobies, %sсиси, %sсисечки)\n", "%sadmin oboobs - показываем ли сисечки по просьбе участников чата (команды %stits, %stities, %sboobs, %sboobies, %sсиси, %sсисечки)\n",
Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign,
) )
answer += fmt.Sprintf("%sadmin obutts # - где 1 - вкл, 0 - выкл плагина obutts\n", Config.Csign)
answer += Config.Csign + "admin obutts # - где 1 - вкл, 0 - выкл плагина obutts\n"
answer += fmt.Sprintf( answer += fmt.Sprintf(
"%sadmin obutts - показываем ли попки по просьбе участников чата (команды %sass, %sbutt, %sbooty, %sпопа, %sпопка)\n", "%sadmin obutts - показываем ли попки по просьбе участников чата (команды %sass, %sbutt, %sbooty, %sпопа, %sпопка)\n",
Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign,
) )
answer += fmt.Sprintf("%sadmin chan_msg - оставляем ли сообщения присланные от имени (других) каналов\n", Config.Csign)
answer += fmt.Sprintf("%sadmin chan_msg # - где 1 - оставляем, 0 - удаляем\n", Config.Csign) answer += Config.Csign + "admin chan_msg - оставляем ли сообщения присланные от имени (других) каналов\n"
answer += fmt.Sprintf( answer += Config.Csign + "admin chan_msg # - где 1 - оставляем, 0 - удаляем\n"
"%sadmin ban userid sec - выдаём ban указанному user-у на указанное количество секунд (от 30 сек до 1 года), доступно только создателю чата\n", answer += Config.Csign + "admin ban userid sec - выдаём ban указанному user-у на указанное количество секунд (от 30 сек до 1 года), доступно только создателю чата\n"
Config.Csign, answer += Config.Csign + "admin mute userid sec - выдаём mute указанному user-у на указанное количество секунд (от 30 сек до 1 года), доступно только создателю чата\n"
) answer += Config.Csign + "admin admin mute - разрешено ли обычным админам мьютить участников чата через бота (если бот - админ), (создатель чата всегда может попросить бота-админа замьютить обычного участника чата)\n"
answer += fmt.Sprintf(
"%sadmin mute userid sec - выдаём mute указанному user-у на указанное количество секунд (от 30 сек до 1 года), доступно только создателю чата\n", answer += Config.Csign + "%sadmin admin mute # - где 1 - разрешено, 0 - не разрешено\n"
Config.Csign,
)
answer += fmt.Sprintf(
"%sadmin admin mute - разрешено ли обычным админам мьютить участников чата через бота (если бот - админ), (создатель чата всегда может попросить бота-админа замьютить обычного участника чата)\n",
Config.Csign,
)
answer += fmt.Sprintf("%sadmin admin mute # - где 1 - разрешено, 0 - не разрешено\n", Config.Csign)
answer += "\n" answer += "\n"
answer += "Типы сообщений:\naudio voice photo video video_note animation sticker dice game poll document\n" answer += "Типы сообщений:\naudio voice photo video video_note animation sticker dice game poll document\n"
answer += "```" answer += "```"

View File

@@ -13,7 +13,7 @@ func Help(cmd *echotron.Update) (bool, error) {
help += fmt.Sprintf("%shelp | %sпомощь - список команд", Config.Csign, Config.Csign) help += fmt.Sprintf("%shelp | %sпомощь - список команд", Config.Csign, Config.Csign)
help += fmt.Sprintf("%sanek | %sанек | %sанекдот - рандомный анекдот с anekdot.ru", Config.Csign, Config.Csign, Config.Csign) help += fmt.Sprintf("%sanek | %sанек | %sанекдот - рандомный анекдот с anekdot.ru", Config.Csign, Config.Csign, Config.Csign)
help += fmt.Sprintf("%sbuni - рандомный стрип hapi buni", Config.Csign) help += Config.Csign + "buni - рандомный стрип hapi buni"
help += fmt.Sprintf("%sbunny | %srabbit | %sкролик - кролик", Config.Csign, Config.Csign, Config.Csign) help += fmt.Sprintf("%sbunny | %srabbit | %sкролик - кролик", Config.Csign, Config.Csign, Config.Csign)
help += fmt.Sprintf("%scat | %sкис - кошечка", Config.Csign, Config.Csign) help += fmt.Sprintf("%scat | %sкис - кошечка", Config.Csign, Config.Csign)
help += fmt.Sprintf("%scoin | %sмонетка - подбросить монетку - орёл или решка?", Config.Csign, Config.Csign) help += fmt.Sprintf("%scoin | %sмонетка - подбросить монетку - орёл или решка?", Config.Csign, Config.Csign)
@@ -28,7 +28,7 @@ func Help(cmd *echotron.Update) (bool, error) {
help += fmt.Sprintf("%sfrog | %sлягушка - лягушка", Config.Csign, Config.Csign) help += fmt.Sprintf("%sfrog | %sлягушка - лягушка", Config.Csign, Config.Csign)
help += fmt.Sprintf("%shorse | %sлошадка - лошадка", Config.Csign, Config.Csign) help += fmt.Sprintf("%shorse | %sлошадка - лошадка", Config.Csign, Config.Csign)
help += fmt.Sprintf("%slat | %sлат - сгенерить фразу из крылатых латинских выражений", Config.Csign, Config.Csign) help += fmt.Sprintf("%slat | %sлат - сгенерить фразу из крылатых латинских выражений", Config.Csign, Config.Csign)
help += fmt.Sprintf("%smonkeyuser - рандомный стрип MonkeyUser", Config.Csign) help += Config.Csign + "monkeyuser - рандомный стрип MonkeyUser"
help += fmt.Sprintf("%sowl | %sсова | %sсыч - сова", Config.Csign, Config.Csign, Config.Csign) help += fmt.Sprintf("%sowl | %sсова | %sсыч - сова", Config.Csign, Config.Csign, Config.Csign)
help += fmt.Sprintf("%sproverb | %sпословица - рандомная русская пословица", Config.Csign, Config.Csign) help += fmt.Sprintf("%sproverb | %sпословица - рандомная русская пословица", Config.Csign, Config.Csign)
help += fmt.Sprintf("%sping | %sпинг - попинговать бота", Config.Csign, Config.Csign) help += fmt.Sprintf("%sping | %sпинг - попинговать бота", Config.Csign, Config.Csign)
@@ -36,11 +36,11 @@ func Help(cmd *echotron.Update) (bool, error) {
help += fmt.Sprintf("%ssnail | %sулитка - улитка", Config.Csign, Config.Csign) help += fmt.Sprintf("%ssnail | %sулитка - улитка", Config.Csign, Config.Csign)
help += fmt.Sprintf("%sver | %sversion | %sверсия - что-то про версию ПО", Config.Csign, Config.Csign, Config.Csign) help += fmt.Sprintf("%sver | %sversion | %sверсия - что-то про версию ПО", Config.Csign, Config.Csign, Config.Csign)
help += fmt.Sprintf("%sw <город> | %sп <город> - погода в указанном городе", Config.Csign, Config.Csign) help += fmt.Sprintf("%sw <город> | %sп <город> - погода в указанном городе", Config.Csign, Config.Csign)
help += fmt.Sprintf("%sweather <город> - погода в указанном городе", Config.Csign) help += Config.Csign + "weather <город> - погода в указанном городе"
help += fmt.Sprintf("%sпогода <город> - погода в указанном городе", Config.Csign) help += Config.Csign + "погода <город> - погода в указанном городе"
help += fmt.Sprintf("%sпогодка <город> - погода в указанном городе", Config.Csign) help += Config.Csign + "погодка <город> - погода в указанном городе"
help += fmt.Sprintf("%sпогадка <город> - погода в указанном городе", Config.Csign) help += Config.Csign + "погадка <город> - погода в указанном городе"
help += fmt.Sprintf("%sxkcd - рандомный стрип с сайта xkcd.ru", Config.Csign) help += Config.Csign + "xkcd - рандомный стрип с сайта xkcd.ru"
help += fmt.Sprintf("%skarma фраза | %sкарма фраза - посмотреть карму фразы", Config.Csign, Config.Csign) help += fmt.Sprintf("%skarma фраза | %sкарма фраза - посмотреть карму фразы", Config.Csign, Config.Csign)
help += "```\n" help += "```\n"
help += "Но на самом деле я бот больше для общения, чем для исполнения команд.\n" help += "Но на самом деле я бот больше для общения, чем для исполнения команд.\n"

46
internal/tg/lib.go Normal file
View File

@@ -0,0 +1,46 @@
package tg
import (
"aleesa-telegram-go/internal/log"
"os"
"path/filepath"
)
// ReadConfig читает конфиг. Есть несколько преодопределённых локаций, откуда он пытается его вычитать.
// ./data/config.json, ~/.aleesa-telegram-go.json, ~/aleesa-telegram-go.json, ~/aleesa-telegram-go.json.
func ReadConfig() {
var (
err error
)
executablePath, err := os.Executable()
if err != nil {
log.Fatalf("Unable to get current executable path: %s", err)
}
configJSONPath := filepath.Dir(executablePath) + "/data/config.json"
locations := []string{
"~/.aleesa-telegram-go.json",
"~/aleesa-telegram-go.json",
"/etc/aleesa-telegram-go.json",
configJSONPath,
}
for _, location := range locations {
Config, err = parseConfig(location)
if err == nil {
break
}
log.Errorf("Unable to parse config at %s: %s", location, err)
}
if err != nil {
os.Exit(1)
}
}
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */

View File

@@ -10,8 +10,8 @@ import (
"github.com/hjson/hjson-go" "github.com/hjson/hjson-go"
) )
// ParseConfig разбирает и валидирует даденный конфиг. // parseConfig разбирает и валидирует даденный конфиг.
func ParseConfig(path string) (MyConfig, error) { func parseConfig(path string) (MyConfig, error) {
fileInfo, err := os.Stat(path) fileInfo, err := os.Stat(path)
// Предполагаем, что файла либо нет, либо мы не можем его прочитать, второе надо бы логгировать, но пока забьём. // Предполагаем, что файла либо нет, либо мы не можем его прочитать, второе надо бы логгировать, но пока забьём.

View File

@@ -31,9 +31,16 @@ var (
// SendGoodMorning отсылает сообщение "с добрым утром" (сейчас - фортунку). Предполагается, что оно прогоняется по // SendGoodMorning отсылает сообщение "с добрым утром" (сейчас - фортунку). Предполагается, что оно прогоняется по
// всем желающим чатам раз в сутки, с утра. Утро отсчитывается от настроек локали в системе. // всем желающим чатам раз в сутки, с утра. Утро отсчитывается от настроек локали в системе.
SendGoodMorning = func() { SendGoodMorning = func() {
me, err := tg.GetMe()
if err != nil {
log.Errorf("Unable to send good mornings message, cannot get info about myself: %s", err)
return
}
for _, chatID := range chatGroupList { for _, chatID := range chatGroupList {
if GetSetting(chatID, "FortuneMsg") == "1" { if GetSetting(chatID, "FortuneMsg") == "1" {
me, err := tg.GetMe()
// Засылаем фразу в misc-канал (в роутер). // Засылаем фразу в misc-канал (в роутер).
var rmsg rMsg var rmsg rMsg

View File

@@ -65,34 +65,29 @@ func InitChatListDB() error {
chatListDB, err = pebble.Open(dbPath, &options) chatListDB, err = pebble.Open(dbPath, &options)
if err != nil { if err != nil {
return fmt.Errorf("Unable to open settings db, %s: %w\n", dbPath, err) return fmt.Errorf("unable to open settings db, %s: %w", dbPath, err)
} }
// Заполним слайс со списком чатов. Операция нудная. // Заполним слайс со списком чатов. Операция нудная.
iterator, err := chatListDB.NewIter(&pebble.IterOptions{}) iterator, err := chatListDB.NewIter(&pebble.IterOptions{})
if !iterator.First() { if !iterator.First() {
return errors.New("Unable to iterate slice with chats") return errors.New("unable to iterate slice with chats")
} }
// Попробуем извлечь список ключей и заполнить слайс с чатами. // Попробуем извлечь список ключей и заполнить слайс с чатами.
for { for !iterator.Valid() {
// Закончили итерировать по списку.
if !iterator.Valid() {
break
}
// Битая база? // Битая база?
if err := iterator.Error(); err != nil { if err := iterator.Error(); err != nil {
chatList = []string{} chatList = []string{}
return fmt.Errorf("Unable to get chat list: %w", err) return fmt.Errorf("unable to get chat list: %w", err)
} }
chatName := iterator.Key() chatName := iterator.Key()
if string(chatName) == "" { if len(chatName) == 0 {
return errors.New("Got empty chat name when query " + chatListDBName) return errors.New("got empty chat name when query " + chatListDBName)
} }
chatID := string(chatName) chatID := string(chatName)
@@ -121,18 +116,21 @@ func AppendChatListDB(chatID string) error {
} }
if err = StoreKV(chatListDB, chatID, "1"); err != nil { if err = StoreKV(chatListDB, chatID, "1"); err != nil {
return fmt.Errorf("Unable to append %s to %s: %w", chatID, chatListDBName, err) return fmt.Errorf("unable to append chat %s to chatListDB %s: %w", chatID, chatListDBName, err)
} }
// Не забываем актуализировать список чатов. // Не забываем актуализировать список чатов.
chatList = append(chatList, chatID) chatList = append(chatList, chatID)
slices.Sort(chatList) slices.Sort(chatList)
chatList = slices.Compact(chatList) chatList = slices.Compact(chatList)
// Если СhatID начинается с - это значит, что мы имеем дело именно с группой/супергруппой/каналом. // Если СhatID начинается с - это значит, что мы имеем дело именно с группой/супергруппой/каналом.
if strings.HasPrefix(chatID, "-") { if strings.HasPrefix(chatID, "-") {
chatGroupList = append(chatGroupList, chatID) chatGroupList = append(chatGroupList, chatID)
slices.Sort(chatGroupList) slices.Sort(chatGroupList)
chatGroupList = slices.Compact(chatGroupList) chatGroupList = slices.Compact(chatGroupList)
} }

View File

@@ -66,6 +66,7 @@ func SigHandler() {
} }
log.Debug("Closing known chat list db") log.Debug("Closing known chat list db")
_ = chatListDB.Close() _ = chatListDB.Close()
os.Exit(0) os.Exit(0)

View File

@@ -75,10 +75,10 @@ func ConstructFullChatName(c *echotron.Chat) string {
func ConstructPartialUserUsername(u *echotron.User) string { func ConstructPartialUserUsername(u *echotron.User) string {
switch { switch {
case u.Username != "": case u.Username != "":
return fmt.Sprintf("@%s", u.Username) return "@" + u.Username
case u.FirstName != "" && u.LastName != "": case u.FirstName != "" && u.LastName != "":
return fmt.Sprintf("%s %s", u.FirstName, u.LastName) return u.FirstName + " " + u.LastName
case u.FirstName != "": case u.FirstName != "":
return u.FirstName return u.FirstName
@@ -96,10 +96,10 @@ func ConstructPartialUserUsername(u *echotron.User) string {
func ConstructPartialChatUsername(c *echotron.Chat) string { func ConstructPartialChatUsername(c *echotron.Chat) string {
switch { switch {
case c.Username != "": case c.Username != "":
return fmt.Sprintf("@%s", c.Username) return "@" + c.Username
case c.FirstName != "" && c.LastName != "": case c.FirstName != "" && c.LastName != "":
return fmt.Sprintf("%s %s", c.FirstName, c.LastName) return c.FirstName + " " + c.LastName
case c.FirstName != "": case c.FirstName != "":
return c.FirstName return c.FirstName
@@ -119,13 +119,13 @@ func ConstructUserFirstLastName(u *echotron.User) string {
switch { switch {
case u.FirstName != "" && u.LastName != "": case u.FirstName != "" && u.LastName != "":
user = fmt.Sprintf("%s %s", u.FirstName, u.LastName) user = u.FirstName + " " + u.LastName
case u.FirstName != "": case u.FirstName != "":
user = u.FirstName user = u.FirstName
case u.LastName != "": case u.LastName != "":
user = u.LastName user = u.LastName
case u.Username != "": case u.Username != "":
user = fmt.Sprintf("@%s", u.Username) user = "@" + u.Username
default: default:
user = strconv.FormatInt(u.ID, 10) user = strconv.FormatInt(u.ID, 10)
} }

View File

@@ -21,7 +21,9 @@ func telegramMsgParser(msg *echotron.Update) {
return return
} }
AppendChatListDB(strconv.FormatInt(msg.ChatID(), 10)) if err := AppendChatListDB(strconv.FormatInt(msg.ChatID(), 10)); err != nil {
log.Error(err.Error())
}
// Сообщение о том, что этот чятик изменился, например, превратился в супергруппу. // Сообщение о том, что этот чятик изменился, например, превратился в супергруппу.
if (msg.Message.MigrateFromChatID < 0) && (msg.Message.MigrateToChatID < 0) { if (msg.Message.MigrateFromChatID < 0) && (msg.Message.MigrateToChatID < 0) {
@@ -77,7 +79,7 @@ func telegramMsgParser(msg *echotron.Update) {
users = strings.Join(usersSlice, ", ") users = strings.Join(usersSlice, ", ")
users += fmt.Sprintf(" and %s", ConstructTelegramHighlightName(lastOne)) users += " and " + ConstructTelegramHighlightName(lastOne)
} else { } else {
users = ConstructTelegramHighlightName(msg.Message.NewChatMembers[0]) users = ConstructTelegramHighlightName(msg.Message.NewChatMembers[0])
} }
@@ -130,7 +132,7 @@ func telegramMsgParser(msg *echotron.Update) {
if GetSetting(strconv.FormatInt(msg.Message.Chat.ID, 10), "GoodbyeMsg") == "1" { if GetSetting(strconv.FormatInt(msg.Message.Chat.ID, 10), "GoodbyeMsg") == "1" {
user := ConstructUserFirstLastName(msg.Message.From) user := ConstructUserFirstLastName(msg.Message.From)
goodbye := fmt.Sprintf("Прощаемся с %s", user) goodbye := "Прощаемся с " + user
opts := echotron.MessageOptions{DisableNotification: true, ParseMode: "MarkdownV2"} opts := echotron.MessageOptions{DisableNotification: true, ParseMode: "MarkdownV2"}