Skip to content

Commit

Permalink
add --install to lastfm suggest
Browse files Browse the repository at this point in the history
  • Loading branch information
kitesi committed Jan 20, 2024
1 parent 6ab3c9e commit c38708a
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 19 deletions.
43 changes: 32 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ go install github.com/kitesi/music@latest

## Usage

This program works off a music directory which defaults to `$HOME/Music`. I
This program works off a music directory which defaults to `$MUSIC_PATH` or `$HOME/Music`.
Commands that consider a music path will have a `--music-path` option. I
recommend a folder structure of:

```text
Expand Down Expand Up @@ -171,13 +172,27 @@ Lastly, it follows the [lastfm standards](https://www.last.fm/api/scrobbling):
1. The track must be longer than 30 seconds.
2. The track has been played for at least half its duration, or for 4 minutes (whichever occurs earlier.)

How to call:
To get started you first need to create a file (".lastfm-credentials") in your cache directory. Your cache directory is determined by Go below:

- On Unix systems, it returns `$XDG_CACHE_HOME` as specified by https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if non-empty, else $HOME/.cache.
- On Darwin, it returns `$HOME/Library/Caches`
- On Windows, it returns `%LocalAppData%`
- On Plan 9, it returns `$home/lib/cache`

In that file you should store your api_key and your api_secret:

```
api_key=xxxxx
api_secret=yyyy
```

Then just run the lastfm watch command, and it will automatically get the session_key:

```
music lastfm --interval 20 --debug
music lastfm watch --interval 20 --debug
```

I personally have this command start on startup, and redirect the output to `/tmp/music-lastfm.log`.
I personally have this command start on startup, and I redirect the output to `/tmp/music-lastfm.log`.

### Lastfm Suggestions

Expand All @@ -187,17 +202,19 @@ You can also get lastfm suggestions (on any OS, without authentication) with the
music lastfm suggest username --limit 20
```

If you would like to automatically install the music add the `--install` flag which will install to `$MUSIC_PATH/Suggestions`.

### Android

If you would like to use the one of main functionalities of querying on android,
you can do so using termux. You will likely have to install go first and then
you can do so using Termux. You will likely have to install go first and then
follow the instructions in #installation.

After you have the music command installed, you want to download the wrapper script
in `./android-termux-mx`. This script calls the play command with the given query
in a dry run so that no program is called. It then sets the results to a new tag (query.m3u).

You should copy the file to a directory in your termux's `$PATH`:
You should copy the file to a directory in your Termux's `$PATH`:

```bash
# assuming your $PATH is just one folder (like default)
Expand All @@ -208,11 +225,15 @@ Once you have the script mx, you can now run it like you would `music play`:
`mx jaxson#tonight`. Now you can open up vlc and see that in your playlists tab
there should be a playlist called "query."

You are able to install vlc/cvlc/nvlc on termux, but I would not suggest doing
so because termux will be hanging and you won't have vlc in your notification
tray.
You are able to install vlc/cvlc/nvlc on termux, and in turn `music play` will
work like normal, but I would not suggest doing so because termux will be
hanging, and you won't have vlc in your notification tray.

### Configuration

There is no configuration file currently. I would suggest setting up an alias
with your desired options.
There is no configuration file currently. I have considered adding one, but this program is
slow enough. I would suggest setting up an alias with your desired options.

Because no one besides me uses this program, a lot of the utility is centered around my workflow,
and I skip a lot of customization options. Feel free to submit an issue if you want a feature,
or just patch it yourself (the codebase is pretty easy to figure it).
51 changes: 45 additions & 6 deletions commands/lastfm/suggest.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import (
"io"
"net/http"
"os"
"os/exec"
"path"
"sync"

stringUtils "github.com/kitesi/music/string-utils"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -45,10 +49,24 @@ func SuggestSetup() *cobra.Command {
lastfmCommand.Flags().BoolVar(&args.debug, "debug", false, "set debug mode")
lastfmCommand.Flags().BoolVar(&args.printUrls, "print-urls", true, "print the urls along with the song name")
lastfmCommand.Flags().IntVarP(&args.limit, "limit", "l", 10, "limit the number of songs to suggest")
lastfmCommand.Flags().StringVarP(&args.musicPath, "music-path", "m", "", "the music path to use")
lastfmCommand.Flags().StringVarP(&args.format, "format", "f", "bestaudio[ext=m4a]", "the format to install")
lastfmCommand.Flags().BoolVarP(&args.install, "install", "i", false, "install the files to the music path under the 'Suggestions' folder")

return lastfmCommand
}

func installSong(args *LastfmSuggestArgs, link string, artist string, title string) error {
ytdlArgs := []string{"--extract-audio", "--format", args.format, "--add-metadata", "--postprocessor-args", fmt.Sprintf("-metadata title=\"%s\" -metadata artist=\"%s\"", title, artist), "--output", path.Join(args.musicPath, "Suggestions", fmt.Sprintf("%s - %s.%%(ext)s", artist, title)), link}

cmd := exec.Command("youtube-dl", ytdlArgs...)

cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout

return cmd.Run()
}

func suggestRunner(args *LastfmSuggestArgs, username string) error {
if username == "" {
credentials, err := setupOrGetCredentials()
Expand Down Expand Up @@ -93,6 +111,18 @@ func suggestRunner(args *LastfmSuggestArgs, username string) error {
args.limit = len(resultJson.Playlist)
}

if args.install && args.musicPath == "" {
defaultMusicPath, err := stringUtils.GetDefaultMusicPath()

if err != nil {
return err
}

args.musicPath = defaultMusicPath
}

var installWaitGroup sync.WaitGroup

for i := 0; i < args.limit; i++ {
item := resultJson.Playlist[i]
albumArtist := ""
Expand All @@ -108,24 +138,33 @@ func suggestRunner(args *LastfmSuggestArgs, username string) error {
}

fmt.Printf("%s - %s", albumArtist, item.Name)
playUrl := ""

if args.printUrls {
playUrl := ""

if args.printUrls || args.install {
for _, playlink := range item.Playlinks {
if playlink.Url != "" {
playUrl = playlink.Url
break
}
}
}

if playUrl != "" {
fmt.Printf(" (%s)", playUrl)
}
if args.printUrls && playUrl != "" {
fmt.Printf(" (%s)", playUrl)
}

fmt.Println()

if args.install && playUrl != "" {
installWaitGroup.Add(1)

go func() {
defer installWaitGroup.Done()
installSong(args, playUrl, albumArtist, item.Name)
}()
}
}

installWaitGroup.Wait()
return nil
}
5 changes: 4 additions & 1 deletion commands/lastfm/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ type LastfmWatchArgs struct {

type LastfmSuggestArgs struct {
debug bool
limit int
printUrls bool
install bool
limit int
musicPath string
format string
}
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module github.com/kitesi/music
go 1.18

require (
github.com/adrg/libvlc-go/v3 v3.1.5
github.com/djherbis/times v1.5.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/pkg/errors v0.9.1
Expand Down
11 changes: 11 additions & 0 deletions string-utils/string-utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@ import (
)

func GetDefaultMusicPath() (string, error) {
envMusicPath, _ := os.LookupEnv("MUSIC_PATH")

if envMusicPath != "" {
return envMusicPath, nil
}

dirname, err := os.UserHomeDir()

if err != nil {
return "", err
}

return filepath.Join(dirname, "Music"), err
}

Expand Down

0 comments on commit c38708a

Please sign in to comment.