Join webbapp core modules into single package
This commit is contained in:
37
internal/config/types.go
Normal file
37
internal/config/types.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Этот package нужен, чтобы разбить кольцевую зависимость.
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/cockroachdb/pebble"
|
||||
"github.com/go-redis/redis/v8"
|
||||
)
|
||||
|
||||
// MyConfig структурка, описывающая конфиг.
|
||||
type MyConfig struct {
|
||||
Server string `json:"server,omitempty"`
|
||||
Port int `json:"port,omitempty"`
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
Loglevel string `json:"loglevel,omitempty"`
|
||||
Log string `json:"log,omitempty"`
|
||||
Channel string `json:"channel,omitempty"`
|
||||
DataDir string `json:"datadir,omitempty"`
|
||||
Csign string `json:"csign,omitempty"`
|
||||
ForwardsMax int64 `json:"forwards_max,omitempty"`
|
||||
OpenWeatherMap struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Country bool `json:"country,omitempty"`
|
||||
Appid string `json:"appid,omitempty"`
|
||||
} `json:"openweathermap,omitempty"`
|
||||
Flickr struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
Secret string `json:"secret,omitempty"`
|
||||
OAuthToken string `json:"oauth_token,omitempty"`
|
||||
OAuthTokenSecret string `json:"oauth_token_secret,omitempty"`
|
||||
} `json:"flickr,omitempty"`
|
||||
UserAgents []string `json:"user_agents,omitempty"`
|
||||
PcacheDB map[string]*pebble.DB
|
||||
RedisClient *redis.Client
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
@@ -1,4 +1,4 @@
|
||||
package lib
|
||||
package webapp
|
||||
|
||||
import (
|
||||
"aleesa-webapp-go/internal/anekdotru"
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"aleesa-webapp-go/internal/prazdnikisegodnyaru"
|
||||
"aleesa-webapp-go/internal/randomfox"
|
||||
"aleesa-webapp-go/internal/thecatapi"
|
||||
"aleesa-webapp-go/internal/types"
|
||||
"aleesa-webapp-go/internal/xkcdru"
|
||||
"context"
|
||||
"encoding/json"
|
||||
@@ -28,7 +27,7 @@ func MsgParser(cfg *config.MyConfig, ctx context.Context, msg string) {
|
||||
var (
|
||||
sendTo string
|
||||
answer string
|
||||
j types.RMsg
|
||||
j RMsg
|
||||
err error
|
||||
)
|
||||
|
||||
@@ -469,7 +468,7 @@ func MsgParser(cfg *config.MyConfig, ctx context.Context, msg string) {
|
||||
}
|
||||
|
||||
// Настало время формировать json и засылать его в дальше
|
||||
var message types.SMsg
|
||||
var message SMsg
|
||||
message.From = j.From
|
||||
message.Userid = j.Userid
|
||||
message.Chatid = j.Chatid
|
||||
@@ -501,62 +500,4 @@ func MsgParser(cfg *config.MyConfig, ctx context.Context, msg string) {
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateRmsg валидирует входящее сообщение.
|
||||
func ValidateRmsg(cfg *config.MyConfig, j types.RMsg, msg string) (types.RMsg, error) {
|
||||
if exist := j.From; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no from field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
if exist := j.Chatid; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no chatid field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
if exist := j.Userid; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no userid field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
// j.Threadid может быть пустым, значит либо нам его не дали, либо дали пустым. Это нормально.
|
||||
|
||||
if exist := j.Message; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no message field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
if exist := j.Plugin; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no plugin field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
if exist := j.Mode; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no mode field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
// j.Misc.Answer может и не быть, тогда ответа на такое сообщение не будет
|
||||
// j.Misc.Botnick тоже можно не передавать, тогда будет записана пустая строка
|
||||
// j.Misc.Csign если нам его не передали, возьмём значение из конфига
|
||||
if exist := j.Misc.Csign; exist == "" {
|
||||
j.Misc.Csign = cfg.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 можно не передавать, тогда будет пустая строка
|
||||
return j, nil
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
@@ -1,54 +1,24 @@
|
||||
package config
|
||||
package webapp
|
||||
|
||||
import (
|
||||
"aleesa-webapp-go/internal/defaults"
|
||||
"aleesa-webapp-go/internal/config"
|
||||
"aleesa-webapp-go/internal/log"
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cockroachdb/pebble"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/hjson/hjson-go"
|
||||
)
|
||||
|
||||
// MyConfig структурка, описывающая конфиг.
|
||||
type MyConfig struct {
|
||||
Server string `json:"server,omitempty"`
|
||||
Port int `json:"port,omitempty"`
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
Loglevel string `json:"loglevel,omitempty"`
|
||||
Log string `json:"log,omitempty"`
|
||||
Channel string `json:"channel,omitempty"`
|
||||
DataDir string `json:"datadir,omitempty"`
|
||||
Csign string `json:"csign,omitempty"`
|
||||
ForwardsMax int64 `json:"forwards_max,omitempty"`
|
||||
OpenWeatherMap struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Country bool `json:"country,omitempty"`
|
||||
Appid string `json:"appid,omitempty"`
|
||||
} `json:"openweathermap,omitempty"`
|
||||
Flickr struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
Secret string `json:"secret,omitempty"`
|
||||
OAuthToken string `json:"oauth_token,omitempty"`
|
||||
OAuthTokenSecret string `json:"oauth_token_secret,omitempty"`
|
||||
} `json:"flickr,omitempty"`
|
||||
UserAgents []string `json:"user_agents,omitempty"`
|
||||
PcacheDB map[string]*pebble.DB
|
||||
RedisClient *redis.Client
|
||||
}
|
||||
|
||||
// ReadConfig читает и валидирует конфиг, а также выставляет некоторые default-ы, если значений для параметров в конфиге
|
||||
// нет.
|
||||
func ReadConfig() (*MyConfig, error) {
|
||||
locations, err := defaults.DefaultConfigFileLocations()
|
||||
func ReadConfig() error {
|
||||
locations, err := DefaultConfigFileLocations()
|
||||
|
||||
if err != nil {
|
||||
return &MyConfig{}, err
|
||||
return err
|
||||
}
|
||||
|
||||
for _, location := range locations {
|
||||
@@ -60,7 +30,7 @@ func ReadConfig() (*MyConfig, error) {
|
||||
}
|
||||
|
||||
// Конфиг-файл длинноват для конфига, попробуем следующего кандидата
|
||||
if fileInfo.Size() > defaults.ConfigFileSize {
|
||||
if fileInfo.Size() > ConfigFileSize {
|
||||
log.Warnf("Config file %s is too long for config, skipping", location)
|
||||
|
||||
continue
|
||||
@@ -79,7 +49,7 @@ func ReadConfig() (*MyConfig, error) {
|
||||
// Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку
|
||||
// сериализуем в json, а потом json преврщааем в стркутурку. Не очень эффективно, но он и не часто требуется.
|
||||
var (
|
||||
sampleConfig *MyConfig
|
||||
sampleConfig *config.MyConfig
|
||||
tmp map[string]interface{}
|
||||
)
|
||||
|
||||
@@ -109,19 +79,19 @@ func ReadConfig() (*MyConfig, error) {
|
||||
|
||||
// Валидируем значения из конфига
|
||||
if sampleConfig.Server == "" {
|
||||
sampleConfig.Server = defaults.Host
|
||||
sampleConfig.Server = Host
|
||||
}
|
||||
|
||||
if sampleConfig.Port == 0 {
|
||||
sampleConfig.Port = defaults.RedisPort
|
||||
sampleConfig.Port = RedisPort
|
||||
}
|
||||
|
||||
if sampleConfig.Timeout == 0 {
|
||||
sampleConfig.Timeout = defaults.NetworkTimeout
|
||||
sampleConfig.Timeout = NetworkTimeout
|
||||
}
|
||||
|
||||
if sampleConfig.Loglevel == "" {
|
||||
sampleConfig.Loglevel = defaults.Loglevel
|
||||
sampleConfig.Loglevel = Loglevel
|
||||
}
|
||||
|
||||
// sampleConfig.Log = "" if not set
|
||||
@@ -133,7 +103,7 @@ func ReadConfig() (*MyConfig, error) {
|
||||
}
|
||||
|
||||
if sampleConfig.DataDir == "" {
|
||||
sampleConfig.DataDir = defaults.DataDir
|
||||
sampleConfig.DataDir = DataDir
|
||||
}
|
||||
|
||||
if sampleConfig.Csign == "" {
|
||||
@@ -143,7 +113,7 @@ func ReadConfig() (*MyConfig, error) {
|
||||
}
|
||||
|
||||
if sampleConfig.ForwardsMax == 0 {
|
||||
sampleConfig.ForwardsMax = defaults.ForwardMax
|
||||
sampleConfig.ForwardsMax = ForwardMax
|
||||
}
|
||||
|
||||
if unsafe.Sizeof(sampleConfig.OpenWeatherMap) == 0 {
|
||||
@@ -165,7 +135,7 @@ func ReadConfig() (*MyConfig, error) {
|
||||
uaList, err := ReadLines(uaFile)
|
||||
|
||||
if err != nil {
|
||||
return &MyConfig{}, fmt.Errorf("unable to read %s: %w", uaFile, err)
|
||||
return fmt.Errorf("unable to read %s: %w", uaFile, err)
|
||||
}
|
||||
|
||||
sampleConfig.UserAgents = uaList
|
||||
@@ -174,37 +144,12 @@ func ReadConfig() (*MyConfig, error) {
|
||||
|
||||
log.Infof("Using %s as config file", location)
|
||||
|
||||
return sampleConfig, nil
|
||||
Config = sampleConfig
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return &MyConfig{}, fmt.Errorf("config was not loaded! Refusing to start")
|
||||
}
|
||||
|
||||
// ReadLines читает даденный файл построчно в массив строк.
|
||||
func ReadLines(path string) ([]string, error) {
|
||||
file, err := os.Open(path)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func(file *os.File) {
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
log.Errorf("Unable to close file %s:%s", path, err)
|
||||
}
|
||||
}(file)
|
||||
|
||||
var (
|
||||
lines []string
|
||||
scanner = bufio.NewScanner(file)
|
||||
)
|
||||
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
|
||||
return lines, scanner.Err()
|
||||
return fmt.Errorf("config was not loaded! Refusing to start")
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
36
internal/webapp/ReadLines.go
Normal file
36
internal/webapp/ReadLines.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package webapp
|
||||
|
||||
import (
|
||||
"aleesa-webapp-go/internal/log"
|
||||
"bufio"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ReadLines читает даденный файл построчно в массив строк.
|
||||
func ReadLines(path string) ([]string, error) {
|
||||
file, err := os.Open(path)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func(file *os.File) {
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
log.Errorf("Unable to close file %s:%s", path, err)
|
||||
}
|
||||
}(file)
|
||||
|
||||
var (
|
||||
lines []string
|
||||
scanner = bufio.NewScanner(file)
|
||||
)
|
||||
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
|
||||
return lines, scanner.Err()
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
66
internal/webapp/ValidateRmsg.go
Normal file
66
internal/webapp/ValidateRmsg.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package webapp
|
||||
|
||||
import (
|
||||
"aleesa-webapp-go/internal/config"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ValidateRmsg валидирует входящее сообщение.
|
||||
func ValidateRmsg(cfg *config.MyConfig, j RMsg, msg string) (RMsg, error) {
|
||||
if exist := j.From; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no from field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
if exist := j.Chatid; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no chatid field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
if exist := j.Userid; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no userid field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
// j.Threadid может быть пустым, значит либо нам его не дали, либо дали пустым. Это нормально.
|
||||
|
||||
if exist := j.Message; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no message field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
if exist := j.Plugin; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no plugin field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
if exist := j.Mode; exist == "" {
|
||||
emsg := fmt.Errorf("incorrect msg from redis, no mode field: %s", msg)
|
||||
|
||||
return j, emsg
|
||||
}
|
||||
|
||||
// j.Misc.Answer может и не быть, тогда ответа на такое сообщение не будет
|
||||
// j.Misc.Botnick тоже можно не передавать, тогда будет записана пустая строка
|
||||
// j.Misc.Csign если нам его не передали, возьмём значение из конфига
|
||||
if exist := j.Misc.Csign; exist == "" {
|
||||
j.Misc.Csign = cfg.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 можно не передавать, тогда будет пустая строка
|
||||
return j, nil
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
@@ -1,4 +1,4 @@
|
||||
package defaults
|
||||
package webapp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -6,14 +6,6 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var ForwardMax int64 = 5
|
||||
var ConfigFileSize int64 = 65535
|
||||
var DataDir = "data"
|
||||
var Host = "localhost"
|
||||
var Loglevel = "info"
|
||||
var RedisPort = 6379
|
||||
var NetworkTimeout = 10
|
||||
|
||||
func DefaultConfigFileLocations() ([]string, error) {
|
||||
var locations []string
|
||||
|
||||
18
internal/webapp/globals.go
Normal file
18
internal/webapp/globals.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package webapp
|
||||
|
||||
import (
|
||||
"aleesa-webapp-go/internal/config"
|
||||
)
|
||||
|
||||
var (
|
||||
ForwardMax int64 = 5
|
||||
ConfigFileSize int64 = 65535
|
||||
DataDir = "data"
|
||||
Host = "localhost"
|
||||
Loglevel = "info"
|
||||
RedisPort = 6379
|
||||
NetworkTimeout = 10
|
||||
Config *config.MyConfig
|
||||
)
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
@@ -1,4 +1,4 @@
|
||||
package types
|
||||
package webapp
|
||||
|
||||
// RMsg структурка, описывающая входящее сообщение из pubsub-канала redis-ки.
|
||||
type RMsg struct {
|
||||
Reference in New Issue
Block a user