Compare commits
	
		
			No commits in common. "55f3f23b356f7f63acb29d8e94e7577006fda7d9" and "2dd919a08fc0ab3848b8e7a28f43f28e161d35d1" have entirely different histories.
		
	
	
		
			55f3f23b35
			...
			2dd919a08f
		
	
		
@ -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
									
									
									
									
									
								
							
							
						
						
									
										188
									
								
								main.go
									
									
									
									
									
								
							@ -1,10 +1,7 @@
 | 
			
		||||
//go:generate stringer -type=FeatureName
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
@ -43,121 +40,38 @@ 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
 | 
			
		||||
	Features   []Feature
 | 
			
		||||
	featureMap map[FeatureName]Feature
 | 
			
		||||
	Server            string
 | 
			
		||||
	VoiceChatAnnounce struct {
 | 
			
		||||
		Enable          bool
 | 
			
		||||
		AnnounceChannel string
 | 
			
		||||
		JoinMessages    []string
 | 
			
		||||
		CleanUpDelay    int
 | 
			
		||||
	}
 | 
			
		||||
	BirthdayAnnounce struct {
 | 
			
		||||
		Enable          bool
 | 
			
		||||
		AnnounceChannel string
 | 
			
		||||
		Birthdays       []Birthday
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c Config) String() string {
 | 
			
		||||
	s := strings.Builder{}
 | 
			
		||||
	s.WriteString(fmt.Sprintf("Guild ID: %s\n", c.Server))
 | 
			
		||||
	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")
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	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")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -209,10 +123,6 @@ 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)
 | 
			
		||||
}
 | 
			
		||||
@ -323,25 +233,11 @@ 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, err := ds.Guild(m.VoiceState.GuildID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Unable to get Guild info: %s", err.Error())
 | 
			
		||||
	guild, _ := ds.Guild(m.VoiceState.GuildID)
 | 
			
		||||
	server := s.configs[guild.ID]
 | 
			
		||||
	if !server.VoiceChatAnnounce.Enable {
 | 
			
		||||
		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:
 | 
			
		||||
@ -381,12 +277,12 @@ func (s *Server) voiceStatus(ds *discordgo.Session, m *discordgo.VoiceStateUpdat
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ch, err := ds.Channel(config.AnnounceChannel)
 | 
			
		||||
	ch, err := ds.Channel(server.VoiceChatAnnounce.AnnounceChannel)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Unable to get announce channel for Guild: %s", m.GuildID)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	messages := append(joinMessages, config.JoinMessages...)
 | 
			
		||||
	messages := append(joinMessages, server.VoiceChatAnnounce.JoinMessages...)
 | 
			
		||||
 | 
			
		||||
	msg := fmt.Sprintf(messages[rand.IntN(len(messages))], m.UserID, m.ChannelID)
 | 
			
		||||
	switch state {
 | 
			
		||||
@ -399,7 +295,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(config.CleanUpDelay), func() {
 | 
			
		||||
	time.AfterFunc(time.Second*time.Duration(server.VoiceChatAnnounce.CleanUpDelay), func() {
 | 
			
		||||
		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 {
 | 
			
		||||
	birthdays := map[string][]Birthday{} // Use a list in case there are collisions (See birthday paradox)
 | 
			
		||||
	for _, guild := range s.configs {
 | 
			
		||||
		ba, ok := guild.featureMap[BirthdayAnnounceFeature]
 | 
			
		||||
		if !ok {
 | 
			
		||||
		if !guild.BirthdayAnnounce.Enable {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		config, ok := ba.(BirthdayAnnounce)
 | 
			
		||||
		if !ok || !config.Enabled {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		for _, b := range config.Birthdays {
 | 
			
		||||
		for _, b := range guild.BirthdayAnnounce.Birthdays {
 | 
			
		||||
			b.server = guild.Server
 | 
			
		||||
			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 {
 | 
			
		||||
			for _, b := range bd {
 | 
			
		||||
				log.Printf("It is %q's birthday today (%s)", b.Member, b.Date)
 | 
			
		||||
				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 {
 | 
			
		||||
				if err := announceBirthday(ds, b.server, s.configs[b.server].BirthdayAnnounce.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)
 | 
			
		||||
@ -468,7 +352,7 @@ func (s *Server) setupBirthdayWatch(ds *discordgo.Session) error {
 | 
			
		||||
	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))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("unable to send message: %w", err)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										54
									
								
								schema.cue
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								schema.cue
									
									
									
									
									
								
							@ -4,46 +4,19 @@
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
	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: {
 | 
			
		||||
@ -51,3 +24,8 @@ package main
 | 
			
		||||
	Member: string
 | 
			
		||||
	Date:   string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#Enabled: {
 | 
			
		||||
    Enable: true
 | 
			
		||||
    ...
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user