chore: remove dead code, fix error casing, and add lint rules

- Remove unused Go functions: buildRawAPEItem, loadCredentials,
  scanAudioFile, scanAudioFileWithKnownModTimeAndDisplayName,
  readM4AIndexValue, musixmatchSearchResponse/LyricsResponse structs
- Remove unused Go fields: downloadDir, utlsTransport.mu/h2Transports
- Lowercase Go error messages per convention (golint/ST1005)
- Simplify LyricsLine conversion and artistsMatch return
- Add Dart analysis rules: always_declare_return_types,
  avoid_types_as_parameter_names, strict_top_level_inference,
  type_annotate_public_apis
- Suppress SA1019 lint for required blowfish import
This commit is contained in:
zarzet 2026-05-06 00:04:49 +07:00
parent 2143de3aa7
commit bb06ab7e12
13 changed files with 37 additions and 115 deletions

View file

@ -36,7 +36,11 @@ linter:
rules: rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule # avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
always_declare_return_types: true
avoid_dynamic_calls: true avoid_dynamic_calls: true
avoid_types_as_parameter_names: true
strict_top_level_inference: true
type_annotate_public_apis: true
cancel_subscriptions: true cancel_subscriptions: true
close_sinks: true close_sinks: true

View file

@ -399,13 +399,3 @@ func createTestExtensionPackage(t *testing.T, path, name, version, js string, ex
} }
} }
} }
func buildRawAPEItem(key, value string, flags uint32) []byte {
var buf bytes.Buffer
_ = binary.Write(&buf, binary.LittleEndian, uint32(len(value)))
_ = binary.Write(&buf, binary.LittleEndian, flags)
buf.WriteString(key)
buf.WriteByte(0)
buf.WriteString(value)
return buf.Bytes()
}

View file

