From 6e909bca5db12f17b9a9004850ac519cc58355e7 Mon Sep 17 00:00:00 2001 From: Wessie Date: Sun, 26 May 2024 16:10:41 +0100 Subject: [PATCH] ircbot: make AnnounceUser only announce if the name is different AnnounceUser also won't announce nil values anymore until a timeout period has been elapsed. storage/test: add track retrieval test util: make CallbackTimer.Stop guard against a nil timer --- ircbot/api.go | 33 +++++++++++++++++++++++++++------ storage/test/track.go | 42 ++++++++++++++++++++++++++++++++++++++++++ util/util.go | 3 +++ 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/ircbot/api.go b/ircbot/api.go index f5d91274..ae5593c6 100644 --- a/ircbot/api.go +++ b/ircbot/api.go @@ -12,6 +12,7 @@ import ( "github.com/R-a-dio/valkyrie/config" "github.com/R-a-dio/valkyrie/errors" "github.com/R-a-dio/valkyrie/rpc" + "github.com/R-a-dio/valkyrie/util" "github.com/lrstanley/girc" "github.com/rs/zerolog" "google.golang.org/grpc" @@ -25,11 +26,16 @@ func NewGRPCServer(ctx context.Context, service radio.AnnounceService) (*grpc.Se } func NewAnnounceService(cfg config.Config, storage radio.StorageService, bot *Bot) radio.AnnounceService { - return &announceService{ + ann := &announceService{ Config: cfg, Storage: storage, bot: bot, } + ann.userTimer = util.NewCallbackTimer(func() { + message := Fmt("Current DJ: {red}None") + ann.bot.c.Cmd.Message(ann.Conf().IRC.MainChannel, message) + }) + return ann } type announceService struct { @@ -40,6 +46,10 @@ type announceService struct { lastAnnounceSongTime time.Time lastAnnounceSong radio.Song + userTimer *util.CallbackTimer + userMu sync.Mutex + userLast string + topicTimerMu sync.Mutex topicTimer *time.Timer topicLastEdit time.Time @@ -237,12 +247,23 @@ func (ann *announceService) AnnounceRequest(ctx context.Context, song radio.Song } func (ann *announceService) AnnounceUser(ctx context.Context, user *radio.User) error { - name := "None" - if user.IsValid() { - name = user.DJ.Name + const userDelay = time.Second * 15 + + if !user.IsValid() { + // only announce no-dj after a period of it being no-dj + ann.userTimer.Start(userDelay) + return nil + } + ann.userTimer.Stop() + + ann.userMu.Lock() + defer ann.userMu.Unlock() + if ann.userLast == user.DJ.Name { + return nil } - message := Fmt("Current DJ: {green}%s", name) + ann.userLast = user.DJ.Name + message := Fmt("Current DJ: {green}%s", user.DJ.Name) ann.bot.c.Cmd.Message(ann.Conf().IRC.MainChannel, message) ann.queueChangeTopic(ctx, user) @@ -250,7 +271,7 @@ func (ann *announceService) AnnounceUser(ctx context.Context, user *radio.User) } func (ann *announceService) queueChangeTopic(ctx context.Context, user *radio.User) { - const topicDelay = time.Second * 15 + const topicDelay = time.Second * 30 ann.topicTimerMu.Lock() if ann.topicTimer != nil { diff --git a/storage/test/track.go b/storage/test/track.go index 447873f2..5ccf6c51 100644 --- a/storage/test/track.go +++ b/storage/test/track.go @@ -42,6 +42,44 @@ func (suite *Suite) TestSongCreateAndRetrieve(t *testing.T) { } } +func (suite *Suite) TestSongCreateAndRetrieveWithTrack(t *testing.T) { + ss := suite.Storage(t).Song(suite.ctx) + ts := suite.Storage(t).Track(suite.ctx) + + song := radio.Song{ + Metadata: "test-song-create-and-retrieve", + Length: time.Second * 300, + DatabaseTrack: &radio.DatabaseTrack{ + Title: "testing title", + Artist: "testing artist", + Album: "testing album", + }, + } + song.Hydrate() + + tid, err := ts.Insert(song) + if assert.NoError(t, err) { + assert.NotZero(t, tid) + } + song.TrackID = tid + + fromHash, err := ss.FromHash(song.Hash) + if assert.NoError(t, err) { + assert.NotNil(t, fromHash) + assert.True(t, song.EqualTo(*fromHash)) + assert.Equal(t, song.Length, fromHash.Length) + assert.Equal(t, song.DatabaseTrack, fromHash.DatabaseTrack) + } + + fromMetadata, err := ss.FromMetadata(song.Metadata) + if assert.NoError(t, err) { + assert.NotNil(t, fromMetadata) + assert.True(t, song.EqualTo(*fromMetadata)) + assert.Equal(t, song.Length, fromMetadata.Length) + assert.Equal(t, song.DatabaseTrack, fromMetadata.DatabaseTrack) + } +} + func (suite *Suite) TestSongLastPlayed(t *testing.T) { ss := suite.Storage(t).Song(suite.ctx) @@ -194,4 +232,8 @@ func (suite *Suite) TestSongFavoritesOf(t *testing.T) { require.NoError(t, err) require.Len(t, faves, limit) require.Equal(t, faveCountExpected, count) + + db, err := ss.FavoritesOfDatabase(nick) + require.NoError(t, err) + require.Len(t, db, 0) } diff --git a/util/util.go b/util/util.go index 95f2efd4..bfb5ff44 100644 --- a/util/util.go +++ b/util/util.go @@ -260,6 +260,9 @@ func (tc *CallbackTimer) Start(timeout time.Duration) { // Stop stops the current timer if one exists func (tc *CallbackTimer) Stop() bool { + if tc == nil { + return true + } tc.mu.Lock() defer tc.mu.Unlock() if tc.timer != nil {