Skip to content

Commit

Permalink
Merge pull request #58 from mbaraa/dev
Browse files Browse the repository at this point in the history
Release v0.0.7
  • Loading branch information
mbaraa authored May 27, 2024
2 parents 73d01e1 + a97d438 commit 14c84b5
Show file tree
Hide file tree
Showing 27 changed files with 698 additions and 118 deletions.
1 change: 1 addition & 0 deletions cmd/migrator/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func Migrate() error {
new(models.PlaylistSong),
new(models.PlaylistOwner),
new(models.History),
new(models.PlaylistSongVoter),
)
if err != nil {
return err
Expand Down
14 changes: 9 additions & 5 deletions cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ func StartServer(staticFS embed.FS) error {
playlistOwnersRepo := db.NewBaseDB[models.PlaylistOwner](dbConn)
playlistSongsRepo := db.NewBaseDB[models.PlaylistSong](dbConn)
historyRepo := db.NewBaseDB[models.History](dbConn)
playlistVotersRepo := db.NewBaseDB[models.PlaylistSongVoter](dbConn)

downloadService := download.New(songRepo)
playlistsService := playlists.New(playlistRepo, playlistOwnersRepo, playlistSongsRepo)
songsService := songs.New(playlistSongsRepo, playlistOwnersRepo, songRepo, playlistRepo, downloadService)
songsService := songs.New(playlistSongsRepo, playlistOwnersRepo, songRepo, playlistRepo, playlistVotersRepo, downloadService)
historyService := history.New(historyRepo, songRepo)

jwtUtil := jwt.NewJWTImpl()
Expand Down Expand Up @@ -85,7 +86,7 @@ func StartServer(staticFS embed.FS) error {

emailLoginApi := apis.NewEmailLoginApi(login.NewEmailLoginService(accountRepo, profileRepo, otpRepo, jwtUtil))
googleLoginApi := apis.NewGoogleLoginApi(login.NewGoogleLoginService(accountRepo, profileRepo, otpRepo, jwtUtil))
songDownloadApi := apis.NewDownloadHandler(downloadService, songsService, historyService)
songApi := apis.NewDownloadHandler(downloadService, songsService, historyService)
playlistsApi := apis.NewPlaylistApi(playlistsService, songsService)
historyApi := apis.NewHistoryApi(historyService)

Expand All @@ -98,13 +99,16 @@ func StartServer(staticFS embed.FS) error {
apisHandler.HandleFunc("/login/google/callback", googleLoginApi.HandleGoogleOAuthLoginCallback)
apisHandler.HandleFunc("GET /logout", apis.HandleLogout)
apisHandler.HandleFunc("GET /search-suggestion", apis.HandleSearchSuggestions)
apisHandler.HandleFunc("GET /song", gHandler.OptionalAuthApi(songDownloadApi.HandlePlaySong))
apisHandler.HandleFunc("GET /song", gHandler.OptionalAuthApi(songApi.HandlePlaySong))
apisHandler.HandleFunc("PUT /song/playlist", gHandler.AuthApi(playlistsApi.HandleToggleSongInPlaylist))
apisHandler.HandleFunc("PUT /song/playlist/plays", gHandler.AuthApi(songApi.HandleIncrementSongPlaysInPlaylist))
apisHandler.HandleFunc("PUT /song/playlist/upvote", gHandler.AuthApi(songApi.HandleUpvoteSongPlaysInPlaylist))
apisHandler.HandleFunc("PUT /song/playlist/downvote", gHandler.AuthApi(songApi.HandleDownvoteSongPlaysInPlaylist))
apisHandler.HandleFunc("GET /playlist/all", gHandler.AuthApi(playlistsApi.HandleGetPlaylistsForPopover))
apisHandler.HandleFunc("POST /playlist", gHandler.AuthApi(playlistsApi.HandleCreatePlaylist))
apisHandler.HandleFunc("PUT /playlist/public", gHandler.AuthApi(playlistsApi.HandleTogglePublicPlaylist))
apisHandler.HandleFunc("PUT /playlist/join", gHandler.AuthApi(playlistsApi.HandleToggleJoinPlaylist))
apisHandler.HandleFunc("DELETE /playlist", gHandler.AuthApi(playlistsApi.HandleDeletePlaylist))
apisHandler.HandleFunc("PUT /toggle-song-in-playlist", gHandler.AuthApi(playlistsApi.HandleToggleSongInPlaylist))
apisHandler.HandleFunc("PUT /increment-song-plays", gHandler.AuthApi(songDownloadApi.HandleIncrementSongPlaysInPlaylist))
apisHandler.HandleFunc("GET /history/{page}", gHandler.AuthApi(historyApi.HandleGetMoreHistoryItems))

applicationHandler := http.NewServeMux()
Expand Down
2 changes: 1 addition & 1 deletion db/allowed_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import "dankmuzikk/models"
type AllowedModels interface {
models.Account | models.Profile | models.EmailVerificationCode |
models.Song | models.Playlist | models.PlaylistSong | models.PlaylistOwner |
models.History
models.History | models.PlaylistSongVoter
GetId() uint
}
1 change: 1 addition & 0 deletions entities/song.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ type Song struct {
ThumbnailUrl string `json:"thumbnail_url"`
Duration string `json:"duration"`
PlayTimes int `json:"play_times"`
Votes int `json:"votes"`
AddedAt string `json:"added_at"`
}
4 changes: 4 additions & 0 deletions handlers/apis/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ func (h *historyApi) HandleGetMoreHistoryItems(w http.ResponseWriter, r *http.Re
if err != nil {
log.Errorln(err)
}
if len(recentPlays) == 0 {
w.WriteHeader(http.StatusNotFound)
return
}

outBuf := bytes.NewBuffer([]byte{})
for _, s := range recentPlays {
Expand Down
32 changes: 31 additions & 1 deletion handlers/apis/playlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"dankmuzikk/log"
"dankmuzikk/services/playlists"
"dankmuzikk/services/playlists/songs"
"dankmuzikk/views/components/playlist"
"dankmuzikk/views/pages"
"encoding/json"
"net/http"
Expand Down Expand Up @@ -78,7 +79,12 @@ func (p *playlistApi) HandleToggleSongInPlaylist(w http.ResponseWriter, r *http.
}

if added {
_, _ = w.Write([]byte("<div class=\"w-[20px] h-[20px] rounded-sm border border-secondary bg-secondary\"></div>"))
_, _ = w.Write([]byte(`<div class="w-[20px] h-[20px] rounded-sm border border-secondary bg-secondary flex justify-center items-center">
<svg width="18" height="14" viewBox="0 0 18 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 6L7.33514 12.3582" stroke="var(--primary-color)" stroke-width="3" stroke-linecap="round"></path>
<path d="M7.4502 12.312L16.4492 1.58739" stroke="var(--primary-color)" stroke-width="3" stroke-linecap="round"></path>
</svg>
</div>`))
} else {
_, _ = w.Write([]byte("<div class=\"w-[20px] h-[20px] rounded-sm border border-secondary\"></div>"))
}
Expand Down Expand Up @@ -160,3 +166,27 @@ func (p *playlistApi) HandleDeletePlaylist(w http.ResponseWriter, r *http.Reques

w.Header().Set("HX-Redirect", "/playlists")
}

func (p *playlistApi) HandleGetPlaylistsForPopover(w http.ResponseWriter, r *http.Request) {
profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
if !profileIdCorrect {
w.Write([]byte("🤷‍♂️"))
return
}

songId := r.URL.Query().Get("song-id")
if songId == "" {
w.WriteHeader(http.StatusBadRequest)
return
}

playlists, songsInPlaylists, err := p.service.GetAllMappedForAddPopover(profileId)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Errorln(err)
return
}

playlist.PlaylistsSelector(songId, playlists, songsInPlaylists).
Render(r.Context(), w)
}
55 changes: 55 additions & 0 deletions handlers/apis/songs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"dankmuzikk/services/history"
"dankmuzikk/services/playlists/songs"
"dankmuzikk/services/youtube/download"
"fmt"
"net/http"
)

Expand Down Expand Up @@ -52,6 +53,60 @@ func (s *songDownloadHandler) HandleIncrementSongPlaysInPlaylist(w http.Response
}
}

func (s *songDownloadHandler) HandleUpvoteSongPlaysInPlaylist(w http.ResponseWriter, r *http.Request) {
profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
if !profileIdCorrect {
w.Write([]byte("🤷‍♂️"))
return
}
songId := r.URL.Query().Get("song-id")
if songId == "" {
w.WriteHeader(http.StatusBadRequest)
return
}
playlistId := r.URL.Query().Get("playlist-id")
if playlistId == "" {
w.WriteHeader(http.StatusBadRequest)
return
}

votes, err := s.songsService.UpvoteSong(songId, playlistId, profileId)
if err != nil {
log.Errorln(err)
w.WriteHeader(http.StatusInternalServerError)
return
}

_, _ = w.Write([]byte(fmt.Sprint(votes)))
}

func (s *songDownloadHandler) HandleDownvoteSongPlaysInPlaylist(w http.ResponseWriter, r *http.Request) {
profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
if !profileIdCorrect {
w.Write([]byte("🤷‍♂️"))
return
}
songId := r.URL.Query().Get("song-id")
if songId == "" {
w.WriteHeader(http.StatusBadRequest)
return
}
playlistId := r.URL.Query().Get("playlist-id")
if playlistId == "" {
w.WriteHeader(http.StatusBadRequest)
return
}

votes, err := s.songsService.DownvoteSong(songId, playlistId, profileId)
if err != nil {
log.Errorln(err)
w.WriteHeader(http.StatusInternalServerError)
return
}

_, _ = w.Write([]byte(fmt.Sprint(votes)))
}

func (s *songDownloadHandler) HandlePlaySong(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get("id")
if id == "" {
Expand Down
10 changes: 2 additions & 8 deletions handlers/pages/pages.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,20 +189,14 @@ func (p *pagesHandler) HandleSearchResultsPage(w http.ResponseWriter, r *http.Re
log.Info("downloading songs' meta data from search")
_ = p.downloadService.DownloadYoutubeSongsMetadata(results)
}
var songsInPlaylists map[string]bool
var playlists []entities.Playlist
profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
if profileIdCorrect {
playlists, songsInPlaylists, _ = p.playlistsService.GetAllMappedForAddPopover(profileId)
}

if handlers.IsNoLayoutPage(r) {
w.Header().Set("HX-Title", "Results for "+query)
w.Header().Set("HX-Push-Url", "/search?query="+query)
pages.SearchResults(results, playlists, songsInPlaylists).Render(r.Context(), w)
pages.SearchResults(results).Render(r.Context(), w)
return
}
layouts.Default("Results for "+query, pages.SearchResults(results, playlists, songsInPlaylists)).Render(r.Context(), w)
layouts.Default("Results for "+query, pages.SearchResults(results)).Render(r.Context(), w)
}

func (p *pagesHandler) HandleSignupPage(w http.ResponseWriter, r *http.Request) {
Expand Down
24 changes: 23 additions & 1 deletion models/playlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,18 @@ func (p *PlaylistSong) BeforeDelete(tx *gorm.DB) error {
return err
}

return tx.
err = tx.
Model(&playlist).
Where("id = ?", p.PlaylistId).
Update("songs_count", playlist.SongsCount-1).
Error
if err != nil {
return err
}

return tx.
Exec("DELETE FROM playlist_song_voters WHERE playlist_id = ? AND song_id = ?", p.PlaylistId, p.SongId).
Error
}

type PlaylistOwner struct {
Expand All @@ -114,3 +121,18 @@ const (
OwnerPermission
NonePermission PlaylistPermissions = 0
)

// PlaylistSongVoter ensures that an account had voted only once.
type PlaylistSongVoter struct {
PlaylistId uint `gorm:"primaryKey"`
SongId uint `gorm:"primaryKey"`
ProfileId uint `gorm:"primaryKey"`
VoteUp bool

CreatedAt time.Time
UpdatedAt time.Time
}

func (p PlaylistSongVoter) GetId() uint {
return p.SongId | p.PlaylistId | p.ProfileId
}
1 change: 1 addition & 0 deletions services/playlists/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ var (
ErrNonOwnerCantDeletePlaylists = errors.New("playlists: non owners can only leave playlists")
ErrUnauthorizedToSeePlaylist = errors.New("playlists: unauthorized to see playlist")
ErrEmptyPlaylist = errors.New("playlists: empty playlists")
ErrUserHasAlreadyVoted = errors.New("playlist: user can't vote more than once")
)
4 changes: 2 additions & 2 deletions services/playlists/playlists.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (p *Service) Get(playlistPubId string, ownerId uint) (playlist entities.Pla
return entities.Playlist{}, models.NonePermission, ErrUnauthorizedToSeePlaylist
}

gigaQuery := `SELECT yt_id, title, artist, thumbnail_url, duration, ps.created_at, ps.play_times
gigaQuery := `SELECT yt_id, title, artist, thumbnail_url, duration, ps.created_at, ps.play_times, ps.votes
FROM
playlist_songs ps
JOIN songs
Expand All @@ -152,7 +152,7 @@ func (p *Service) Get(playlistPubId string, ownerId uint) (playlist entities.Pla
for rows.Next() {
var song entities.Song
var addedAt time.Time
err = rows.Scan(&song.YtId, &song.Title, &song.Artist, &song.ThumbnailUrl, &song.Duration, &addedAt, &song.PlayTimes)
err = rows.Scan(&song.YtId, &song.Title, &song.Artist, &song.ThumbnailUrl, &song.Duration, &addedAt, &song.PlayTimes, &song.Votes)
if err != nil {
continue
}
Expand Down
Loading

0 comments on commit 14c84b5

Please sign in to comment.