-
Notifications
You must be signed in to change notification settings - Fork 0
Split the analysis into track - album - artist #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -81,6 +81,8 @@ export const getRecentlyPlayed = async (session: Omit<SessionData, 'spotifyId'>) | |
| export const convertSpotifyTrackToTrackDetails = (track: SpotifyTrack): TrackDetails => { | ||
| return { | ||
| trackId: track.id, | ||
| albumId: track.album.id, | ||
| artistId: track.artists[0].id, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assumes |
||
| name: track.name, | ||
| artist: track.artists.map((artist) => artist.name).join(', '), | ||
| album: track.album.name, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,52 @@ | ||
| import redisClient from "./redis"; | ||
| import { TrackDetails } from "./types"; | ||
| import { TrackDetails, AlbumAnalysis, TrackAnalysis, ArtistAnalysis } from "./types"; | ||
|
|
||
| const TRACK_KEY_PREFIX = "track:"; | ||
| const HISTORY_KEY_PREFIX = "history:"; | ||
| const ANALYSIS_KEY_PREFIX = "analysis:"; | ||
|
|
||
| const getUserHistoryKey = (userId: string) => `${HISTORY_KEY_PREFIX}${userId}`; | ||
| const getTrackKey = (trackId: string) => `${TRACK_KEY_PREFIX}${trackId}`; | ||
| // | ||
| const getArtistAnalysisKey = (artistId: string) => `${ANALYSIS_KEY_PREFIX}${artistId}`; | ||
| const getAlbumAnalysisKey = (albumId: string) => `${ANALYSIS_KEY_PREFIX}${albumId}`; | ||
| const getTrackAnalysisKey = (trackId: string) => `${ANALYSIS_KEY_PREFIX}${trackId}`; | ||
|
Comment on lines
+10
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All three analysis types share the same |
||
|
|
||
| export const updateJSON = async <T>(key: string, data: T) => { | ||
| await redisClient.set(key, JSON.stringify(data)); | ||
| }; | ||
|
|
||
| export const getJSON = async <T>(key: string): Promise<T | undefined> => { | ||
| const data = await redisClient.get(key); | ||
| return data ? JSON.parse(data) : undefined; | ||
| }; | ||
|
|
||
| export const updateTrack = async (trackId: string, trackDetails: TrackDetails) => { | ||
| // handle the different fields | ||
| await redisClient.set(getTrackKey(trackId), JSON.stringify(trackDetails)); | ||
| await updateJSON(getTrackKey(trackId), trackDetails); | ||
|
|
||
| const analysis = trackDetails.analysis; | ||
| if (analysis?.track) { | ||
| await updateJSON(getTrackAnalysisKey(trackId), analysis.track); | ||
| } | ||
| if (analysis?.album) { | ||
| await updateJSON(getAlbumAnalysisKey(trackDetails.albumId), analysis.album); | ||
| } | ||
| if (analysis?.artist) { | ||
| await updateJSON(getArtistAnalysisKey(trackDetails.artistId), analysis.artist); | ||
| } | ||
| }; | ||
|
Comment on lines
23
to
36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||
|
|
||
| export const getTrack = async (trackId: string): Promise<TrackDetails | null> => { | ||
| const data = await redisClient.get(getTrackKey(trackId)); | ||
| return data ? JSON.parse(data) : null; | ||
| export const getTrack = async (trackId: string): Promise<TrackDetails | undefined> => { | ||
| const track = await getJSON<TrackDetails>(getTrackKey(trackId)); | ||
| if(!track) return undefined; | ||
| const analysis = { | ||
| album: await getJSON<AlbumAnalysis>(getAlbumAnalysisKey(track.albumId)), | ||
| track: await getJSON<TrackAnalysis>(getTrackAnalysisKey(track.trackId)), | ||
| artist: await getJSON<ArtistAnalysis>(getArtistAnalysisKey(track.artistId)), | ||
| } | ||
| return { | ||
| ...track, | ||
| analysis | ||
| }; | ||
| }; | ||
|
|
||
| export const pushHistory = async (userId: string, trackId: string) => { | ||
|
|
@@ -57,19 +88,20 @@ export const getRelatedTracks = async (trackId: string, userId: string, count = | |
| }; | ||
|
|
||
| const findTracksWithCommonTags = (track: TrackDetails, tracks: TrackDetails[]) => { | ||
| const targetTags = track?.analysis?.tags ?? []; | ||
| const targetTags = track?.analysis?.track?.tags ?? []; | ||
| const commonTracks = tracks.reduce<TrackDetails[]>((prev, curr) => { | ||
| const currTags = curr?.analysis?.track?.tags ?? []; | ||
| if (curr.trackId === track.trackId) return prev; | ||
| if (prev.some(t => t.trackId === curr.trackId)) return prev; | ||
| if (curr.analysis?.tags?.length === 0) return prev; | ||
| if (curr.analysis?.tags?.some(tag => targetTags.includes(tag))) { | ||
| if (currTags.length === 0) return prev; | ||
| if (currTags.some(tag => targetTags.includes(tag))) { | ||
| return [...prev, curr]; | ||
| } | ||
| return prev; | ||
| }, []); | ||
|
|
||
| const countTagsInCommon = (track: TrackDetails) => { | ||
| const tags = track.analysis?.tags ?? []; | ||
| const tags = track.analysis?.track?.tags ?? []; | ||
| return targetTags.filter(tag => tags.includes(tag)).length; | ||
| }; | ||
| return commonTracks.sort((a, b) => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ export interface SpotifyImage { | |
| } | ||
|
|
||
| export interface SpotifyArtist { | ||
| id: string; | ||
| name: string; | ||
| } | ||
|
|
||
|
|
@@ -13,6 +14,7 @@ export interface SpotifyTrack { | |
| name: string; | ||
| artists: SpotifyArtist[]; | ||
| album: { | ||
| id: string; | ||
| name: string; | ||
| images: SpotifyImage[]; | ||
| release_date: string; | ||
|
|
@@ -35,6 +37,8 @@ export interface SpotifyTokenResponse { | |
|
|
||
| export interface TrackDetails { | ||
| trackId: string; | ||
| albumId: string; | ||
| artistId: string; | ||
| name: string; | ||
| artist: string; | ||
| album: string; | ||
|
|
@@ -52,11 +56,15 @@ export interface Recommendation { | |
| } | ||
|
|
||
| export interface AnalysisData { | ||
| albumAnalysis?: string; | ||
| trackAnalysis?: string; | ||
| track?: TrackAnalysis, | ||
| album?: AlbumAnalysis, | ||
| artist?: ArtistAnalysis, | ||
| // video / images / audio | ||
| } | ||
|
|
||
| export interface TrackAnalysis { | ||
| personnelAndPlaces?: string; | ||
| artistBiography?: string; | ||
| culturalContext?: string; | ||
| analysis?: string; | ||
| recommendations?: { | ||
| albums: Recommendation[]; | ||
| tracks: Recommendation[]; | ||
|
|
@@ -66,12 +74,21 @@ export interface AnalysisData { | |
| tags?: string[]; | ||
| } | ||
|
|
||
| export interface AlbumAnalysis { | ||
| analysis?: string; | ||
| culturalContext?: string; | ||
| } | ||
|
|
||
| export interface ArtistAnalysis { | ||
| biography?: string; | ||
| } | ||
|
Comment on lines
58
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These type changes break the existing analysis generation code in |
||
|
|
||
| export interface SessionData { | ||
| accessToken: string; | ||
| refreshToken: string; | ||
| expiresAt: number; | ||
| spotifyId: string; | ||
| } | ||
| } | ||
|
|
||
| export interface SpotifyUser { | ||
| id: string; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
defaultTrackAnalysisis unused in the codebase.