@ -2230,7 +2230,7 @@ func ConvertSpotifyToDeezer(resourceType, spotifyID string) (string, error) {
return string(jsonBytes), nil return string(jsonBytes), nil
} }
return "", fmt.Errorf("Spotify to Deezer conversion only supported for tracks and albums. Please search by name for %s", resourceType) return "", fmt.Errorf("spotify to Deezer conversion only supported for tracks and albums: please search by name for %s", resourceType)
} }
func CheckAvailabilityFromDeezerID(deezerTrackID string) (string, error) { func CheckAvailabilityFromDeezerID(deezerTrackID string) (string, error) {

View file

@ -157,12 +157,12 @@ func (m *extensionManager) SetDirectories(extensionsDir, dataDir string) error {
func (m *extensionManager) LoadExtensionFromFile(filePath string) (*loadedExtension, error) { func (m *extensionManager) LoadExtensionFromFile(filePath string) (*loadedExtension, error) {
if !strings.HasSuffix(strings.ToLower(filePath), ".spotiflac-ext") { if !strings.HasSuffix(strings.ToLower(filePath), ".spotiflac-ext") {
return nil, fmt.Errorf("Invalid file format. Please select a .spotiflac-ext file") return nil, fmt.Errorf("invalid file format: please select a .spotiflac-ext file")
} }
zipReader, err := zip.OpenReader(filePath) zipReader, err := zip.OpenReader(filePath)
if err != nil { if err != nil {
return nil, fmt.Errorf("Cannot open extension file. The file may be corrupted or not a valid extension package") return nil, fmt.Errorf("cannot open extension file: the file may be corrupted or not a valid extension package")
} }
defer zipReader.Close() defer zipReader.Close()
@ -187,16 +187,16 @@ func (m *extensionManager) LoadExtensionFromFile(filePath string) (*loadedExtens
} }
if manifestData == nil { if manifestData == nil {
return nil, fmt.Errorf("Invalid extension package: manifest.json not found") return nil, fmt.Errorf("invalid extension package: manifest.json not found")
} }
if !hasIndexJS { if !hasIndexJS {
return nil, fmt.Errorf("Invalid extension package: index.js not found") return nil, fmt.Errorf("invalid extension package: index.js not found")
} }
manifest, err := ParseManifest(manifestData) manifest, err := ParseManifest(manifestData)
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid extension manifest: %w", err) return nil, fmt.Errorf("invalid extension manifest: %w", err)
} }
m.mu.RLock() m.mu.RLock()
@ -214,9 +214,9 @@ func (m *extensionManager) LoadExtensionFromFile(filePath string) (*loadedExtens
if versionCompare > 0 { if versionCompare > 0 {
return m.UpgradeExtension(filePath) return m.UpgradeExtension(filePath)
} else if versionCompare == 0 { } else if versionCompare == 0 {
return nil, fmt.Errorf("Extension '%s' v%s is already installed", existingDisplayName, existingVersion) return nil, fmt.Errorf("extension '%s' v%s is already installed", existingDisplayName, existingVersion)
} else { } else {
return nil, fmt.Errorf("Cannot downgrade '%s' from v%s to v%s", existingDisplayName, existingVersion, manifest.Version) return nil, fmt.Errorf("cannot downgrade '%s' from v%s to v%s", existingDisplayName, existingVersion, manifest.Version)
} }
} }
@ -224,7 +224,7 @@ func (m *extensionManager) LoadExtensionFromFile(filePath string) (*loadedExtens
defer m.mu.Unlock() defer m.mu.Unlock()
if _, exists := m.extensions[manifest.Name]; exists { if _, exists := m.extensions[manifest.Name]; exists {
return nil, fmt.Errorf("Extension '%s' was installed by another process", manifest.DisplayName) return nil, fmt.Errorf("extension '%s' was installed by another process", manifest.DisplayName)
} }
extDir := filepath.Join(m.extensionsDir, manifest.Name) extDir := filepath.Join(m.extensionsDir, manifest.Name)
@ -426,7 +426,7 @@ func initializeExtensionRuntimeWithSettings(
) error { ) error {
settingsJSON, err := json.Marshal(settings) settingsJSON, err := json.Marshal(settings)
if err != nil { if err != nil {
return fmt.Errorf("Failed to save settings") return fmt.Errorf("failed to save settings")
} }
script := fmt.Sprintf(` script := fmt.Sprintf(`
@ -472,7 +472,7 @@ func initializeExtensionWithSettingsLocked(
settings map[string]interface{}, settings map[string]interface{},
) error { ) error {
if ext.VM == nil { if ext.VM == nil {
return fmt.Errorf("Extension failed to load. Please reinstall the extension") return fmt.Errorf("extension failed to load: please reinstall the extension")
} }
if err := initializeExtensionRuntimeWithSettings(ext.VM, ext.ID, settings); err != nil { if err := initializeExtensionRuntimeWithSettings(ext.VM, ext.ID, settings); err != nil {
@ -570,7 +570,7 @@ func (m *extensionManager) UnloadExtension(extensionID string) error {
ext, exists := m.extensions[extensionID] ext, exists := m.extensions[extensionID]
if !exists { if !exists {
return fmt.Errorf("Extension not found") return fmt.Errorf("extension not found")
} }
ext.VMMu.Lock() ext.VMMu.Lock()
@ -589,7 +589,7 @@ func (m *extensionManager) GetExtension(extensionID string) (*loadedExtension, e
ext, exists := m.extensions[extensionID] ext, exists := m.extensions[extensionID]
if !exists { if !exists {
return nil, fmt.Errorf("Extension not found") return nil, fmt.Errorf("extension not found")
} }
return ext, nil return ext, nil
} }
@ -611,7 +611,7 @@ func (m *extensionManager) SetExtensionEnabled(extensionID string, enabled bool)
ext, exists := m.extensions[extensionID] ext, exists := m.extensions[extensionID]
if !exists { if !exists {
return fmt.Errorf("Extension not found") return fmt.Errorf("extension not found")
} }
if enabled { if enabled {
@ -689,12 +689,12 @@ func (m *extensionManager) loadExtensionFromDirectory(dirPath string) (*loadedEx
manifest, err := ParseManifest(manifestData) manifest, err := ParseManifest(manifestData)
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid extension manifest: %w", err) return nil, fmt.Errorf("invalid extension manifest: %w", err)
} }
indexPath := filepath.Join(dirPath, "index.js") indexPath := filepath.Join(dirPath, "index.js")
if _, err := os.Stat(indexPath); os.IsNotExist(err) { if _, err := os.Stat(indexPath); os.IsNotExist(err) {
return nil, fmt.Errorf("Extension is missing index.js file") return nil, fmt.Errorf("extension is missing index.js file")
} }
if existing, exists := m.extensions[manifest.Name]; exists { if existing, exists := m.extensions[manifest.Name]; exists {
@ -757,12 +757,12 @@ func (m *extensionManager) RemoveExtension(extensionID string) error {
// Only allows upgrades (new version > current version), not downgrades // Only allows upgrades (new version > current version), not downgrades
func (m *extensionManager) UpgradeExtension(filePath string) (*loadedExtension, error) { func (m *extensionManager) UpgradeExtension(filePath string) (*loadedExtension, error) {
if !strings.HasSuffix(strings.ToLower(filePath), ".spotiflac-ext") { if !strings.HasSuffix(strings.ToLower(filePath), ".spotiflac-ext") {
return nil, fmt.Errorf("Invalid file format. Please select a .spotiflac-ext file") return nil, fmt.Errorf("invalid file format: please select a .spotiflac-ext file")
} }
zipReader, err := zip.OpenReader(filePath) zipReader, err := zip.OpenReader(filePath)
if err != nil { if err != nil {
return nil, fmt.Errorf("Cannot open extension file. The file may be corrupted or not a valid extension package") return nil, fmt.Errorf("cannot open extension file: the file may be corrupted or not a valid extension package")
} }
defer zipReader.Close() defer zipReader.Close()
@ -787,16 +787,16 @@ func (m *extensionManager) UpgradeExtension(filePath string) (*loadedExtension,
} }
if manifestData == nil { if manifestData == nil {
return nil, fmt.Errorf("Invalid extension package: manifest.json not found") return nil, fmt.Errorf("invalid extension package: manifest.json not found")
} }
if !hasIndexJS { if !hasIndexJS {
return nil, fmt.Errorf("Invalid extension package: index.js not found") return nil, fmt.Errorf("invalid extension package: index.js not found")
} }
newManifest, err := ParseManifest(manifestData) newManifest, err := ParseManifest(manifestData)
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid extension manifest: %w", err) return nil, fmt.Errorf("invalid extension manifest: %w", err)
} }
m.mu.RLock() m.mu.RLock()
@ -804,15 +804,15 @@ func (m *extensionManager) UpgradeExtension(filePath string) (*loadedExtension,
m.mu.RUnlock() m.mu.RUnlock()
if !exists { if !exists {
return nil, fmt.Errorf("Extension '%s' is not installed. Use install instead of upgrade.", newManifest.DisplayName) return nil, fmt.Errorf("extension '%s' is not installed; use install instead of upgrade", newManifest.DisplayName)
} }
versionCompare := compareVersions(newManifest.Version, existing.Manifest.Version) versionCompare := compareVersions(newManifest.Version, existing.Manifest.Version)
if versionCompare < 0 { if versionCompare < 0 {
return nil, fmt.Errorf("Cannot downgrade extension. Current version: %s, New version: %s", existing.Manifest.Version, newManifest.Version) return nil, fmt.Errorf("cannot downgrade extension: current version: %s, new version: %s", existing.Manifest.Version, newManifest.Version)
} }
if versionCompare == 0 { if versionCompare == 0 {
return nil, fmt.Errorf("Extension is already at version %s", existing.Manifest.Version) return nil, fmt.Errorf("extension is already at version %s", existing.Manifest.Version)
} }
GoLog("[Extension] Upgrading %s from v%s to v%s\n", newManifest.DisplayName, existing.Manifest.Version, newManifest.Version) GoLog("[Extension] Upgrading %s from v%s to v%s\n", newManifest.DisplayName, existing.Manifest.Version, newManifest.Version)
@ -906,13 +906,13 @@ type ExtensionUpgradeInfo struct {
func (m *extensionManager) checkExtensionUpgradeInternal(filePath string) (*ExtensionUpgradeInfo, error) { func (m *extensionManager) checkExtensionUpgradeInternal(filePath string) (*ExtensionUpgradeInfo, error) {
if !strings.HasSuffix(strings.ToLower(filePath), ".spotiflac-ext") { if !strings.HasSuffix(strings.ToLower(filePath), ".spotiflac-ext") {
return nil, fmt.Errorf("Invalid file format. Please select a .spotiflac-ext file") return nil, fmt.Errorf("invalid file format: please select a .spotiflac-ext file")
} }
zipReader, err := zip.OpenReader(filePath) zipReader, err := zip.OpenReader(filePath)
if err != nil { if err != nil {
return nil, fmt.Errorf("Cannot open extension file") return nil, fmt.Errorf("cannot open extension file")
} }
defer zipReader.Close() defer zipReader.Close()
@ -939,7 +939,7 @@ func (m *extensionManager) checkExtensionUpgradeInternal(filePath string) (*Exte
newManifest, err := ParseManifest(manifestData) newManifest, err := ParseManifest(manifestData)
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid manifest: %w", err) return nil, fmt.Errorf("invalid manifest: %w", err)
} }
m.mu.RLock() m.mu.RLock()
@ -1082,7 +1082,7 @@ func (m *extensionManager) InitializeExtension(extensionID string, settings map[
ext, exists := m.extensions[extensionID] ext, exists := m.extensions[extensionID]
if !exists { if !exists {
return fmt.Errorf("Extension not found") return fmt.Errorf("extension not found")
} }
ext.VMMu.Lock() ext.VMMu.Lock()
@ -1100,7 +1100,7 @@ func (m *extensionManager) CleanupExtension(extensionID string) error {
ext, exists := m.extensions[extensionID] ext, exists := m.extensions[extensionID]
if !exists { if !exists {
return fmt.Errorf("Extension not found") return fmt.Errorf("extension not found")
} }
if ext.VM == nil { if ext.VM == nil {

View file

@ -3333,11 +3333,7 @@ func (p *extensionProviderWrapper) FetchLyrics(trackName, artistName, albumName
} }
for _, line := range extResult.Lines { for _, line := range extResult.Lines {
response.Lines = append(response.Lines, LyricsLine{ response.Lines = append(response.Lines, LyricsLine(line))
StartTimeMs: line.StartTimeMs,
Words: line.Words,
EndTimeMs: line.EndTimeMs,
})
} }
if len(response.Lines) == 0 && response.PlainLyrics != "" && !response.Instrumental { if len(response.Lines) == 0 && response.PlainLyrics != "" && !response.Instrumental {

View file

@ -9,6 +9,7 @@ import (
"strings" "strings"
"github.com/dop251/goja" "github.com/dop251/goja"
//lint:ignore SA1019 Blowfish is required for legacy extension crypto compatibility.
"golang.org/x/crypto/blowfish" "golang.org/x/crypto/blowfish"
) )

View file

@ -340,16 +340,6 @@ func (r *extensionRuntime) ensureCredentialsLoaded() error {
return nil return nil
} }
func (r *extensionRuntime) loadCredentials() (map[string]interface{}, error) {
if err := r.ensureCredentialsLoaded(); err != nil {
return nil, err
}
r.credentialsMu.RLock()
defer r.credentialsMu.RUnlock()
return cloneInterfaceMap(r.credentialsCache), nil
}
func (r *extensionRuntime) saveCredentials(creds map[string]interface{}) error { func (r *extensionRuntime) saveCredentials(creds map[string]interface{}) error {
data, err := json.Marshal(creds) data, err := json.Marshal(creds)
if err != nil { if err != nil {

View file

@ -10,16 +10,13 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"strings" "strings"
"sync"
utls "github.com/refraction-networking/utls" utls "github.com/refraction-networking/utls"
"golang.org/x/net/http2" "golang.org/x/net/http2"
) )
type utlsTransport struct { type utlsTransport struct {
dialer *net.Dialer dialer *net.Dialer
mu sync.Mutex
h2Transports map[string]*http2.Transport
} }
func newUTLSTransport() *utlsTransport { func newUTLSTransport() *utlsTransport {
@ -28,7 +25,6 @@ func newUTLSTransport() *utlsTransport {
Timeout: 30 * Second, Timeout: 30 * Second,
KeepAlive: 30 * Second, KeepAlive: 30 * Second,
}, },
h2Transports: make(map[string]*http2.Transport),
} }
} }

View file

@ -276,18 +276,10 @@ func ScanLibraryFolder(folderPath string) (string, error) {
return string(jsonBytes), nil return string(jsonBytes), nil
} }
func scanAudioFile(filePath, scanTime string) (*LibraryScanResult, error) {
return scanAudioFileWithKnownModTimeAndDisplayName(filePath, "", scanTime, 0)
}
func scanAudioFileWithKnownModTime(filePath, scanTime string, knownModTime int64) (*LibraryScanResult, error) { func scanAudioFileWithKnownModTime(filePath, scanTime string, knownModTime int64) (*LibraryScanResult, error) {
return scanAudioFileWithKnownModTimeAndDisplayNameAndCoverCacheKey(filePath, "", "", scanTime, knownModTime) return scanAudioFileWithKnownModTimeAndDisplayNameAndCoverCacheKey(filePath, "", "", scanTime, knownModTime)
} }
func scanAudioFileWithKnownModTimeAndDisplayName(filePath, displayNameHint, scanTime string, knownModTime int64) (*LibraryScanResult, error) {
return scanAudioFileWithKnownModTimeAndDisplayNameAndCoverCacheKey(filePath, displayNameHint, "", scanTime, knownModTime)
}
func scanAudioFileWithKnownModTimeAndDisplayNameAndCoverCacheKey(filePath, displayNameHint, coverCacheKey, scanTime string, knownModTime int64) (*LibraryScanResult, error) { func scanAudioFileWithKnownModTimeAndDisplayNameAndCoverCacheKey(filePath, displayNameHint, coverCacheKey, scanTime string, knownModTime int64) (*LibraryScanResult, error) {
ext := resolveLibraryAudioExt(filePath, displayNameHint) ext := resolveLibraryAudioExt(filePath, displayNameHint)

View file

@ -16,32 +16,6 @@ type MusixmatchClient struct {
baseURL string baseURL string
} }
type musixmatchSearchResponse struct {
ID int64 `json:"id"`
SongName string `json:"songName"`
ArtistName string `json:"artistName"`
AlbumName string `json:"albumName"`
Artwork string `json:"artwork"`
ReleaseDate string `json:"releaseDate"`
Duration int `json:"duration"`
URL string `json:"url"`
AlbumID int64 `json:"albumId"`
HasSyncedLyrics bool `json:"hasSyncedLyrics"`
HasUnsyncedLyrics bool `json:"hasUnsyncedLyrics"`
AvailableLanguages []string `json:"availableLanguages"`
OriginalLanguage string `json:"originalLanguage"`
SyncedLyrics *musixmatchLyricsResponse `json:"syncedLyrics"`
UnsyncedLyrics *musixmatchLyricsResponse `json:"unsyncedLyrics"`
}
type musixmatchLyricsResponse struct {
ID int64 `json:"id"`
Duration int `json:"duration"`
Language string `json:"language"`
UpdatedTime string `json:"updatedTime"`
Lyrics string `json:"lyrics"`
}
func NewMusixmatchClient() *MusixmatchClient { func NewMusixmatchClient() *MusixmatchClient {
return &MusixmatchClient{ return &MusixmatchClient{
httpClient: NewMetadataHTTPClient(15 * time.Second), httpClient: NewMetadataHTTPClient(15 * time.Second),

View file

@ -1150,17 +1150,6 @@ func readM4ATextValue(f *os.File, parent atomHeader, fileSize int64) (string, er
return strings.TrimSpace(strings.TrimRight(string(payload), "\x00")), nil return strings.TrimSpace(strings.TrimRight(string(payload), "\x00")), nil
} }
func readM4AIndexValue(f *os.File, parent atomHeader, fileSize int64) (int, error) {
payload, err := readM4ADataPayload(f, parent, fileSize)
if err != nil {
return 0, err
}
if len(payload) < 4 {
return 0, fmt.Errorf("index payload too short in %s", parent.typ)
}
return int(binary.BigEndian.Uint16(payload[2:4])), nil
}
func readM4AIndexPair(f *os.File, parent atomHeader, fileSize int64) (int, int, error) { func readM4AIndexPair(f *os.File, parent atomHeader, fileSize int64) (int, int, error) {
payload, err := readM4ADataPayload(f, parent, fileSize) payload, err := readM4ADataPayload(f, parent, fileSize)
if err != nil { if err != nil {

View file

@ -56,9 +56,6 @@ type progressBridgeState struct {
} }
var ( var (
downloadDir string
downloadDirMu sync.RWMutex
multiProgress = MultiProgress{Items: make(map[string]*ItemProgress)} multiProgress = MultiProgress{Items: make(map[string]*ItemProgress)}
multiMu sync.RWMutex multiMu sync.RWMutex
multiProgressDirty = true multiProgressDirty = true
@ -368,9 +365,6 @@ func ClearAllItemProgress() {
} }
func setDownloadDir(path string) error { func setDownloadDir(path string) error {
downloadDirMu.Lock()
defer downloadDirMu.Unlock()
downloadDir = path
return nil return nil
} }

View file

@ -138,11 +138,7 @@ func artistsMatch(expectedArtist, foundArtist string) bool {
} }
} }
if isLatinScript(expectedArtist) != isLatinScript(foundArtist) { return isLatinScript(expectedArtist) != isLatinScript(foundArtist)
return true
}
return false
} }
func splitArtists(artists string) []string { func splitArtists(artists string) []string {