Overhaul the entire database layer force it to only use bitcask for the time being
--- a/database/bitcask.go Fri Apr 19 15:34:30 2019 -0500
+++ b/database/bitcask.go Fri May 10 22:41:06 2019 -0500
@@ -1,72 +1,31 @@
+ "github.com/prologic/bitcask" - "github.com/prologic/bitcask"
- log "github.com/sirupsen/logrus"
-type db_bitcask struct {
- database *bitcask.Bitcask
- database, _ := bitcask.Open("./db")
- Register("bitcask", db_bitcask{
-func (db db_bitcask) GetGuild(guildid string) *Guild {
- data, err := db.database.Get(guildid)
- if err != nil || len(data) == 0 {
- log.Errorf("Bitcask GetGuild error: %s", err)
- // We need to return a empty Guild object
+func Open(filename string) error { + database, err := bitcask.Open(filename) - guild := toGuildObject(data)
-func (db db_bitcask) AddGuild(guild *Guild) {
- err := db.database.Put(guild.ID, toJsonObject(*guild))
- log.Errorf("Bitcask AddGuild error: %s", err)
-func (db db_bitcask) UpdateGuild(guild *Guild) {
-func (db db_bitcask) AlreadyPostedStatus(channelid, streamid string) bool {
- data, err := db.database.Get("alp_" + channelid)
- if err != nil || len(data) == 0 {
- log.Errorf("Bitcask AlreadySend error: %s", err)
- return strings.EqualFold(streamid, string(data))
-func (db db_bitcask) AddStatusUpdate(channelid, streamid string) error {
- if db.AlreadyPostedStatus("alp_"+channelid, streamid) {
- return fmt.Errorf("Bitcask AddStatusUpdate failed for %s -> %s", channelid, streamid)
- return db.database.Put(channelid, []byte(streamid))
-func (db db_bitcask) Close() {
--- a/database/database.go Fri Apr 19 15:34:30 2019 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
- log "github.com/sirupsen/logrus"
-type Database interface {
- GetGuild(guildid string) *Guild
- UpdateGuild(guild *Guild)
- AlreadyPostedStatus(channelid, streamid string) bool
- AddStatusUpdate(channelid, streamid string) error
-var supported map[string]Database
-func Register(name string, db Database) {
- if len(supported) <= 0 {
- supported = make(map[string]Database)
-func Get(name string) Database {
-func Supported() []string {
- ret := make([]string, len(supported))
- for n, _ := range supported {
-func toGuildObject(data []byte) Guild {
- err := json.Unmarshal(data, &item)
- log.Errorf("toGuildObject failed: %#v", err)
-func toJsonObject(guild Guild) []byte {
- data, err := json.Marshal(guild)
- log.Errorf("toJsonObject failed: %#v", err)
--- a/database/guild.go Fri Apr 19 15:34:30 2019 -0500
+++ b/database/guild.go Fri May 10 22:41:06 2019 -0500
@@ -1,41 +1,45 @@
-// TODO: enable more features like config
+ log "github.com/sirupsen/logrus"
+ ID string `json:"guild_id"` + Channel string `json:"announce_channel"` + History map[string]string `json:"history"` + Ignore []string `json:"ignore"` -// TODO: add methods to channel that let us use this system more
-func (guild *Guild) HasChannel(channel string) bool {
- for _, g := range guild.Channels {
+func LoadGuild(id string) (*Guild, error) { + data, err := db.Get("guild-" + id) + log.Debugf("guild %s not found : %v", id, err) + log.Infof("guild %s not found, creating new", id)
+ json.Unmarshal(data, guild) -func (guild *Guild) AddChannel(channel string) {
- if guild.HasChannel(channel) {
+ // if the load failed for any reason we create a new one + guild.History = map[string]string{} + guild.Ignore = []string{} - guild.Channels = append(guild.Channels, Channel{channel})
-func (guild *Guild) RemoveChannel(channel string) {
- newChannels := make([]Channel, 0)
- for _, g := range guild.Channels {
- newChannels = append(newChannels, g)
+func (g *Guild) Save() error { + data, err := json.Marshal(g) - guild.Channels = newChannels
+ return db.Put("guild-"+g.ID, data) --- a/discord/command_remove_channel.go Fri Apr 19 15:34:30 2019 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
- "github.com/bwmarrin/discordgo"
-type commandRemoveChannel struct{}
-func (cmd *commandRemoveChannel) Help() string {
- return "removes the channel from the bot to send messages to"
-func (cmd *commandRemoveChannel) Run(args []string, c *DiscordClient, m *discordgo.MessageCreate) (interface{}, error) {
- guild := c.db.GetGuild(m.GuildID)
- return "This guild is not registered please use `set-channel`", nil
- if !guild.HasChannel(m.ChannelID) {
- return fmt.Sprintf("<#%s> is not a registered channel, please use `set-channel`", m.ChannelID), nil
- guild.RemoveChannel(m.ChannelID)
- c.db.UpdateGuild(guild)
- return fmt.Sprintf("<#%s> has been removed from the channels list", m.ChannelID), nil
--- a/discord/command_set_channel.go Fri Apr 19 15:34:30 2019 -0500
+++ b/discord/command_set_channel.go Fri May 10 22:41:06 2019 -0500
@@ -4,6 +4,8 @@
"github.com/bwmarrin/discordgo"
+ "bitbucket.org/TheToyz/nowdead/database" type commandSetChannel struct{}
@@ -13,17 +15,17 @@
func (cmd *commandSetChannel) Run(args []string, c *DiscordClient, m *discordgo.MessageCreate) (interface{}, error) {
- guild := c.db.GetGuild(m.GuildID)
- guild.AddChannel(m.ChannelID)
+ guild, err := database.LoadGuild(m.GuildID) + if guild.Channel != m.ChannelID { + guild.Channel = m.ChannelID return fmt.Sprintf("Set <#%s> as the announcement channel", m.ChannelID), nil
- // TODO: actually make this do something other then update
- c.db.UpdateGuild(guild)
- return fmt.Sprintf("<#%s> is already set as a registered channel", m.ChannelID), nil
+ return fmt.Sprintf("<#%s> is already set as the announcement channel", m.ChannelID), nil --- a/discord/commands.go Fri Apr 19 15:34:30 2019 -0500
+++ b/discord/commands.go Fri May 10 22:41:06 2019 -0500
@@ -20,7 +20,6 @@
commands.Set("help", &commandHelp{})
commands.Set("set-channel", &commandSetChannel{})
- commands.Set("remove-channel", &commandRemoveChannel{})
commands.Set("status", &commandStatus{})
commands.Set("uptime", &commandUptime{})
--- a/discord/discord.go Fri Apr 19 15:34:30 2019 -0500
+++ b/discord/discord.go Fri May 10 22:41:06 2019 -0500
@@ -1,7 +1,6 @@
@@ -13,14 +12,13 @@
type DiscordClient struct {
client *discordgo.Session
-func New(token string, db database.Database) (*DiscordClient, error) {
+func New(token string) (*DiscordClient, error) { client, err := discordgo.New("Bot " + strings.TrimSpace(token))
@@ -28,7 +26,6 @@
started: time.Now().UTC(),
@@ -55,20 +52,12 @@
func (c *DiscordClient) send(guildID, message string) error {
- // channelID := c.db.GetChannel(guild)
- guild := c.db.GetGuild(guildID)
- return errors.New("Guild does not exist")
+ guild, err := database.LoadGuild(guildID) - if len(guild.Channels) == 0 || guild.Channels[0].ID == "" {
- return errors.New("No channel set")
- channelID := guild.Channels[0].ID
- return c.sendChannel(channelID, message)
+ return c.sendChannel(guild.Channel, message) func (c *DiscordClient) sendChannel(channelID, message string) error {
--- a/discord/presence.go Fri Apr 19 15:34:30 2019 -0500
+++ b/discord/presence.go Fri May 10 22:41:06 2019 -0500
@@ -8,6 +8,7 @@
"github.com/dustin/go-humanize"
log "github.com/sirupsen/logrus"
+ "bitbucket.org/TheToyz/nowdead/database" "bitbucket.org/TheToyz/nowdead/presence"
@@ -20,19 +21,27 @@
- guild, _ := c.client.Guild(p.GuildID)
+ guild, err := database.LoadGuild(p.GuildID) + log.Errorf("error loading guild: %v", err) - log.Infof("server: %s username: %s is now streaming", guild.Name, p.Presence.User.Username)
+ log.Infof("server: %s username: %s is now streaming", guild.ID, p.Presence.User.Username) presence, _ := presence.GetPresence(p.Game.URL)
- if c.db.AlreadyPostedStatus(presence.UserID, presence.StreamID) {
- log.Debugf("already sent presence to guild %s: %v", p.GuildID, presence)
+ if lastID, ok := guild.History[presence.UserID]; ok { + if lastID == presence.StreamID { + log.Infof("already sent presence to guild %s: %v", p.GuildID, presence) - if err := c.db.AddStatusUpdate(presence.UserID, presence.StreamID); err != nil {
- log.Warnf("failed to add user (%s) stream (%s) to database, %v", presence.UserID, presence.StreamID, err)
+ guild.History[presence.UserID] = presence.StreamID + log.Warnf("failed to save stream update for %s: %v", presence.UserID, err) if err := c.sendPresence(p.GuildID, presence); err != nil {
@@ -41,18 +50,20 @@
func (c *DiscordClient) sendPresence(guildID string, presence presence.Presence) error {
- guild := c.db.GetGuild(guildID)
+ guild, err := database.LoadGuild(guildID) return errors.New("Guild does not exist")
- if len(guild.Channels) == 0 || guild.Channels[0].ID == "" {
+ if guild.Channel == "" { return errors.New("No channel set")
- channelID := guild.Channels[0].ID
- return c.sendPresenceChannel(channelID, presence)
+ return c.sendPresenceChannel(guild.Channel, presence) func (c *DiscordClient) sendPresenceChannel(channelID string, presence presence.Presence) error {
--- a/main.go Fri Apr 19 15:34:30 2019 -0500
+++ b/main.go Fri May 10 22:41:06 2019 -0500
@@ -25,11 +25,7 @@
discordToken = app.Flag("discord-token", "The bot token for discord").Short('d').Envar("NOWDEAD_DISCORD_TOKEN").Required().String()
twitchClientID = app.Flag("twitch-client-id", "The client id").Short('t').Envar("NOWDEAD_TWITCH_CLIENT_ID").Required().String()
- databaseType = app.Flag("database", "The database engine to use").Default("bitcask").Enum(database.Supported()...)
@@ -44,7 +40,11 @@
- db = database.Get(*databaseType)
+ if err := database.Open("db"); err != nil { + log.Errorf("failed to open database: %v", err) if len(*twitchClientID) > 0 {
provider, err := twitch.New(*twitchClientID)
@@ -60,7 +60,7 @@
errChan := make(chan error, 1)
// create the discord client
- dc, err := discord.New(*discordToken, db)
+ dc, err := discord.New(*discordToken) fmt.Println("error creating Discord session,", err)