End transition to go project layout
This commit is contained in:
78
Makefile
78
Makefile
@@ -1,19 +1,87 @@
|
||||
#!/usr/bin/env gmake -f
|
||||
|
||||
GOOPTS=CGO_ENABLED=0
|
||||
BUILDOPTS=-ldflags="-s -w" -a -gcflags=all=-l -trimpath
|
||||
BUILDOPTS=-ldflags="-s -w" -a -gcflags=all=-l -trimpath -buildvcs=false
|
||||
MYNAME=aleesa-irc-go
|
||||
BINARY=${MYNAME}
|
||||
UNIX_BINARY=${MYNAME}
|
||||
WINDOWS_BINARY=${MYNAME}.exe
|
||||
RMCMD=rm -rf
|
||||
|
||||
# На windows имя бинарника может зависеть не только от платформы, но и от выбранной цели, для linux-а суффикс .exe
|
||||
# не нужен
|
||||
ifeq ($(OS),Windows_NT)
|
||||
ifdef GOOS
|
||||
ifeq ($(GOOS),windows)
|
||||
BINARY=${WINDOWS_BINARY}
|
||||
else # not ifeq ($(GOOS),windows)
|
||||
BINARY=${MYNAME}
|
||||
endif # ifeq ($(GOOS),windows)
|
||||
else # not ifdef GOOS
|
||||
BINARY=${WINDOWS_BINARY}
|
||||
endif # ifdef GOOS
|
||||
ifeq ($(SHELL), sh.exe)
|
||||
RMCMD=DEL /Q /F
|
||||
endif
|
||||
endif
|
||||
|
||||
# Явно определяем символ новой строки, чтобы избежать неоднозначности на windows
|
||||
define IFS
|
||||
|
||||
endef
|
||||
|
||||
|
||||
all: clean build
|
||||
|
||||
|
||||
build:
|
||||
${GOOPTS} go build ${BUILDOPTS} -o aleesa-irc-go .
|
||||
ifeq ($(OS),Windows_NT)
|
||||
# Looks like on windows gnu make explicitly set SHELL to sh.exe, if it was not set.
|
||||
ifeq ($(SHELL), sh.exe)
|
||||
# # Vanilla cmd.exe / powershell.
|
||||
SET "CGO_ENABLED=0"
|
||||
go build ${BUILDOPTS} -o ${BINARY} ./cmd/${MYNAME}
|
||||
else ifeq (,$(findstring(Git/usr/bin/sh.exe, $(SHELL))))
|
||||
# # git-bash
|
||||
CGO_ENABLED=0 go build ${BUILDOPTS} -o ${BINARY} ./cmd/${MYNAME}
|
||||
else # not ifeq (,$(findstring(Git/usr/bin/sh.exe, $(SHELL))))
|
||||
# # Some other shell.
|
||||
# # TODO: handle it.
|
||||
$(info "-- Dunno how to handle this shell: ${SHELL}")
|
||||
endif # ifeq (,$(findstring(Git/usr/bin/sh.exe, $(SHELL))))
|
||||
else # not ($(OS),Windows_NT)
|
||||
CGO_ENABLED=0 go build ${BUILDOPTS} -o ${BINARY} ./cmd/${MYNAME}
|
||||
endif # ifeq ($(OS),Windows_NT)
|
||||
|
||||
|
||||
clean:
|
||||
go clean
|
||||
ifeq ($(OS),Windows_NT)
|
||||
ifeq ($(SHELL),sh.exe)
|
||||
# # Vanilla cmd.exe / powershell.
|
||||
if exist ${WINDOWS_BINARY} ${RMCMD} ${WINDOWS_BINARY}
|
||||
if exist ${UNIX_BINARY} ${RMCMD} ${UNIX_BINARY}
|
||||
else # not ifeq ($(SHELL),sh.exe)
|
||||
${RMCMD} ./${WINDOWS_BINARY}
|
||||
${RMCMD} ./${UNIX_BINARY}
|
||||
endif # ifeq ($(SHELL),sh.exe)
|
||||
else # not ifeq ($(OS),Windows_NT)
|
||||
${RMCMD} ./${BINARY}
|
||||
endif
|
||||
|
||||
|
||||
upgrade:
|
||||
rm -rf vendor
|
||||
go get -u -t -tool ./...
|
||||
ifeq ($(OS),Windows_NT)
|
||||
ifeq ($(SHELL),sh.exe)
|
||||
# # Vanilla cmd.exe / powershell.
|
||||
if exist vendor DEL /F /S /Q vendor >nul
|
||||
else # not ifeq ($(SHELL),sh.exe)
|
||||
# # git-bash
|
||||
$(RM) -r vendor
|
||||
endif # ifeq ($(SHELL),sh.exe)
|
||||
else # not ifeq ($(OS),Windows_NT)
|
||||
$(RM) -r vendor
|
||||
endif
|
||||
go get -u ./...
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package irc
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
@@ -15,24 +15,24 @@ import (
|
||||
)
|
||||
|
||||
// ircClientInit горутинка для работы с протоколом irc.
|
||||
func ircClientRun() {
|
||||
for !shutdown {
|
||||
func IrcClientRun() {
|
||||
for !Shutdown {
|
||||
// Иницализируем irc-клиента.
|
||||
// TODO: make use of capabilities: https://defs.ircdocs.horse/defs/clientcaps .
|
||||
// TODO: make use of tags caps https://defs.ircdocs.horse/defs/tags .
|
||||
serverString := fmt.Sprintf("%s:%d", config.Irc.Server, config.Irc.Port)
|
||||
serverString := fmt.Sprintf("%s:%d", Config.Irc.Server, Config.Irc.Port)
|
||||
log.Debugf("Preparing to connect to %s", serverString)
|
||||
log.Debugf("Using nick %s and username %s", config.Irc.Nick, config.Irc.User)
|
||||
ircClient = irc.IRC(config.Irc.Nick, config.Irc.User)
|
||||
ircClient.RealName = config.Irc.User
|
||||
log.Debugf("Using nick %s and username %s", Config.Irc.Nick, Config.Irc.User)
|
||||
ircClient = irc.IRC(Config.Irc.Nick, Config.Irc.User)
|
||||
ircClient.RealName = Config.Irc.User
|
||||
ircClient.Version = "Aleesa Bot v4.something"
|
||||
|
||||
if config.Irc.Ssl {
|
||||
if Config.Irc.Ssl {
|
||||
log.Debug("Force use ssl for connection")
|
||||
|
||||
ircClient.UseTLS = true
|
||||
|
||||
if !config.Irc.SslVerify {
|
||||
if !Config.Irc.SslVerify {
|
||||
log.Debug("Skip server certificate validation")
|
||||
|
||||
ircClient.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
@@ -43,9 +43,9 @@ func ircClientRun() {
|
||||
log.Debug("Skip ssl for connection")
|
||||
}
|
||||
|
||||
if config.Irc.Sasl && config.Irc.Password != "" {
|
||||
ircClient.SASLLogin = config.Irc.User
|
||||
ircClient.SASLPassword = config.Irc.Password
|
||||
if Config.Irc.Sasl && Config.Irc.Password != "" {
|
||||
ircClient.SASLLogin = Config.Irc.User
|
||||
ircClient.SASLPassword = Config.Irc.Password
|
||||
ircClient.UseSASL = true
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ func ircClientRun() {
|
||||
dstNick := e.Arguments[1]
|
||||
|
||||
for _, channelWithMode := range channelsWithModes {
|
||||
for _, mychannel := range config.Irc.Channels {
|
||||
for _, mychannel := range Config.Irc.Channels {
|
||||
tmp := regexp.MustCompile("#").Split(channelWithMode, 2)
|
||||
channel := tmp[1]
|
||||
modes := tmp[0]
|
||||
@@ -129,7 +129,7 @@ func ircClientRun() {
|
||||
namesString := e.Arguments[3]
|
||||
channel := e.Arguments[2]
|
||||
|
||||
for _, mychannel := range config.Irc.Channels {
|
||||
for _, mychannel := range Config.Irc.Channels {
|
||||
if channel == mychannel {
|
||||
for _, name := range strings.Split(namesString, " ") {
|
||||
mode := name[:1]
|
||||
@@ -179,17 +179,17 @@ func ircClientRun() {
|
||||
log.Info("Skip +B flag, server did not announce modes (yet?), noone will know that I am bot")
|
||||
}
|
||||
|
||||
if !config.Irc.Sasl && config.Irc.Password != "" && !nickIsUsed {
|
||||
if !Config.Irc.Sasl && Config.Irc.Password != "" && !nickIsUsed {
|
||||
log.Info("Identifying via NickServ")
|
||||
|
||||
message := fmt.Sprintf("identify %s %s", config.Irc.Nick, config.Irc.Password)
|
||||
message := fmt.Sprintf("identify %s %s", Config.Irc.Nick, Config.Irc.Password)
|
||||
imChan <- iMsg{ChatID: "NickServ", Text: message}
|
||||
}
|
||||
// TODO: wait until +R flag been set? could be implemented with waiting for channel message.
|
||||
|
||||
log.Debug("Trying to join to preconfigured channels")
|
||||
|
||||
for _, channel := range config.Irc.Channels {
|
||||
for _, channel := range Config.Irc.Channels {
|
||||
log.Infof("Joining to %s channel", channel)
|
||||
ircClient.Join(channel)
|
||||
}
|
||||
@@ -248,17 +248,17 @@ func ircClientRun() {
|
||||
}
|
||||
}
|
||||
|
||||
if !config.Irc.Sasl && config.Irc.Password != "" && !nickIsUsed {
|
||||
if !Config.Irc.Sasl && Config.Irc.Password != "" && !nickIsUsed {
|
||||
log.Info("Identifying via NickServ")
|
||||
|
||||
message := fmt.Sprintf("identify %s %s", config.Irc.Nick, config.Irc.Password)
|
||||
message := fmt.Sprintf("identify %s %s", Config.Irc.Nick, Config.Irc.Password)
|
||||
imChan <- iMsg{ChatID: "NickServ", Text: message}
|
||||
}
|
||||
// TODO: wait until +R flag been set? could be implemented with waiting for channel message.
|
||||
|
||||
log.Debug("Trying to join to preconfigured channels")
|
||||
|
||||
for _, channel := range config.Irc.Channels {
|
||||
for _, channel := range Config.Irc.Channels {
|
||||
log.Infof("Joining to %s channel", channel)
|
||||
ircClient.Join(channel)
|
||||
}
|
||||
@@ -279,7 +279,7 @@ func ircClientRun() {
|
||||
|
||||
<-time.NewTimer(60 * time.Second).C // 1 minute sleep.
|
||||
|
||||
ircClient.Nick(config.Irc.Nick)
|
||||
ircClient.Nick(Config.Irc.Nick)
|
||||
})
|
||||
|
||||
ircClient.AddCallback("436", func(e *irc.Event) {
|
||||
@@ -345,7 +345,7 @@ func ircClientRun() {
|
||||
<-time.NewTimer(30 * time.Second).C
|
||||
|
||||
// Проверяем, а должны ли мы быть заджоенныеми к указанному, каналу, а то вдруг нет?
|
||||
if slices.Contains(config.Irc.Channels, channel) {
|
||||
if slices.Contains(Config.Irc.Channels, channel) {
|
||||
ircClient.Join(channel)
|
||||
}
|
||||
})
|
||||
@@ -362,7 +362,7 @@ func ircClientRun() {
|
||||
<-time.NewTimer(30 * time.Second).C
|
||||
|
||||
// Проверяем, а должны ли мы быть заджоенными к указанному, каналу, а то вдруг нет?
|
||||
if slices.Contains(config.Irc.Channels, channel) {
|
||||
if slices.Contains(Config.Irc.Channels, channel) {
|
||||
ircClient.Join(channel)
|
||||
}
|
||||
})
|
||||
@@ -379,7 +379,7 @@ func ircClientRun() {
|
||||
// TODO: вынести в настройки?
|
||||
|
||||
// Проверяем, а должны ли мы быть заджоенныеми к указанному, каналу, а то вдруг нет?
|
||||
if slices.Contains(config.Irc.Channels, channel) {
|
||||
if slices.Contains(Config.Irc.Channels, channel) {
|
||||
ircClient.Join(channel)
|
||||
}
|
||||
})
|
||||
@@ -432,7 +432,7 @@ func ircClientRun() {
|
||||
|
||||
if e.Arguments[1] == ircClient.GetNick() {
|
||||
// Нас кикнули с канала, и мы теряем информацию о MODE-ах пользователей
|
||||
userMode.Delete(channel)
|
||||
UserMode.Delete(channel)
|
||||
// TODO: reason?
|
||||
log.Warnf("%s kicks us from %s", srcFullNick, channel)
|
||||
<-time.NewTimer(10 * time.Second).C
|
||||
@@ -449,15 +449,15 @@ func ircClientRun() {
|
||||
srcNick := e.Nick
|
||||
dstNick := e.Arguments[0]
|
||||
|
||||
if e.Nick == config.Irc.Nick {
|
||||
if e.Nick == Config.Irc.Nick {
|
||||
nickIsUsed = false
|
||||
|
||||
if config.Irc.Password != "" {
|
||||
if Config.Irc.Password != "" {
|
||||
log.Warn("I regain my nick")
|
||||
} else {
|
||||
log.Warn("I regain my nick, trying to identify myself via NickServ")
|
||||
|
||||
message := fmt.Sprintf("identify %s %s", config.Irc.Nick, config.Irc.Password)
|
||||
message := fmt.Sprintf("identify %s %s", Config.Irc.Nick, Config.Irc.Password)
|
||||
imChan <- iMsg{ChatID: "NickServ", Text: message}
|
||||
}
|
||||
} else {
|
||||
@@ -493,7 +493,7 @@ func ircClientRun() {
|
||||
|
||||
if nick == ircClient.GetNick() {
|
||||
log.Infof("I parted from %s", channel)
|
||||
userMode.Delete(channel)
|
||||
UserMode.Delete(channel)
|
||||
} else {
|
||||
log.Infof("%s parted from %s", fullNick, channel)
|
||||
userModeDeleteUser(channel, nick)
|
||||
@@ -591,11 +591,11 @@ func ircClientRun() {
|
||||
|
||||
// ircSend отправляет сообщение в irc. Якобы с применением ratelimit-ов, но на практике длинные сообщения разделяются
|
||||
// на более короткие и тут ratelimit не срабатывает. Если не повезёт, то сервер может за такое дело и кикнуть.
|
||||
func ircSend() {
|
||||
func IrcSend() {
|
||||
for {
|
||||
m := <-imChan
|
||||
|
||||
switch config.Irc.RateLimit.Type {
|
||||
switch Config.Irc.RateLimit.Type {
|
||||
case "simple_delay":
|
||||
log.Debugf("Sending to chat %s message: %s", m.ChatID, m.Text)
|
||||
|
||||
@@ -605,13 +605,13 @@ func ircSend() {
|
||||
ircClient.Privmsg(m.ChatID, m.Text)
|
||||
}
|
||||
|
||||
sleepDelay := time.Duration(config.Irc.RateLimit.SimpleDelay) * time.Millisecond
|
||||
sleepDelay := time.Duration(Config.Irc.RateLimit.SimpleDelay) * time.Millisecond
|
||||
log.Debugf("Due to delay type simple_delay waiting for %d milliseconds", int(sleepDelay))
|
||||
<-time.NewTimer(sleepDelay).C
|
||||
case "token_bucket":
|
||||
var currentTimeMs = time.Now().UnixMilli()
|
||||
|
||||
var expirationTimeMs = config.Irc.RateLimit.TokenBucket.ExpirationTime * 1000
|
||||
var expirationTimeMs = Config.Irc.RateLimit.TokenBucket.ExpirationTime * 1000
|
||||
|
||||
if len(msgBucket.Timestamps) > 0 {
|
||||
var newBucket bucket
|
||||
@@ -623,11 +623,11 @@ func ircSend() {
|
||||
}
|
||||
|
||||
bucketFill := len(newBucket.Timestamps)
|
||||
log.Debugf("Message bucket filled with %d/%d messages", bucketFill, config.Irc.RateLimit.TokenBucket.Size)
|
||||
log.Debugf("Message bucket filled with %d/%d messages", bucketFill, Config.Irc.RateLimit.TokenBucket.Size)
|
||||
|
||||
newBucket.Timestamps = append(newBucket.Timestamps, currentTimeMs)
|
||||
|
||||
if bucketFill >= config.Irc.RateLimit.TokenBucket.Size {
|
||||
if bucketFill >= Config.Irc.RateLimit.TokenBucket.Size {
|
||||
newBucket.IsFull = true
|
||||
}
|
||||
|
||||
@@ -644,8 +644,8 @@ func ircSend() {
|
||||
|
||||
sleepPeriod := expirationTimeMs - (currentTimeMs - msgBucket.Timestamps[len(msgBucket.Timestamps)-1])
|
||||
|
||||
if config.Irc.RateLimit.TokenBucket.Limit > 0 {
|
||||
sleepPeriod /= int64(config.Irc.RateLimit.TokenBucket.Limit)
|
||||
if Config.Irc.RateLimit.TokenBucket.Limit > 0 {
|
||||
sleepPeriod /= int64(Config.Irc.RateLimit.TokenBucket.Limit)
|
||||
}
|
||||
|
||||
log.Debugf("Sleeping for %d milliseconds", sleepPeriod)
|
||||
@@ -675,7 +675,7 @@ func ircSend() {
|
||||
}
|
||||
}
|
||||
|
||||
func ircSendUnrestricted() {
|
||||
func IrcSendUnrestricted() {
|
||||
for {
|
||||
m := <-imChanUnrestricted
|
||||
log.Debugf("Skipping ratelimit and sending to chat %s message: %s", m.ChatID, m.Text)
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package irc
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
// Config - это у нас глобальная штука :).
|
||||
var config myConfig
|
||||
var Config MyConfig
|
||||
|
||||
// To break circular message forwarding we must set some sane default, it can be overridden via config.
|
||||
var forwardMax int64 = 5
|
||||
@@ -22,17 +22,17 @@ var ircClient *irc.Connection
|
||||
var nickIsUsed = false
|
||||
|
||||
// Объектики клиента-редиски.
|
||||
var redisClient *redis.Client
|
||||
var subscriber *redis.PubSub
|
||||
var RedisClient *redis.Client
|
||||
var Subscriber *redis.PubSub
|
||||
|
||||
// Main context.
|
||||
var ctx = context.Background()
|
||||
|
||||
// Ставится в true, если мы получили сигнал на выключение.
|
||||
var shutdown = false
|
||||
var Shutdown = false
|
||||
|
||||
// Канал, в который приходят уведомления для хэндлера сигналов от траппера сигналов.
|
||||
var sigChan = make(chan os.Signal, 1)
|
||||
var SigChan = make(chan os.Signal, 1)
|
||||
|
||||
// Канал, в который пишутся сообщения для отправки в IRC в обычном порядке.
|
||||
var imChan = make(chan iMsg, 10000)
|
||||
@@ -44,7 +44,7 @@ var imChanUnrestricted = make(chan iMsg, 100)
|
||||
var msgBucket bucket
|
||||
|
||||
// "Базюлька" с MODE-ами пользователей на каналах.
|
||||
var userMode = anycollection.NewCollection()
|
||||
var UserMode = anycollection.NewCollection()
|
||||
|
||||
// "Базюлька" с доступными MODE-ами пользователя.
|
||||
var availableUserModes = boolcollection.NewCollection()
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package irc
|
||||
|
||||
import "strings"
|
||||
|
||||
@@ -10,23 +10,23 @@ import "strings"
|
||||
|
||||
// Удаляет сведения о MODE-ах пользователя для заданного канала.
|
||||
func userModeDeleteUser(ircChan string, nick string) {
|
||||
channel, ok := userMode.Get(ircChan)
|
||||
channel, ok := UserMode.Get(ircChan)
|
||||
|
||||
if ok {
|
||||
channelData := channel.(map[string]map[string]bool)
|
||||
delete(channelData, nick)
|
||||
|
||||
if len(channelData) == 0 {
|
||||
userMode.Delete(ircChan)
|
||||
UserMode.Delete(ircChan)
|
||||
} else {
|
||||
userMode.Set(ircChan, channelData)
|
||||
UserMode.Set(ircChan, channelData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Удаляет сведения о MODE-ах пользователя для всех каналов, на которых есть бот.
|
||||
func userModePurgeUser(nick string) {
|
||||
for _, channel := range config.Irc.Channels {
|
||||
for _, channel := range Config.Irc.Channels {
|
||||
userModeDeleteUser(channel, nick)
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func userModePurgeUser(nick string) {
|
||||
func userModeUpdateUser(ircChan string, nick string, modes string) {
|
||||
var channelData map[string]map[string]bool
|
||||
|
||||
channel, ok := userMode.Get(ircChan)
|
||||
channel, ok := UserMode.Get(ircChan)
|
||||
|
||||
if ok {
|
||||
channelData = channel.(map[string]map[string]bool)
|
||||
@@ -60,14 +60,14 @@ func userModeUpdateUser(ircChan string, nick string, modes string) {
|
||||
}
|
||||
}
|
||||
|
||||
userMode.Set(ircChan, channelData)
|
||||
UserMode.Set(ircChan, channelData)
|
||||
}
|
||||
|
||||
// Возвращает значение MODE-а v для запрошенного ника.
|
||||
func userModeIsVoiced(ircChan string, nick string) bool {
|
||||
var channelData map[string]map[string]bool
|
||||
|
||||
channel, ok := userMode.Get(ircChan)
|
||||
channel, ok := UserMode.Get(ircChan)
|
||||
|
||||
if ok {
|
||||
channelData = channel.(map[string]map[string]bool)
|
||||
@@ -94,7 +94,7 @@ func userModeIsVoiced(ircChan string, nick string) bool {
|
||||
func userModeIsOped(ircChan string, nick string) bool {
|
||||
var channelData map[string]map[string]bool
|
||||
|
||||
channel, ok := userMode.Get(ircChan)
|
||||
channel, ok := UserMode.Get(ircChan)
|
||||
|
||||
if ok {
|
||||
channelData = channel.(map[string]map[string]bool)
|
||||
@@ -120,7 +120,7 @@ func userModeIsOped(ircChan string, nick string) bool {
|
||||
func userModeIsHere(ircChan string, nick string) bool {
|
||||
var channelData map[string]map[string]bool
|
||||
|
||||
channel, ok := userMode.Get(ircChan)
|
||||
channel, ok := UserMode.Get(ircChan)
|
||||
|
||||
if ok {
|
||||
channelData = channel.(map[string]map[string]bool)
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package irc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -16,7 +16,7 @@ func ircMsgParser(channel string, nick string, user string, source string, msg s
|
||||
// nick - это выбранный пользователем nick (если он занят, то его "нарисует" сервер)
|
||||
// user - это короткое имя пользователя, под которым его видит сервер
|
||||
// source - это длинное имя пользователя, оно содержит в себе помимо user, ещё и ip с которого пришёл пользователь
|
||||
if shutdown {
|
||||
if Shutdown {
|
||||
// Если мы завершаем работу программы, то нам ничего обрабатывать не надо
|
||||
return
|
||||
}
|
||||
@@ -28,72 +28,72 @@ func ircMsgParser(channel string, nick string, user string, source string, msg s
|
||||
}
|
||||
|
||||
// Ловим команды и обрабатываем их
|
||||
if (len(msg) > len(config.Csign)) && (msg[:len(config.Csign)] == config.Csign) {
|
||||
if (len(msg) > len(Config.Csign)) && (msg[:len(Config.Csign)] == Config.Csign) {
|
||||
var outgoingMessage string
|
||||
|
||||
var message sMsg
|
||||
message.From = config.Redis.MyChannel
|
||||
message.From = Config.Redis.MyChannel
|
||||
message.Userid = user // как его видит сервер
|
||||
message.Chatid = channel // чятик, в который написал user
|
||||
message.Threadid = "" // тредиков в irc нету, поэтому это поле отправляем пустым
|
||||
message.Plugin = config.Redis.MyChannel
|
||||
message.Plugin = Config.Redis.MyChannel
|
||||
message.Mode = "public"
|
||||
// Предполагается, что на команды бот автоматом отвечает
|
||||
message.Misc.Answer = 1
|
||||
message.Misc.Fwdcnt = 0
|
||||
message.Misc.Csign = config.Csign
|
||||
message.Misc.Csign = Config.Csign
|
||||
message.Misc.Username = nick
|
||||
message.Misc.Botnick = config.Irc.Nick
|
||||
message.Misc.Botnick = Config.Irc.Nick
|
||||
message.Misc.Msgformat = 0
|
||||
|
||||
var cmd = msg[len(config.Csign):]
|
||||
var cmd = msg[len(Config.Csign):]
|
||||
|
||||
switch {
|
||||
case cmd == "help" || msg == "помощь":
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%shelp | %sпомощь - это сообщение", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sanek | %sанек | %sанекдот - рандомный анекдот с anekdot.ru", config.Csign, config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sbuni - комикс-стрип hapi buni", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sbunny - кролик", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%srabbit | %sкролик - кролик", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%scat | %sкис - кошечка", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sdice | %sroll | %sкости - бросить кости", config.Csign, config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sdig | %sкопать - заняться археологией", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sdrink | %sпраздник - какой сегодня праздник?", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sfish | %sfisher - порыбачить", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sрыба | %sрыбка | %sрыбалка - порыбачить", config.Csign, config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sf | %sф - рандомная фраза из сборника цитат fortune_mod", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sfortune | %sфортунка - рандомная фраза из сборника цитат fortune_mod", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sfox | %sлис - лисичка", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sfriday | %sпятница - а не пятница ли сегодня?", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sfrog | %sлягушка - лягушка", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%shorse | %sлошадь | %sлошадка - лошадка", config.Csign, config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%skarma фраза - посмотреть карму фразы", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sкарма фраза - посмотреть карму фразы", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%shelp | %sпомощь - это сообщение", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sanek | %sанек | %sанекдот - рандомный анекдот с anekdot.ru", Config.Csign, Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sbuni - комикс-стрип hapi buni", Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sbunny - кролик", Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%srabbit | %sкролик - кролик", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%scat | %sкис - кошечка", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sdice | %sroll | %sкости - бросить кости", Config.Csign, Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sdig | %sкопать - заняться археологией", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sdrink | %sпраздник - какой сегодня праздник?", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sfish | %sfisher - порыбачить", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sрыба | %sрыбка | %sрыбалка - порыбачить", Config.Csign, Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sf | %sф - рандомная фраза из сборника цитат fortune_mod", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sfortune | %sфортунка - рандомная фраза из сборника цитат fortune_mod", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sfox | %sлис - лисичка", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sfriday | %sпятница - а не пятница ли сегодня?", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sfrog | %sлягушка - лягушка", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%shorse | %sлошадь | %sлошадка - лошадка", Config.Csign, Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%skarma фраза - посмотреть карму фразы", Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sкарма фраза - посмотреть карму фразы", Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintln("фраза++ | фраза-- - повысить или понизить карму фразы")}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%slat | %sлат - сгенерировать фразу из крылатого латинского выражения", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%smonkeyuser - комикс-стрип MonkeyUser", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sowl | %sсова - сова", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sping | %sпинг - попинговать бота", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sproverb | %sпословица - рандомная русская пословица", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%ssnail | %sулитка - улитка", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%ssome_brew - выдать соответствующий напиток, бармен может налить rum, ром, vodka, водку, tequila, текила, whisky, виски, absinthe, абсент", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sver | %sversion - написать что-то про версию ПО", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sверсия - написать что-то про версию ПО", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sw <город> | %sп <город> - погода в городе", config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sxkcd - комикс-стрип с xkcb.ru", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%slat | %sлат - сгенерировать фразу из крылатого латинского выражения", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%smonkeyuser - комикс-стрип MonkeyUser", Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sowl | %sсова - сова", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sping | %sпинг - попинговать бота", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sproverb | %sпословица - рандомная русская пословица", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%ssnail | %sулитка - улитка", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%ssome_brew - выдать соответствующий напиток, бармен может налить rum, ром, vodka, водку, tequila, текила, whisky, виски, absinthe, абсент", Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sver | %sversion - написать что-то про версию ПО", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sверсия - написать что-то про версию ПО", Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sw <город> | %sп <город> - погода в городе", Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sxkcd - комикс-стрип с xkcb.ru", Config.Csign)}
|
||||
|
||||
if userModeIsOped(channel, nick) {
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sadmin - настройки некоторых плагинов бота для канала", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sadmin - настройки некоторых плагинов бота для канала", Config.Csign)}
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
case cmd == "admin":
|
||||
if userModeIsOped(channel, nick) {
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sadmin oboobs # - где 1 - вкл, 0 - выкл плагина oboobs", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sadmin oboobs показываем ли сисечки по просьбе участников чата (команды %stits, %stities, %sboobs, %sboobies, %sсиси, %sсисечки)", config.Csign, config.Csign, config.Csign, config.Csign, config.Csign, config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sadmin obutts # - где 1 - вкл, 0 - выкл плагина obutts", config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sadmin obutts показываем ли попки по просьбе участников чата (команды %sass, %sbutt, %sbooty, %sпопа, %sпопка)", config.Csign, config.Csign, config.Csign, config.Csign, config.Csign, config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sadmin oboobs # - где 1 - вкл, 0 - выкл плагина oboobs", Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sadmin oboobs показываем ли сисечки по просьбе участников чата (команды %stits, %stities, %sboobs, %sboobies, %sсиси, %sсисечки)", Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sadmin obutts # - где 1 - вкл, 0 - выкл плагина obutts", Config.Csign)}
|
||||
imChan <- iMsg{ChatID: nick, Text: fmt.Sprintf("%sadmin obutts показываем ли попки по просьбе участников чата (команды %sass, %sbutt, %sbooty, %sпопа, %sпопка)", Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign, Config.Csign)}
|
||||
}
|
||||
|
||||
return
|
||||
@@ -311,21 +311,21 @@ func ircMsgParser(channel string, nick string, user string, source string, msg s
|
||||
}
|
||||
|
||||
// Заталкиваем наш 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)
|
||||
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))
|
||||
log.Debugf("Sent msg to redis channel %s: %s", Config.Redis.Channel, string(data))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Это уже просто трёп в чятике
|
||||
var message sMsg
|
||||
message.From = config.Redis.MyChannel
|
||||
message.From = Config.Redis.MyChannel
|
||||
message.Userid = user // как его видит сервер
|
||||
message.Chatid = channel // чятик, в который написал user
|
||||
message.Threadid = "" // тредиков в irc нету, поэтому это поле отправляем пустым
|
||||
message.Message = msg
|
||||
message.Plugin = config.Redis.MyChannel
|
||||
message.Plugin = Config.Redis.MyChannel
|
||||
message.Mode = "public"
|
||||
|
||||
// Если во фразе содержится ключевые слова, под это есть костыль в craniac-е - (предполагаем, что) он
|
||||
@@ -352,9 +352,9 @@ func ircMsgParser(channel string, nick string, user string, source string, msg s
|
||||
}
|
||||
|
||||
message.Misc.Fwdcnt = 0
|
||||
message.Misc.Csign = config.Csign
|
||||
message.Misc.Csign = Config.Csign
|
||||
message.Misc.Username = nick
|
||||
message.Misc.Botnick = config.Irc.Nick
|
||||
message.Misc.Botnick = Config.Irc.Nick
|
||||
message.Misc.Msgformat = 0
|
||||
|
||||
data, err := json.Marshal(message)
|
||||
@@ -366,17 +366,17 @@ func ircMsgParser(channel string, nick string, user string, source string, msg s
|
||||
}
|
||||
|
||||
// Заталкиваем наш 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)
|
||||
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))
|
||||
log.Debugf("Sent msg to redis channel %s: %s", Config.Redis.Channel, string(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// redisMsgParser парсит json-чики прилетевшие из REDIS-ки, причём, json-чики должны быть относительно валидными.
|
||||
func redisMsgParser(msg string) {
|
||||
if shutdown {
|
||||
// RedisMsgParser парсит json-чики прилетевшие из REDIS-ки, причём, json-чики должны быть относительно валидными.
|
||||
func RedisMsgParser(msg string) {
|
||||
if Shutdown {
|
||||
// Если мы завершаем работу программы, то нам ничего обрабатывать не надо
|
||||
return
|
||||
}
|
||||
@@ -438,7 +438,7 @@ func redisMsgParser(msg string) {
|
||||
// j.Misc.BotNick тоже можно не передавать, тогда будет записана пустая строка
|
||||
// j.Misc.CSign если нам его не передали, возьмём значение из конфига
|
||||
if exist := j.Misc.Csign; exist == "" {
|
||||
j.Misc.Csign = config.Csign
|
||||
j.Misc.Csign = Config.Csign
|
||||
}
|
||||
|
||||
// j.Misc.FwdCnt если нам его не передали, то будет 0
|
||||
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
package irc
|
||||
|
||||
// Конфиг.
|
||||
type myConfig struct {
|
||||
type MyConfig struct {
|
||||
Redis struct {
|
||||
Server string `json:"server,omitempty"`
|
||||
Port int `json:"port,omitempty"`
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package irc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Читает и валидирует конфиг, а также выставляет некоторые default-ы, если значений для параметров в конфиге нет.
|
||||
func readConfig() {
|
||||
// ReadConfig читает и валидирует конфиг, а также выставляет некоторые default-ы, если значений для параметров в конфиге нет.
|
||||
func ReadConfig() {
|
||||
configLoaded := false
|
||||
executablePath, err := os.Executable()
|
||||
|
||||
@@ -58,7 +58,7 @@ func readConfig() {
|
||||
// Исходя из документации, hjson какбы умеет парсить "кривой" json, но парсит его в map-ку.
|
||||
// Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку
|
||||
// сериализуем в json, а потом json преврщааем в стркутурку. Не очень эффективно, но он и не часто требуется.
|
||||
var sampleConfig myConfig
|
||||
var sampleConfig MyConfig
|
||||
|
||||
var tmp map[string]interface{}
|
||||
err = hjson.Unmarshal(buf, &tmp)
|
||||
@@ -190,7 +190,7 @@ func readConfig() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
config = sampleConfig
|
||||
Config = sampleConfig
|
||||
configLoaded = true
|
||||
|
||||
log.Infof("Using %s as config file", location)
|
||||
@@ -204,12 +204,12 @@ func readConfig() {
|
||||
}
|
||||
}
|
||||
|
||||
// Хэндлер сигналов закрывает все бд, все сетевые соединения и сваливает из приложения.
|
||||
func sigHandler() {
|
||||
// SigHandler хэндлер сигналов закрывает все бд, все сетевые соединения и сваливает из приложения.
|
||||
func SigHandler() {
|
||||
var err error
|
||||
|
||||
for {
|
||||
var s = <-sigChan
|
||||
var s = <-SigChan
|
||||
switch s {
|
||||
case syscall.SIGINT:
|
||||
log.Infoln("Got SIGINT, quitting")
|
||||
@@ -224,16 +224,16 @@ func sigHandler() {
|
||||
}
|
||||
|
||||
// Чтобы не срать в логи ошибками от редиски, проставим 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)
|
||||
} else {
|
||||
log.Debug("Unsubscribe from all redis channels")
|
||||
}
|
||||
|
||||
if err = subscriber.Close(); err != nil {
|
||||
if err = Subscriber.Close(); err != nil {
|
||||
log.Errorf("Unable to close redis connection cleanly: %s", err)
|
||||
} else {
|
||||
log.Debug("Close redis connection")
|
||||
@@ -243,7 +243,7 @@ func sigHandler() {
|
||||
ircClient.Quit()
|
||||
|
||||
log.Debug("Close userModeDB")
|
||||
userMode.Close()
|
||||
UserMode.Close()
|
||||
|
||||
log.Debug("Close settingsDB")
|
||||
setting.CloseAll()
|
||||
106
main.go
106
main.go
@@ -1,106 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"aleesa-irc-go/internal/setting"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Производит некоторую инициализацию перед запуском main().
|
||||
func init() {
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
DisableQuote: true,
|
||||
DisableLevelTruncation: false,
|
||||
DisableColors: true,
|
||||
FullTimestamp: true,
|
||||
TimestampFormat: "2006-01-02 15:04:05",
|
||||
})
|
||||
|
||||
readConfig()
|
||||
|
||||
// no panic, no trace
|
||||
switch config.Loglevel {
|
||||
case "fatal":
|
||||
log.SetLevel(log.FatalLevel)
|
||||
case "error":
|
||||
log.SetLevel(log.ErrorLevel)
|
||||
case "warn":
|
||||
log.SetLevel(log.WarnLevel)
|
||||
case "info":
|
||||
log.SetLevel(log.InfoLevel)
|
||||
case "debug":
|
||||
log.SetLevel(log.DebugLevel)
|
||||
default:
|
||||
log.SetLevel(log.InfoLevel)
|
||||
}
|
||||
|
||||
// Проинициализируем мапку MODE-ами пользователей произвольным значением и удалим его
|
||||
var usersModes = map[string]map[string]map[string]bool{
|
||||
"user": {
|
||||
"mode": {
|
||||
"v": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
userMode.Set("channel", usersModes)
|
||||
userMode.Delete("channel")
|
||||
|
||||
setting.DataDir = config.DataDir
|
||||
}
|
||||
|
||||
// Собственно, какбэ "точка входа" - основная процедура в нашем боте.
|
||||
func main() {
|
||||
// Main context
|
||||
var ctx = context.Background()
|
||||
|
||||
// Откроем лог и скормим его логгеру
|
||||
if config.Log != "" {
|
||||
logfile, err := os.OpenFile(config.Log, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to open log file %s: %s", config.Log, err)
|
||||
}
|
||||
|
||||
log.SetOutput(logfile)
|
||||
}
|
||||
|
||||
// Иницализируем redis-клиента
|
||||
redisClient = redis.NewClient(&redis.Options{
|
||||
Addr: fmt.Sprintf("%s:%d", config.Redis.Server, config.Redis.Port),
|
||||
})
|
||||
|
||||
log.Debugf("Lazy connect() to redis at %s:%d", config.Redis.Server, config.Redis.Port)
|
||||
subscriber = redisClient.Subscribe(ctx, config.Redis.MyChannel)
|
||||
redisMsgChan := subscriber.Channel()
|
||||
|
||||
go ircClientRun()
|
||||
go ircSend()
|
||||
go ircSendUnrestricted()
|
||||
|
||||
// Самое время поставить траппер сигналов
|
||||
signal.Notify(sigChan,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGTERM,
|
||||
syscall.SIGQUIT)
|
||||
|
||||
go sigHandler()
|
||||
|
||||
// Обработчик событий от редиски
|
||||
for msg := range redisMsgChan {
|
||||
if shutdown {
|
||||
continue
|
||||
}
|
||||
|
||||
redisMsgParser(msg.Payload)
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
Reference in New Issue
Block a user