Created new config type to use base feature type for easier per-server configs.
This commit is contained in:
parent
59da01b0e5
commit
bd1406d7c1
25
featurename_string.go
Normal file
25
featurename_string.go
Normal file
@ -0,0 +1,25 @@
|
||||
// Code generated by "stringer -type=FeatureName"; DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[UnknownFeature-0]
|
||||
_ = x[VoiceChatAnnounceFeature-1]
|
||||
_ = x[BirthdayAnnounceFeature-2]
|
||||
}
|
||||
|
||||
const _FeatureName_name = "UnknownFeatureVoiceChatAnnounceFeatureBirthdayAnnounceFeature"
|
||||
|
||||
var _FeatureName_index = [...]uint8{0, 14, 38, 61}
|
||||
|
||||
func (i FeatureName) String() string {
|
||||
if i < 0 || i >= FeatureName(len(_FeatureName_index)-1) {
|
||||
return "FeatureName(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _FeatureName_name[_FeatureName_index[i]:_FeatureName_index[i+1]]
|
||||
}
|
188
main.go
188
main.go
@ -1,7 +1,10 @@
|
||||
//go:generate stringer -type=FeatureName
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -40,38 +43,121 @@ func init() {
|
||||
//go:embed schema.cue
|
||||
var schemaFile string
|
||||
|
||||
type FeatureName int
|
||||
|
||||
const (
|
||||
UnknownFeature FeatureName = iota
|
||||
VoiceChatAnnounceFeature
|
||||
BirthdayAnnounceFeature
|
||||
)
|
||||
|
||||
type Feature interface {
|
||||
Name() FeatureName
|
||||
}
|
||||
|
||||
func (c *Config) UnmarshalJSON(in []byte) error {
|
||||
c2 := BaseConfig{}
|
||||
c.featureMap = map[FeatureName]Feature{}
|
||||
err := json.Unmarshal(in, &c2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Server = c2.Server
|
||||
for _, f := range c2.Features {
|
||||
base := BaseFeature{}
|
||||
err := json.Unmarshal(f, &base)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
continue
|
||||
}
|
||||
switch base.Feature {
|
||||
case VoiceChatAnnounceFeature:
|
||||
f2 := VoiceChatAnnounce{}
|
||||
err := json.Unmarshal(f, &f2)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
continue
|
||||
}
|
||||
c.Features = append(c.Features, f2)
|
||||
c.featureMap[VoiceChatAnnounceFeature] = f2
|
||||
case BirthdayAnnounceFeature:
|
||||
f2 := BirthdayAnnounce{}
|
||||
err := json.Unmarshal(f, &f2)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
continue
|
||||
}
|
||||
c.Features = append(c.Features, f2)
|
||||
c.featureMap[BirthdayAnnounceFeature] = f2
|
||||
default:
|
||||
fmt.Println("Unknown feature")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type BaseConfig struct {
|
||||
Server string
|
||||
Features []json.RawMessage
|
||||
}
|
||||
|
||||
type BaseFeature struct {
|
||||
Feature FeatureName
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
type AccounceFeature struct {
|
||||
BaseFeature `json:",inline"`
|
||||
AnnounceChannel string
|
||||
}
|
||||
|
||||
type VoiceChatAnnounce struct {
|
||||
AccounceFeature `json:",inline"`
|
||||
JoinMessages []string
|
||||
CleanUpDelay int
|
||||
}
|
||||
|
||||
func (VoiceChatAnnounce) Name() FeatureName { return VoiceChatAnnounceFeature }
|
||||
|
||||
type BirthdayAnnounce struct {
|
||||
AccounceFeature `json:",inline"`
|
||||
Birthdays []Birthday
|
||||
}
|
||||
|
||||
func (BirthdayAnnounce) Name() FeatureName { return BirthdayAnnounceFeature }
|
||||
|
||||
type Config struct {
|
||||
Server string
|
||||
VoiceChatAnnounce struct {
|
||||
Enable bool
|
||||
AnnounceChannel string
|
||||
JoinMessages []string
|
||||
CleanUpDelay int
|
||||
}
|
||||
BirthdayAnnounce struct {
|
||||
Enable bool
|
||||
AnnounceChannel string
|
||||
Birthdays []Birthday
|
||||
}
|
||||
Server string
|
||||
Features []Feature
|
||||
featureMap map[FeatureName]Feature
|
||||
}
|
||||
|
||||
func (c Config) String() string {
|
||||
s := strings.Builder{}
|
||||
s.WriteString(fmt.Sprintf("Guild ID: %s\n", c.Server))
|
||||
if c.VoiceChatAnnounce.Enable {
|
||||
s.WriteString("\tVoice Chat Accounce: ✅ \n")
|
||||
s.WriteString(fmt.Sprintf("\t\tTo Channel: %s\n", c.VoiceChatAnnounce.AnnounceChannel))
|
||||
s.WriteString(fmt.Sprintf("\t\t %d Custom messages\n", len(c.VoiceChatAnnounce.JoinMessages)))
|
||||
} else {
|
||||
s.WriteString("\tVoice Chat Accounce: ❌ \n")
|
||||
}
|
||||
if c.BirthdayAnnounce.Enable {
|
||||
s.WriteString("\tBirthday Accounce: ✅ \n")
|
||||
s.WriteString(fmt.Sprintf("\t\tTo Channel: %s\n", c.BirthdayAnnounce.AnnounceChannel))
|
||||
s.WriteString(fmt.Sprintf("\t\t %d Birthdays to Announce\n", len(c.BirthdayAnnounce.Birthdays)))
|
||||
} else {
|
||||
s.WriteString("\tBirthday Accounce: ❌ \n")
|
||||
for _, f := range c.Features {
|
||||
switch f2 := f.(type) {
|
||||
case VoiceChatAnnounce:
|
||||
if f2.Enabled {
|
||||
s.WriteString("\tVoice Chat Accounce: ✅ \n")
|
||||
s.WriteString(fmt.Sprintf("\t\tTo Channel: %s\n", f2.AnnounceChannel))
|
||||
s.WriteString(fmt.Sprintf("\t\t %d Custom messages\n", len(f2.JoinMessages)))
|
||||
} else {
|
||||
s.WriteString("\tVoice Chat Accounce: ❌ \n")
|
||||
}
|
||||
|
||||
case BirthdayAnnounce:
|
||||
if f2.Enabled {
|
||||
s.WriteString("\tBirthday Accounce: ✅ \n")
|
||||
s.WriteString(fmt.Sprintf("\t\tTo Channel: %s\n", f2.AnnounceChannel))
|
||||
s.WriteString(fmt.Sprintf("\t\t %d Birthdays to Announce\n", len(f2.Birthdays)))
|
||||
} else {
|
||||
s.WriteString("\tBirthday Accounce: ❌ \n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s.String()
|
||||
}
|
||||
|
||||
@ -123,6 +209,10 @@ func NewServer(dbFile string) (*Server, error) {
|
||||
}
|
||||
|
||||
func (s *Server) AddConfig(c Config) {
|
||||
c.featureMap = map[FeatureName]Feature{}
|
||||
for _, f := range c.Features {
|
||||
c.featureMap[f.Name()] = f
|
||||
}
|
||||
s.configs[c.Server] = c
|
||||
log.Printf("Added server: \n%s\n", c)
|
||||
}
|
||||
@ -233,11 +323,25 @@ func (s VoiceState) String() string {
|
||||
|
||||
// Handle for when someone joins a voice channel - send notification about them joining.
|
||||
func (s *Server) voiceStatus(ds *discordgo.Session, m *discordgo.VoiceStateUpdate) {
|
||||
guild, _ := ds.Guild(m.VoiceState.GuildID)
|
||||
server := s.configs[guild.ID]
|
||||
if !server.VoiceChatAnnounce.Enable {
|
||||
guild, err := ds.Guild(m.VoiceState.GuildID)
|
||||
if err != nil {
|
||||
log.Printf("Unable to get Guild info: %s", err.Error())
|
||||
return
|
||||
}
|
||||
server, serverConfigured := s.configs[guild.ID]
|
||||
if !serverConfigured {
|
||||
log.Printf("Server %q not configured", guild.Name)
|
||||
return
|
||||
}
|
||||
|
||||
vc, ok := server.featureMap[VoiceChatAnnounceFeature]
|
||||
if !ok {
|
||||
log.Printf("Server %q not configured for voice chat announcements", guild.Name)
|
||||
return
|
||||
}
|
||||
|
||||
config := vc.(VoiceChatAnnounce)
|
||||
|
||||
var state VoiceState
|
||||
switch {
|
||||
case len(m.ChannelID) == 0:
|
||||
@ -277,12 +381,12 @@ func (s *Server) voiceStatus(ds *discordgo.Session, m *discordgo.VoiceStateUpdat
|
||||
return
|
||||
}
|
||||
|
||||
ch, err := ds.Channel(server.VoiceChatAnnounce.AnnounceChannel)
|
||||
ch, err := ds.Channel(config.AnnounceChannel)
|
||||
if err != nil {
|
||||
log.Printf("Unable to get announce channel for Guild: %s", m.GuildID)
|
||||
return
|
||||
}
|
||||
messages := append(joinMessages, server.VoiceChatAnnounce.JoinMessages...)
|
||||
messages := append(joinMessages, config.JoinMessages...)
|
||||
|
||||
msg := fmt.Sprintf(messages[rand.IntN(len(messages))], m.UserID, m.ChannelID)
|
||||
switch state {
|
||||
@ -295,7 +399,7 @@ func (s *Server) voiceStatus(ds *discordgo.Session, m *discordgo.VoiceStateUpdat
|
||||
log.Printf("unable to send message: %s", err)
|
||||
}
|
||||
|
||||
time.AfterFunc(time.Second*time.Duration(server.VoiceChatAnnounce.CleanUpDelay), func() {
|
||||
time.AfterFunc(time.Second*time.Duration(config.CleanUpDelay), func() {
|
||||
ds.ChannelMessageDelete(sent.ChannelID, sent.ID)
|
||||
})
|
||||
}
|
||||
@ -303,10 +407,15 @@ func (s *Server) voiceStatus(ds *discordgo.Session, m *discordgo.VoiceStateUpdat
|
||||
func (s *Server) setupBirthdayWatch(ds *discordgo.Session) error {
|
||||
birthdays := map[string][]Birthday{} // Use a list in case there are collisions (See birthday paradox)
|
||||
for _, guild := range s.configs {
|
||||
if !guild.BirthdayAnnounce.Enable {
|
||||
ba, ok := guild.featureMap[BirthdayAnnounceFeature]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, b := range guild.BirthdayAnnounce.Birthdays {
|
||||
config, ok := ba.(BirthdayAnnounce)
|
||||
if !ok || !config.Enabled {
|
||||
continue
|
||||
}
|
||||
for _, b := range config.Birthdays {
|
||||
b.server = guild.Server
|
||||
birthdays[b.Date] = append(birthdays[b.Date], b)
|
||||
}
|
||||
@ -332,14 +441,21 @@ func (s *Server) setupBirthdayWatch(ds *discordgo.Session) error {
|
||||
if bd, ok := birthdays[dateString]; ok {
|
||||
for _, b := range bd {
|
||||
log.Printf("It is %q's birthday today (%s)", b.Member, b.Date)
|
||||
if err := announceBirthday(ds, b.server, s.configs[b.server].BirthdayAnnounce.AnnounceChannel, b.Member); err != nil {
|
||||
ba, ok := s.configs[b.server].featureMap[BirthdayAnnounceFeature]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
config, ok := ba.(BirthdayAnnounce)
|
||||
if !ok || !config.Enabled {
|
||||
continue
|
||||
}
|
||||
if err := announceBirthday(ds, config.AnnounceChannel, b.Member); err != nil {
|
||||
log.Printf("Error w/ announcing: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
time.AfterFunc(initialDelay, func() {
|
||||
|
||||
log.Printf("Birthday watcher initiated")
|
||||
// Run now, but also set up a daily job
|
||||
birthdayMatcher(ds)
|
||||
@ -352,7 +468,7 @@ func (s *Server) setupBirthdayWatch(ds *discordgo.Session) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func announceBirthday(ds *discordgo.Session, guildID, channelID, userId string) error {
|
||||
func announceBirthday(ds *discordgo.Session, channelID, userId string) error {
|
||||
_, err := ds.ChannelMessageSend(channelID, fmt.Sprintf("Happy Birthday to <@%s>!!", userId))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to send message: %w", err)
|
||||
|
54
schema.cue
54
schema.cue
@ -4,28 +4,50 @@
|
||||
|
||||
package main
|
||||
|
||||
#FeatureName: int // #enumFeatureName
|
||||
|
||||
#enumFeatureName:
|
||||
#VoiceChatAnnounceFeature |
|
||||
#BirthdayAnnounceFeature
|
||||
|
||||
#values_FeatureName: {
|
||||
VoiceChatAnnounceFeature: #VoiceChatAnnounceFeature
|
||||
BirthdayAnnounceFeature: #BirthdayAnnounceFeature
|
||||
}
|
||||
|
||||
#VoiceChatAnnounceFeature: #FeatureName & 1
|
||||
#BirthdayAnnounceFeature: #FeatureName & 2
|
||||
|
||||
#Feature: _
|
||||
|
||||
#BaseFeature: {
|
||||
Feature!: #enumFeatureName
|
||||
Enabled: bool | *true
|
||||
...
|
||||
}
|
||||
|
||||
#AccounceFeature: #BaseFeature & {
|
||||
AnnounceChannel!: string
|
||||
}
|
||||
|
||||
#VoiceChatAnnounce: #AccounceFeature & {
|
||||
Feature: #VoiceChatAnnounceFeature
|
||||
JoinMessages: [...string] @go(,[]string)
|
||||
CleanUpDelay: int | *100
|
||||
}
|
||||
|
||||
#BirthdayAnnounce: #AccounceFeature &{
|
||||
Feature: #BirthdayAnnounceFeature
|
||||
Birthdays: [...#Birthday] @go(,[]Birthday)
|
||||
}
|
||||
|
||||
#Config: {
|
||||
Server: string
|
||||
VoiceChatAnnounce?: {
|
||||
Enable: bool | *false
|
||||
AnnounceChannel: string | *""
|
||||
JoinMessages: [...string] @go(,[]string)
|
||||
CleanUpDelay: int | *30
|
||||
} @go(,struct{Enable bool; AnnounceChannel string; JoinMessages []string; CleanUpDelay int})
|
||||
BirthdayAnnounce?: {
|
||||
Enable: bool | *false
|
||||
AnnounceChannel: string | *""
|
||||
Birthdays: [...#Birthday] @go(,[]Birthday)
|
||||
} @go(,struct{Enable bool; AnnounceChannel string; Birthdays []Birthday})
|
||||
Features: [...#Feature] @go(,[]Feature)
|
||||
}
|
||||
|
||||
#Birthday: {
|
||||
Name: string
|
||||
Member: string
|
||||
Date: string
|
||||
}
|
||||
|
||||
#Enabled: {
|
||||
Enable: true
|
||||
...
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user