[WIP] music platform user data scraper
teal-fm atproto
at main 4.1 kB view raw
1package models 2 3import "time" 4 5// ListenBrainzSubmission represents the top-level submission format 6type ListenBrainzSubmission struct { 7 ListenType string `json:"listen_type"` 8 Payload []ListenBrainzPayload `json:"payload"` 9} 10 11// ListenBrainzPayload represents individual listen data 12type ListenBrainzPayload struct { 13 ListenedAt *int64 `json:"listened_at,omitempty"` 14 TrackMetadata ListenBrainzTrackMetadata `json:"track_metadata"` 15} 16 17// ListenBrainzTrackMetadata contains the track information 18type ListenBrainzTrackMetadata struct { 19 ArtistName string `json:"artist_name"` 20 TrackName string `json:"track_name"` 21 ReleaseName *string `json:"release_name,omitempty"` 22 AdditionalInfo *ListenBrainzAdditionalInfo `json:"additional_info,omitempty"` 23} 24 25// ListenBrainzAdditionalInfo contains optional metadata 26type ListenBrainzAdditionalInfo struct { 27 MediaPlayer *string `json:"media_player,omitempty"` 28 SubmissionClient *string `json:"submission_client,omitempty"` 29 SubmissionClientVersion *string `json:"submission_client_version,omitempty"` 30 RecordingMBID *string `json:"recording_mbid,omitempty"` 31 ArtistMBIDs []string `json:"artist_mbids,omitempty"` 32 ReleaseMBID *string `json:"release_mbid,omitempty"` 33 ReleaseGroupMBID *string `json:"release_group_mbid,omitempty"` 34 TrackMBID *string `json:"track_mbid,omitempty"` 35 WorkMBIDs []string `json:"work_mbids,omitempty"` 36 Tags []string `json:"tags,omitempty"` 37 DurationMs *int64 `json:"duration_ms,omitempty"` 38 SpotifyID *string `json:"spotify_id,omitempty"` 39 ISRC *string `json:"isrc,omitempty"` 40 TrackNumber *int `json:"tracknumber,omitempty"` 41 DiscNumber *int `json:"discnumber,omitempty"` 42 MusicService *string `json:"music_service,omitempty"` 43 MusicServiceName *string `json:"music_service_name,omitempty"` 44 OriginURL *string `json:"origin_url,omitempty"` 45 LastFMTrackURL *string `json:"lastfm_track_url,omitempty"` 46 YoutubeID *string `json:"youtube_id,omitempty"` 47} 48 49// ConvertToTrack converts ListenBrainz format to internal Track format 50func (lbp *ListenBrainzPayload) ConvertToTrack(userID int64) Track { 51 track := Track{ 52 Name: lbp.TrackMetadata.TrackName, 53 Artist: []Artist{{Name: lbp.TrackMetadata.ArtistName}}, 54 } 55 56 // Set timestamp 57 if lbp.ListenedAt != nil { 58 track.Timestamp = time.Unix(*lbp.ListenedAt, 0) 59 } else { 60 track.Timestamp = time.Now() 61 } 62 63 // Set album/release name 64 if lbp.TrackMetadata.ReleaseName != nil { 65 track.Album = *lbp.TrackMetadata.ReleaseName 66 } 67 68 // Handle additional info if present 69 if info := lbp.TrackMetadata.AdditionalInfo; info != nil { 70 // Set MBIDs 71 if info.RecordingMBID != nil { 72 track.RecordingMBID = info.RecordingMBID 73 } 74 if info.ReleaseMBID != nil { 75 track.ReleaseMBID = info.ReleaseMBID 76 } 77 78 // Set duration 79 if info.DurationMs != nil { 80 track.DurationMs = *info.DurationMs 81 } 82 83 // Set ISRC 84 if info.ISRC != nil { 85 track.ISRC = *info.ISRC 86 } 87 88 // Handle multiple artists from MBIDs 89 if len(info.ArtistMBIDs) > 0 { 90 artists := make([]Artist, len(info.ArtistMBIDs)) 91 for i, mbid := range info.ArtistMBIDs { 92 artists[i] = Artist{ 93 Name: lbp.TrackMetadata.ArtistName, // Use main artist name 94 MBID: &mbid, 95 } 96 } 97 track.Artist = artists 98 } 99 100 // Set service information 101 if info.MusicService != nil { 102 track.ServiceBaseUrl = *info.MusicService 103 } 104 if info.OriginURL != nil { 105 track.URL = *info.OriginURL 106 } 107 if info.SpotifyID != nil { 108 track.URL = "https://open.spotify.com/track/" + *info.SpotifyID 109 track.ServiceBaseUrl = "spotify" 110 } 111 } 112 113 // Default service if not set 114 if track.ServiceBaseUrl == "" { 115 track.ServiceBaseUrl = "listenbrainz" 116 } 117 118 // Mark as stamped since it came from external submission 119 track.HasStamped = true 120 121 return track 122}