Compare commits

..

No commits in common. "55f3f23b356f7f63acb29d8e94e7577006fda7d9" and "2dd919a08fc0ab3848b8e7a28f43f28e161d35d1" have entirely different histories.

3 changed files with 52 additions and 215 deletions

View File

@ -1,25 +0,0 @@
// 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
View File

@ -1,10 +1,7 @@
//go:generate stringer -type=FeatureName
package main package main
import ( import (
"database/sql" "database/sql"
"encoding/json"
"flag" "flag"
"fmt" "fmt"
"io" "io"
@ -43,121 +40,38 @@ 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
Features []Feature VoiceChatAnnounce struct {
featureMap map[FeatureName]Feature Enable bool
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))
for _, f := range c.Features { if c.VoiceChatAnnounce.Enable {
switch f2 := f.(type) { s.WriteString("\tVoice Chat Accounce: ✅ \n")
case VoiceChatAnnounce: s.WriteString(fmt.Sprintf("\t\tTo Channel: %s\n", c.VoiceChatAnnounce.AnnounceChannel))
if f2.Enabled { s.WriteString(fmt.Sprintf("\t\t %d Custom messages\n", len(c.VoiceChatAnnounce.JoinMessages)))
s.WriteString("\tVoice Chat Accounce: ✅ \n") } else {
s.WriteString(fmt.Sprintf("\t\tTo Channel: %s\n", f2.AnnounceChannel)) s.WriteString("\tVoice Chat Accounce: ❌ \n")
s.WriteString(fmt.Sprintf("\t\t %d Custom messages\n", len(f2.JoinMessages))) }
} else { if c.BirthdayAnnounce.Enable {
s.WriteString("\tVoice Chat Accounce: ❌ \n") 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)))
case BirthdayAnnounce: } else {
if f2.Enabled { s.WriteString("\tBirthday Accounce: ❌ \n")
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()
} }
@ -209,10 +123,6 @@ 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)
} }
@ -323,25 +233,11 @@ 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, err := ds.Guild(m.VoiceState.GuildID) guild, _ := ds.Guild(m.VoiceState.GuildID)
if err != nil { server := s.configs[guild.ID]
log.Printf("Unable to get Guild info: %s", err.Error()) if !server.VoiceChatAnnounce.Enable {
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:
@ -381,12 +277,12 @@ func (s *Server) voiceStatus(ds *discordgo.Session, m *discordgo.VoiceStateUpdat
return return
} }
ch, err := ds.Channel(config.AnnounceChannel) ch, err := ds.Channel(server.VoiceChatAnnounce.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, config.JoinMessages...) messages := append(joinMessages, server.VoiceChatAnnounce.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 {
@ -399,7 +295,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(config.CleanUpDelay), func() { time.AfterFunc(time.Second*time.Duration(server.VoiceChatAnnounce.CleanUpDelay), func() {
ds.ChannelMessageDelete(sent.ChannelID, sent.ID) ds.ChannelMessageDelete(sent.ChannelID, sent.ID)
}) })
} }
@ -407,15 +303,10 @@ 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 {
ba, ok := guild.featureMap[BirthdayAnnounceFeature] if !guild.BirthdayAnnounce.Enable {
if !ok {
continue continue
} }
config, ok := ba.(BirthdayAnnounce) for _, b := range guild.BirthdayAnnounce.Birthdays {
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)
} }
@ -441,21 +332,14 @@ 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)
ba, ok := s.configs[b.server].featureMap[BirthdayAnnounceFeature] if err := announceBirthday(ds, b.server, s.configs[b.server].BirthdayAnnounce.AnnounceChannel, b.Member); err != nil {
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)
@ -468,7 +352,7 @@ func (s *Server) setupBirthdayWatch(ds *discordgo.Session) error {
return nil return nil
} }
func announceBirthday(ds *discordgo.Session, channelID, userId string) error { func announceBirthday(ds *discordgo.Session, guildID, 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)

View File

@ -4,46 +4,19 @@
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
Features: [...#Feature] @go(,[]Feature) 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})
} }
#Birthday: { #Birthday: {
@ -51,3 +24,8 @@ package main
Member: string Member: string
Date: string Date: string
} }
#Enabled: {
Enable: true
...
}