实现音频服务api
This commit is contained in:
121
db.go
121
db.go
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"butterfliu/internal/repository"
|
||||||
"butterfliu/migrations"
|
"butterfliu/migrations"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -55,10 +56,10 @@ func CloseDB() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddLibrary(name, path string) (Library, error) {
|
func AddLibrary(name, path string) (repository.Library, error) {
|
||||||
absPath, err := filepath.Abs(path)
|
absPath, err := filepath.Abs(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Library{}, err
|
return repository.Library{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := DB.Exec(
|
result, err := DB.Exec(
|
||||||
@@ -66,31 +67,31 @@ func AddLibrary(name, path string) (Library, error) {
|
|||||||
name, absPath,
|
name, absPath,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Library{}, err
|
return repository.Library{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := result.LastInsertId()
|
id, err := result.LastInsertId()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Library{}, err
|
return repository.Library{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return Library{
|
return repository.Library{
|
||||||
ID: int(id),
|
ID: int(id),
|
||||||
Name: name,
|
Name: name,
|
||||||
Path: absPath,
|
Path: absPath,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLibraries() ([]Library, error) {
|
func GetLibraries() ([]repository.Library, error) {
|
||||||
rows, err := DB.Query("SELECT id, name, path FROM libraries")
|
rows, err := DB.Query("SELECT id, name, path FROM libraries")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
libraries := []Library{}
|
libraries := []repository.Library{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var lib Library
|
var lib repository.Library
|
||||||
if err := rows.Scan(&lib.ID, &lib.Name, &lib.Path); err != nil {
|
if err := rows.Scan(&lib.ID, &lib.Name, &lib.Path); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -100,11 +101,11 @@ func GetLibraries() ([]Library, error) {
|
|||||||
return libraries, nil
|
return libraries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLibraryByID(id int) (Library, error) {
|
func GetLibraryByID(id int) (repository.Library, error) {
|
||||||
row := DB.QueryRow("SELECT id, name, path FROM libraries WHERE id = ?", id)
|
row := DB.QueryRow("SELECT id, name, path FROM libraries WHERE id = ?", id)
|
||||||
var lib Library
|
var lib repository.Library
|
||||||
if err := row.Scan(&lib.ID, &lib.Name, &lib.Path); err != nil {
|
if err := row.Scan(&lib.ID, &lib.Name, &lib.Path); err != nil {
|
||||||
return Library{}, err
|
return repository.Library{}, err
|
||||||
}
|
}
|
||||||
return lib, nil
|
return lib, nil
|
||||||
}
|
}
|
||||||
@@ -128,58 +129,58 @@ func DeleteLibrary(id int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddMediaFile(path string, libraryID int) (MediaFile, error) {
|
func AddMediaFile(path string, libraryID int) (repository.MediaFile, error) {
|
||||||
result, err := DB.Exec("INSERT INTO media_files (path, library_id) VALUES (?, ?)", path, libraryID)
|
result, err := DB.Exec("INSERT INTO media_files (path, library_id) VALUES (?, ?)", path, libraryID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return MediaFile{}, err
|
return repository.MediaFile{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := result.LastInsertId()
|
id, err := result.LastInsertId()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return MediaFile{}, err
|
return repository.MediaFile{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return MediaFile{
|
return repository.MediaFile{
|
||||||
ID: int(id),
|
ID: int(id),
|
||||||
Path: path,
|
Path: path,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMediaFileByPath(path string) (MediaFile, error) {
|
func GetMediaFileByPath(path string) (repository.MediaFile, error) {
|
||||||
row := DB.QueryRow("SELECT id, path FROM media_files WHERE path = ?", path)
|
row := DB.QueryRow("SELECT id, path FROM media_files WHERE path = ?", path)
|
||||||
var mediaFile MediaFile
|
var mediaFile repository.MediaFile
|
||||||
if err := row.Scan(&mediaFile.ID, &mediaFile.Path); err != nil {
|
if err := row.Scan(&mediaFile.ID, &mediaFile.Path); err != nil {
|
||||||
return MediaFile{}, err
|
return repository.MediaFile{}, err
|
||||||
}
|
}
|
||||||
return mediaFile, nil
|
return mediaFile, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddArtist(name string) (Artist, error) {
|
func AddArtist(name string) (repository.Artist, error) {
|
||||||
result, err := DB.Exec("INSERT INTO artists (name) VALUES (?)", name)
|
result, err := DB.Exec("INSERT INTO artists (name) VALUES (?)", name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Artist{}, err
|
return repository.Artist{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := result.LastInsertId()
|
id, err := result.LastInsertId()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Artist{}, err
|
return repository.Artist{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return Artist{
|
return repository.Artist{
|
||||||
ID: int(id),
|
ID: int(id),
|
||||||
Name: name,
|
Name: name,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetArtists() ([]Artist, error) {
|
func GetArtists() ([]repository.Artist, error) {
|
||||||
rows, err := DB.Query("SELECT id, name FROM artists")
|
rows, err := DB.Query("SELECT id, name FROM artists")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
artists := []Artist{}
|
artists := []repository.Artist{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var artist Artist
|
var artist repository.Artist
|
||||||
if err := rows.Scan(&artist.ID, &artist.Name); err != nil {
|
if err := rows.Scan(&artist.ID, &artist.Name); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -187,19 +188,19 @@ func GetArtists() ([]Artist, error) {
|
|||||||
}
|
}
|
||||||
return artists, nil
|
return artists, nil
|
||||||
}
|
}
|
||||||
func GetArtistByID(id int) (Artist, error) {
|
func GetArtistByID(id int) (repository.Artist, error) {
|
||||||
row := DB.QueryRow("SELECT id, name FROM artists WHERE id = ?", id)
|
row := DB.QueryRow("SELECT id, name FROM artists WHERE id = ?", id)
|
||||||
var artist Artist
|
var artist repository.Artist
|
||||||
if err := row.Scan(&artist.ID, &artist.Name); err != nil {
|
if err := row.Scan(&artist.ID, &artist.Name); err != nil {
|
||||||
return Artist{}, err
|
return repository.Artist{}, err
|
||||||
}
|
}
|
||||||
return artist, nil
|
return artist, nil
|
||||||
}
|
}
|
||||||
func GetArtistByName(name string) (Artist, error) {
|
func GetArtistByName(name string) (repository.Artist, error) {
|
||||||
row := DB.QueryRow("SELECT id, name FROM artists WHERE name = ?", name)
|
row := DB.QueryRow("SELECT id, name FROM artists WHERE name = ?", name)
|
||||||
var artist Artist
|
var artist repository.Artist
|
||||||
if err := row.Scan(&artist.ID, &artist.Name); err != nil {
|
if err := row.Scan(&artist.ID, &artist.Name); err != nil {
|
||||||
return Artist{}, err
|
return repository.Artist{}, err
|
||||||
}
|
}
|
||||||
return artist, nil
|
return artist, nil
|
||||||
}
|
}
|
||||||
@@ -213,32 +214,32 @@ func DeleteArtist(id int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddAlbum(title string, artistID int) (Album, error) {
|
func AddAlbum(title string, artistID int) (repository.Album, error) {
|
||||||
result, err := DB.Exec("INSERT INTO albums (title, artist_id) VALUES (?, ?)", title, artistID)
|
result, err := DB.Exec("INSERT INTO albums (title, artist_id) VALUES (?, ?)", title, artistID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Album{}, err
|
return repository.Album{}, err
|
||||||
}
|
}
|
||||||
id, err := result.LastInsertId()
|
id, err := result.LastInsertId()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Album{}, err
|
return repository.Album{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return Album{
|
return repository.Album{
|
||||||
ID: int(id),
|
ID: int(id),
|
||||||
Title: title,
|
Title: title,
|
||||||
ArtistID: artistID,
|
ArtistID: artistID,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAlbums() ([]Album, error) {
|
func GetAlbums() ([]repository.Album, error) {
|
||||||
rows, err := DB.Query("SELECT id, title, artist_id FROM albums")
|
rows, err := DB.Query("SELECT id, title, artist_id FROM albums")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
albums := []Album{}
|
albums := []repository.Album{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var album Album
|
var album repository.Album
|
||||||
if err := rows.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil {
|
if err := rows.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -247,42 +248,42 @@ func GetAlbums() ([]Album, error) {
|
|||||||
return albums, nil
|
return albums, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAlbumByID(id int) (Album, error) {
|
func GetAlbumByID(id int) (repository.Album, error) {
|
||||||
row := DB.QueryRow("SELECT id, title, artist_id FROM albums WHERE id = ?", id)
|
row := DB.QueryRow("SELECT id, title, artist_id FROM albums WHERE id = ?", id)
|
||||||
var album Album
|
var album repository.Album
|
||||||
if err := row.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil {
|
if err := row.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil {
|
||||||
return Album{}, err
|
return repository.Album{}, err
|
||||||
}
|
}
|
||||||
return album, nil
|
return album, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAlbumByTitle(title string) (Album, error) {
|
func GetAlbumByTitle(title string) (repository.Album, error) {
|
||||||
row := DB.QueryRow("SELECT id, title, artist_id FROM albums WHERE title = ?", title)
|
row := DB.QueryRow("SELECT id, title, artist_id FROM albums WHERE title = ?", title)
|
||||||
var album Album
|
var album repository.Album
|
||||||
if err := row.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil {
|
if err := row.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil {
|
||||||
return Album{}, err
|
return repository.Album{}, err
|
||||||
}
|
}
|
||||||
return album, nil
|
return album, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAlbumByTitleAndArtist(title string, artistID int) (Album, error) {
|
func GetAlbumByTitleAndArtist(title string, artistID int) (repository.Album, error) {
|
||||||
row := DB.QueryRow("SELECT id, title, artist_id FROM albums WHERE title = ? AND artist_id = ?", title, artistID)
|
row := DB.QueryRow("SELECT id, title, artist_id FROM albums WHERE title = ? AND artist_id = ?", title, artistID)
|
||||||
var album Album
|
var album repository.Album
|
||||||
if err := row.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil {
|
if err := row.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil {
|
||||||
return Album{}, err
|
return repository.Album{}, err
|
||||||
}
|
}
|
||||||
return album, nil
|
return album, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAlbumsByArtist(artistID int) ([]Album, error) {
|
func GetAlbumsByArtist(artistID int) ([]repository.Album, error) {
|
||||||
rows, err := DB.Query("SELECT id, title, artist_id FROM albums WHERE artist_id = ?", artistID)
|
rows, err := DB.Query("SELECT id, title, artist_id FROM albums WHERE artist_id = ?", artistID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
albums := []Album{}
|
albums := []repository.Album{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var album Album
|
var album repository.Album
|
||||||
if err := rows.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil {
|
if err := rows.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -304,18 +305,18 @@ func DeleteAlbum(id int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddSong(title string, artistID, albumID, duration, mediaFileID int) (Song, error) {
|
func AddSong(title string, artistID, albumID, duration, mediaFileID int) (repository.Song, error) {
|
||||||
result, err := DB.Exec("INSERT INTO songs (title, artist_id, album_id, duration, media_file_id) VALUES (?, ?, ?, ?, ?)", title, artistID, albumID, duration, mediaFileID)
|
result, err := DB.Exec("INSERT INTO songs (title, artist_id, album_id, duration, media_file_id) VALUES (?, ?, ?, ?, ?)", title, artistID, albumID, duration, mediaFileID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Song{}, err
|
return repository.Song{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := result.LastInsertId()
|
id, err := result.LastInsertId()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Song{}, err
|
return repository.Song{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return Song{
|
return repository.Song{
|
||||||
ID: int(id),
|
ID: int(id),
|
||||||
Title: title,
|
Title: title,
|
||||||
ArtistID: artistID,
|
ArtistID: artistID,
|
||||||
@@ -324,15 +325,15 @@ func AddSong(title string, artistID, albumID, duration, mediaFileID int) (Song,
|
|||||||
MediaFileID: mediaFileID,
|
MediaFileID: mediaFileID,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
func GetSongs() ([]Song, error) {
|
func GetSongs() ([]repository.Song, error) {
|
||||||
rows, err := DB.Query("SELECT id, artist_id, album_id, duration, media_file_id FROM songs")
|
rows, err := DB.Query("SELECT id, artist_id, album_id, duration, media_file_id FROM songs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
songs := []Song{}
|
songs := []repository.Song{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var song Song
|
var song repository.Song
|
||||||
if err := rows.Scan(&song.ID, &song.ArtistID, &song.AlbumID, &song.Duration, &song.MediaFileID); err != nil {
|
if err := rows.Scan(&song.ID, &song.ArtistID, &song.AlbumID, &song.Duration, &song.MediaFileID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -361,7 +362,7 @@ func DeleteSong(id int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSongsByLibrary(libraryID int) ([]Song, error) {
|
func GetSongsByLibrary(libraryID int) ([]repository.Song, error) {
|
||||||
rows, err := DB.Query(`
|
rows, err := DB.Query(`
|
||||||
SELECT s.id, s.title, s.artist_id, s.album_id, s.duration, s.media_file_id
|
SELECT s.id, s.title, s.artist_id, s.album_id, s.duration, s.media_file_id
|
||||||
FROM songs s
|
FROM songs s
|
||||||
@@ -373,9 +374,9 @@ func GetSongsByLibrary(libraryID int) ([]Song, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
songs := []Song{}
|
songs := []repository.Song{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var song Song
|
var song repository.Song
|
||||||
if err := rows.Scan(&song.ID, &song.Title, &song.ArtistID, &song.AlbumID, &song.Duration, &song.MediaFileID); err != nil {
|
if err := rows.Scan(&song.ID, &song.Title, &song.ArtistID, &song.AlbumID, &song.Duration, &song.MediaFileID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,15 +153,6 @@ func (c *LibraryController) GetSongs(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(songs)
|
json.NewEncoder(w).Encode(songs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *LibraryController) GetAllSongs(w http.ResponseWriter, r *http.Request) {
|
|
||||||
songs, err := c.service.GetAllSongs()
|
|
||||||
if err != nil {
|
|
||||||
json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
json.NewEncoder(w).Encode(songs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LibraryController) GetArtists(w http.ResponseWriter, r *http.Request) {
|
func (c *LibraryController) GetArtists(w http.ResponseWriter, r *http.Request) {
|
||||||
artists, err := c.service.GetArtists()
|
artists, err := c.service.GetArtists()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
44
internal/controller/song.go
Normal file
44
internal/controller/song.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"butterfliu/internal/service"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SongController struct {
|
||||||
|
service *service.SongService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSongController(service *service.SongService) *SongController {
|
||||||
|
return &SongController{service: service}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SongController) GetAllWithDetails(w http.ResponseWriter, r *http.Request) {
|
||||||
|
songs, err := c.service.GetAllWithDetails()
|
||||||
|
if err != nil {
|
||||||
|
json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(songs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SongController) Stream(w http.ResponseWriter, r *http.Request) {
|
||||||
|
parmaID := chi.URLParam(r, "id")
|
||||||
|
id, err := strconv.Atoi(parmaID)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "无效的歌曲 ID", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaFile, err := c.service.GetMediaFile(id)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "未找到该媒体文件", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.ServeFile(w, r, mediaFile.Path)
|
||||||
|
}
|
||||||
@@ -4,38 +4,6 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Library struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MediaFile struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
LibraryID int `json:"library_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Artist struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Album struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
ArtistID int `json:"artist_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Song struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
ArtistID int `json:"artist_id"`
|
|
||||||
AlbumID int `json:"album_id"`
|
|
||||||
Duration int `json:"duration"`
|
|
||||||
MediaFileID int `json:"media_file_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SongDetail struct {
|
type SongDetail struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
@@ -140,31 +108,6 @@ func (r *LibraryRepository) GetSongsByLibraryWithDetails(libraryID int) ([]SongD
|
|||||||
return songs, nil
|
return songs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *LibraryRepository) GetAllSongsWithDetails() ([]SongDetail, error) {
|
|
||||||
rows, err := r.db.Query(`
|
|
||||||
SELECT s.id, s.title, a.name as artist_name, al.title as album_title, s.duration, mf.path
|
|
||||||
FROM songs s
|
|
||||||
INNER JOIN media_files mf ON s.media_file_id = mf.id
|
|
||||||
INNER JOIN artists a ON s.artist_id = a.id
|
|
||||||
INNER JOIN albums al ON s.album_id = al.id
|
|
||||||
ORDER BY s.title
|
|
||||||
`)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
songs := []SongDetail{}
|
|
||||||
for rows.Next() {
|
|
||||||
var song SongDetail
|
|
||||||
if err := rows.Scan(&song.ID, &song.Title, &song.Artist, &song.Album, &song.Duration, &song.Path); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
songs = append(songs, song)
|
|
||||||
}
|
|
||||||
return songs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *LibraryRepository) GetMediaFileByPath(path string) (MediaFile, error) {
|
func (r *LibraryRepository) GetMediaFileByPath(path string) (MediaFile, error) {
|
||||||
row := r.db.QueryRow("SELECT id, path, library_id FROM media_files WHERE path = ?", path)
|
row := r.db.QueryRow("SELECT id, path, library_id FROM media_files WHERE path = ?", path)
|
||||||
var mediaFile MediaFile
|
var mediaFile MediaFile
|
||||||
@@ -300,21 +243,3 @@ func (r *LibraryRepository) GetAlbums() ([]Album, error) {
|
|||||||
}
|
}
|
||||||
return albums, nil
|
return albums, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *LibraryRepository) GetSongs() ([]Song, error) {
|
|
||||||
rows, err := r.db.Query("SELECT id, title, artist_id, album_id, duration, media_file_id FROM songs")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
songs := []Song{}
|
|
||||||
for rows.Next() {
|
|
||||||
var song Song
|
|
||||||
if err := rows.Scan(&song.ID, &song.Title, &song.ArtistID, &song.AlbumID, &song.Duration, &song.MediaFileID); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
songs = append(songs, song)
|
|
||||||
}
|
|
||||||
return songs, nil
|
|
||||||
}
|
|
||||||
|
|||||||
26
internal/repository/media_repo.go
Normal file
26
internal/repository/media_repo.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import "database/sql"
|
||||||
|
|
||||||
|
type MediaRepository struct {
|
||||||
|
db *sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMediaRepository(db *sql.DB) *MediaRepository {
|
||||||
|
return &MediaRepository{db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MediaRepository) Get(id int) (MediaFile, error) {
|
||||||
|
var m MediaFile
|
||||||
|
rows, err := r.db.Query("SELECT id, path, library_id FROM media_files WHERE id = $1", id)
|
||||||
|
if err != nil {
|
||||||
|
return MediaFile{}, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
if rows.Next() {
|
||||||
|
if err := rows.Scan(&m.ID, &m.Path, &m.LibraryID); err != nil {
|
||||||
|
return MediaFile{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package repository
|
||||||
|
|
||||||
type Library struct {
|
type Library struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
67
internal/repository/song_repo.go
Normal file
67
internal/repository/song_repo.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import "database/sql"
|
||||||
|
|
||||||
|
type SongRepository struct {
|
||||||
|
db *sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSongRepository(db *sql.DB) *SongRepository {
|
||||||
|
return &SongRepository{db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SongRepository) GetAll() ([]Song, error) {
|
||||||
|
rows, err := r.db.Query("SELECT id, title, artist_id, album_id, duration, media_file_id FROM songs")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
songs := []Song{}
|
||||||
|
for rows.Next() {
|
||||||
|
var song Song
|
||||||
|
if err := rows.Scan(&song.ID, &song.Title, &song.ArtistID, &song.AlbumID, &song.Duration, &song.MediaFileID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
songs = append(songs, song)
|
||||||
|
}
|
||||||
|
return songs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SongRepository) GetAllWithDetails() ([]SongDetail, error) {
|
||||||
|
rows, err := r.db.Query(`
|
||||||
|
SELECT s.id, s.title, a.name as artist_name, al.title as album_title, s.duration, mf.path
|
||||||
|
FROM songs s
|
||||||
|
INNER JOIN media_files mf ON s.media_file_id = mf.id
|
||||||
|
INNER JOIN artists a ON s.artist_id = a.id
|
||||||
|
INNER JOIN albums al ON s.album_id = al.id
|
||||||
|
ORDER BY s.title
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
songs := []SongDetail{}
|
||||||
|
for rows.Next() {
|
||||||
|
var song SongDetail
|
||||||
|
if err := rows.Scan(&song.ID, &song.Title, &song.Artist, &song.Album, &song.Duration, &song.Path); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
songs = append(songs, song)
|
||||||
|
}
|
||||||
|
return songs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SongRepository) Get(id int) (Song, error) {
|
||||||
|
var song Song
|
||||||
|
rows, err := r.db.Query("SELECT id, title, artist_id, album_id, duration, media_file_id FROM songs WHERE id = ?", id)
|
||||||
|
if err != nil {
|
||||||
|
return Song{}, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
if rows.Next() {
|
||||||
|
rows.Scan(&song.ID, &song.Title, &song.ArtistID, &song.AlbumID, &song.Duration, &song.MediaFileID)
|
||||||
|
}
|
||||||
|
return song, nil
|
||||||
|
}
|
||||||
@@ -42,10 +42,6 @@ func (s *LibraryService) GetSongs(id int) ([]repository.SongDetail, error) {
|
|||||||
return s.repo.GetSongsByLibraryWithDetails(id)
|
return s.repo.GetSongsByLibraryWithDetails(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LibraryService) GetAllSongs() ([]repository.SongDetail, error) {
|
|
||||||
return s.repo.GetAllSongsWithDetails()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LibraryService) GetArtists() ([]repository.Artist, error) {
|
func (s *LibraryService) GetArtists() ([]repository.Artist, error) {
|
||||||
return s.repo.GetArtists()
|
return s.repo.GetArtists()
|
||||||
}
|
}
|
||||||
|
|||||||
32
internal/service/song_svc.go
Normal file
32
internal/service/song_svc.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import "butterfliu/internal/repository"
|
||||||
|
|
||||||
|
type SongService struct {
|
||||||
|
songRepo *repository.SongRepository
|
||||||
|
mediaRepo *repository.MediaRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSongService(songRepo *repository.SongRepository, mediaRepo *repository.MediaRepository) *SongService {
|
||||||
|
return &SongService{songRepo, mediaRepo}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SongService) GetAll() ([]repository.Song, error) {
|
||||||
|
return s.songRepo.GetAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SongService) GetAllWithDetails() ([]repository.SongDetail, error) {
|
||||||
|
return s.songRepo.GetAllWithDetails()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (service *SongService) GetMediaFile(id int) (repository.MediaFile, error) {
|
||||||
|
song, err := service.songRepo.Get(id)
|
||||||
|
if err != nil {
|
||||||
|
return repository.MediaFile{}, err
|
||||||
|
}
|
||||||
|
media, err := service.mediaRepo.Get(song.MediaFileID)
|
||||||
|
if err != nil {
|
||||||
|
return repository.MediaFile{}, err
|
||||||
|
}
|
||||||
|
return media, nil
|
||||||
|
}
|
||||||
10
main.go
10
main.go
@@ -21,8 +21,12 @@ func main() {
|
|||||||
r.Use(middleware.Logger)
|
r.Use(middleware.Logger)
|
||||||
|
|
||||||
libraryRepo := repository.NewLibraryRepository(GetDB())
|
libraryRepo := repository.NewLibraryRepository(GetDB())
|
||||||
|
songRepo := repository.NewSongRepository(GetDB())
|
||||||
|
mediaRepo := repository.NewMediaRepository(GetDB())
|
||||||
libraryService := service.NewLibraryService(libraryRepo)
|
libraryService := service.NewLibraryService(libraryRepo)
|
||||||
|
songService := service.NewSongService(songRepo, mediaRepo)
|
||||||
libraryController := controller.NewLibraryController(libraryService)
|
libraryController := controller.NewLibraryController(libraryService)
|
||||||
|
songController := controller.NewSongController(songService)
|
||||||
|
|
||||||
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte("Hello World!"))
|
w.Write([]byte("Hello World!"))
|
||||||
@@ -39,8 +43,12 @@ func main() {
|
|||||||
r.Get("/{id}/songs", libraryController.GetSongs)
|
r.Get("/{id}/songs", libraryController.GetSongs)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
r.Route("/api/songs", func(r chi.Router) {
|
||||||
|
r.Get("/", songController.GetAllWithDetails)
|
||||||
|
r.Get("/{id}/stream", songController.Stream)
|
||||||
|
})
|
||||||
|
|
||||||
r.Route("/api", func(r chi.Router) {
|
r.Route("/api", func(r chi.Router) {
|
||||||
r.Get("/songs", libraryController.GetAllSongs)
|
|
||||||
r.Get("/artists", libraryController.GetArtists)
|
r.Get("/artists", libraryController.GetArtists)
|
||||||
r.Get("/albums", libraryController.GetAlbums)
|
r.Get("/albums", libraryController.GetAlbums)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user