Compare commits

..

2 Commits

Author SHA1 Message Date
riwiwa
a8352c5bf9 Update README.md 2026-01-08 04:41:03 -08:00
679d7f9202 early working LastFM import functionality 2026-01-08 04:36:54 -08:00
3 changed files with 97 additions and 11 deletions

View File

@@ -4,17 +4,9 @@
### Dependencies ### Dependencies
- PostgreSQL - PostgreSQL
### Installation Instructions (for testing and development) \[Only Supports Spotify Imports ATM\]:
1. Clone the repo:<br>```git clone https://github.com/riwiwa/muzi```
2. Copy over all zip archives obtained from Spotify into the ```imports/spotify-data/zip/``` directory.
3. Ensure PostgreSQL is installed and running locally on port 5432.
4. Run the app with:<br>```go run main.go```
5. Navigate to ```localhost:1234/history``` to see your sorted listening history.
6. Comment out ```importsongs.ImportSpotify()``` from ```main.go``` to prevent the app's attempts to import the Spotify data again
### Roadmap: ### Roadmap:
- Ability to import all listening statistics and scrobbles from: \[In Progress\] - Ability to import all listening statistics and scrobbles from: \[In Progress\]
- lastfm - lastfm \[In progress\]
- spotify \[Complete\] - spotify \[Complete\]
- apple music - apple music

View File

@@ -5,11 +5,15 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/jackc/pgx/v5"
"io" "io"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"time"
"github.com/jackc/pgx/v5"
) )
const ( const (
@@ -150,6 +154,97 @@ func AddDirToDB(path string, platform int) {
} }
} }
func ImportLastFM() {
if !DbExists() {
err := CreateDB()
if err != nil {
panic(err)
}
}
conn, err := pgx.Connect(context.Background(), "postgres://postgres:postgres@localhost:5432/muzi")
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot connect to muzi database: %v\n", err)
panic(err)
}
defer conn.Close(context.Background())
if !TableExists("history", conn) {
_, err = conn.Exec(context.Background(), "CREATE TABLE history ( ms_played INTEGER, timestamp TIMESTAMPTZ, song_name TEXT, artist TEXT, album_name TEXT, PRIMARY KEY (timestamp, ms_played, artist, song_name));")
}
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot create history table: %v\n", err)
panic(err)
}
username := ""
apiKey := ""
resp, err := http.Get("https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=" + username + "&api_key=" + apiKey + "&format=json&limit=1")
if err != nil {
panic(err)
}
type Response struct {
Recenttracks struct {
Track []struct {
Artist struct {
Mbid string `json:"mbid"`
Text string `json:"#text"`
} `json:"artist"`
Streamable string `json:"streamable"`
Image []struct {
Size string `json:"size"`
Text string `json:"#text"`
} `json:"image"`
Mbid string `json:"mbid"`
Album struct {
Mbid string `json:"mbid"`
Text string `json:"#text"`
} `json:"album"`
Name string `json:"name"`
URL string `json:"url"`
Date struct {
Uts string `json:"uts"`
Text string `json:"#text"`
} `json:"date"`
} `json:"track"`
Attr struct {
PerPage string `json:"perPage"`
TotalPages string `json:"totalPages"`
Page string `json:"page"`
Total string `json:"total"`
User string `json:"user"`
} `json:"@attr"`
} `json:"recenttracks"`
}
var data Response
json.NewDecoder(resp.Body).Decode(&data)
totalPages, err := strconv.Atoi(data.Recenttracks.Attr.TotalPages)
if totalPages%100 != 0 {
totalPages = totalPages / 100
totalPages++
} else {
totalPages = totalPages / 100
}
for i := 1; i <= totalPages; i++ {
resp, err := http.Get("https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=" + username + "&api_key=" + apiKey + "&format=json&limit=100&page=" + strconv.Itoa(i))
if err != nil {
panic(err)
}
json.NewDecoder(resp.Body).Decode(&data)
for j := range 100 {
unixTime, err := strconv.ParseInt(data.Recenttracks.Track[j].Date.Uts, 10, 64)
if err != nil {
panic(err)
}
ts := time.Unix(unixTime, 0)
_, err = conn.Exec(context.Background(), "INSERT INTO history (timestamp, song_name, artist, album_name, ms_played) VALUES ($1, $2, $3, $4, $5);", ts, data.Recenttracks.Track[j].Name, data.Recenttracks.Track[j].Artist.Text, data.Recenttracks.Track[j].Album.Text, 0)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't add track to muzi DB (%s): %v\n", (data.Recenttracks.Track[j].Artist.Text + " - " + data.Recenttracks.Track[j].Name), err)
}
}
}
}
func ImportSpotify() { func ImportSpotify() {
path := filepath.Join(".", "imports", "spotify", "zip") path := filepath.Join(".", "imports", "spotify", "zip")
targetBase := filepath.Join(".", "imports", "spotify", "extracted") targetBase := filepath.Join(".", "imports", "spotify", "extracted")

View File

@@ -68,6 +68,5 @@ func main() {
return return
} }
importsongs.ImportSpotify()
web.Start() web.Start()
} }