0

Исправлены места, на которые ругался линтер

This commit is contained in:
eleksir
2024-02-27 02:07:10 +03:00
parent a5e8896870
commit 9ec26ec735
4 changed files with 77 additions and 47 deletions

View File

@@ -13,82 +13,95 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
// Горутинка, которая парсит json-чики прилетевшие из REDIS-ки // msgParser горутинка, которая парсит json-чики прилетевшие из REDIS-ки.
func msgParser(ctx context.Context, msg string) { func msgParser(ctx context.Context, msg string) {
var sendTo = "craniac" var (
var j rMsg sendTo = "craniac"
j rMsg
)
log.Debugf("Incomming raw json: %s", msg) log.Debugf("Incomming raw json: %s", msg)
if err := json.Unmarshal([]byte(msg), &j); err != nil { if err := json.Unmarshal([]byte(msg), &j); err != nil {
log.Warnf("Unable to to parse message from redis channel: %s", err) log.Warnf("Unable to to parse message from redis channel: %s", err)
return return
} }
// Validate our j // Validate our j.
if exist := j.From; exist == "" { if exist := j.From; exist == "" {
log.Warnf("Incorrect msg from redis, no from field: %s", msg) log.Warnf("Incorrect msg from redis, no from field: %s", msg)
return return
} }
if exist := j.Chatid; exist == "" { if exist := j.Chatid; exist == "" {
log.Warnf("Incorrect msg from redis, no chatid field: %s", msg) log.Warnf("Incorrect msg from redis, no chatid field: %s", msg)
return return
} }
if exist := j.Userid; exist == "" { if exist := j.Userid; exist == "" {
log.Warnf("Incorrect msg from redis, no userid field: %s", msg) log.Warnf("Incorrect msg from redis, no userid field: %s", msg)
return return
} }
// j.Threadid может быит пустымб значит либо нам его не дали, либо дали пустым. Это нормально. // j.Threadid может быть пустым, значит либо нам его не дали, либо дали пустым. Это нормально.
if exist := j.Message; exist == "" { if exist := j.Message; exist == "" {
log.Warnf("Incorrect msg from redis, no message field: %s", msg) log.Warnf("Incorrect msg from redis, no message field: %s", msg)
return return
} }
if exist := j.Plugin; exist == "" { if exist := j.Plugin; exist == "" {
log.Warnf("Incorrect msg from redis, no plugin field: %s", msg) log.Warnf("Incorrect msg from redis, no plugin field: %s", msg)
return return
} }
if exist := j.Mode; exist == "" { if exist := j.Mode; exist == "" {
log.Warnf("Incorrect msg from redis, no mode field: %s", msg) log.Warnf("Incorrect msg from redis, no mode field: %s", msg)
return return
} }
// j.Misc.Answer может и не быть, тогда ответа на такое сообщение не будет // j.Misc.Answer может и не быть, тогда ответа на такое сообщение не будет.
// j.Misc.Botnick тоже можно не передавать, тогда будет записана пустая строка // j.Misc.Botnick тоже можно не передавать, тогда будет записана пустая строка.
// j.Misc.Csign если нам его не передали, возьмём значение из конфига // j.Misc.Csign если нам его не передали, возьмём значение из конфига.
if exist := j.Misc.Csign; exist == "" { if exist := j.Misc.Csign; exist == "" {
j.Misc.Csign = config.Csign j.Misc.Csign = config.Csign
} }
// j.Misc.Fwdcnt если нам его не передали, то будет 0 // j.Misc.Fwdcnt если нам его не передали, то будет 0.
if exist := j.Misc.Fwdcnt; exist == 0 { if exist := j.Misc.Fwdcnt; exist == 0 {
j.Misc.Fwdcnt = 1 j.Misc.Fwdcnt = 1
} }
// j.Misc.GoodMorning может быть быть 1 или 0, по-умолчанию 0 // j.Misc.GoodMorning может быть 1 или 0, по-умолчанию 0.
// j.Misc.Msgformat может быть быть 1 или 0, по-умолчанию 0 // j.Misc.Msgformat может быть 1 или 0, по-умолчанию 0.
// j.Misc.Username можно не передавать, тогда будет пустая строка // j.Misc.Username можно не передавать, тогда будет пустая строка.
// Отвалидировались, теперь вернёмся к нашим баранам. // Отвалидировались, теперь вернёмся к нашим баранам.
// Если у нас циклическая пересылка сообщения, попробуем её тут разорвать, отбросив сообщение // Если у нас циклическая пересылка сообщения, попробуем её тут разорвать, отбросив сообщение.
if j.Misc.Fwdcnt > config.ForwardsMax { if j.Misc.Fwdcnt > config.ForwardsMax {
log.Warnf("Discarding msg with fwd_cnt exceeding max value: %s", msg) log.Warnf("Discarding msg with fwd_cnt exceeding max value: %s", msg)
return return
} else {
j.Misc.Fwdcnt++
} }
// Классифицирем входящие сообщения. Первым делом, попробуем определить команды j.Misc.Fwdcnt++
// Классифицирем входящие сообщения. Первым делом, попробуем определить команды.
if j.Message[0:len(j.Misc.Csign)] == j.Misc.Csign { if j.Message[0:len(j.Misc.Csign)] == j.Misc.Csign {
// Может быть, это команда модуля phrases? // Может быть, это команда модуля phrases?
var done = false var (
var cmd = j.Message[len(j.Misc.Csign):] done = false
cmd = j.Message[len(j.Misc.Csign):]
)
cmds := []string{"friday", "пятница", "proverb", "пословица", "пословиться", "fortune", "фортунка", "f", "ф", cmds := []string{"friday", "пятница", "proverb", "пословица", "пословиться", "fortune", "фортунка", "f", "ф",
"karma", "карма", "rum", "ром", "vodka", "водка", "beer", "пиво", "tequila", "текила", "whisky", "виски", "karma", "карма", "rum", "ром", "vodka", "водка", "beer", "пиво", "tequila", "текила", "whisky", "виски",
"absinthe", "абсент", "fuck"} "absinthe", "абсент", "fuck"}
@@ -97,12 +110,13 @@ func msgParser(ctx context.Context, msg string) {
if cmd == command { if cmd == command {
sendTo = config.ForwardChannels.Phrases sendTo = config.ForwardChannels.Phrases
// Костыль для кармы // Костыль для кармы.
if cmd == "karma" || cmd == "карма" { if cmd == "karma" || cmd == "карма" {
j.Misc.Answer = 1 j.Misc.Answer = 1
} }
done = true done = true
break break
} }
} }
@@ -117,6 +131,7 @@ func msgParser(ctx context.Context, msg string) {
if cmd == command { if cmd == command {
sendTo = config.ForwardChannels.Webapp sendTo = config.ForwardChannels.Webapp
done = true done = true
break break
} }
} }
@@ -132,6 +147,7 @@ func msgParser(ctx context.Context, msg string) {
if cmd == command { if cmd == command {
sendTo = config.ForwardChannels.WebappGo sendTo = config.ForwardChannels.WebappGo
done = true done = true
break break
} }
} }
@@ -145,6 +161,7 @@ func msgParser(ctx context.Context, msg string) {
if cmd == command { if cmd == command {
sendTo = config.ForwardChannels.Games sendTo = config.ForwardChannels.Games
done = true done = true
break break
} }
} }
@@ -160,12 +177,13 @@ func msgParser(ctx context.Context, msg string) {
if cmdLen > len(command) && cmd[0:len(command)] == command { if cmdLen > len(command) && cmd[0:len(command)] == command {
sendTo = config.ForwardChannels.WebappGo sendTo = config.ForwardChannels.WebappGo
done = true done = true
break break
} }
} }
} }
// Опять мимо? Давай тогда попытаем удачу в поиске комплексной команды для phrases // Опять мимо? Давай тогда попытаем удачу в поиске комплексной команды для phrases.
if !done { if !done {
cmdLen := len(cmd) cmdLen := len(cmd)
@@ -186,10 +204,10 @@ func msgParser(ctx context.Context, msg string) {
} }
} }
} else { } else {
// Попробуем выискать изменение кармы // Попробуем выискать изменение кармы.
msgLen := len(j.Message) msgLen := len(j.Message)
// ++ или -- на конце фразы - это наш кандидат // ++ или -- на конце фразы - это наш кандидат.
if msgLen > len("++") { if msgLen > len("++") {
if j.Message[msgLen-len("--"):msgLen] == "--" || j.Message[msgLen-len("++"):msgLen] == "++" { if j.Message[msgLen-len("--"):msgLen] == "--" || j.Message[msgLen-len("++"):msgLen] == "++" {
// Предполагается, что менять карму мы будем для одной фразы, то есть для 1 строки // Предполагается, что менять карму мы будем для одной фразы, то есть для 1 строки
@@ -203,7 +221,7 @@ func msgParser(ctx context.Context, msg string) {
} }
} }
// Настало время формировать json и засылать его в дальше // Настало время формировать json и засылать его в дальше.
var message sMsg var message sMsg
message.From = j.From message.From = j.From
message.Userid = j.Userid message.Userid = j.Userid
@@ -224,10 +242,11 @@ func msgParser(ctx context.Context, msg string) {
if err != nil { if err != nil {
log.Warnf("Unable to to serialize message for redis: %s", err) log.Warnf("Unable to to serialize message for redis: %s", err)
return return
} }
// Заталкиваем наш json в редиску // Заталкиваем наш json в редиску.
if err := redisClient.Publish(ctx, sendTo, data).Err(); err != nil { if err := redisClient.Publish(ctx, sendTo, data).Err(); err != nil {
log.Warnf("Unable to send data to redis channel %s: %s", sendTo, err) log.Warnf("Unable to send data to redis channel %s: %s", sendTo, err)
} else { } else {
@@ -235,7 +254,8 @@ func msgParser(ctx context.Context, msg string) {
} }
} }
// Читает и валидирует конфиг, а также выставляет некоторые default-ы, если значений для параметров в конфиге нет // readConfig читает и валидирует конфиг, а также выставляет некоторые default-ы, если значений для параметров в конфиге
// нет.
func readConfig() { func readConfig() {
configLoaded := false configLoaded := false
executablePath, err := os.Executable() executablePath, err := os.Executable()
@@ -264,6 +284,7 @@ func readConfig() {
// Конфиг-файл длинноват для конфига, попробуем следующего кандидата // Конфиг-файл длинноват для конфига, попробуем следующего кандидата
if fileInfo.Size() > 65535 { if fileInfo.Size() > 65535 {
log.Warnf("Config file %s is too long for config, skipping", location) log.Warnf("Config file %s is too long for config, skipping", location)
continue continue
} }
@@ -272,19 +293,24 @@ func readConfig() {
// Не удалось прочитать, попробуем следующего кандидата // Не удалось прочитать, попробуем следующего кандидата
if err != nil { if err != nil {
log.Warnf("Skip reading config file %s: %s", location, err) log.Warnf("Skip reading config file %s: %s", location, err)
continue continue
} }
// Исходя из документации, hjson какбы умеет парсить "кривой" json, но парсит его в map-ку. // Исходя из документации, hjson какбы умеет парсить "кривой" json, но парсит его в map-ку.
// Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку // Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку
// сериализуем в json, а потом json преврщааем в стркутурку. Не очень эффективно, но он и не часто требуется. // сериализуем в json, а потом json преврщааем в стркутурку. Не очень эффективно, но он и не часто требуется.
var sampleConfig myConfig var (
var tmp map[string]interface{} sampleConfig myConfig
tmp map[string]interface{}
)
err = hjson.Unmarshal(buf, &tmp) err = hjson.Unmarshal(buf, &tmp)
// Не удалось распарсить - попробуем следующего кандидата // Не удалось распарсить - попробуем следующего кандидата
if err != nil { if err != nil {
log.Warnf("Skip parsing config file %s: %s", location, err) log.Warnf("Skip parsing config file %s: %s", location, err)
continue continue
} }
@@ -293,11 +319,13 @@ func readConfig() {
// Не удалось преобразовать map-ку в json // Не удалось преобразовать map-ку в json
if err != nil { if err != nil {
log.Warnf("Skip parsing config file %s: %s", location, err) log.Warnf("Skip parsing config file %s: %s", location, err)
continue continue
} }
if err := json.Unmarshal(tmpjson, &sampleConfig); err != nil { if err := json.Unmarshal(tmpjson, &sampleConfig); err != nil {
log.Warnf("Skip parsing config file %s: %s", location, err) log.Warnf("Skip parsing config file %s: %s", location, err)
continue continue
} }
@@ -355,7 +383,9 @@ func readConfig() {
config = sampleConfig config = sampleConfig
configLoaded = true configLoaded = true
log.Infof("Using %s as config file", location) log.Infof("Using %s as config file", location)
break break
} }
@@ -365,7 +395,7 @@ func readConfig() {
} }
} }
// Хэндлер сигналов закрывает все бд и сваливает из приложения // sigHandler хэндлер сигналов закрывает все бд и сваливает из приложения.
func sigHandler() { func sigHandler() {
var err error var err error
@@ -379,15 +409,15 @@ func sigHandler() {
case syscall.SIGQUIT: case syscall.SIGQUIT:
log.Infoln("Got SIGQUIT, quitting") log.Infoln("Got SIGQUIT, quitting")
// Заходим на новую итерацию, если у нас "неинтересный" сигнал // Заходим на новую итерацию, если у нас "неинтересный" сигнал.
default: default:
continue continue
} }
// Чтобы не срать в логи ошибками от редиски, проставим shutdown state приложения в true // Чтобы не срать в логи ошибками от редиски, проставим shutdown state приложения в true.
shutdown = true shutdown = true
// Отпишемся от всех каналов и закроем коннект к редиске // Отпишемся от всех каналов и закроем коннект к редиске.
if err = subscriber.Unsubscribe(ctx); err != nil { if err = subscriber.Unsubscribe(ctx); err != nil {
log.Errorf("Unable to unsubscribe from redis channels cleanly: %s", err) log.Errorf("Unable to unsubscribe from redis channels cleanly: %s", err)
} }

View File

@@ -7,23 +7,23 @@ import (
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
) )
// Config - это у нас глобальная штука :) // Config - это у нас глобальная штука.
var config myConfig var config myConfig
// To break circular message forwarding we must set some sane default, it can be overridden via config // To break circular message forwarding we must set some sane default, it can be overridden via config.
var forwardMax int64 = 5 var forwardMax int64 = 5
// Объектики клиента-редиски // Объектики клиента-редиски.
var redisClient *redis.Client var redisClient *redis.Client
var subscriber *redis.PubSub var subscriber *redis.PubSub
// Main context // Main context
var ctx = context.Background() var ctx = context.Background()
// Ставится в true, если мы получили сигнал на выключение // Ставится в true, если мы получили сигнал на выключение.
var shutdown = false var shutdown = false
// Канал, в который приходят уведомления для хэндлера сигналов от траппера сигналов // Канал, в который приходят уведомления для хэндлера сигналов от траппера сигналов.
var sigChan = make(chan os.Signal, 1) var sigChan = make(chan os.Signal, 1)
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */ /* vim: set ft=go noet ai ts=4 sw=4 sts=4: */

16
main.go
View File

@@ -11,7 +11,7 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
// Производит некоторую инициализацию перед запуском main() // init производит некоторую инициализацию перед запуском main().
func init() { func init() {
log.SetFormatter(&log.TextFormatter{ log.SetFormatter(&log.TextFormatter{
DisableQuote: true, DisableQuote: true,
@@ -23,7 +23,7 @@ func init() {
readConfig() readConfig()
// no panic, no trace // no panic, no trace.
switch config.Loglevel { switch config.Loglevel {
case "fatal": case "fatal":
log.SetLevel(log.FatalLevel) log.SetLevel(log.FatalLevel)
@@ -39,18 +39,18 @@ func init() {
log.SetLevel(log.InfoLevel) log.SetLevel(log.InfoLevel)
} }
// Иницализируем клиента Редиски // Иницализируем клиента Редиски.
redisClient = redis.NewClient(&redis.Options{ redisClient = redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", config.Server, config.Port), Addr: fmt.Sprintf("%s:%d", config.Server, config.Port),
}).WithContext(ctx).WithTimeout(time.Duration(config.Timeout) * time.Second) }).WithContext(ctx).WithTimeout(time.Duration(config.Timeout) * time.Second)
// Обозначим, что хотим после соединения подписаться на события из канала config.Channel // Обозначим, что хотим после соединения подписаться на события из канала config.Channel.
subscriber = redisClient.Subscribe(ctx, config.Channel) subscriber = redisClient.Subscribe(ctx, config.Channel)
} }
// Основная функция программы, не добавить и не убавить // main основная функция программы, не добавить и не убавить.
func main() { func main() {
// Откроем лог и скормим его логгеру // Откроем лог и скормим его логгеру.
if config.Log != "" { if config.Log != "" {
logfile, err := os.OpenFile(config.Log, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) logfile, err := os.OpenFile(config.Log, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
@@ -61,7 +61,7 @@ func main() {
log.SetOutput(logfile) log.SetOutput(logfile)
} }
// Самое время поставить траппер сигналов // Самое время поставить траппер сигналов.
signal.Notify(sigChan, signal.Notify(sigChan,
syscall.SIGINT, syscall.SIGINT,
syscall.SIGTERM, syscall.SIGTERM,
@@ -69,7 +69,7 @@ func main() {
go sigHandler() go sigHandler()
// Начнём выгребать события из редиски (длина ковеера/буфера канала по-умолчанию - 100 сообщений) // Начнём выгребать события из редиски (длина ковеера/буфера канала по-умолчанию - 100 сообщений).
ch := subscriber.Channel() ch := subscriber.Channel()
for msg := range ch { for msg := range ch {

View File

@@ -1,6 +1,6 @@
package main package main
// Конфиг // myConfig структура, описывающая формат Конфига приложения.
type myConfig struct { type myConfig struct {
Server string `json:"server,omitempty"` Server string `json:"server,omitempty"`
Port int `json:"port,omitempty"` Port int `json:"port,omitempty"`
@@ -19,7 +19,7 @@ type myConfig struct {
ForwardsMax int64 `json:"forwards_max,omitempty"` ForwardsMax int64 `json:"forwards_max,omitempty"`
} }
// Входящее сообщение из pubsub-канала redis-ки // rMsg структура, описывающая формат входящего сообщения из pubsub-канала redis-ки.
type rMsg struct { type rMsg struct {
From string `json:"from,omitempty"` From string `json:"from,omitempty"`
Chatid string `json:"chatid,omitempty"` Chatid string `json:"chatid,omitempty"`
@@ -39,7 +39,7 @@ type rMsg struct {
} `json:"Misc"` } `json:"Misc"`
} }
// Исходящее сообщение в pubsub-канал redis-ки // sMsg структура, описывающая формат исходящего сообщения в pubsub-канал redis-ки.
type sMsg struct { type sMsg struct {
From string `json:"from"` From string `json:"from"`
Chatid string `json:"chatid"` Chatid string `json:"chatid"`