Merge pull request 'Created new config type to use base feature type for easier per-server configs.' (#4) from push-prrnolnltotq into main
Reviewed-on: #4
This commit is contained in:
commit
55f3f23b35
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -40,38 +43,121 @@ func init() {
|
|||||||
//go:embed schema.cue
|
//go:embed schema.cue
|
||||||
var schemaFile string
|
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 {
|
type Config struct {
|
||||||
Server string
|
Server string
|
||||||
VoiceChatAnnounce struct {
|
Features []Feature
|
||||||
Enable bool
|
featureMap map[FeatureName]Feature
|
||||||
AnnounceChannel string
|
|
||||||
JoinMessages []string
|
|
||||||
CleanUpDelay int
|
|
||||||
}
|
|
||||||
BirthdayAnnounce struct {
|
|
||||||
Enable bool
|
|
||||||
AnnounceChannel string
|
|
||||||
Birthdays []Birthday
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Config) String() string {
|
func (c Config) String() string {
|
||||||
s := strings.Builder{}
|
s := strings.Builder{}
|
||||||
s.WriteString(fmt.Sprintf("Guild ID: %s\n", c.Server))
|
s.WriteString(fmt.Sprintf("Guild ID: %s\n", c.Server))
|
||||||
if c.VoiceChatAnnounce.Enable {
|
for _, f := range c.Features {
|
||||||
s.WriteString("\tVoice Chat Accounce: ✅ \n")
|
switch f2 := f.(type) {
|
||||||
s.WriteString(fmt.Sprintf("\t\tTo Channel: %s\n", c.VoiceChatAnnounce.AnnounceChannel))
|
case VoiceChatAnnounce:
|
||||||
s.WriteString(fmt.Sprintf("\t\t %d Custom messages\n", len(c.VoiceChatAnnounce.JoinMessages)))
|
if f2.Enabled {
|
||||||
} else {
|
s.WriteString("\tVoice Chat Accounce: ✅ \n")
|
||||||
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)))
|
||||||
if c.BirthdayAnnounce.Enable {
|
} else {
|
||||||
s.WriteString("\tBirthday Accounce: ✅ \n")
|
s.WriteString("\tVoice Chat 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 {
|
case BirthdayAnnounce:
|
||||||
s.WriteString("\tBirthday Accounce: ❌ \n")
|
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()
|
return s.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +209,10 @@ func NewServer(dbFile string) (*Server, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) AddConfig(c Config) {
|
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
|
s.configs[c.Server] = c
|
||||||
log.Printf("Added server: \n%s\n", 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.
|
// Handle for when someone joins a voice channel - send notification about them joining.
|
||||||
func (s *Server) voiceStatus(ds *discordgo.Session, m *discordgo.VoiceStateUpdate) {
|
func (s *Server) voiceStatus(ds *discordgo.Session, m *discordgo.VoiceStateUpdate) {
|
||||||
guild, _ := ds.Guild(m.VoiceState.GuildID)
|
guild, err := ds.Guild(m.VoiceState.GuildID)
|
||||||
server := s.configs[guild.ID]
|
if err != nil {
|
||||||
if !server.VoiceChatAnnounce.Enable {
|
log.Printf("Unable to get Guild info: %s", err.Error())
|
||||||
return
|
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
|
var state VoiceState
|
||||||
switch {
|
switch {
|
||||||
case len(m.ChannelID) == 0:
|
case len(m.ChannelID) == 0:
|
||||||
@ -277,12 +381,12 @@ func (s *Server) voiceStatus(ds *discordgo.Session, m *discordgo.VoiceStateUpdat
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ch, err := ds.Channel(server.VoiceChatAnnounce.AnnounceChannel)
|
ch, err := ds.Channel(config.AnnounceChannel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to get announce channel for Guild: %s", m.GuildID)
|
log.Printf("Unable to get announce channel for Guild: %s", m.GuildID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
messages := append(joinMessages, server.VoiceChatAnnounce.JoinMessages...)
|
messages := append(joinMessages, config.JoinMessages...)
|
||||||
|
|
||||||
msg := fmt.Sprintf(messages[rand.IntN(len(messages))], m.UserID, m.ChannelID)
|
msg := fmt.Sprintf(messages[rand.IntN(len(messages))], m.UserID, m.ChannelID)
|
||||||
switch state {
|
switch state {
|
||||||
@ -295,7 +399,7 @@ func (s *Server) voiceStatus(ds *discordgo.Session, m *discordgo.VoiceStateUpdat
|
|||||||
log.Printf("unable to send message: %s", err)
|
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)
|
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 {
|
func (s *Server) setupBirthdayWatch(ds *discordgo.Session) error {
|
||||||
birthdays := map[string][]Birthday{} // Use a list in case there are collisions (See birthday paradox)
|
birthdays := map[string][]Birthday{} // Use a list in case there are collisions (See birthday paradox)
|
||||||
for _, guild := range s.configs {
|
for _, guild := range s.configs {
|
||||||
if !guild.BirthdayAnnounce.Enable {
|
ba, ok := guild.featureMap[BirthdayAnnounceFeature]
|
||||||
|
if !ok {
|
||||||
continue
|
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
|
b.server = guild.Server
|
||||||
birthdays[b.Date] = append(birthdays[b.Date], b)
|
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 {
|
if bd, ok := birthdays[dateString]; ok {
|
||||||
for _, b := range bd {
|
for _, b := range bd {
|
||||||
log.Printf("It is %q's birthday today (%s)", b.Member, b.Date)
|
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)
|
log.Printf("Error w/ announcing: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
time.AfterFunc(initialDelay, func() {
|
time.AfterFunc(initialDelay, func() {
|
||||||
|
|
||||||
log.Printf("Birthday watcher initiated")
|
log.Printf("Birthday watcher initiated")
|
||||||
// Run now, but also set up a daily job
|
// Run now, but also set up a daily job
|
||||||
birthdayMatcher(ds)
|
birthdayMatcher(ds)
|
||||||
@ -352,7 +468,7 @@ func (s *Server) setupBirthdayWatch(ds *discordgo.Session) error {
|
|||||||
return nil
|
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))
|
_, err := ds.ChannelMessageSend(channelID, fmt.Sprintf("Happy Birthday to <@%s>!!", userId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to send message: %w", err)
|
return fmt.Errorf("unable to send message: %w", err)
|
||||||
|
54
schema.cue
54
schema.cue
@ -4,28 +4,50 @@
|
|||||||
|
|
||||||
package main
|
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: {
|
#Config: {
|
||||||
Server: string
|
Server: string
|
||||||
VoiceChatAnnounce?: {
|
Features: [...#Feature] @go(,[]Feature)
|
||||||
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})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#Birthday: {
|
#Birthday: {
|
||||||
Name: string
|
Name: string
|
||||||
Member: string
|
Member: string
|
||||||
Date: string
|
Date: string
|
||||||
}
|
|
||||||
|
|
||||||
#Enabled: {
|
|
||||||
Enable: true
|
|
||||||
...
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user