Files
aleesa-phrases-go/internal/lib/msg-parser.go

203 lines
8.3 KiB
Go

package lib
import (
"context"
"encoding/json"
"fmt"
"regexp"
"strings"
log "github.com/sirupsen/logrus"
)
// Горутинка, которая парсит json-чики прилетевшие из REDIS-ки
func MsgParser(ctx context.Context, msg string) {
var sendTo string
var j rMsg
var message sMsg
log.Debugf("Incomming raw json: %s", msg)
if err := json.Unmarshal([]byte(msg), &j); err != nil {
log.Warnf("Unable to to parse message from redis channel: %s", err)
return
}
// Validate our j
if exist := j.From; exist == "" {
log.Warnf("Incorrect msg from redis, no from field: %s", msg)
return
}
if exist := j.ChatID; exist == "" {
log.Warnf("Incorrect msg from redis, no chatid field: %s", msg)
return
}
if exist := j.UserID; exist == "" {
log.Warnf("Incorrect msg from redis, no userid field: %s", msg)
return
}
// j.ThreadID может быть пустым, это нормально
if exist := j.Message; exist == "" {
log.Warnf("Incorrect msg from redis, no message field: %s", msg)
return
}
if exist := j.Plugin; exist == "" {
log.Warnf("Incorrect msg from redis, no plugin field: %s", msg)
return
} else {
sendTo = j.Plugin
}
if exist := j.Mode; exist == "" {
log.Warnf("Incorrect msg from redis, no mode field: %s", msg)
return
}
// j.Misc.Answer может и не быть, тогда ответа на такое сообщение не будет
if j.Misc.Answer == 0 {
log.Debug("Field Misc->Answer = 0, skipping message")
return
}
// j.Misc.BotNick тоже можно не передавать, тогда будет записана пустая строка
// j.Misc.CSign если нам его не передали, возьмём значение из конфига
if exist := j.Misc.CSign; exist == "" {
j.Misc.CSign = Config.CSign
}
// j.Misc.FwdCnt если нам его не передали, то будет 0
if exist := j.Misc.FwdCnt; exist == 0 {
j.Misc.FwdCnt = 1
}
// j.Misc.GoodMorning может быть быть 1 или 0, по-умолчанию 0
// j.Misc.MsgFormat может быть быть 1 или 0, по-умолчанию 0
// j.Misc.Username можно не передавать, тогда будет пустая строка
// Отвалидировались, теперь вернёмся к нашим баранам.
// Если у нас циклическая пересылка сообщения, попробуем её тут разорвать, отбросив сообщение
if j.Misc.FwdCnt > Config.ForwardsMax {
log.Warnf("Discarding msg with fwd_cnt exceeding max value: %s", msg)
return
} else {
j.Misc.FwdCnt++
}
// Классифицирем входящие сообщения. Первым делом, попробуем определить команды
msgLen := len(j.Message)
if j.Message[0:len(j.Misc.CSign)] == j.Misc.CSign { //nolint:gocritic
cmd := j.Message[len(j.Misc.CSign):]
if cmd == "friday" || cmd == "пятница" {
j.Message = friday()
} else if (cmd == "proverb") || (cmd == "пословица") || (cmd == "пословиться") {
j.Message = proverb()
} else if (cmd == "f") || (cmd == "ф") {
j.Message = fortune()
} else if (cmd == "fortune") || (cmd == "фортунка") {
j.Message = fortune()
} else if (cmd == "karma") || (cmd == "карма") {
j.Message = getKarma(j.ChatID, "")
} else if match, _ := regexp.MatchString("^(rum|ром)[[:space:]]?([[:space:]].+)*$", cmd); match {
format := "/me притаскивает на подносе стопку рома для %s, края стопки искрятся кристаллами соли."
j.Message = fmt.Sprintf(format, j.Misc.Username)
} else if match, _ := regexp.MatchString("^(vodka|водка)[[:space:]]?([[:space:]].+)*$", cmd); match {
format := "/me подаёт шот водки с небольшим маринованным огурчиком на блюдце для %s. Из огурчика торчит "
format += "небольшая вилочка."
j.Message = fmt.Sprintf(format, j.Misc.Username)
} else if match, _ := regexp.MatchString("^(beer|пиво)[[:space:]]?([[:space:]].+)*$", cmd); match {
format := "/me бахает об стол перед %s кружкой холодного пива, часть пенной шапки сползает по запотевшей "
format += "стенке кружки."
j.Message = fmt.Sprintf(format, j.Misc.Username)
} else if match, _ := regexp.MatchString("^(tequila|текила)[[:space:]]?([[:space:]].+)*$", cmd); match {
format := "/me ставит рядом с %s шот текилы, аккуратно на ребро стопки насаживает дольку лайма и ставит "
format += "кофейное блюдце с горочкой соли."
j.Message = fmt.Sprintf(format, j.Misc.Username)
} else if match, _ := regexp.MatchString("^(whisky|виски)[[:space:]]?([[:space:]].+)*$", cmd); match {
format := "/me демонстративно достаёт из морозилки пару кубических камушков, бросает их в толстодонный "
format += "стакан и аккуратно наливает Jack Daniels. Запускает стакан вдоль барной стойки, он "
format += "останавливается около %s."
j.Message = fmt.Sprintf(format, j.Misc.Username)
} else if match, _ := regexp.MatchString("^(absinth|абсент)[[:space:]]?([[:space:]].+)*$", cmd); match {
format := "/me наливает абсент в стопку. Смочив кубик сахара в абсенте кладёт его на дырявую ложечку и "
format += "поджигает. Как только пламя потухнет, %s размешивает оплавившийся кубик в абсенте и подносит "
format += "стопку %s."
j.Message = fmt.Sprintf(format, j.Misc.BotNick, j.Misc.Username)
} else if match, _ := regexp.MatchString("^fuck[[:space:]]*$", cmd); match {
j.Message = "Не ругайся."
} else {
cmdLen := len(cmd)
cmds := []string{"karma ", "карма "}
for _, command := range cmds {
if cmdLen > len(command) && cmd[0:len(command)] == command {
j.Message = getKarma(j.ChatID, cmd[len(command):])
break
}
}
}
// Это последняя проверка, поэтому во всех else мы исходящее сообщение можем смело ставить в пустую строку
} else if msgLen > len("++") {
if j.Message[msgLen-len("--"):msgLen] == "--" || j.Message[msgLen-len("++"):msgLen] == "++" {
// Предполагается, что менять карму мы будем для одной фразы, то есть для 1 строки
if len(strings.Split(j.Message, "\n")) == 1 {
if j.Message[msgLen-len("--"):msgLen] == "--" {
j.Message = changeKarma(j.ChatID, j.Message[0:msgLen-len("--")], "--")
} else if j.Message[msgLen-len("++"):msgLen] == "++" {
j.Message = changeKarma(j.ChatID, j.Message[0:msgLen-len("++")], "++")
} else {
j.Message = ""
}
} else {
j.Message = ""
}
} else {
j.Message = ""
}
} else {
j.Message = ""
}
if j.Message != "" {
// Настало время формировать json и засылать его в дальше
message.From = j.From
message.Userid = j.UserID
message.ChatID = j.ChatID
message.ThreadID = j.ThreadID
message.Message = j.Message
message.Plugin = j.Plugin
message.Mode = j.Mode
message.Misc.FwdCnt = j.Misc.FwdCnt
message.Misc.CSign = j.Misc.CSign
message.Misc.Username = j.Misc.Username
message.Misc.Answer = j.Misc.Answer
message.Misc.BotNick = j.Misc.BotNick
message.Misc.MsgFormat = j.Misc.MsgFormat
data, err := json.Marshal(message)
if err != nil {
log.Warnf("Unable to to serialize message for redis: %s", err)
return
}
// Заталкиваем наш json в редиску
if err := RedisClient.Publish(ctx, sendTo, data).Err(); err != nil {
log.Warnf("Unable to send data to redis channel %s: %s", sendTo, err)
} else {
log.Debugf("Send msg to redis channel %s: %s", sendTo, string(data))
}
}
}
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */