Skip to content

Commit

Permalink
feat(lyric): add view
Browse files Browse the repository at this point in the history
  • Loading branch information
Topvennie committed Dec 1, 2024
1 parent 56de0fd commit 31ec12a
Show file tree
Hide file tree
Showing 20 changed files with 931 additions and 116 deletions.
4 changes: 4 additions & 0 deletions config/development.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,7 @@ interval_s = 60

[tui.gamification]
interval_s = 3600

[tui.song]
interval_current_s = 5
interval_top_s = 3600
6 changes: 3 additions & 3 deletions db/migrations/20241128115057_alter_song_table_add_lyrics.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ ADD COLUMN lyrics TEXT;
-- +goose Down
-- +goose StatementBegin
ALTER TABLE song
DROP COLUMN isrc_id;
DROP COLUMN lyrics;

ALTER TABLE song
DROP COLUMN lyrics;
DROP COLUMN lyrics_type;

ALTER TABLE song
DROP COLUMN common_id;
DROP COLUMN album;
-- +goose StatementEnd
39 changes: 38 additions & 1 deletion db/queries/song.sql
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ FROM song_artist
WHERE name = ?;

-- name: GetLastSongFull :many
SELECT s.title AS song_title, s.spotify_id, s.album, s.duration_ms, s.lyrics_type, s.lyrics, a.name AS artist_name, g.genre AS genre
SELECT s.id, s.title AS song_title, s.spotify_id, s.album, s.duration_ms, s.lyrics_type, s.lyrics, sh.created_at, a.id AS artist_id, a.name AS artist_name, a.spotify_id AS artist_spotify_id, a.followers AS artist_followers, a.popularity AS artist_popularity, g.id AS genre_id, g.genre AS genre, sh.created_at
FROM song_history sh
JOIN song s ON sh.song_id = s.id
LEFT JOIN song_artist_song sa ON s.id = sa.song_id
Expand All @@ -69,3 +69,40 @@ LEFT JOIN song_artist_genre ag ON ag.artist_id = a.id
LEFT JOIN song_genre g ON ag.genre_id = g.id
WHERE sh.created_at = (SELECT MAX(created_at) FROM song_history)
ORDER BY a.name, g.genre;

-- name: GetSongHistory :many
SELECT s.title
FROM song_history sh
JOIN song s ON sh.song_id = s.id
ORDER BY created_at DESC
LIMIT 5;

-- name: GetTopSongs :many
SELECT s.id AS song_id, s.title, COUNT(sh.id) AS play_count
FROM song_history sh
JOIN song s ON sh.song_id = s.id
GROUP BY s.id, s.title
ORDER BY play_count DESC
LIMIT 5;

-- name: GetTopArtists :many
SELECT sa.id AS artist_id, sa.name AS artist_name, COUNT(sh.id) AS total_plays
FROM song_history sh
JOIN song s ON sh.song_id = s.id
JOIN song_artist_song sas ON s.id = sas.song_id
JOIN song_artist sa ON sas.artist_id = sa.id
GROUP BY sa.id, sa.name
ORDER BY total_plays DESC
LIMIT 5;

-- name: GetTopGenres :many
SELECT g.genre AS genre_name, COUNT(sh.id) AS total_plays
FROM song_history sh
JOIN song s ON sh.song_id = s.id
JOIN song_artist_song sas ON s.id = sas.song_id
JOIN song_artist sa ON sas.artist_id = sa.id
JOIN song_artist_genre sag ON sa.id = sag.artist_id
JOIN song_genre g ON sag.genre_id = g.id
GROUP BY g.genre
ORDER BY total_plays DESC
LIMIT 5;
9 changes: 5 additions & 4 deletions internal/cmd/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

var screens = map[string]func(*db.DB) screen.Screen{
"cammie": screen.NewCammie,
"song": screen.NewSong,
"test": screen.NewTest,
}

Expand All @@ -42,7 +43,7 @@ func TUI(db *db.DB) error {
for _, updateData := range screen.GetUpdateViews() {
done := make(chan bool)
dones = append(dones, done)
go tuiPeriodicUpdates(db, p, updateData, done)
go tuiPeriodicUpdates(p, updateData, done)
}

_, err := p.Run()
Expand All @@ -54,14 +55,14 @@ func TUI(db *db.DB) error {
return err
}

func tuiPeriodicUpdates(db *db.DB, p *tea.Program, updateData view.UpdateData, done chan bool) {
func tuiPeriodicUpdates(p *tea.Program, updateData view.UpdateData, done chan bool) {
zap.S().Info("TUI: Starting periodic update for ", updateData.Name, " with an interval of ", updateData.Interval, " seconds")

ticker := time.NewTicker(time.Duration(updateData.Interval) * time.Second)
defer ticker.Stop()

// Immediatly update once
msg, err := updateData.Update(db, updateData.View)
msg, err := updateData.Update(updateData.View)
if err != nil {
zap.S().Error("TUI: Error updating ", updateData.Name, "\n", err)
}
Expand All @@ -77,7 +78,7 @@ func tuiPeriodicUpdates(db *db.DB, p *tea.Program, updateData view.UpdateData, d
return
case <-ticker.C:
// Update
msg, err := updateData.Update(db, updateData.View)
msg, err := updateData.Update(updateData.View)
if err != nil {
zap.S().Error("TUI: Error updating ", updateData.Name, "\n", err)
}
Expand Down
63 changes: 63 additions & 0 deletions internal/pkg/db/dto/song.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dto

import (
"database/sql"
"time"

"github.com/zeusWPI/scc/internal/pkg/db/sqlc"
)
Expand All @@ -15,6 +16,7 @@ type Song struct {
DurationMS int64 `json:"duration_ms"`
LyricsType string `json:"lyrics_type"` // Either 'synced' or 'plain'
Lyrics string `json:"lyrics"`
CreatedAt time.Time `json:"created_at"`
Artists []SongArtist `json:"artists"`
}

Expand Down Expand Up @@ -56,6 +58,67 @@ func SongDTO(song sqlc.Song) *Song {
}
}

// SongDTOHistory converts a sqlc.GetLastSongFullRow array to a Song
func SongDTOHistory(songs []sqlc.GetLastSongFullRow) *Song {
if len(songs) == 0 {
return nil
}

var lyricsType string
if songs[0].LyricsType.Valid {
lyricsType = songs[0].LyricsType.String
}
var lyrics string
if songs[0].Lyrics.Valid {
lyrics = songs[0].Lyrics.String
}

artistsMap := make(map[int64]SongArtist)
for _, song := range songs {
if !song.ArtistID.Valid {
continue
}

// Get artist
artist, ok := artistsMap[song.ArtistID.Int64]
if !ok {
// Artist doesn't exist yet, add him
artist = SongArtist{
ID: song.ArtistID.Int64,
Name: song.ArtistName.String,
SpotifyID: song.ArtistSpotifyID.String,
Followers: song.ArtistFollowers.Int64,
Popularity: song.ArtistPopularity.Int64,
Genres: make([]SongGenre, 0),
}
artistsMap[song.ArtistID.Int64] = artist
}

// Add genre
artist.Genres = append(artist.Genres, SongGenre{
ID: song.GenreID.Int64,
Genre: song.Genre.String,
})
}

artists := make([]SongArtist, 0, len(artistsMap))
for _, artist := range artistsMap {
artists = append(artists, artist)
}

return &Song{
ID: songs[0].ID,
Title: songs[0].SongTitle,
Album: songs[0].Album,
SpotifyID: songs[0].SpotifyID,
DurationMS: songs[0].DurationMs,
LyricsType: lyricsType,
Lyrics: lyrics,
CreatedAt: songs[0].CreatedAt,
Artists: artists,
}
}

// CreateSongParams converts a Song DTO to a sqlc CreateSongParams object
func (s *Song) CreateSongParams() *sqlc.CreateSongParams {
lyricsType := sql.NullString{String: s.LyricsType, Valid: false}
Expand Down
Loading

0 comments on commit 31ec12a

Please sign in to comment.