Add persistent store and module IDs

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2021-08-07 16:16:14 +02:00
parent da426e7d68
commit 5bd54dd15c
Signed by: luzifer
GPG key ID: 0066F03ED215AD7D
9 changed files with 134 additions and 9 deletions

View file

@ -13,13 +13,15 @@ import (
type (
configFile struct {
BotToken string `yaml:"bot_token"`
GuildID string `yaml:"guild_id"`
BotToken string `yaml:"bot_token"`
GuildID string `yaml:"guild_id"`
StoreLocation string `yaml:"store_location"`
ModuleConfigs []moduleConfig `yaml:"module_configs"`
}
moduleConfig struct {
ID string `yaml:"id"`
Type string `yaml:"type"`
Attributes moduleAttributeStore `yaml:"attributes"`
}

18
main.go
View file

@ -23,6 +23,7 @@ var (
}{}
config *configFile
store *metaStore
version = "dev"
)
@ -57,6 +58,14 @@ func main() {
log.WithError(err).Fatal("Unable to load config file")
}
if config.StoreLocation == "" {
log.Fatal("Config contains no store location")
}
if store, err = newMetaStoreFromDisk(config.StoreLocation); err != nil {
log.WithError(err).Fatal("Unable to load store")
}
// Connect to Discord
if discord, err = discordgo.New(strings.Join([]string{"Bot", config.BotToken}, " ")); err != nil {
log.WithError(err).Fatal("Unable to create discord client")
@ -66,15 +75,22 @@ func main() {
for i, mc := range config.ModuleConfigs {
logger := log.WithFields(log.Fields{
"id": mc.ID,
"idx": i,
"module": mc.Type,
})
if mc.ID == "" {
logger.Error("Module contains no ID and will be disabled")
continue
}
mod := GetModuleByName(mc.Type)
if mod == nil {
logger.Fatal("Found configuration for unsupported module")
}
if err = mod.Initialize(crontab, discord, mc.Attributes); err != nil {
if err = mod.Initialize(mc.ID, crontab, discord, mc.Attributes); err != nil {
logger.WithError(err).Fatal("Unable to initialize module")
}

86
metastore.go Normal file
View file

@ -0,0 +1,86 @@
package main
import (
"encoding/json"
"os"
"sync"
"github.com/pkg/errors"
)
type metaStore struct {
ModuleAttributes map[string]moduleAttributeStore `json:"module_attributes"`
filename string
lock sync.RWMutex
}
func newMetaStoreFromDisk(filename string) (*metaStore, error) {
out := &metaStore{
ModuleAttributes: map[string]moduleAttributeStore{},
filename: filename,
}
f, err := os.Open(filename)
switch {
case err == nil:
// This is fine
case os.IsNotExist(err):
// No store yet, return empty store
return out, nil
default:
return nil, errors.Wrap(err, "opening store")
}
defer f.Close()
return out, errors.Wrap(
json.NewDecoder(f).Decode(out),
"decoding store",
)
}
func (m *metaStore) Save() error {
m.lock.RLock()
defer m.lock.RUnlock()
return m.save()
}
func (m *metaStore) save() error {
f, err := os.Create(m.filename)
if err != nil {
return errors.Wrap(err, "creating storage file")
}
defer f.Close()
return errors.Wrap(
json.NewEncoder(f).Encode(m),
"encoding storage file",
)
}
func (m *metaStore) Set(moduleID, key string, value interface{}) error {
m.lock.Lock()
defer m.lock.Unlock()
if m.ModuleAttributes[moduleID] == nil {
m.ModuleAttributes[moduleID] = make(moduleAttributeStore)
}
m.ModuleAttributes[moduleID][key] = value
return errors.Wrap(m.save(), "saving store")
}
func (m *metaStore) ReadWithLock(moduleID string, fn func(m moduleAttributeStore) error) error {
m.lock.RLock()
defer m.lock.RUnlock()
if m.ModuleAttributes[moduleID] == nil {
return fn(moduleAttributeStore{})
}
return fn(m.ModuleAttributes[moduleID])
}

View file

@ -28,11 +28,15 @@ func init() {
type modClearChannel struct {
attrs moduleAttributeStore
discord *discordgo.Session
id string
}
func (m *modClearChannel) Initialize(crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error {
func (m modClearChannel) ID() string { return m.id }
func (m *modClearChannel) Initialize(id string, crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error {
m.attrs = attrs
m.discord = discord
m.id = id
if err := attrs.Expect(
"discord_channel_id",

View file

@ -36,11 +36,15 @@ func init() {
type modLivePosting struct {
attrs moduleAttributeStore
discord *discordgo.Session
id string
}
func (m *modLivePosting) Initialize(crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error {
func (m modLivePosting) ID() string { return m.id }
func (m *modLivePosting) Initialize(id string, crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error {
m.attrs = attrs
m.discord = discord
m.id = id
if err := attrs.Expect(
"discord_channel_id",

View file

@ -24,11 +24,15 @@ func init() {
type modLiveRole struct {
attrs moduleAttributeStore
discord *discordgo.Session
id string
}
func (m *modLiveRole) Initialize(crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error {
func (m modLiveRole) ID() string { return m.id }
func (m *modLiveRole) Initialize(id string, crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error {
m.attrs = attrs
m.discord = discord
m.id = id
if err := attrs.Expect(
"role_streamers_live",

View file

@ -28,11 +28,15 @@ func init() {
type modPresence struct {
attrs moduleAttributeStore
discord *discordgo.Session
id string
}
func (m *modPresence) Initialize(crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error {
func (m modPresence) ID() string { return m.id }
func (m *modPresence) Initialize(id string, crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error {
m.attrs = attrs
m.discord = discord
m.id = id
if err := attrs.Expect(
"fallback_text",

View file

@ -34,11 +34,15 @@ func init() {
type modStreamSchedule struct {
attrs moduleAttributeStore
discord *discordgo.Session
id string
}
func (m *modStreamSchedule) Initialize(crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error {
func (m modStreamSchedule) ID() string { return m.id }
func (m *modStreamSchedule) Initialize(id string, crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error {
m.attrs = attrs
m.discord = discord
m.id = id
if err := attrs.Expect(
"discord_channel_id",

View file

@ -15,7 +15,8 @@ var (
type (
module interface {
Initialize(crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error
ID() string
Initialize(id string, crontab *cron.Cron, discord *discordgo.Session, attrs moduleAttributeStore) error
Setup() error
}