Skip to content

Instantly share code, notes, and snippets.

@ariankordi
Last active November 19, 2018 22:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ariankordi/11866a2c9df40c20d6f1fea77aca0d10 to your computer and use it in GitHub Desktop.
Save ariankordi/11866a2c9df40c20d6f1fea77aca0d10 to your computer and use it in GitHub Desktop.
downloads track(s) (plural) from spotify (premium) with librespot LO LOLOLOLOLLO OLOLOLLOLLOLOOLLOLOOLOLOLOOLOLOLOLOLO
package main
// AS OF this being posted, librespot-golang has some deadlocking and you will need to use this fork: https://github.com/benpye/librespot-golang
import (
"Spotify"
"librespot"
"librespot/core"
"librespot/utils"
"github.com/mitchellh/ioprogress"
"encoding/json"
"strings"
"io/ioutil"
"io"
"os"
"log"
"fmt"
)
const (
username = "change this change this"
password = "change this change this"
deviceName = "librespot"
)
func main() {
if len(os.Args) < 2 {
fmt.Println(`usage:", os.Args[0], "(json of [ [id, filename], [id, filename] ])
like [ ["7sNoYrWSysPqaTT5LCMEmn", "/dev/shm/oedo-controller.ogg"] ] and multiple assets etc`)
os.Exit(0)
}
var tracksToDownload [][]string
err := json.Unmarshal([]byte(os.Args[1]), &tracksToDownload)
if err != nil {
log.Fatal("your json argument is invalid:", err)
}
var session *core.Session
log.Println("logging in... checking if blob exists (spotify-auth-blob.bin)")
blobBytes, err := ioutil.ReadFile("spotify-auth-blob.bin")
if err != nil && !os.IsNotExist(err) {
log.Fatal("err loading blob:", err)
}
if blobBytes != nil {
log.Println("blob exists, logging in with it...")
session, err = librespot.LoginSaved(username, blobBytes, deviceName)
} else {
log.Println("blob doesn't exist, logging in with username & password... (will create blob)")
session, err = librespot.Login(username, password, deviceName)
}
if err != nil {
log.Fatal("err logging in:", err)
}
if blobBytes == nil {
log.Println("creating blob... (spotify-auth-blob.bin)")
blobFile, err := os.Create("spotify-auth-blob.bin")
if err != nil {
log.Fatal("err creating blob file:", err)
}
blobFile.Write(session.ReusableAuthBlob())
blobFile.Close()
log.Println("wrote blob.")
}
// phew
log.Println("iterating through argument...")
for _, trackToDownload := range tracksToDownload {
if strings.HasPrefix(trackToDownload[0], "spotify:track:") {
trackToDownload[0] = strings.TrimPrefix(trackToDownload[0], "spotify:track:")
}
log.Println("loading track " + trackToDownload[0])
track, err := session.Mercury().GetTrack(utils.Base62ToHex(trackToDownload[0]))
if err != nil {
log.Println("err loading track:", err)
continue
}
trackName := track.GetName()
if trackName == "" {
log.Println("track doesn't exist, skipping...")
continue
}
var selectedFile *Spotify.AudioFile
for _, file := range track.GetFile() {
if file.GetFormat() == Spotify.AudioFile_OGG_VORBIS_320 {
selectedFile = file
break
}
}
if len(trackToDownload) < 2 || trackToDownload[1] == "" {
trackToDownload = []string{
trackToDownload[0],
strings.Replace(strings.Replace(strings.ToLower(trackName), " ", "-", -1), "/", "", -1) + ".ogg",
}
}
downloadFile, err := os.Create(trackToDownload[1])
if err != nil {
log.Println("err creating file " + trackToDownload[1] + ":", err)
log.Println("skipping track " + trackName)
continue
}
log.Println("downloading track " + trackName + "...")
audioFile, err := session.Player().LoadTrack(selectedFile, track.GetGid())
if err != nil {
log.Println("err downloading track:", err)
log.Println("skipping track " + trackName)
continue
}
// copy
progressReader := &ioprogress.Reader{
Reader: audioFile,
}
io.Copy(downloadFile, progressReader)
downloadFile.Close()
log.Println("track " + trackName + " finished")
}
log.Println("finished")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment