From a8d976b97e134dd6c2aacb5ca99b1fc66af31867 Mon Sep 17 00:00:00 2001 From: lzw-723 Date: Mon, 6 Apr 2026 13:17:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=90=86=E4=BB=A3=E7=A0=81=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + db.go | 400 +----------------------------- internal/controller/library.go | 96 ++++--- internal/controller/response.go | 20 ++ internal/controller/song.go | 9 +- internal/repository/media_repo.go | 2 +- queue.go | 2 + scanner.go | 95 ------- scanner_test.go | 40 --- 9 files changed, 94 insertions(+), 571 deletions(-) create mode 100644 internal/controller/response.go delete mode 100644 scanner.go delete mode 100644 scanner_test.go diff --git a/.gitignore b/.gitignore index 29bb7f6..df6d963 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .idea/ .vscode/ +.zed/ *.exe *.db \ No newline at end of file diff --git a/db.go b/db.go index 1ad5765..bc6edee 100644 --- a/db.go +++ b/db.go @@ -1,13 +1,14 @@ package main import ( - "butterfliu/internal/repository" "butterfliu/migrations" "database/sql" "fmt" "log" "os" "path/filepath" + + _ "github.com/mattn/go-sqlite3" ) var DB *sql.DB @@ -25,10 +26,14 @@ func InitDB(dbPath string) error { } var err error + DB, err = sql.Open("sqlite3", dbPath) + if err != nil { + return fmt.Errorf("failed to open database: %v", err) + } - DB, _ = sql.Open("sqlite3", dbPath) - - DB.Ping() + if err = DB.Ping(); err != nil { + return fmt.Errorf("failed to ping database: %v", err) + } if err = migrations.InitMigrationTable(DB); err != nil { return fmt.Errorf("failed to initialize migration table: %v", err) @@ -55,390 +60,3 @@ func CloseDB() error { } return nil } - -func AddLibrary(name, path string) (repository.Library, error) { - absPath, err := filepath.Abs(path) - if err != nil { - return repository.Library{}, err - } - - result, err := DB.Exec( - "INSERT INTO libraries (name, path) VALUES (?, ?)", - name, absPath, - ) - if err != nil { - return repository.Library{}, err - } - - id, err := result.LastInsertId() - if err != nil { - return repository.Library{}, err - } - - return repository.Library{ - ID: int(id), - Name: name, - Path: absPath, - }, nil -} - -func GetLibraries() ([]repository.Library, error) { - rows, err := DB.Query("SELECT id, name, path FROM libraries") - if err != nil { - return nil, err - } - defer rows.Close() - - libraries := []repository.Library{} - for rows.Next() { - var lib repository.Library - if err := rows.Scan(&lib.ID, &lib.Name, &lib.Path); err != nil { - return nil, err - } - libraries = append(libraries, lib) - } - - return libraries, nil -} - -func GetLibraryByID(id int) (repository.Library, error) { - row := DB.QueryRow("SELECT id, name, path FROM libraries WHERE id = ?", id) - var lib repository.Library - if err := row.Scan(&lib.ID, &lib.Name, &lib.Path); err != nil { - return repository.Library{}, err - } - return lib, nil -} - -func UpdateLibraryName(id int, name string) error { - _, err := DB.Exec( - "UPDATE libraries SET name = ? WHERE id = ?", - name, id, - ) - return err -} -func UpdateLibraryPath(id int, path string) error { - _, err := DB.Exec( - "UPDATE libraries SET path = ? WHERE id = ?", - path, id, - ) - return err -} -func DeleteLibrary(id int) error { - _, err := DB.Exec("DELETE FROM libraries WHERE id = ?", id) - return err -} - -func AddMediaFile(path string, libraryID int) (repository.MediaFile, error) { - result, err := DB.Exec("INSERT INTO media_files (path, library_id) VALUES (?, ?)", path, libraryID) - if err != nil { - return repository.MediaFile{}, err - } - - id, err := result.LastInsertId() - if err != nil { - return repository.MediaFile{}, err - } - - return repository.MediaFile{ - ID: int(id), - Path: path, - }, nil -} - -func GetMediaFileByPath(path string) (repository.MediaFile, error) { - row := DB.QueryRow("SELECT id, path FROM media_files WHERE path = ?", path) - var mediaFile repository.MediaFile - if err := row.Scan(&mediaFile.ID, &mediaFile.Path); err != nil { - return repository.MediaFile{}, err - } - return mediaFile, nil -} - -func AddArtist(name string) (repository.Artist, error) { - result, err := DB.Exec("INSERT INTO artists (name) VALUES (?)", name) - if err != nil { - return repository.Artist{}, err - } - - id, err := result.LastInsertId() - if err != nil { - return repository.Artist{}, err - } - - return repository.Artist{ - ID: int(id), - Name: name, - }, nil -} - -func GetArtists() ([]repository.Artist, error) { - rows, err := DB.Query("SELECT id, name FROM artists") - if err != nil { - return nil, err - } - defer rows.Close() - artists := []repository.Artist{} - for rows.Next() { - var artist repository.Artist - if err := rows.Scan(&artist.ID, &artist.Name); err != nil { - return nil, err - } - artists = append(artists, artist) - } - return artists, nil -} -func GetArtistByID(id int) (repository.Artist, error) { - row := DB.QueryRow("SELECT id, name FROM artists WHERE id = ?", id) - var artist repository.Artist - if err := row.Scan(&artist.ID, &artist.Name); err != nil { - return repository.Artist{}, err - } - return artist, nil -} -func GetArtistByName(name string) (repository.Artist, error) { - row := DB.QueryRow("SELECT id, name FROM artists WHERE name = ?", name) - var artist repository.Artist - if err := row.Scan(&artist.ID, &artist.Name); err != nil { - return repository.Artist{}, err - } - return artist, nil -} -func UpdateArtistName(id int, name string) error { - _, err := DB.Exec("UPDATE artists SET name = ? WHERE id = ?", name, id) - return err -} - -func DeleteArtist(id int) error { - _, err := DB.Exec("DELETE FROM artists WHERE id = ?", id) - return err -} - -func AddAlbum(title string, artistID int) (repository.Album, error) { - result, err := DB.Exec("INSERT INTO albums (title, artist_id) VALUES (?, ?)", title, artistID) - if err != nil { - return repository.Album{}, err - } - id, err := result.LastInsertId() - if err != nil { - return repository.Album{}, err - } - - return repository.Album{ - ID: int(id), - Title: title, - ArtistID: artistID, - }, nil -} - -func GetAlbums() ([]repository.Album, error) { - rows, err := DB.Query("SELECT id, title, artist_id FROM albums") - if err != nil { - return nil, err - } - defer rows.Close() - albums := []repository.Album{} - for rows.Next() { - var album repository.Album - if err := rows.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil { - return nil, err - } - albums = append(albums, album) - } - return albums, nil -} - -func GetAlbumByID(id int) (repository.Album, error) { - row := DB.QueryRow("SELECT id, title, artist_id FROM albums WHERE id = ?", id) - var album repository.Album - if err := row.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil { - return repository.Album{}, err - } - return album, nil -} - -func GetAlbumByTitle(title string) (repository.Album, error) { - row := DB.QueryRow("SELECT id, title, artist_id FROM albums WHERE title = ?", title) - var album repository.Album - if err := row.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil { - return repository.Album{}, err - } - return album, nil -} - -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) - var album repository.Album - if err := row.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil { - return repository.Album{}, err - } - return album, nil -} - -func GetAlbumsByArtist(artistID int) ([]repository.Album, error) { - rows, err := DB.Query("SELECT id, title, artist_id FROM albums WHERE artist_id = ?", artistID) - if err != nil { - return nil, err - } - defer rows.Close() - albums := []repository.Album{} - for rows.Next() { - var album repository.Album - if err := rows.Scan(&album.ID, &album.Title, &album.ArtistID); err != nil { - return nil, err - } - albums = append(albums, album) - } - return albums, nil -} - -func UpdateAlbumTitle(id int, title string) error { - _, err := DB.Exec("UPDATE albums SET title = ? WHERE id = ?", title, id) - return err -} -func UpdateAlbumArtistID(id, artistID int) error { - _, err := DB.Exec("UPDATE albums SET artist_id = ?", artistID) - return err -} -func DeleteAlbum(id int) error { - _, err := DB.Exec("DELETE FROM albums WHERE id = ?", id) - return err -} - -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) - if err != nil { - return repository.Song{}, err - } - - id, err := result.LastInsertId() - if err != nil { - return repository.Song{}, err - } - - return repository.Song{ - ID: int(id), - Title: title, - ArtistID: artistID, - AlbumID: albumID, - Duration: duration, - MediaFileID: mediaFileID, - }, nil -} -func GetSongs() ([]repository.Song, error) { - rows, err := DB.Query("SELECT id, artist_id, album_id, duration, media_file_id FROM songs") - if err != nil { - return nil, err - } - defer rows.Close() - songs := []repository.Song{} - for rows.Next() { - var song repository.Song - if err := rows.Scan(&song.ID, &song.ArtistID, &song.AlbumID, &song.Duration, &song.MediaFileID); err != nil { - return nil, err - } - songs = append(songs, song) - } - return songs, nil -} -func UpdateSongTitle(id int, title string) error { - _, err := DB.Exec("UPDATE songs SET title = ? WHERE id = ?", title, id) - return err -} -func UpdateSongArtistID(id int, artistID int) error { - _, err := DB.Exec("UPDATE songs SET artist_id = ?", artistID) - return err -} -func UpdateSongAlbumID(id, albumID int) error { - _, err := DB.Exec("UPDATE songs SET album_id = ?", albumID) - return err -} -func UpdateSongDuration(id, duration int) error { - _, err := DB.Exec("UPDATE songs SET duration = ?", duration) - return err -} -func DeleteSong(id int) error { - _, err := DB.Exec("DELETE FROM songs WHERE id = ?", id) - return err -} - -func GetSongsByLibrary(libraryID int) ([]repository.Song, error) { - rows, err := DB.Query(` - SELECT s.id, s.title, s.artist_id, s.album_id, s.duration, s.media_file_id - FROM songs s - INNER JOIN media_files mf ON s.media_file_id = mf.id - WHERE mf.library_id = ? - ORDER BY s.title - `, libraryID) - if err != nil { - return nil, err - } - defer rows.Close() - songs := []repository.Song{} - for rows.Next() { - var song repository.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 -} - -type SongDetail struct { - ID int `json:"id"` - Title string `json:"title"` - Artist string `json:"artist"` - Album string `json:"album"` - Duration int `json:"duration"` - Path string `json:"path"` -} - -func GetSongsByLibraryWithDetails(libraryID int) ([]SongDetail, error) { - rows, err := 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 - WHERE mf.library_id = ? - ORDER BY s.title - `, libraryID) - 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 GetAllSongsWithDetails() ([]SongDetail, error) { - rows, err := 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 -} diff --git a/internal/controller/library.go b/internal/controller/library.go index a472c49..e5a0dde 100644 --- a/internal/controller/library.go +++ b/internal/controller/library.go @@ -3,7 +3,6 @@ package controller import ( "butterfliu/internal/service" "encoding/json" - "io" "log" "net/http" "strconv" @@ -23,69 +22,84 @@ func NewLibraryController(service *service.LibraryService) *LibraryController { } func (c *LibraryController) GetAll(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") libraries, err := c.service.GetAll() if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusInternalServerError) return } - json.NewEncoder(w).Encode(libraries) + jsonResponse(w, libraries, http.StatusOK) } func (c *LibraryController) Create(w http.ResponseWriter, r *http.Request) { - var library map[string]interface{} - err := json.NewDecoder(r.Body).Decode(&library) - if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + var req struct { + Name string `json:"name"` + Path string `json:"path"` + } + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + jsonError(w, err.Error(), http.StatusBadRequest) return } - _, err = c.service.Create(library["name"].(string), library["path"].(string)) - if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + if req.Name == "" || req.Path == "" { + jsonError(w, "name and path are required", http.StatusBadRequest) return } - json.NewEncoder(w).Encode(map[string]string{"msg": "Add library successfully."}) + _, err := c.service.Create(req.Name, req.Path) + if err != nil { + jsonError(w, err.Error(), http.StatusInternalServerError) + return + } + jsonMsg(w, "Add library successfully.") } func (c *LibraryController) UpdateName(w http.ResponseWriter, r *http.Request) { idParam := chi.URLParam(r, "id") - name, _ := io.ReadAll(r.Body) - defer r.Body.Close() id, err := strconv.Atoi(idParam) if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusBadRequest) return } - err = c.service.UpdateName(id, string(name)) + + var name string + if err := json.NewDecoder(r.Body).Decode(&name); err != nil { + jsonError(w, err.Error(), http.StatusBadRequest) + return + } + + err = c.service.UpdateName(id, name) if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusInternalServerError) return } - json.NewEncoder(w).Encode(map[string]string{"msg": "Updated library name."}) + jsonMsg(w, "Updated library name.") } func (c *LibraryController) UpdatePath(w http.ResponseWriter, r *http.Request) { idParam := chi.URLParam(r, "id") - path, _ := io.ReadAll(r.Body) - defer r.Body.Close() id, err := strconv.Atoi(idParam) if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusBadRequest) return } - err = c.service.UpdatePath(id, string(path)) + + var path string + if err := json.NewDecoder(r.Body).Decode(&path); err != nil { + jsonError(w, err.Error(), http.StatusBadRequest) + return + } + + err = c.service.UpdatePath(id, path) if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusInternalServerError) return } - json.NewEncoder(w).Encode(map[string]string{"msg": "Updated library path."}) + jsonMsg(w, "Updated library path.") } func (c *LibraryController) Scan(w http.ResponseWriter, r *http.Request) { c.scanMutex.Lock() if c.isScanning { c.scanMutex.Unlock() - json.NewEncoder(w).Encode(map[string]string{"error": "Another scan is already in progress"}) + jsonError(w, "Another scan is already in progress", http.StatusConflict) return } c.isScanning = true @@ -97,7 +111,7 @@ func (c *LibraryController) Scan(w http.ResponseWriter, r *http.Request) { c.scanMutex.Lock() c.isScanning = false c.scanMutex.Unlock() - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusBadRequest) return } @@ -117,56 +131,60 @@ func (c *LibraryController) Scan(w http.ResponseWriter, r *http.Request) { log.Printf("Scan completed successfully for library %d", id) }() - json.NewEncoder(w).Encode(map[string]string{"msg": "Library scan started."}) + jsonMsg(w, "Library scan started.") } func (c *LibraryController) GetScanStatus(w http.ResponseWriter, r *http.Request) { c.scanMutex.Lock() scanning := c.isScanning c.scanMutex.Unlock() - json.NewEncoder(w).Encode(map[string]bool{"scanning": scanning}) + jsonResponse(w, map[string]bool{"scanning": scanning}, http.StatusOK) } func (c *LibraryController) Delete(w http.ResponseWriter, r *http.Request) { idParam := chi.URLParam(r, "id") - id, _ := strconv.Atoi(idParam) - err := c.service.Delete(id) + id, err := strconv.Atoi(idParam) if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusBadRequest) return } - json.NewEncoder(w).Encode(map[string]string{"msg": "Deleted library."}) + err = c.service.Delete(id) + if err != nil { + jsonError(w, err.Error(), http.StatusInternalServerError) + return + } + jsonMsg(w, "Deleted library.") } func (c *LibraryController) GetSongs(w http.ResponseWriter, r *http.Request) { idParam := chi.URLParam(r, "id") id, err := strconv.Atoi(idParam) if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusBadRequest) return } songs, err := c.service.GetSongs(id) if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusInternalServerError) return } - json.NewEncoder(w).Encode(songs) + jsonResponse(w, songs, http.StatusOK) } func (c *LibraryController) GetArtists(w http.ResponseWriter, r *http.Request) { artists, err := c.service.GetArtists() if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusInternalServerError) return } - json.NewEncoder(w).Encode(artists) + jsonResponse(w, artists, http.StatusOK) } func (c *LibraryController) GetAlbums(w http.ResponseWriter, r *http.Request) { albums, err := c.service.GetAlbums() if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + jsonError(w, err.Error(), http.StatusInternalServerError) return } - json.NewEncoder(w).Encode(albums) + jsonResponse(w, albums, http.StatusOK) } diff --git a/internal/controller/response.go b/internal/controller/response.go new file mode 100644 index 0000000..92d7ad7 --- /dev/null +++ b/internal/controller/response.go @@ -0,0 +1,20 @@ +package controller + +import ( + "encoding/json" + "net/http" +) + +func jsonResponse(w http.ResponseWriter, data interface{}, status int) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(status) + json.NewEncoder(w).Encode(data) +} + +func jsonError(w http.ResponseWriter, message string, status int) { + jsonResponse(w, map[string]string{"error": message}, status) +} + +func jsonMsg(w http.ResponseWriter, message string) { + jsonResponse(w, map[string]string{"msg": message}, http.StatusOK) +} diff --git a/internal/controller/song.go b/internal/controller/song.go index 91c903c..f3e113a 100644 --- a/internal/controller/song.go +++ b/internal/controller/song.go @@ -2,7 +2,6 @@ package controller import ( "butterfliu/internal/service" - "encoding/json" "net/http" "strconv" @@ -20,15 +19,15 @@ func NewSongController(service *service.SongService) *SongController { 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()}) + jsonError(w, err.Error(), http.StatusInternalServerError) return } - json.NewEncoder(w).Encode(songs) + jsonResponse(w, songs, http.StatusOK) } func (c *SongController) Stream(w http.ResponseWriter, r *http.Request) { - parmaID := chi.URLParam(r, "id") - id, err := strconv.Atoi(parmaID) + paramID := chi.URLParam(r, "id") + id, err := strconv.Atoi(paramID) if err != nil { http.Error(w, "无效的歌曲 ID", http.StatusBadRequest) return diff --git a/internal/repository/media_repo.go b/internal/repository/media_repo.go index 5063624..135dfb2 100644 --- a/internal/repository/media_repo.go +++ b/internal/repository/media_repo.go @@ -12,7 +12,7 @@ func NewMediaRepository(db *sql.DB) *MediaRepository { 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) + rows, err := r.db.Query("SELECT id, path, library_id FROM media_files WHERE id = ?", id) if err != nil { return MediaFile{}, err } diff --git a/queue.go b/queue.go index 4632b78..5bd3c08 100644 --- a/queue.go +++ b/queue.go @@ -1,3 +1,5 @@ +// Package main - Task queue for background processing. +// Currently unused but kept for future async task support (e.g., background scanning). package main import ( diff --git a/scanner.go b/scanner.go deleted file mode 100644 index 330d8ea..0000000 --- a/scanner.go +++ /dev/null @@ -1,95 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/dhowden/tag" -) - -type ScannedSong struct { - Title string - Artist string - Album string - Duration int - Path string -} - -func scanDirectory(dirPath string) ([]ScannedSong, error) { - songs := []ScannedSong{} - - if _, err := os.Stat(dirPath); os.IsNotExist(err) { - return songs, err - } - filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { - - if info.IsDir() { - return nil - } - - if !isAudioFile(path) { - return nil - } - - if song, err := processAudioFile(path); err != nil { - return err - } else { - songs = append(songs, song) - } - return nil - }) - - return songs, nil -} - -func processAudioFile(filePath string) (ScannedSong, error) { - file, err := os.Open(filePath) - if err != nil { - return ScannedSong{}, fmt.Errorf("failed to open file: %v", err) - } - defer file.Close() - - // Read metadata - metadata, err := tag.ReadFrom(file) - if err != nil { - return ScannedSong{}, fmt.Errorf("failed to read metadata: %v", err) - } - - // Extract metadata - title := metadata.Title() - if title == "" { - title = filepath.Base(filePath) - } - - artist := metadata.Artist() - if artist == "" { - artist = "Unknown Artist" - } - - album := metadata.Album() - if album == "" { - album = "Unknown Album" - } - - return ScannedSong{ - Title: title, - Artist: artist, - Album: album, - Duration: 100, - Path: filePath, - }, nil -} - -func isAudioFile(path string) bool { - ext := strings.ToLower(filepath.Ext(path)) - audioExtensions := []string{".mp3", ".flac", ".m4a", ".wav", ".ogg"} - - for _, audioExt := range audioExtensions { - if ext == audioExt { - return true - } - } - return false -} diff --git a/scanner_test.go b/scanner_test.go deleted file mode 100644 index ab46e0d..0000000 --- a/scanner_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package main - -import ( - "testing" -) - -func TestIsAudioFile(t *testing.T) { - - tests := []struct { - name string - path string - expected bool - }{ - {"mp3 file", "song.mp3", true}, - {"flac file", "song.flac", true}, - {"m4a file", "song.m4a", true}, - {"wav file", "song.wav", true}, - {"ogg file", "song.ogg", true}, - {"aac file", "song.aac", false}, - {"wma file", "song.wma", false}, - {"uppercase extension", "song.MP3", true}, - {"mixed case", "song.Mp3", true}, - {"txt file", "song.txt", false}, - {"jpg file", "song.jpg", false}, - {"no extension", "song", false}, - {"dot in name", "my.song.mp3", true}, - {"multiple dots", "my.song.final.mp3", true}, - {"path with directory", "/path/to/song.mp3", true}, - {"Windows path", "C:\\Music\\song.mp3", true}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := isAudioFile(tt.path) - if result != tt.expected { - t.Errorf("isAudioFile(%q) = %v, want %v", tt.path, result, tt.expected) - } - }) - } -}