This commit is contained in:
bodqhrohro 2019-10-29 03:23:57 +02:00
parent 695c9fc353
commit 7e036fd795
6 changed files with 39 additions and 23 deletions

View file

@ -5,3 +5,6 @@ all:
test: test:
go test -v ./config go test -v ./config
lint:
$(GOPATH)/bin/golint ./...

View file

@ -9,12 +9,14 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
// Config is for top-level struct for config
type Config struct { type Config struct {
Telegram TelegramConfig `yaml:":telegram"` Telegram TelegramConfig `yaml:":telegram"`
Xmpp XmppConfig `yaml:":xmpp"` XMPP XMPPConfig `yaml:":xmpp"`
} }
type XmppConfig struct { // XMPPConfig is for :xmpp: subtree
type XMPPConfig struct {
Loglevel string `yaml:":loglevel"` Loglevel string `yaml:":loglevel"`
Jid string `yaml:":jid"` Jid string `yaml:":jid"`
Host string `yaml:":host"` Host string `yaml:":host"`
@ -23,6 +25,7 @@ type XmppConfig struct {
Db string `yaml:":db"` Db string `yaml:":db"`
} }
// TelegramConfig is for :telegram: subtree
type TelegramConfig struct { type TelegramConfig struct {
Loglevel string `yaml:":loglevel"` Loglevel string `yaml:":loglevel"`
Content TelegramContentConfig `yaml:":content"` Content TelegramContentConfig `yaml:":content"`
@ -30,26 +33,31 @@ type TelegramConfig struct {
Tdlib TelegramTdlibConfig `yaml:":tdlib"` Tdlib TelegramTdlibConfig `yaml:":tdlib"`
} }
// TelegramContentConfig is for :content: subtree
type TelegramContentConfig struct { type TelegramContentConfig struct {
Path string `yaml:":path"` Path string `yaml:":path"`
Link string `yaml:":link"` Link string `yaml:":link"`
Upload string `yaml:":upload"` Upload string `yaml:":upload"`
} }
// TelegramTdlibConfig is for :tdlib: subtree
type TelegramTdlibConfig struct { type TelegramTdlibConfig struct {
Path string `yaml:":lib_path"` Path string `yaml:":lib_path"`
Logfile string `yaml:":logfile"`
Client TelegramTdlibClientConfig `yaml:":client"` Client TelegramTdlibClientConfig `yaml:":client"`
} }
// TelegramTdlibClientConfig is for :client: subtree
type TelegramTdlibClientConfig struct { type TelegramTdlibClientConfig struct {
ApiId string `yaml:":api_id"` APIID string `yaml:":api_id"`
ApiHash string `yaml:":api_hash"` APIHash string `yaml:":api_hash"`
DeviceModel string `yaml:":device_model"` DeviceModel string `yaml:":device_model"`
ApplicationVersion string `yaml:":application_version"` ApplicationVersion string `yaml:":application_version"`
UseChatInfoDatabase bool `yaml:":use_chat_info_database"` UseChatInfoDatabase bool `yaml:":use_chat_info_database"`
} }
func ReadConfig(path string, schema_path string) (Config, error) { // ReadConfig reads the specified config file, validates it and returns a struct
func ReadConfig(path string, schemaPath string) (Config, error) {
var config Config var config Config
file, err := ioutil.ReadFile(path) file, err := ioutil.ReadFile(path)
@ -62,7 +70,7 @@ func ReadConfig(path string, schema_path string) (Config, error) {
return config, errors.Wrap(err, "Error parsing config") return config, errors.Wrap(err, "Error parsing config")
} }
err = validateConfig(file, schema_path) err = validateConfig(file, schemaPath)
if err != nil { if err != nil {
return config, errors.Wrap(err, "Validation error") return config, errors.Wrap(err, "Validation error")
} }
@ -70,25 +78,25 @@ func ReadConfig(path string, schema_path string) (Config, error) {
return config, nil return config, nil
} }
func validateConfig(file []byte, schema_path string) error { func validateConfig(file []byte, schemaPath string) error {
schema, err := jsonschema.Compile(schema_path) schema, err := jsonschema.Compile(schemaPath)
if err != nil { if err != nil {
return errors.Wrap(err, "Corrupted JSON schema") return errors.Wrap(err, "Corrupted JSON schema")
} }
var config_generic interface{} var configGeneric interface{}
err = yaml.Unmarshal(file, &config_generic) err = yaml.Unmarshal(file, &configGeneric)
if err != nil { if err != nil {
return errors.Wrap(err, "Error re-parsing config") return errors.Wrap(err, "Error re-parsing config")
} }
config_generic, err = convertToStringKeysRecursive(config_generic, "") configGeneric, err = convertToStringKeysRecursive(configGeneric, "")
if err != nil { if err != nil {
return errors.Wrap(err, "Config conversion error") return errors.Wrap(err, "Config conversion error")
} }
err = schema.ValidateInterface(config_generic) err = schema.ValidateInterface(configGeneric)
if err != nil { if err != nil {
return errors.Wrap(err, "Config validation error") return errors.Wrap(err, "Config validation error")
} }

View file

@ -4,24 +4,24 @@ import (
"testing" "testing"
) )
const SCHEMA_PATH string = "../config_schema.json" const schemaPath string = "../config_schema.json"
func TestNoConfig(t *testing.T) { func TestNoConfig(t *testing.T) {
_, err := ReadConfig("../test/sfklase.yml", SCHEMA_PATH) _, err := ReadConfig("../test/sfklase.yml", schemaPath)
if err == nil { if err == nil {
t.Errorf("Non-existent config was successfully read") t.Errorf("Non-existent config was successfully read")
} }
} }
func TestGoodConfig(t *testing.T) { func TestGoodConfig(t *testing.T) {
_, err := ReadConfig("../test/good_config.yml", SCHEMA_PATH) _, err := ReadConfig("../test/good_config.yml", schemaPath)
if err != nil { if err != nil {
t.Errorf("Good config is not accepted: %v", err) t.Errorf("Good config is not accepted: %v", err)
} }
} }
func TestBadConfig(t *testing.T) { func TestBadConfig(t *testing.T) {
_, err := ReadConfig("../test/bad_config.yml", SCHEMA_PATH) _, err := ReadConfig("../test/bad_config.yml", schemaPath)
if err == nil { if err == nil {
t.Errorf("Bad config is accepted but it shouldn't!") t.Errorf("Bad config is accepted but it shouldn't!")
} else { } else {

View file

@ -7,16 +7,18 @@ import (
"dev.narayana.im/narayana/telegabber/xmpp" "dev.narayana.im/narayana/telegabber/xmpp"
) )
const CONFIG_PATH string = "config.yml" // YAML config, compatible with the format of Zhabogram 2.0.0
const SCHEMA_PATH string = "./config_schema.json" const configPath string = "config.yml"
// JSON schema (not for editing by a user)
const schemaPath string = "./config_schema.json"
func main() { func main() {
config, err := config.ReadConfig(CONFIG_PATH, SCHEMA_PATH) config, err := config.ReadConfig(configPath, schemaPath)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
cm := xmpp.NewComponent(config.Xmpp) cm := xmpp.NewComponent(config.XMPP)
// reconnect automatically // reconnect automatically
log.Fatal(cm.Run()) log.Fatal(cm.Run())

View file

@ -8,7 +8,9 @@ import (
"gosrc.io/xmpp" "gosrc.io/xmpp"
) )
func NewComponent(conf config.XmppConfig) *xmpp.StreamManager { // NewComponent starts a new component and wraps it in
// a stream manager that you should start yourself
func NewComponent(conf config.XMPPConfig) *xmpp.StreamManager {
options := xmpp.ComponentOptions{ options := xmpp.ComponentOptions{
Address: conf.Host + ":" + conf.Port, Address: conf.Host + ":" + conf.Port,
Domain: conf.Jid, Domain: conf.Jid,

View file

@ -8,6 +8,7 @@ import (
"gosrc.io/xmpp/stanza" "gosrc.io/xmpp/stanza"
) )
// HandleMessage processes an incoming XMPP message
func HandleMessage(s xmpp.Sender, p stanza.Packet) { func HandleMessage(s xmpp.Sender, p stanza.Packet) {
msg, ok := p.(stanza.Message) msg, ok := p.(stanza.Message)
if !ok { if !ok {