diff --git a/apps/mongo-mp/.gitignore b/apps/mongo-mp/.gitignore new file mode 100644 index 0000000..f650315 --- /dev/null +++ b/apps/mongo-mp/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules + +# next.js +/.next/ +/out/ + +# production +/build + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts \ No newline at end of file diff --git a/apps/mongo-mp/README.md b/apps/mongo-mp/README.md new file mode 100644 index 0000000..63f313c --- /dev/null +++ b/apps/mongo-mp/README.md @@ -0,0 +1,299 @@ +# MongoMP - MongoDB Music Platform + +![Build Status](https://img.shields.io/badge/build-passing-brightgreen) +![Version](https://img.shields.io/badge/version-1.0.0-blue) +![License](https://img.shields.io/badge/license-MIT-green) + +![MognoMP](./mongomp-ui.png) +MongoMP is a cutting-edge music streaming platform that leverages the power of MongoDB and Next.js to provide a personalized and immersive listening experience. + +## Features + +- 🎵 Extensive music library with various genres +- 🤖 AI-powered song recommendations using MongoDB's vector search + - This approach enables the system to identify songs with similar musical characteristics by comparing their vector embeddings to the user's centroid vector, leading to more accurate and personalized recommendations. [Learn more about centroid calculation](#centroid-calculation). +- 🔍 Advanced search functionality +- 📊 Real-time play count and last played tracking +- 📱 Responsive design for seamless use across devices +- 🎨 Customizable user profiles +- 📜 Playlist creation and management +- 🔐 Secure user authentication with JWT + +## Tech Stack + +- **Frontend**: Next.js 14 with App Router +- **Backend**: Node.js with Next.js API Routes +- **Database**: MongoDB +- **Authentication**: JWT (JSON Web Tokens) +- **Styling**: Tailwind CSS and shadcn/ui components + + +## centroid-calculation + +The centroid calculation mechanism works by automatically computing and updating a user's musical taste profile based on their liked songs. Here's how it works: + +### Overview +When a user likes or unlikes songs (updating their `likes` array), a MongoDB Trigger automatically calculates the centroid (average) of the musical embeddings for all liked songs. + +### Technical Implementation +1. **Trigger Activation**: Monitors changes to user documents' `likes` array +2. **Data Processing Pipeline**: + - Matches all liked songs in the songs collection + - Unwinds the musical embeddings arrays + - Groups and averages embeddings by dimension + - Sorts to maintain dimensional order + - Combines into a single centroid vector + +### Code Example +```javascript +exports = async function(changeEvent) { + const docId = changeEvent.documentKey._id; + const serviceName = ""; + const db = context.services.get(serviceName).db("mongomp"); + const usersCollection = db.collection("users"); + const songsCollection = db.collection("songs"); + + try { + // Get the updated user document + const userDoc = changeEvent.fullDocument; + + if (!userDoc.likes || userDoc.likes.length === 0) { + console.log("No likes found for user:", docId); + return; + } + + const pipeline = [ + // Match liked songs + { + $match: { + _id: { $in: userDoc.likes } + } + }, + // Unwind the embeddings array to work with individual elements + { + $unwind: { + path: "$music_embeddings", + includeArrayIndex: "dimension_index" + } + }, + // Group by dimension index to calculate averages + { + $group: { + _id: "$dimension_index", + avg_value: { $avg: "$music_embeddings" } + } + }, + // Sort by dimension index to maintain order + { + $sort: { + _id: 1 + } + }, + // Project to get just the averaged values in array form + { + $group: { + _id: null, + liked_embeddings: { + $push: "$avg_value" + } + } + } + ]; + + const aggregationResult = await songsCollection.aggregate(pipeline).toArray(); + + if (!aggregationResult || aggregationResult.length === 0) { + console.log("No embeddings calculated"); + return; + } + + // Update user document with averaged embeddings + const updateResult = await usersCollection.updateOne( + { _id: docId }, + { + $set: { + liked_embeddings: aggregationResult[0].liked_embeddings + } + } + ); + + console.log("Updated user embeddings:", { + userId: docId, + numberOfLikes: userDoc.likes.length, + embeddingsDimensions: aggregationResult[0].liked_embeddings.length, + updateResult: updateResult + }); + + } catch (err) { + console.log("Error processing embeddings:", err.message); + console.log("Full error:", JSON.stringify(err)); + } +}; +``` + +The resulting centroid vector becomes the user's musical taste profile, stored in `liked_embeddings`, enabling personalized song recommendations through vector similarity search. + +## Getting Started + +### Prerequisites + +- Node.js (v14 or later) +- MongoDB (v4.4 or later) +- npm or yarn + +### Installation + +1. Clone the repository: + ```bash + git clone + ``` + +2. Navigate to the project directory: + ```bash + cd mongo-mp + ``` + +3. Install dependencies: + ```bash + npm install + ``` + or + ```bash + yarn install + ``` + +### Setting up the Database + +1. Ensure your MongoDB instance is running and accessible. + +2. Create a `.env.local` file in the root directory of the project and add your MongoDB connection string: + ``` + MONGODB_URI=your_mongodb_connection_string + JWT_SECRET=your_jwt_secret + ``` + +3. Run the database seeding script to populate your database with sample data and create indexes: + ```bash + npm run seed + ``` + or + ```bash + yarn seed + ``` + This script is located in `scripts/seed-db.js` and will create sample users, songs, and needed indexes. + + +### Running the Application + +1. Start the development server: + ``` + npm run dev + ``` + or + ```bash + yarn dev + ``` + +2. Your application should now be running on `http://localhost:3000` + + +## Installation and Deployment + +### Building Locally + +1. After following the installation steps, build the project: + ``` + npm run build + ``` + + +2. Start the production server: + ``` + npm start + ``` + +3. Your application should now be running on `http://localhost:3000` + +### Deployment + +MongoMP can be easily deployed to Vercel: + +1. Push your code to a GitHub repository. +2. Go to [Vercel](https://vercel.com) and sign up or log in. +3. Click on "New Project" and import your GitHub repository. +4. Configure your environment variables (MONGODB_URI and JWT_SECRET). +5. Click "Deploy" and wait for the build to complete. + +Your MongoMP instance will now be live on a Vercel URL! + +## Project Structure + +Here's an overview of the MongoMP project structure: + +``` +mongo-mp/ +├── app/ +│ ├── api/ +│ │ ├── auth/ +│ │ │ ├── login/ +│ │ │ ├── logout/ +│ │ │ ├── register/ +│ │ │ └── user/ +│ │ ├── playlists/ +│ │ ├── songs/ +│ │ └── user/ +│ ├── admin/ +│ │ └── users/ +│ ├── library/ +│ ├── login/ +│ ├── profile/ +│ ├── register/ +│ ├── search/ +│ ├── home-content.tsx +│ ├── layout.tsx +│ └── page.tsx +├── components/ +│ ├── ui/ +│ ├── bottom-nav.tsx +│ ├── code-block.tsx +│ ├── info-tooltip.tsx +│ ├── library-content.tsx +│ ├── navbar.tsx +│ ├── notification.tsx +│ ├── playing-song-popup.tsx +│ ├── playlist-player.tsx +│ ├── RetroEqualizer.tsx +│ ├── search-bar.tsx +│ ├── song-card.tsx +│ ├── song-list.tsx +│ ├── suggested-songs.tsx +│ ├── tag.tsx +│ └── user-menu.tsx +├── contexts/ +│ └── UserContext.tsx +├── hooks/ +│ ├── useAudio.ts +│ └── useUser.ts +├── lib/ +│ ├── mock-data.ts +│ ├── mock-users.ts +│ ├── mongodb.ts +│ └── utils.ts +├── public/ +│ └── placeholder.svg +├── scripts/ +│ └── seed-db.js +├── types/ +│ ├── playlist.ts +│ └── song.ts +├── .env.local +├── .gitignore +├── next.config.js +├── package.json +├── README.md +├── tailwind.config.js +└── tsconfig.json +``` + +This structure shows the main directories and files in the MongoMP project. The `app/` directory contains the Next.js 14 App Router structure, with API routes and page components. The `components/` directory holds reusable React components, and `lib/` contains utility functions and database connection logic. + diff --git a/apps/mongo-mp/app/admin/users/page.tsx b/apps/mongo-mp/app/admin/users/page.tsx new file mode 100644 index 0000000..ea765c0 --- /dev/null +++ b/apps/mongo-mp/app/admin/users/page.tsx @@ -0,0 +1,16 @@ +import { Metadata } from 'next' +import { UserManagement } from '@/components/user-management' + +export const metadata: Metadata = { + title: 'User Management - MongoMP Admin', + description: 'Manage users of the MongoMP music streaming platform', +} + +export default function UsersPage() { + return ( +
+ +
+ ) +} + diff --git a/apps/mongo-mp/app/api/auth/login/route.ts b/apps/mongo-mp/app/api/auth/login/route.ts new file mode 100644 index 0000000..a9465b1 --- /dev/null +++ b/apps/mongo-mp/app/api/auth/login/route.ts @@ -0,0 +1,87 @@ +export const dynamic = 'force-dynamic'; +import { NextResponse } from 'next/server'; +import { compare } from 'bcrypt'; +import { sign } from 'jsonwebtoken'; +import { ObjectId } from 'mongodb'; +import clientPromise from '@/lib/mongodb'; + +if (!process.env.JWT_SECRET) { + throw new Error('JWT_SECRET is not defined'); +} + +export async function POST(request: Request) { + try { + const { email, password } = await request.json(); + + if (!email || !password) { + return NextResponse.json({ error: 'Missing required fields' }, { status: 400 }); + } + + const client = await clientPromise; + const db = client.db("mongomp"); + + // Find user by email + const user = await db.collection("users").findOne( + { email }, + { + projection: { + _id: 1, + name: 1, + email: 1, + password: 1, + likes: 1, + playlists: 1, + last_played: 1 + } + } + ); + + if (!user) { + return NextResponse.json({ error: 'Invalid credentials' }, { status: 401 }); + } + + // Compare passwords + const passwordMatch = await compare(password, user.password); + if (!passwordMatch) { + return NextResponse.json({ error: 'Invalid credentials' }, { status: 401 }); + } + + // Generate JWT token + const token = sign( + { + userId: user._id.toString(), + email: user.email + }, + process.env.JWT_SECRET, + { expiresIn: '24h' } + ); + + // Create response with user data + const response = NextResponse.json({ + message: 'Login successful', + user: { + id: user._id.toString(), + name: user.name, + email: user.email, + likes: user.likes || [], + playlists: user.playlists || [], + last_played: user.last_played || [] + } + }); + + // Set HTTP-only cookie with token + response.cookies.set('token', token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 86400, + path: '/', + }); + + return response; + } catch (error) { + console.error('Login error:', error); + return NextResponse.json({ error: 'An error occurred during login' }, { status: 500 }); + } +} + diff --git a/apps/mongo-mp/app/api/auth/logout/route.ts b/apps/mongo-mp/app/api/auth/logout/route.ts new file mode 100644 index 0000000..227a0ec --- /dev/null +++ b/apps/mongo-mp/app/api/auth/logout/route.ts @@ -0,0 +1,12 @@ +import { NextResponse } from 'next/server'; + +export async function POST() { + const response = NextResponse.json({ message: 'Logged out successfully' }); + response.cookies.set('token', '', { + httpOnly: true, + expires: new Date(0), + path: '/', + }); + return response; +} + diff --git a/apps/mongo-mp/app/api/auth/register/route.ts b/apps/mongo-mp/app/api/auth/register/route.ts new file mode 100644 index 0000000..749895d --- /dev/null +++ b/apps/mongo-mp/app/api/auth/register/route.ts @@ -0,0 +1,38 @@ +import { NextResponse } from 'next/server'; +import { hash } from 'bcrypt'; +import clientPromise from '@/lib/mongodb'; + +export async function POST(request: Request) { + try { + const { name, email, password } = await request.json(); + + if (!name || !email || !password) { + return NextResponse.json({ error: 'Missing required fields' }, { status: 400 }); + } + + const client = await clientPromise; + const db = client.db("mongomp"); + + // Check if user already exists + const existingUser = await db.collection("users").findOne({ email }); + if (existingUser) { + return NextResponse.json({ error: 'User already exists' }, { status: 400 }); + } + + // Hash the password + const hashedPassword = await hash(password, 10); + + // Create new user + const result = await db.collection("users").insertOne({ + name, + email, + password: hashedPassword, + }); + + return NextResponse.json({ message: 'User registered successfully', userId: result.insertedId }); + } catch (error) { + console.error('Registration error:', error); + return NextResponse.json({ error: 'An error occurred during registration' }, { status: 500 }); + } +} + diff --git a/apps/mongo-mp/app/api/auth/user/route.ts b/apps/mongo-mp/app/api/auth/user/route.ts new file mode 100644 index 0000000..87d7ad0 --- /dev/null +++ b/apps/mongo-mp/app/api/auth/user/route.ts @@ -0,0 +1,59 @@ +export const dynamic = 'force-dynamic'; +import { NextResponse } from 'next/server'; +import { verify } from 'jsonwebtoken'; +import { cookies } from 'next/headers'; +import { ObjectId } from 'mongodb'; +import clientPromise from '@/lib/mongodb'; + +if (!process.env.JWT_SECRET) { + throw new Error('JWT_SECRET is not defined'); +} + +export async function GET() { + try { + const cookieStore = cookies(); + const token = cookieStore.get('token'); + + if (!token) { + return NextResponse.json({ error: 'Not authenticated' }, { status: 401 }); + } + + // Verify and decode the token + const decoded = verify(token.value, process.env.JWT_SECRET) as { userId: string }; + + const client = await clientPromise; + const db = client.db("mongomp"); + + // Find user with proper projection (only include what we need) + const user = await db.collection("users").findOne( + { _id: new ObjectId(decoded.userId) }, + { + projection: { + name: 1, + email: 1, + _id: 1 + } + } + ); + + if (!user) { + return NextResponse.json({ error: 'User not found' }, { status: 404 }); + } + + // Transform the response + const userResponse = { + id: user._id.toString(), + name: user.name, + email: user.email + }; + + return NextResponse.json(userResponse); + } catch (error) { + console.error('Error fetching user:', error); + if (error.name === 'JsonWebTokenError') { + return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); + } + return NextResponse.json({ error: 'An error occurred' }, { status: 500 }); + } +} + diff --git a/apps/mongo-mp/app/api/playlists/[id]/add-song/route.ts b/apps/mongo-mp/app/api/playlists/[id]/add-song/route.ts new file mode 100644 index 0000000..cea2867 --- /dev/null +++ b/apps/mongo-mp/app/api/playlists/[id]/add-song/route.ts @@ -0,0 +1,49 @@ +import { NextResponse } from 'next/server'; +import { ObjectId } from 'mongodb'; +import clientPromise from '@/lib/mongodb'; +import { verify } from 'jsonwebtoken'; +import { cookies } from 'next/headers'; + +export async function POST( + request: Request, + { params }: { params: { id: string } } +) { + try { + const cookieStore = cookies(); + const token = cookieStore.get('token'); + + if (!token) { + return NextResponse.json({ error: 'Not authenticated' }, { status: 401 }); + } + + let decoded; + try { + decoded = verify(token.value, process.env.JWT_SECRET!) as { userId: string }; + } catch (error) { + return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); + } + + const { songId } = await request.json(); + if (!songId) { + return NextResponse.json({ error: 'Song ID is required' }, { status: 400 }); + } + + const client = await clientPromise; + const db = client.db("mongomp"); + + const result = await db.collection("playlists").updateOne( + { _id: new ObjectId(params.id), user_id: new ObjectId(decoded.userId) }, + { $addToSet: { songs: new ObjectId(songId) } } + ); + + if (result.matchedCount === 0) { + return NextResponse.json({ error: 'Playlist not found or unauthorized' }, { status: 404 }); + } + + return NextResponse.json({ message: 'Song added to playlist successfully' }); + } catch (e) { + console.error(e); + return NextResponse.json({ error: 'Failed to add song to playlist' }, { status: 500 }); + } +} + diff --git a/apps/mongo-mp/app/api/playlists/[id]/route.ts b/apps/mongo-mp/app/api/playlists/[id]/route.ts new file mode 100644 index 0000000..9128e82 --- /dev/null +++ b/apps/mongo-mp/app/api/playlists/[id]/route.ts @@ -0,0 +1,44 @@ +import { NextResponse } from 'next/server' +import { ObjectId } from 'mongodb' +import clientPromise from '@/lib/mongodb' +import { verify } from 'jsonwebtoken'; +import { cookies } from 'next/headers'; + +export async function DELETE( + request: Request, + { params }: { params: { id: string } } +) { + try { + const cookieStore = cookies(); + const token = cookieStore.get('token'); + + if (!token) { + return NextResponse.json({ error: 'Not authenticated' }, { status: 401 }); + } + + let decoded; + try { + decoded = verify(token.value, process.env.JWT_SECRET!) as { userId: string }; + } catch (error) { + return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); + } + + const client = await clientPromise + const db = client.db("mongomp") + + const result = await db.collection("playlists").deleteOne({ + _id: new ObjectId(params.id), + user_id: new ObjectId(decoded.userId) + }) + + if (result.deletedCount === 0) { + return NextResponse.json({ error: 'Playlist not found or unauthorized' }, { status: 404 }) + } + + return NextResponse.json({ message: 'Playlist deleted successfully' }) + } catch (e) { + console.error(e) + return NextResponse.json({ error: 'Failed to delete playlist' }, { status: 500 }) + } +} + diff --git a/apps/mongo-mp/app/api/playlists/[id]/songs/route.ts b/apps/mongo-mp/app/api/playlists/[id]/songs/route.ts new file mode 100644 index 0000000..37a78fd --- /dev/null +++ b/apps/mongo-mp/app/api/playlists/[id]/songs/route.ts @@ -0,0 +1,49 @@ +import { NextResponse } from 'next/server' +import { ObjectId } from 'mongodb' +import clientPromise from '@/lib/mongodb' +import { verify } from 'jsonwebtoken'; +import { cookies } from 'next/headers'; + +export async function GET( + request: Request, + { params }: { params: { id: string } } +) { + try { + const cookieStore = cookies(); + const token = cookieStore.get('token'); + + if (!token) { + return NextResponse.json({ error: 'Not authenticated' }, { status: 401 }); + } + + let decoded; + try { + decoded = verify(token.value, process.env.JWT_SECRET!) as { userId: string }; + } catch (error) { + return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); + } + + const client = await clientPromise + const db = client.db("mongomp") + + const playlist = await db.collection("playlists").findOne( + { _id: new ObjectId(params.id), user_id: new ObjectId(decoded.userId) } + ) + + if (!playlist) { + return NextResponse.json({ error: 'Playlist not found or unauthorized' }, { status: 404 }) + } + + const songIds = playlist.songs.map((id: string) => new ObjectId(id)) + const songs = await db.collection("songs").find({ _id: { $in: songIds } }).toArray() + + return NextResponse.json(songs.map(song => ({ + ...song, + _id: song._id.toString() + }))) + } catch (e) { + console.error(e) + return NextResponse.json({ error: 'Failed to fetch playlist songs' }, { status: 500 }) + } +} + diff --git a/apps/mongo-mp/app/api/playlists/route.ts b/apps/mongo-mp/app/api/playlists/route.ts new file mode 100644 index 0000000..75cc0ed --- /dev/null +++ b/apps/mongo-mp/app/api/playlists/route.ts @@ -0,0 +1,100 @@ +import { NextResponse } from 'next/server' +import { ObjectId } from 'mongodb' +import clientPromise from '@/lib/mongodb' +import { verify } from 'jsonwebtoken'; +import { cookies } from 'next/headers'; + +export async function GET() { + try { + const cookieStore = cookies(); + const token = cookieStore.get('token'); + + if (!token) { + return NextResponse.json({ error: 'Not authenticated' }, { status: 401 }); + } + + let decoded; + try { + decoded = verify(token.value, process.env.JWT_SECRET!) as { userId: string }; + } catch (error) { + return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); + } + + const client = await clientPromise + const db = client.db("mongomp") + + // Get all playlists for the user + const playlists = await db.collection("playlists") + .find({ user_id: new ObjectId(decoded.userId) }) + .toArray() + + // For each playlist, fetch the full song details + const playlistsWithSongs = await Promise.all( + playlists.map(async (playlist) => { + const songIds = playlist.songs.map((id: string) => new ObjectId(id)) + const songs = await db.collection("songs") + .find({ _id: { $in: songIds } }) + .toArray() + + return { + ...playlist, + _id: playlist._id.toString(), + songs: songs.map(song => ({ + ...song, + _id: song._id.toString() + })) + } + }) + ) + + return NextResponse.json(playlistsWithSongs) + } catch (e) { + console.error(e) + return NextResponse.json({ error: 'Failed to fetch playlists' }, { status: 500 }) + } +} + +export async function POST(request: Request) { + try { + const cookieStore = cookies(); + const token = cookieStore.get('token'); + + if (!token) { + return NextResponse.json({ error: 'Not authenticated' }, { status: 401 }); + } + + let decoded; + try { + decoded = verify(token.value, process.env.JWT_SECRET!) as { userId: string }; + } catch (error) { + return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); + } + + const { name } = await request.json() + if (!name) { + return NextResponse.json({ error: 'Playlist name is required' }, { status: 400 }) + } + + const client = await clientPromise + const db = client.db("mongomp") + + const result = await db.collection("playlists").insertOne({ + name, + user_id: new ObjectId(decoded.userId), + songs: [], + created_at: new Date(), + updated_at: new Date() + }) + + const newPlaylist = await db.collection("playlists").findOne({ _id: result.insertedId }) + + return NextResponse.json({ + ...newPlaylist, + _id: newPlaylist?._id.toString() + }) + } catch (e) { + console.error(e) + return NextResponse.json({ error: 'Failed to create playlist' }, { status: 500 }) + } +} + diff --git a/apps/mongo-mp/app/api/songs/[genre]/route.ts b/apps/mongo-mp/app/api/songs/[genre]/route.ts new file mode 100644 index 0000000..7a56622 --- /dev/null +++ b/apps/mongo-mp/app/api/songs/[genre]/route.ts @@ -0,0 +1,22 @@ +import { NextResponse } from 'next/server' +import clientPromise from '@/lib/mongodb' + +export async function GET( + request: Request, + { params }: { params: { genre: string } } +) { + try { + const client = await clientPromise + const db = client.db("mongomp") + + const songs = await db.collection("songs") + .find({ genre: params.genre }) + .toArray() + + return NextResponse.json(songs) + } catch (e) { + console.error(e) + return NextResponse.json({ error: 'Failed to fetch songs' }, { status: 500 }) + } +} + diff --git a/apps/mongo-mp/app/api/songs/increment-plays/route.ts b/apps/mongo-mp/app/api/songs/increment-plays/route.ts new file mode 100644 index 0000000..8ef0427 --- /dev/null +++ b/apps/mongo-mp/app/api/songs/increment-plays/route.ts @@ -0,0 +1,47 @@ +export const dynamic = 'force-dynamic'; +import { NextResponse } from 'next/server'; +import { ObjectId } from 'mongodb'; +import clientPromise from '@/lib/mongodb'; + +export async function POST(request: Request) { + try { + const { songId } = await request.json(); + + if (!songId) { + return NextResponse.json({ error: 'Song ID is required' }, { status: 400 }); + } + + const client = await clientPromise; + const db = client.db("mongomp"); + + // Update play count and last_played timestamp + const result = await db.collection("songs").updateOne( + { _id: new ObjectId(songId) }, + { + $inc: { play_count: 1 }, + $set: { last_played: new Date().toISOString() } + } + ); + + if (result.modifiedCount === 0) { + return NextResponse.json({ error: 'Song not found' }, { status: 404 }); + } + + // Get updated song data + const updatedSong = await db.collection("songs").findOne( + { _id: new ObjectId(songId) } + ); + + return NextResponse.json({ + message: 'Play count incremented successfully', + song: { + ...updatedSong, + _id: updatedSong?._id.toString() + } + }); + } catch (e) { + console.error('Error incrementing play count:', e); + return NextResponse.json({ error: 'Failed to increment play count' }, { status: 500 }); + } +} + diff --git a/apps/mongo-mp/app/api/songs/route.ts b/apps/mongo-mp/app/api/songs/route.ts new file mode 100644 index 0000000..57ac47d --- /dev/null +++ b/apps/mongo-mp/app/api/songs/route.ts @@ -0,0 +1,68 @@ +export const dynamic = 'force-dynamic'; +import { NextResponse } from 'next/server' +import clientPromise from '@/lib/mongodb' + +export async function GET(request: Request) { + const { searchParams } = new URL(request.url) + const query = searchParams.get('query') + + try { + const client = await clientPromise + const db = client.db("mongomp") + + let songs + if (query) { + // Using the actual schema fields for text search + songs = await db.collection("songs").aggregate([ + { + '$search': { + 'index': 'default', + 'text': { + 'query': query, + 'path': ['title', 'artist', 'genre', 'tags'] + } + } + }, + { + '$project': { + '_id': 1, + 'title': 1, + 'artist': 1, + 'genre': 1, + 'duration': 1, + 'coverUrl': 1, + 'play_count': 1, + 'tags': 1, + 'url': 1, + 'last_played': 1 + } + } + ]).toArray() + } else { + // Get all songs with their complete structure, excluding music_embeddings + songs = await db.collection("songs").find({}, { + projection: { + music_embeddings: 0 + } + }).toArray() + } + + // Group songs by genre as per our UI structure + const songsByGenre = songs.reduce((acc, song) => { + if (!acc[song.genre]) { + acc[song.genre] = [] + } + acc[song.genre].push({ + ...song, + _id: song._id.toString() + }) + return acc + }, {} as Record) + + return NextResponse.json(songsByGenre) + } catch (e) { + console.error('Error fetching songs:', e) + return NextResponse.json({ error: 'Failed to fetch songs' }, { status: 500 }) + } +} + diff --git a/apps/mongo-mp/app/api/songs/similar/route.ts b/apps/mongo-mp/app/api/songs/similar/route.ts new file mode 100644 index 0000000..83a5b0e --- /dev/null +++ b/apps/mongo-mp/app/api/songs/similar/route.ts @@ -0,0 +1,69 @@ +import { NextResponse } from 'next/server' +import { ObjectId } from 'mongodb' +import clientPromise from '@/lib/mongodb' + +export async function GET(request: Request) { + const { searchParams } = new URL(request.url) + const songId = searchParams.get('songId') + + if (!songId) { + return NextResponse.json({ error: 'Song ID is required' }, { status: 400 }) + } + + try { + const client = await clientPromise + const db = client.db("mongomp") + + // First, get the music_embeddings for the current song + const currentSong = await db.collection("songs").findOne( + { _id: new ObjectId(songId) }, + { projection: { music_embeddings: 1 } } + ) + + + if (!currentSong || !currentSong.music_embeddings) { + return NextResponse.json({ error: 'Song not found or has no embeddings' }, { status: 404 }) + } + + // Then, use $vectorSearch to find similar songs + const similarSongs = await db.collection("songs").aggregate([ + { + $vectorSearch: { + index: "vector_index", + path: "music_embeddings", + queryVector: currentSong.music_embeddings, + numCandidates: 50, + limit: 6 + } + }, + { + $match: { + _id: { $ne: new ObjectId(songId) } // Exclude the current song + } + }, + { + $project: { + _id: 1, + title: 1, + artist: 1, + duration: 1, + genre: 1, + tags: 1, + play_count: 1, + last_played: 1, + coverUrl: 1, + url: 1 + } + } + ]).toArray() + + + const filteredSongs = similarSongs.filter(song => song._id.toString() !== songId) + + return NextResponse.json(filteredSongs) + } catch (e) { + console.error('Error fetching similar songs:', e) + return NextResponse.json({ error: 'Failed to fetch similar songs' }, { status: 500 }) + } +} + diff --git a/apps/mongo-mp/app/api/songs/suggested/route.ts b/apps/mongo-mp/app/api/songs/suggested/route.ts new file mode 100644 index 0000000..b906a2f --- /dev/null +++ b/apps/mongo-mp/app/api/songs/suggested/route.ts @@ -0,0 +1,68 @@ +import { NextResponse } from "next/server" +import { ObjectId } from "mongodb" +import clientPromise from "@/lib/mongodb" +import { verify } from "jsonwebtoken" +import { cookies } from "next/headers" + +if (!process.env.JWT_SECRET) { + throw new Error("JWT_SECRET is not defined") +} + +export async function GET() { + try { + const cookieStore = cookies() + const token = cookieStore.get("token") + + if (!token) { + return NextResponse.json({ error: "Not authenticated" }, { status: 401 }) + } + + const decoded = verify(token.value, process.env.JWT_SECRET) as { userId: string } + + const client = await clientPromise + const db = client.db("mongomp") + + const user = await db + .collection("users") + .findOne({ _id: new ObjectId(decoded.userId) }, { projection: { liked_embeddings: 1 } }) + + if (!user || !user.liked_embeddings || user.liked_embeddings.length === 0) { + return NextResponse.json([]) + } + + const suggestedSongs = await db + .collection("songs") + .aggregate([ + { + $vectorSearch: { + index: "vector_index", + path: "music_embeddings", + queryVector: user.liked_embeddings, + numCandidates: 100, + limit: 10, + }, + }, + { + $project: { + _id: 1, + title: 1, + artist: 1, + duration: 1, + genre: 1, + tags: 1, + play_count: 1, + last_played: 1, + coverUrl: 1, + url: 1, + }, + }, + ]) + .toArray() + + return NextResponse.json(suggestedSongs) + } catch (e) { + console.error("Error fetching suggested songs:", e) + return NextResponse.json({ error: "Failed to fetch suggested songs" }, { status: 500 }) + } +} + diff --git a/apps/mongo-mp/app/api/user/profile/route.ts b/apps/mongo-mp/app/api/user/profile/route.ts new file mode 100644 index 0000000..4a32311 --- /dev/null +++ b/apps/mongo-mp/app/api/user/profile/route.ts @@ -0,0 +1,88 @@ +export const dynamic = "force-dynamic" +import { NextResponse } from "next/server" +import { verify } from "jsonwebtoken" +import { cookies } from "next/headers" +import { ObjectId } from "mongodb" +import clientPromise from "@/lib/mongodb" + +if (!process.env.JWT_SECRET) { + throw new Error("JWT_SECRET is not defined") +} + +export async function GET() { + try { + const cookieStore = cookies() + const token = cookieStore.get("token") + + if (!token) { + return NextResponse.json({ error: "Not authenticated" }, { status: 401 }) + } + + const decoded = verify(token.value, process.env.JWT_SECRET) as { userId: string } + + const client = await clientPromise + const db = client.db("mongomp") + + // Get user data excluding password + const user = await db.collection("users").findOne( + { _id: new ObjectId(decoded.userId) }, + { + projection: { + password: 0, // Exclude only the password field + }, + }, + ) + + if (!user) { + return NextResponse.json({ error: "User not found" }, { status: 404 }) + } + + // Fetch liked songs if the user has any + let likedSongs = [] + if (user.likes && Array.isArray(user.likes) && user.likes.length > 0) { + likedSongs = await db + .collection("songs") + .find({ + _id: { $in: user.likes.map((id) => new ObjectId(id)) }, + }) + .toArray() + } + + // Fetch last played songs if they exist + let lastPlayedSongs = [] + if (user.last_played && Array.isArray(user.last_played) && user.last_played.length > 0) { + const songIds = user.last_played.map((play) => new ObjectId(play.song_id)) + lastPlayedSongs = await db + .collection("songs") + .find({ + _id: { $in: songIds }, + }) + .toArray() + } + + // Transform the response + const userResponse = { + ...user, + _id: user._id.toString(), + liked_embeddings: user.liked_embeddings || [], + likes: likedSongs.map((song) => ({ + ...song, + _id: song._id.toString(), + })), + last_played: + user.last_played?.map((play: any) => ({ + ...play, + song: lastPlayedSongs.find((s) => s._id.equals(new ObjectId(play.song_id))), + })) || [], + } + + return NextResponse.json(userResponse) + } catch (error) { + console.error("Error fetching user profile:", error) + if (error.name === "JsonWebTokenError") { + return NextResponse.json({ error: "Invalid token" }, { status: 401 }) + } + return NextResponse.json({ error: "An error occurred" }, { status: 500 }) + } +} + diff --git a/apps/mongo-mp/app/api/user/toggle-like/route.ts b/apps/mongo-mp/app/api/user/toggle-like/route.ts new file mode 100644 index 0000000..e32bbe8 --- /dev/null +++ b/apps/mongo-mp/app/api/user/toggle-like/route.ts @@ -0,0 +1,99 @@ +export const dynamic = 'force-dynamic'; +import { NextResponse } from 'next/server'; +import { verify } from 'jsonwebtoken'; +import { cookies } from 'next/headers'; +import { ObjectId } from 'mongodb'; +import clientPromise from '@/lib/mongodb'; + +if (!process.env.JWT_SECRET) { + throw new Error('JWT_SECRET is not defined'); +} + +export async function POST(request: Request) { + try { + const cookieStore = cookies(); + const token = cookieStore.get('token'); + + if (!token) { + return NextResponse.json({ error: 'Not authenticated' }, { status: 401 }); + } + + const decoded = verify(token.value, process.env.JWT_SECRET) as { userId: string }; + const { songId } = await request.json(); + + if (!songId) { + return NextResponse.json({ error: 'Song ID is required' }, { status: 400 }); + } + + const client = await clientPromise; + const db = client.db("mongomp"); + + // First check if the song exists + const song = await db.collection("songs").findOne({ + _id: new ObjectId(songId) + }); + + if (!song) { + return NextResponse.json({ error: 'Song not found' }, { status: 404 }); + } + + // Get user's current likes + const user = await db.collection("users").findOne({ + _id: new ObjectId(decoded.userId) + }); + + if (!user) { + return NextResponse.json({ error: 'User not found' }, { status: 404 }); + } + + const likes = user.likes || []; + const songObjectId = new ObjectId(songId); + let operation; + let message; + + if (likes.some((id: ObjectId) => id.equals(songObjectId))) { + // Unlike - remove from likes array + operation = { + $pull: { likes: songObjectId } + }; + message = 'Song removed from likes'; + } else { + // Like - add to likes array + operation = { + $addToSet: { likes: songObjectId } + }; + message = 'Song added to likes'; + } + + // Update user's likes + await db.collection("users").updateOne( + { _id: new ObjectId(decoded.userId) }, + operation + ); + + // Get updated user data with populated likes + const updatedUser = await db.collection("users").findOne( + { _id: new ObjectId(decoded.userId) } + ); + + // Fetch all liked songs + const likedSongs = await db.collection("songs").find({ + _id: { $in: updatedUser?.likes || [] } + }).toArray(); + + return NextResponse.json({ + message, + likes: likedSongs.map(song => ({ + ...song, + _id: song._id.toString() + })) + }); + } catch (error) { + console.error('Error toggling like:', error); + if (error.name === 'JsonWebTokenError') { + return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); + } + return NextResponse.json({ error: 'An error occurred' }, { status: 500 }); + } +} + diff --git a/apps/mongo-mp/app/data/mongomp.songs-comedy.json b/apps/mongo-mp/app/data/mongomp.songs-comedy.json new file mode 100644 index 0000000..9e04304 --- /dev/null +++ b/apps/mongo-mp/app/data/mongomp.songs-comedy.json @@ -0,0 +1,10315 @@ +[{ + "title": "Friendly Welcome Full Mix", + "artist": "artist Pop", + "duration": 210, + "genre": "Comedy", + "tags": [ + "upbeat", + "party" + ], + "play_count": 1, + "last_played": "2025-01-22T19:46:21.767Z", + "url": "https://soundscout.s3.eu-central-1.amazonaws.com/Friendly Welcome Full Mix.mp3", + "music_embeddings": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03904338926076889, + 0, + 0, + 0.05233590677380562, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.049208320677280426, + 0, + 0.04497300833463669, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.13293570280075073, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01193156000226736, + 0, + 0.04021373391151428, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05269965901970863, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1231161430478096, + 0, + 0, + 0, + 0, + 0.07482476532459259, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.040146321058273315, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10451792180538177, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.020972564816474915, + 0, + 0, + 0, + 0.028990747407078743, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03215501829981804, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11558006703853607, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04078984260559082, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.19088947772979736, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.043304942548274994, + 0, + 0.07580049335956573, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06276718527078629, + 0, + 0, + 0, + 0, + 0.04135148972272873, + 0, + 0.04862400144338608, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1085551455616951, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.029420431703329086, + 0, + 0, + 0.011170103214681149, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.33994030952453613, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12514039874076843, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01691375859081745, + 0, + 0, + 0, + 0.16243354976177216, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04356294125318527, + 0, + 0, + 0, + 0, + 0.00908615067601204, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.022550510242581367, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06659118831157684, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0034190441947430372, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06720677763223648, + 0, + 0, + 0, + 0.00868653692305088, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01469919178634882, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09434095025062561, + 0.0007813042029738426, + 0, + 0, + 0, + 0, + 0, + 0.18199887871742249, + 0, + 0.24393239617347717, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.19330227375030518, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.005325068719685078, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09593168646097183, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0034384229220449924, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.13195380568504333, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12872329354286194, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.033813782036304474, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09070802479982376, + 0, + 0, + 0, + 0.0002079165424220264, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06669775396585464, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07968835532665253, + 0, + 0, + 0.10797180235385895, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.014793545007705688, + 0, + 0, + 0, + 0, + 0, + 0.042734358459711075, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08586414158344269, + 0, + 0.09785482287406921, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06048223748803139, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05520850419998169, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.00675740884616971, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.015738045796751976, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03087981417775154, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09630482643842697, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10051630437374115, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0052652908489108086, + 0, + 0, + 0, + 0, + 0.10267612338066101, + 0, + 0, + 0, + 0, + 0, + 0, + 0.000924810825381428, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.17039112746715546, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.017583247274160385, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10735785961151123, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05244586244225502, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0750083476305008, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04555758088827133, + 0, + 0, + 0.079367995262146, + 0, + 0, + 0.1290879100561142, + 0, + 0, + 0, + 0, + 0.021078264340758324, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11167172342538834, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.013087310828268528, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.043849337846040726, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0770498663187027, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.013860022649168968, + 0, + 0, + 0, + 0, + 0.1995398998260498, + 0.1073974221944809, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.005360348615795374, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07280594855546951, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.009334594011306763, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07879365980625153, + 0, + 0, + 0, + 0, + 0.10777806490659714, + 0, + 0, + 0, + 0, + 0.0028161853551864624, + 0, + 0, + 0, + 0, + 0, + 0.07618611305952072, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04238409548997879, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0035944744013249874, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10417252033948898, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.020756689831614494, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.027809347957372665, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.032211001962423325, + 0, + 0, + 0, + 0, + 0, + 0, + 0.009824397973716259, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10345279425382614, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.00631293561309576, + 0, + 0, + 0, + 0.10903903841972351, + 0, + 0.16359111666679382, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0943848267197609, + 0, + 0, + 0, + 0.05917453020811081, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.13099519908428192, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05544748529791832, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08135419338941574, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09919339418411255, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02700343169271946, + 0, + 0.09287373721599579, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08279268443584442, + 0, + 0, + 0.03415249288082123, + 0, + 0, + 0.0873820036649704, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05599569156765938, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.022937914356589317, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0596882626414299, + 0, + 0, + 0.07868015766143799, + 0.13493220508098602, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.15474680066108704, + 0, + 0, + 0, + 0, + 0, + 0.19177544116973877, + 0, + 0, + 0, + 0, + 0, + 0.03993453457951546, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06852855533361435, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.012656732462346554, + 0.0018114305566996336, + 0 + ] +}, +{ + "title": "Stumble Up Full Mix", + "artist": "artist Pop", + "duration": 210, + "genre": "Comedy", + "tags": [ + "upbeat", + "party" + ], + "play_count": 2, + "last_played": "2025-01-21T13:36:47.350Z", + "url": "https://soundscout.s3.eu-central-1.amazonaws.com/Stumble Up Full Mix.mp3", + "music_embeddings": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05976416915655136, + 0, + 0, + 0.014663715846836567, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07778502255678177, + 0, + 0.028968067839741707, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1117454245686531, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.029864385724067688, + 0, + 0.03831430524587631, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02173011004924774, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.13024422526359558, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.007939335890114307, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02428613416850567, + 0.05989294871687889, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02176949754357338, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05837192013859749, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06026763468980789, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05001030117273331, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09871696680784225, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05225135758519173, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.18431730568408966, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05202171579003334, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.013531685806810856, + 0, + 0, + 0, + 0, + 0.009911519475281239, + 0, + 0.07194165140390396, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1611173003911972, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05548720806837082, + 0, + 0, + 0.030255792662501335, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.3620510995388031, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11051146686077118, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.006291649304330349, + 0, + 0, + 0, + 0.14234225451946259, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03389454260468483, + 0, + 0, + 0, + 0, + 0.05499837175011635, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03605210408568382, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.006280028726905584, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06683240085840225, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10333261638879776, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09935598820447922, + 0, + 0.23115302622318268, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.20929251611232758, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05360465869307518, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11708447337150574, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1814109832048416, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04636489972472191, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.052055247128009796, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10572157055139542, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08765929937362671, + 0, + 0, + 0.034168921411037445, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.007768609095364809, + 0, + 0, + 0, + 0, + 0, + 0.04133225604891777, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12059403955936432, + 0, + 0.04417797178030014, + 0.03262351453304291, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0283682718873024, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04477926343679428, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.00036603433545678854, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.060373324900865555, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0026585429441183805, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.042702630162239075, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08935562521219254, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.15396343171596527, + 0, + 0, + 0, + 0.04678694158792496, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09712160378694534, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0264600720256567, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.18889780342578888, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03859057277441025, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09627184271812439, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03268637880682945, + 0, + 0, + 0.1076500415802002, + 0, + 0, + 0.12873397767543793, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1258421540260315, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.035093940794467926, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07739906013011932, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09328047186136246, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.21190761029720306, + 0.10420878976583481, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0055915885604918, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05381041392683983, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06959054619073868, + 0, + 0, + 0, + 0, + 0.12163467705249786, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09419231116771698, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08940214663743973, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06288382411003113, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09813569486141205, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.008716192096471786, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.025985989719629288, + 0.09666027128696442, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05932292714715004, + 0, + 0, + 0, + 0.13126789033412933, + 0, + 0.19273482263088226, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0666126236319542, + 0, + 0, + 0, + 0.040537770837545395, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09567688405513763, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.00017299198952969164, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.018402794376015663, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09896805137395859, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.00436674989759922, + 0, + 0.08538831025362015, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06460125744342804, + 0, + 0, + 0.030323529615998268, + 0, + 0, + 0.017772909253835678, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05854729562997818, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03488646820187569, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.030126797035336494, + 0, + 0, + 0.09705918282270432, + 0.14658798277378082, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08873768895864487, + 0, + 0, + 0, + 0, + 0, + 0.19490696489810944, + 0, + 0, + 0, + 0, + 0, + 0.029106929898262024, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01786920614540577, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1166708767414093, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.035216160118579865, + 0.01418325025588274, + 0.005356535315513611, + 0 + ] +}, +{ + "title": "Swoop It Full Mix", + "artist": "artist Pop", + "duration": 210, + "genre": "Comedy", + "tags": [ + "upbeat", + "party" + ], + "play_count": 2, + "last_played": "2025-01-20T20:19:07.116Z", + "url": "https://soundscout.s3.eu-central-1.amazonaws.com/Swoop It Full Mix.mp3", + "music_embeddings": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04132658988237381, + 0, + 0, + 0.036057837307453156, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08387541025876999, + 0.012137331068515778, + 0.09956797957420349, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1392192244529724, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.009388217702507973, + 0, + 0.07182616740465164, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06949783861637115, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.13497672975063324, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04397724196314812, + 0, + 0.01216517947614193, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04258408397436142, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.019277382642030716, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.028513414785265923, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0236460343003273, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.001794045907445252, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10657823830842972, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06897499412298203, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.18760664761066437, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.012124350294470787, + 0, + 0.08475293219089508, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.013508370146155357, + 0, + 0, + 0, + 0, + 0.029173439368605614, + 0, + 0.06830320507287979, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1746736764907837, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.046694036573171616, + 0, + 0, + 0.00003264281986048445, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.3312353491783142, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0714631900191307, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03276146203279495, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.030126316472887993, + 0, + 0, + 0, + 0.11758338660001755, + 0, + 0, + 0, + 0, + 0, + 0, + 0.011297741904854774, + 0, + 0, + 0, + 0, + 0.08047328144311905, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.023431211709976196, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06929270923137665, + 0, + 0, + 0, + 0.003294736612588167, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02577287144958973, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.14247407019138336, + 0.021286776289343834, + 0, + 0, + 0, + 0, + 0, + 0.18067850172519684, + 0, + 0.2708350718021393, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.15551160275936127, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.014151681214571, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.005202687811106443, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.011150049977004528, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.012165551073849201, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.14410975575447083, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03479477018117905, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.009131791070103645, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07623552531003952, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09908748418092728, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05862483009696007, + 0, + 0, + 0.0682305097579956, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.021175866946578026, + 0, + 0, + 0, + 0, + 0, + 0.029291817918419838, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06372828036546707, + 0, + 0.10076199471950531, + 0.004218368791043758, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05517742410302162, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.035235825926065445, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0003014514222741127, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05740029737353325, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02463124692440033, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12299256026744843, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.021443553268909454, + 0, + 0, + 0, + 0.029504813253879547, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.039786405861377716, + 0, + 0, + 0, + 0, + 0.13288594782352448, + 0, + 0, + 0, + 0, + 0, + 0, + 0.037124644964933395, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.20701371133327484, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.006431106943637133, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12566830217838287, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.020515678450465202, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.13835999369621277, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06674380600452423, + 0, + 0, + 0.059198979288339615, + 0, + 0, + 0.09834162890911102, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09141816198825836, + 0, + 0, + 0.0032523111440241337, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05736791715025902, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.055369116365909576, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.22920508682727814, + 0.136479452252388, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.001231711939908564, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.004178078379482031, + 0, + 0, + 0, + 0, + 0.0782812163233757, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.008459105156362057, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0501367449760437, + 0, + 0, + 0, + 0, + 0.08062341809272766, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.047813475131988525, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.078520268201828, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.035765569657087326, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04680165648460388, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06234222650527954, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04026355966925621, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03450070321559906, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.021993381902575493, + 0.0784662738442421, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.025016261264681816, + 0, + 0, + 0, + 0.07089731097221375, + 0, + 0.15029430389404297, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07946322113275528, + 0, + 0, + 0, + 0.03839487582445145, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08799277245998383, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05897624045610428, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01185645442456007, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08061633259057999, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07309526950120926, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02682826854288578, + 0, + 0.06789660453796387, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09218477457761765, + 0.012889716774225235, + 0, + 0.05190863087773323, + 0, + 0, + 0.06076231971383095, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07875049859285355, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02701372466981411, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08867599070072174, + 0, + 0, + 0.13611651957035065, + 0.1606769859790802, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07490185648202896, + 0, + 0, + 0, + 0, + 0, + 0.20851755142211914, + 0, + 0.006575167179107666, + 0, + 0, + 0, + 0.06378842145204544, + 0, + 0, + 0, + 0, + 0, + 0, + 0.022140689194202423, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03566286340355873, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10460215061903, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0019808493088930845, + 0.027258865535259247, + 0.024420175701379776, + 0 + ] +}, +{ + "title": "Chatter Fest Full Mix", + "artist": "artist Pop", + "duration": 210, + "genre": "Comedy", + "tags": [ + "upbeat", + "party" + ], + "play_count": 0, + "last_played": "2025-01-15T12:34:56Z", + "url": "https://soundscout.s3.eu-central-1.amazonaws.com/Chatter Fest Full Mix.mp3", + "music_embeddings": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08005049079656601, + 0, + 0, + 0.03792828321456909, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06532762944698334, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.007144981063902378, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.18375030159950256, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.029070518910884857, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03268799930810928, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1375517100095749, + 0, + 0, + 0, + 0, + 0.0721096321940422, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02777816727757454, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.010528822429478168, + 0.04249442368745804, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01742570288479328, + 0, + 0, + 0, + 0.02256559208035469, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03562101721763611, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09462344646453857, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05236849933862686, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.14617972075939178, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.034241028130054474, + 0, + 0.06188637763261795, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.043235987424850464, + 0, + 0, + 0, + 0, + 0.012809250503778458, + 0, + 0.05160369724035263, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.13177011907100677, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0021980812307447195, + 0, + 0, + 0.041724592447280884, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.35333341360092163, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.14155317842960358, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.025329479947686195, + 0, + 0, + 0, + 0.16346608102321625, + 0, + 0, + 0, + 0, + 0, + 0, + 0.018556684255599976, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0430520661175251, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05612384155392647, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.025559652596712112, + 0, + 0, + 0, + 0.025918129831552505, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09807886928319931, + 0, + 0.2176557183265686, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01726413518190384, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.24802875518798828, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.007039427757263184, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06082281470298767, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.033092595636844635, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09426341950893402, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11978921294212341, + 0, + 0, + 0.022588545456528664, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03681459650397301, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1164257600903511, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12038855254650116, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12344349175691605, + 0, + 0, + 0.07678547501564026, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03829227387905121, + 0, + 0, + 0, + 0, + 0, + 0.0799679234623909, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12852047383785248, + 0, + 0.11800380796194077, + 0.002630988135933876, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07441090047359467, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.035735394805669785, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08229946345090866, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10933424532413483, + 0, + 0, + 0, + 0.063017338514328, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11969753354787827, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.012236012145876884, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.21003735065460205, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01998182199895382, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0009831009665504098, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11299143731594086, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.038971155881881714, + 0, + 0, + 0.04192374274134636, + 0, + 0, + 0.15853990614414215, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1694381982088089, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.017642918974161148, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0168100968003273, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06556157022714615, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1990465521812439, + 0.06813818961381912, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0071120294742286205, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07542214542627335, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04541782662272453, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.011500784195959568, + 0, + 0, + 0, + 0, + 0.09683701395988464, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06915408372879028, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.019531745463609695, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.041907716542482376, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.057055987417697906, + 0, + 0, + 0, + 0, + 0, + 0, + 0.016764426603913307, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.022120166569948196, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09873286634683609, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.002305653877556324, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.030438685789704323, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04524785280227661, + 0.1198723167181015, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.058147650212049484, + 0, + 0, + 0, + 0.09940554946660995, + 0, + 0.1755988746881485, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11444627493619919, + 0, + 0, + 0, + 0.023177560418844223, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09096808731555939, + 0, + 0, + 0, + 0.01405058242380619, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1386915147304535, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05875413492321968, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04554015398025513, + 0, + 0, + 0.056368567049503326, + 0, + 0, + 0.0005541832069866359, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02596423029899597, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04394388943910599, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.009633866138756275, + 0, + 0, + 0, + 0.03395364433526993, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11831589043140411, + 0, + 0, + 0.05810341238975525, + 0.12856654822826385, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.14071513712406158, + 0, + 0, + 0, + 0, + 0, + 0.12383733689785004, + 0, + 0.02331383526325226, + 0, + 0, + 0, + 0.03836379945278168, + 0, + 0, + 0, + 0, + 0, + 0, + 0.026141822338104248, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.010599547997117043, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1117236390709877, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0316026546061039, + 0, + 0 + ] +}, +{ + "title": "Fishy Manouver Full Mix", + "artist": "artist Pop", + "duration": 210, + "genre": "Comedy", + "tags": [ + "upbeat", + "party" + ], + "play_count": 1, + "last_played": "2025-01-17T06:25:49.577Z", + "url": "https://soundscout.s3.eu-central-1.amazonaws.com/Fishy Manouver Full Mix.mp3", + "music_embeddings": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.032270051538944244, + 0, + 0, + 0.034896425902843475, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06337086111307144, + 0, + 0.04235533997416496, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1631404608488083, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.021363088861107826, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.010271038860082626, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1494757980108261, + 0, + 0, + 0, + 0, + 0.021557897329330444, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02597561664879322, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.027558328583836555, + 0.026381567120552063, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01794677972793579, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05436676740646362, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0023747384548187256, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10203494876623154, + 0, + 0, + 0.003436536528170109, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05835749953985214, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.18402265012264252, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02683471515774727, + 0, + 0.08923830091953278, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02784864977002144, + 0, + 0, + 0, + 0, + 0.009985116310417652, + 0, + 0.07489951699972153, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.14618463814258575, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06264299154281616, + 0, + 0, + 0.05890462547540665, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.3166194558143616, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08501794934272766, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.015109018422663212, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.17960134148597717, + 0, + 0, + 0, + 0, + 0, + 0, + 0.010550590232014656, + 0, + 0, + 0, + 0, + 0.011275327764451504, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0321398563683033, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.000673504953738302, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.045230504125356674, + 0, + 0, + 0, + 0.005141285713762045, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07039697468280792, + 0, + 0, + 0, + 0, + 0, + 0, + 0.18620014190673828, + 0, + 0.2447715848684311, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1991139054298401, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.011798735707998276, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.022466877475380898, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.061490096151828766, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1323065161705017, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1154070645570755, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09460573643445969, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08644453436136246, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03167925029993057, + 0, + 0, + 0.047878388315439224, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06945270299911499, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0941450372338295, + 0, + 0.0652376338839531, + 0.03980709984898567, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0668221190571785, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0484822541475296, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03273703157901764, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.005273283924907446, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.006744705140590668, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03303554654121399, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1095452606678009, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11372696608304977, + 0, + 0, + 0, + 0.00775640644133091, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.014151278883218765, + 0, + 0, + 0, + 0, + 0.06593409180641174, + 0, + 0, + 0, + 0, + 0, + 0, + 0.019925037398934364, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.19482089579105377, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03077702969312668, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06861976534128189, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11542271077632904, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03392379730939865, + 0, + 0, + 0.07044309377670288, + 0, + 0, + 0.1222011148929596, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08300109952688217, + 0, + 0, + 0.0028932474087923765, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.004636160098016262, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.040524523705244064, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07870879769325256, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.002997287083417177, + 0, + 0, + 0, + 0, + 0.23739303648471832, + 0.07010398060083389, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.005758277140557766, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05669564753770828, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08168420195579529, + 0, + 0, + 0, + 0, + 0.08745025098323822, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03259759023785591, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.010789948515594006, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06572215259075165, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06313081830739975, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03891731798648834, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07809272408485413, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.013329816982150078, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05606474727392197, + 0, + 0, + 0, + 0, + 0, + 0, + 0.008875254541635513, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0018115207785740495, + 0.10414224863052368, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06463251262903214, + 0, + 0, + 0, + 0.10974990576505661, + 0, + 0.1823040097951889, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09632577747106552, + 0, + 0, + 0, + 0.032565221190452576, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11338929086923599, + 0, + 0, + 0, + 0.014720253646373749, + 0, + 0, + 0, + 0, + 0.08481056243181229, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09947983175516129, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.010028262622654438, + 0, + 0.08761565387248993, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11319006234407425, + 0.03375522047281265, + 0, + 0.03995712101459503, + 0, + 0, + 0.02894826978445053, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06430496275424957, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11357073485851288, + 0, + 0, + 0.11454030871391296, + 0.1647062450647354, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1062682569026947, + 0, + 0, + 0, + 0, + 0, + 0.19484421610832214, + 0, + 0, + 0, + 0, + 0, + 0.014298594556748867, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02335480786859989, + 0, + 0.008223198354244232, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1365320384502411, + 0, + 0, + 0, + 0.0011612335219979286, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0637587234377861, + 0.035454198718070984, + 0.023670019581913948, + 0 + ] +}] \ No newline at end of file diff --git a/apps/mongo-mp/app/data/mongomp.songs-pop.json b/apps/mongo-mp/app/data/mongomp.songs-pop.json new file mode 100644 index 0000000..27836f7 --- /dev/null +++ b/apps/mongo-mp/app/data/mongomp.songs-pop.json @@ -0,0 +1,4162 @@ +[{ + "title": "Marimba Love Full Mix", + "artist": "artist Pop", + "duration": 210, + "genre": "Modern Orchestral, Pop", + "tags": [ + "upbeat", + "party" + ], + "play_count": 0, + "last_played": "2025-01-15T12:34:56Z", + "url": "https://soundscout.s3.eu-central-1.amazonaws.com/Marimba Love Full Mix.mp3", + "music_embeddings": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07058347761631012, + 0, + 0, + 0.002305924892425537, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.045002322643995285, + 0, + 0.06715960055589676, + 0, + 0.009506220929324627, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03146078437566757, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0813857913017273, + 0, + 0, + 0, + 0, + 0.045903608202934265, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.00912359170615673, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11694025248289108, + 0, + 0.038095541298389435, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04864491522312164, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11824236065149307, + 0, + 0, + 0, + 0, + 0.028110437095165253, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.048068366944789886, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.009131885133683681, + 0, + 0, + 0.0661332830786705, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.027808038517832756, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.015232144854962826, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.008507270365953445, + 0, + 0, + 0, + 0.08057171106338501, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03231493756175041, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.14966416358947754, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.025824904441833496, + 0, + 0.051515139639377594, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04504519701004028, + 0, + 0, + 0, + 0, + 0.07868269085884094, + 0, + 0.10099848359823227, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.22303105890750885, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04920518398284912, + 0, + 0, + 0.02919520065188408, + 0, + 0, + 0.01708385907113552, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.3174404203891754, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11823546141386032, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05100241303443909, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.010149781592190266, + 0, + 0, + 0, + 0.028015166521072388, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04801054298877716, + 0, + 0, + 0, + 0, + 0.028099285438656807, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02957683801651001, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.014178645797073841, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.018651379272341728, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06366222351789474, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.020306210964918137, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11155828833580017, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10777553915977478, + 0, + 0.254911333322525, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11118628829717636, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08987566828727722, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0021321079693734646, + 0, + 0, + 0.08075692504644394, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0658172145485878, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.019298652186989784, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09419754892587662, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06036078557372093, + 0, + 0, + 0.07710756361484528, + 0, + 0.06954970955848694, + 0, + 0, + 0, + 0, + 0, + 0.04172829911112785, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11893979460000992, + 0, + 0, + 0, + 0.0020906308200210333, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03437502309679985, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11893147230148315, + 0, + 0, + 0.024541687220335007, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11224784702062607, + 0, + 0, + 0, + 0, + 0, + 0.03268701210618019, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.058768659830093384, + 0, + 0.13864845037460327, + 0.021464966237545013, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03748352825641632, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.061650924384593964, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01761339232325554, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05868840590119362, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.017000243067741394, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0988314226269722, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12167911976575851, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.15315337479114532, + 0.008645045571029186, + 0, + 0, + 0, + 0, + 0, + 0.047556884586811066, + 0, + 0.05667077377438545, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0018489916110411286, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.13665153086185455, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.00173928530421108, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05172180011868477, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.042273424565792084, + 0, + 0, + 0.14652468264102936, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.008668742142617702, + 0, + 0, + 0.054616592824459076, + 0, + 0, + 0, + 0, + 0.018492799252271652, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12111968547105789, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02559681423008442, + 0, + 0.04087340086698532, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.054704245179891586, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05651715397834778, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.16405735909938812, + 0.1437089443206787, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.014644280076026917, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.016714096069335938, + 0, + 0, + 0, + 0, + 0.12150134146213531, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.03208164870738983, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12975502014160156, + 0, + 0, + 0.0024963056202977896, + 0, + 0.009421538561582565, + 0, + 0, + 0, + 0, + 0, + 0.0096582667902112, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.009679611772298813, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08387768268585205, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.017958272248506546, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.018537649884819984, + 0.03162151575088501, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08409356325864792, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1305374801158905, + 0.13916485011577606, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07761761546134949, + 0, + 0, + 0, + 0.04588392376899719, + 0, + 0.13274022936820984, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08842536062002182, + 0, + 0, + 0, + 0.16101185977458954, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0494137667119503, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1347985863685608, + 0, + 0, + 0, + 0.005943062715232372, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.027768701314926147, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.003342563984915614, + 0, + 0.09351745247840881, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.009390704333782196, + 0, + 0.1123277097940445, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.033940792083740234, + 0.04132971912622452, + 0, + 0.0659063532948494, + 0, + 0, + 0, + 0, + 0, + 0.0782952755689621, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07492587715387344, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07511259615421295, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.02333926223218441, + 0, + 0, + 0.10658147186040878, + 0.1359645426273346, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0752234235405922, + 0, + 0, + 0, + 0, + 0.09902378916740417, + 0, + 0, + 0, + 0, + 0, + 0.17466214299201965, + 0, + 0.00044839351903647184, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.008620152249932289, + 0, + 0, + 0, + 0, + 0, + 0.10166521370410919, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.036514051258563995, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06321442872285843, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08511844277381897, + 0, + 0.01211757306009531, + 0 + ] +}, +{ + "title": "One Fine Afternoon Full Mix", + "artist": "artist Pop", + "duration": 210, + "genre": "Modern Orchestral, Pop", + "tags": [ + "upbeat", + "party" + ], + "play_count": 0, + "last_played": "2025-01-15T12:34:56Z", + "url": "https://soundscout.s3.eu-central-1.amazonaws.com/One Fine Afternoon Full Mix.mp3", + "music_embeddings": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.028768055140972137, + 0, + 0, + 0.07625844329595566, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10188353806734085, + 0, + 0.0007964075775817037, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.010792466811835766, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.021573254838585854, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05373798683285713, + 0, + 0, + 0, + 0, + 0.09035530686378479, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01147210132330656, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.009876905009150505, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.004365305881947279, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10142308473587036, + 0, + 0, + 0, + 0, + 0.06609238684177399, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0668126717209816, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.000536030565854162, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04916839674115181, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0472155325114727, + 0, + 0, + 0, + 0.022633764892816544, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.17144188284873962, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.12014561891555786, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.013754953630268574, + 0, + 0, + 0, + 0, + 0.056501004844903946, + 0, + 0.07403000444173813, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.16375300288200378, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.3369368016719818, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1096111610531807, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08521420508623123, + 0, + 0, + 0, + 0, + 0, + 0, + 0.004531885031610727, + 0, + 0, + 0, + 0, + 0.0847717747092247, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06885875761508942, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.013056464493274689, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.051162488758563995, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.09654688090085983, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0738520622253418, + 0, + 0, + 0, + 0, + 0, + 0, + 0.026349635794758797, + 0, + 0.21542975306510925, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06140386313199997, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.21087200939655304, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10657978057861328, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10733581334352493, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1480184942483902, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06659117341041565, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11759539693593979, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0474214144051075, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01258150115609169, + 0, + 0, + 0.005272106267511845, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11928004026412964, + 0, + 0, + 0, + 0, + 0, + 0.07147502899169922, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.11970635503530502, + 0, + 0.14709579944610596, + 0.011244316585361958, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05460784211754799, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.015957359224557877, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.003010774962604046, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.15768040716648102, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0030588426161557436, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.010486562736332417, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.004949369002133608, + 0, + 0.07944969087839127, + 0, + 0.05282389372587204, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1511356234550476, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07927601039409637, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07139500230550766, + 0, + 0, + 0.04755778983235359, + 0, + 0, + 0.05948105826973915, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06817180663347244, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.05317932367324829, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07468295842409134, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06617885828018188, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1604437530040741, + 0.12936320900917053, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.014933418482542038, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.005932854954153299, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0325913168489933, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.06644929945468903, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.07359486818313599, + 0, + 0, + 0, + 0, + 0.08365151286125183, + 0, + 0, + 0, + 0, + 0.02466716803610325, + 0, + 0, + 0, + 0, + 0, + 0.08612598478794098, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.00920781958848238, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.08459272235631943, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0016804318875074387, + 0, + 0, + 0, + 0.03771078214049339, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01133562158793211, + 0.061228763312101364, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.030126171186566353, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.14592725038528442, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10081960260868073, + 0.10753805935382843, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0408739298582077, + 0, + 0, + 0, + 0.15489524602890015, + 0, + 0.1270170658826828, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.1592322736978531, + 0, + 0, + 0, + 0.11256143450737, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.16164593398571014, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.14632098376750946, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.04170627146959305, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.021129420027136803, + 0, + 0, + 0.02545253001153469, + 0, + 0, + 0.0477590337395668, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0617479607462883, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.10327090322971344, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.038755666464567184, + 0, + 0, + 0, + 0.023577682673931122, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.042301151901483536, + 0, + 0, + 0, + 0.12921738624572754, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.21493706107139587, + 0, + 0, + 0, + 0, + 0, + 0.19340994954109192, + 0, + 0.0541253536939621, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.022130485624074936, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.01907787285745144, + 0, + 0, + 0, + 0.09986758232116699, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.00672247726470232, + 0.06240645423531532, + 0 + ] +}, +{ + "title": "Vicious Circle Full Mix", + "artist": "artist Pop", + "duration": 210, + "genre": "Pop", + "tags": [ + "upbeat", + "party" + ], + "play_count": 3, + "last_played": "2025-01-21T21:23:54.749Z" +}, +{ + "title": "Alone In The Dark Full Mix", + "artist": "artist Pop", + "duration": 210, + "genre": "Pop", + "tags": [ + "upbeat", + "party" + ], + "play_count": 1, + "last_played": "2025-01-16T17:18:13.461Z" +}, +{ + "title": "Lonely Again Full Mix", + "artist": "artist Pop", + "duration": 210, + "genre": "Pop", + "tags": [ + "upbeat", + "party" + ], + "play_count": 1, + "last_played": "2025-01-20T20:18:29.945Z" +}] \ No newline at end of file diff --git a/apps/mongo-mp/app/data/playlists.json b/apps/mongo-mp/app/data/playlists.json new file mode 100644 index 0000000..cb69538 --- /dev/null +++ b/apps/mongo-mp/app/data/playlists.json @@ -0,0 +1,24 @@ +[ + { + "name": "Chill Vibes", + "user_id": "6788f9225cff3e39e01b81be", + "songs": [ + "6788f9225cff3e39e01b81be", + "6788f9225cff3e39e01b81bf", + "6788f9225cff3e39e01b81c0", + "6788f9225cff3e39e01b81c1", + "6788f9225cff3e39e01b81c2" + ] + }, + { + "name": "Workout Mix", + "user_id": "6788f9225cff3e39e01b81bf", + "songs": [ + "6788f9225cff3e39e01b81c8", + "6788f9225cff3e39e01b81c9", + "6788f9225cff3e39e01b81af", + "6788f9225cff3e39e01b81b7", + "6788f9225cff3e39e01b81b9" + ] + } +] diff --git a/apps/mongo-mp/app/data/users.json b/apps/mongo-mp/app/data/users.json new file mode 100644 index 0000000..51468c6 --- /dev/null +++ b/apps/mongo-mp/app/data/users.json @@ -0,0 +1,12 @@ +[ + { + "name": "John Doe", + "email": "john@example.com", + "password": "password123" + }, + { + "name": "Jane Smith", + "email": "jane@example.com", + "password": "password456" + } +] diff --git a/apps/mongo-mp/app/globals.css b/apps/mongo-mp/app/globals.css new file mode 100644 index 0000000..436f3c9 --- /dev/null +++ b/apps/mongo-mp/app/globals.css @@ -0,0 +1,60 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 142.1 76.2% 36.3%; + --primary-foreground: 355.7 100% 97.3%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 142.1 76.2% 36.3%; + --radius: 0.5rem; + } + + .dark { + --background: 20 14.3% 4.1%; + --foreground: 0 0% 95%; + --card: 24 9.8% 10%; + --card-foreground: 0 0% 95%; + --popover: 0 0% 9%; + --popover-foreground: 0 0% 95%; + --primary: 142.1 70.6% 45.3%; + --primary-foreground: 144.9 80.4% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 15%; + --muted-foreground: 240 5% 64.9%; + --accent: 12 6.5% 15.1%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 85.7% 97.3%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 142.4 71.8% 29.2%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} + diff --git a/apps/mongo-mp/app/home-content.tsx b/apps/mongo-mp/app/home-content.tsx new file mode 100644 index 0000000..938c001 --- /dev/null +++ b/apps/mongo-mp/app/home-content.tsx @@ -0,0 +1,362 @@ +"use client" + +import { useState, useEffect, useCallback, useMemo } from "react" +import { useRouter, useSearchParams } from "next/navigation" +import { Music2, PlayCircle, Radio } from "lucide-react" +import { Button } from "@/components/ui/button" +import { SongList } from "@/components/song-list" +import { PlayingSongPopup } from "@/components/playing-song-popup" +import { SearchBar } from "@/components/search-bar" +import { InfoTooltip } from "@/components/info-tooltip" +import { mockFeaturedArtists } from "@/lib/mock-data" +import type { Song } from "@/types/song" +import type { Playlist } from "@/types/playlist" +import Image from "next/image" +import { useUser } from "@/contexts/UserContext" +import { useToast } from "@/components/ui/use-toast" +import { PlaylistPlayer } from "@/components/playlist-player" +import { SuggestedSongs } from "@/components/suggested-songs" + +export default function HomeContent() { + const [songsByGenre, setSongsByGenre] = useState>({}) + const [currentSong, setCurrentSong] = useState(null) + const [isPlaying, setIsPlaying] = useState(false) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + const [playlists, setPlaylists] = useState([]) + const [currentPlaylistId, setCurrentPlaylistId] = useState(null) + const { user } = useUser() + const searchParams = useSearchParams() + const { toast } = useToast() + const router = useRouter() + + const fetchSongs = async (query?: string) => { + try { + setLoading(true) + const url = query ? `/api/songs?query=${encodeURIComponent(query)}` : "/api/songs" + const response = await fetch(url) + if (!response.ok) throw new Error("Failed to fetch songs") + const data = await response.json() + setSongsByGenre(data) + } catch (err) { + setError(err instanceof Error ? err.message : "Failed to fetch songs") + } finally { + setLoading(false) + } + } + + const fetchPlaylists = async () => { + try { + const response = await fetch("/api/playlists") + if (response.ok) { + const data = await response.json() + setPlaylists(data) + } else { + console.error("Failed to fetch playlists") + } + } catch (error) { + console.error("Error fetching playlists:", error) + } + } + + const fetchPlaylistSongs = async (playlistId: string) => { + try { + const response = await fetch(`/api/playlists/${playlistId}/songs`) + if (response.ok) { + const data = await response.json() + if (data.length > 0) { + setCurrentSong(data[0]) + setIsPlaying(true) + } + } else { + console.error("Failed to fetch playlist songs") + } + } catch (error) { + console.error("Error fetching playlist songs:", error) + } + } + + useEffect(() => { + fetchSongs() + fetchPlaylists() + }, []) + + useEffect(() => { + const songId = searchParams.get("song") + if (songId) { + const findAndPlaySong = (songId: string) => { + for (const genre in songsByGenre) { + const song = songsByGenre[genre].find((s) => s._id === songId) + if (song) { + setCurrentSong(song) + setIsPlaying(true) + return + } + } + } + findAndPlaySong(songId) + } + }, [searchParams, songsByGenre]) + + useEffect(() => { + const playlistId = searchParams.get("playlist") + if (playlistId) { + fetchPlaylistSongs(playlistId) + } + }, [searchParams]) + + const handleSearch = (query: string) => { + fetchSongs(query) + } + + const handleTogglePlay = (song: Song) => { + if (currentSong && currentSong._id === song._id) { + setIsPlaying(!isPlaying) + } else { + setCurrentSong(song) + setIsPlaying(true) + } + } + + const handleToggleLike = async (songId: string) => { + // This function will be passed down to SongList and then to SongCard + // The actual API call is handled in the SongCard component + } + + const handleAddToPlaylist = async (songId: string, playlistId: string) => { + try { + const response = await fetch(`/api/playlists/${playlistId}/add-song`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ songId }), + }) + + if (response.ok) { + toast({ + title: "Success", + description: "Song added to playlist successfully", + }) + // Optionally, you can update the local state of playlists here + } else { + throw new Error("Failed to add song to playlist") + } + } catch (error) { + console.error("Error adding song to playlist:", error) + toast({ + title: "Error", + description: "Failed to add song to playlist", + variant: "destructive", + }) + } + } + + const handlePlayPlaylist = (playlistId: string) => { + setCurrentPlaylistId(playlistId) + } + + const getRandomSong = useCallback(() => { + const allSongs = Object.values(songsByGenre).flat() + if (allSongs.length === 0) return null + const randomIndex = Math.floor(Math.random() * allSongs.length) + return allSongs[randomIndex] + }, [songsByGenre]) + + const playRandomSong = useCallback(() => { + const randomSong = getRandomSong() + if (randomSong) { + router.push(`/?song=${randomSong._id}`) + } else { + toast({ + title: "Error", + description: "No songs available to play", + variant: "destructive", + }) + } + }, [getRandomSong, router, toast]) + + const selectRandomSong = useCallback( + (currentSongId: string) => { + const allSongs = Object.values(songsByGenre).flat() + const availableSongs = allSongs.filter((song) => song._id !== currentSongId) + if (availableSongs.length === 0) return + const randomIndex = Math.floor(Math.random() * availableSongs.length) + const randomSong = availableSongs[randomIndex] + setCurrentSong(randomSong) + setIsPlaying(true) + }, + [songsByGenre], + ) + + const handleSelectSong = (song: Song) => { + setCurrentSong(song) + setIsPlaying(true) + } + + if (loading) return
Loading...
+ if (error) return
{error}
+ + return ( +
+ {/* Hero Section */} +
+ +

+ Welcome to MongoMP + +

+

+ Your premium music streaming platform. Discover millions of songs, create playlists, and enjoy high-quality + audio. +

+
+ + +
+
+ + {/* Search Bar */} +
+
+ + +
+
+ + {/* Suggested Songs */} +
+ +
+ + {/* Songs by Genre */} +
+

+ Songs by Genre + { + if (!acc[song.genre]) { + acc[song.genre] = [] + } + acc[song.genre].push({ + ...song, + _id: song._id.toString() + }) + return acc +}, {})`} + /> +

+ {Object.entries(songsByGenre).map(([genre, songs]) => ( + + ))} +
+ + {/* Featured Artists */} +
+

+ Featured Artists + +

+
+ {mockFeaturedArtists.map((artist) => ( +
+
+ {artist.name} +
+
+

{artist.name}

+

{artist.genre}

+

{artist.followers.toLocaleString()} followers

+
+
+
+ ))} +
+
+ + {currentSong && ( + setIsPlaying(!isPlaying)} + onClose={() => { + setCurrentSong(null) + setIsPlaying(false) + }} + onSelectRandomSong={selectRandomSong} + onSelectSong={handleSelectSong} + /> + )} + {currentPlaylistId && ( + setCurrentPlaylistId(null)} /> + )} +
+ ) +} + diff --git a/apps/mongo-mp/app/layout.tsx b/apps/mongo-mp/app/layout.tsx new file mode 100644 index 0000000..7e4e5a3 --- /dev/null +++ b/apps/mongo-mp/app/layout.tsx @@ -0,0 +1,42 @@ +import { Inter } from 'next/font/google' +import { UserProvider } from '@/contexts/UserContext' +import { Navbar } from '@/components/navbar' +import { BottomNav } from '@/components/bottom-nav' +import './globals.css' + +const inter = Inter({ subsets: ['latin'] }) + +export const metadata = { + title: 'MongoMP - Music Streaming Platform', + description: 'Stream your favorite music with MongoMP', +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + +
+ + {children} + +
+
+ + + ) +} + diff --git a/apps/mongo-mp/app/library/page.tsx b/apps/mongo-mp/app/library/page.tsx new file mode 100644 index 0000000..203a610 --- /dev/null +++ b/apps/mongo-mp/app/library/page.tsx @@ -0,0 +1,16 @@ +import { Metadata } from "next" +import { LibraryContent } from "@/components/library-content" + +export const metadata: Metadata = { + title: "Library - MongoMP", + description: "Your music library and playlists on MongoMP", +} + +export default function LibraryPage() { + return ( +
+ +
+ ) +} + diff --git a/apps/mongo-mp/app/login/page.tsx b/apps/mongo-mp/app/login/page.tsx new file mode 100644 index 0000000..ee1928e --- /dev/null +++ b/apps/mongo-mp/app/login/page.tsx @@ -0,0 +1,87 @@ +'use client' + +import { useState } from 'react' +import Link from 'next/link' +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card" +import { Notification } from "@/components/notification" +import { useUser } from '@/contexts/UserContext' + +export default function LoginPage() { + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [isLoading, setIsLoading] = useState(false) + const [error, setError] = useState(null) + const { login } = useUser() + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setIsLoading(true) + setError(null) + + try { + await login(email, password) + } catch (error) { + setError('Login failed. Please check your credentials and try again.') + } finally { + setIsLoading(false) + } + } + + return ( +
+ + + Login + Enter your email and password to log in + + +
+
+
+ + setEmail(e.target.value)} + required + /> +
+
+ + setPassword(e.target.value)} + required + /> +
+
+ +
+
+ +

+ Don't have an account? Register +

+
+
+ {error && ( + + )} +
+ ) +} + diff --git a/apps/mongo-mp/app/page.tsx b/apps/mongo-mp/app/page.tsx new file mode 100644 index 0000000..6f23cd7 --- /dev/null +++ b/apps/mongo-mp/app/page.tsx @@ -0,0 +1,15 @@ +'use client' + +import { Suspense } from 'react' +import HomeContent from './home-content' + +export const dynamic = 'force-dynamic' + +export default function Home() { + return ( + Loading...}> + + + ) +} + diff --git a/apps/mongo-mp/app/profile/page.tsx b/apps/mongo-mp/app/profile/page.tsx new file mode 100644 index 0000000..136b1dc --- /dev/null +++ b/apps/mongo-mp/app/profile/page.tsx @@ -0,0 +1,154 @@ +'use client' + +import { useEffect, useState } from 'react' +import { useRouter } from 'next/navigation' +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Button } from "@/components/ui/button" +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import { Notification } from "@/components/notification" +import { InfoTooltip } from "@/components/info-tooltip" +import { Song } from "@/types/song" + +interface User { + _id: string; + name: string; + email: string; + likes: Song[]; +} + +export default function ProfilePage() { + const [user, setUser] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const router = useRouter(); + + useEffect(() => { + const fetchUserProfile = async () => { + try { + const response = await fetch('/api/user/profile', { + credentials: 'include' + }); + if (response.ok) { + const userData = await response.json(); + console.log('Fetched user data:', userData); + setUser(userData); + } else if (response.status === 401) { + router.push('/login'); + } else { + throw new Error('Failed to fetch user profile'); + } + } catch (err) { + setError('An error occurred while fetching your profile.'); + console.error(err); + } finally { + setIsLoading(false); + } + }; + + fetchUserProfile(); + }, [router]); + + const handlePlayLikedSong = (songId: string) => { + router.push(`/?song=${songId}`); + }; + + if (isLoading) { + return
Loading...
; + } + + if (error) { + return ; + } + + if (!user) { + return
No user data available.
; + } + + return ( +
+ + +
+ + + {user.name.split(' ').map(n => n[0]).join('')} + +
+ + {user.name} + + + + {user.email} + + +
+
+
+ + + + Info + Likes + + +
+
+ + +
+
+ + +
+ +
+
+ +
+

+ Liked Songs + + db.songs.findOne({ _id: songId }) +)`} + side="right" + /> +

+ {user.likes && user.likes.length > 0 ? ( + user.likes.map((song) => ( +
+
+

{song.title}

+

{song.artist}

+
+ +
+ )) + ) : ( +

You haven't liked any songs yet.

+ )} +
+
+
+
+
+
+ ) +} + diff --git a/apps/mongo-mp/app/register/page.tsx b/apps/mongo-mp/app/register/page.tsx new file mode 100644 index 0000000..f8d1925 --- /dev/null +++ b/apps/mongo-mp/app/register/page.tsx @@ -0,0 +1,96 @@ +'use client' + +import { useState } from 'react' +import { useRouter } from 'next/navigation' +import Link from 'next/link' +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card" + +export default function RegisterPage() { + const [name, setName] = useState('') + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [error, setError] = useState('') + const router = useRouter() + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setError('') + + try { + const response = await fetch('/api/auth/register', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, email, password }), + }) + + if (response.ok) { + router.push('/login') + } else { + const data = await response.json() + setError(data.error || 'Registration failed') + } + } catch (error) { + setError('An error occurred. Please try again.') + } + } + + return ( +
+ + + Register + Create a new account + + +
+
+
+ + setName(e.target.value)} + required + /> +
+
+ + setEmail(e.target.value)} + required + /> +
+
+ + setPassword(e.target.value)} + required + /> +
+
+ {error &&

{error}

} + +
+
+ +

+ Already have an account? Log in +

+
+
+
+ ) +} + diff --git a/apps/mongo-mp/app/search/page.tsx b/apps/mongo-mp/app/search/page.tsx new file mode 100644 index 0000000..1c94d90 --- /dev/null +++ b/apps/mongo-mp/app/search/page.tsx @@ -0,0 +1,16 @@ +import { Metadata } from "next" + +export const metadata: Metadata = { + title: "Search - MongoMP", + description: "Search for your favorite songs on MongoMP", +} + +export default function SearchPage() { + return ( +
+

Search

+

Search functionality coming soon!

+
+ ) +} + diff --git a/apps/mongo-mp/components.json b/apps/mongo-mp/components.json new file mode 100644 index 0000000..d9ef0ae --- /dev/null +++ b/apps/mongo-mp/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} \ No newline at end of file diff --git a/apps/mongo-mp/components/RetroEqualizer.tsx b/apps/mongo-mp/components/RetroEqualizer.tsx new file mode 100644 index 0000000..f34c4ea --- /dev/null +++ b/apps/mongo-mp/components/RetroEqualizer.tsx @@ -0,0 +1,57 @@ +import React from 'react'; + +interface RetroEqualizerProps { + bpm: number; + isPlaying: boolean; +} + +const RetroEqualizer: React.FC = ({ bpm, isPlaying }) => { + // Convert BPM to animation duration in seconds + const getDuration = (bpm: number) => { + return (60 / bpm) * 2; + }; + + const barHeights = [120, 80, 140, 60, 100, 120, 40, 80, 140]; + const barColors = ['#FF3D3D', '#FF9F3D', '#FFE03D', '#48FF3D', '#3DCFFF', '#3D51FF', '#B03DFF', '#FF3DC3', '#FF3D3D']; + + return ( +
+ + + + + {barHeights.map((height, index) => ( + + {isPlaying && ( + + )} + + ))} + + + + + + + + + + +
+ ); +}; + +export default RetroEqualizer; + diff --git a/apps/mongo-mp/components/bottom-nav.tsx b/apps/mongo-mp/components/bottom-nav.tsx new file mode 100644 index 0000000..817cc8b --- /dev/null +++ b/apps/mongo-mp/components/bottom-nav.tsx @@ -0,0 +1,40 @@ +'use client' + +import Link from 'next/link' +import { usePathname } from 'next/navigation' +import { Home, Search, Library, User } from 'lucide-react' +import { cn } from '@/lib/utils' + +const navItems = [ + { icon: Home, label: 'Home', href: '/' }, + { icon: Search, label: 'Search', href: '/search' }, + { icon: Library, label: 'Library', href: '/library' }, + { icon: User, label: 'Profile', href: '/profile' }, +] + +export function BottomNav() { + const pathname = usePathname() + + return ( + + ) +} + diff --git a/apps/mongo-mp/components/code-block.tsx b/apps/mongo-mp/components/code-block.tsx new file mode 100644 index 0000000..f0195ce --- /dev/null +++ b/apps/mongo-mp/components/code-block.tsx @@ -0,0 +1,17 @@ +'use client' + +interface CodeBlockProps { + code: string; + language?: string; +} + +export function CodeBlock({ code, language = 'javascript' }: CodeBlockProps) { + return ( +
+      
+        {code}
+      
+    
+ ); +} + diff --git a/apps/mongo-mp/components/info-tooltip.tsx b/apps/mongo-mp/components/info-tooltip.tsx new file mode 100644 index 0000000..d72b13c --- /dev/null +++ b/apps/mongo-mp/components/info-tooltip.tsx @@ -0,0 +1,40 @@ +'use client' + +import { Info } from 'lucide-react' +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip" +import { CodeBlock } from "./code-block" + +interface InfoTooltipProps { + content: string; + query?: string; + side?: 'top' | 'right' | 'bottom' | 'left'; + align?: 'start' | 'center' | 'end'; +} + +export function InfoTooltip({ content, query, side = 'right', align = 'center' }: InfoTooltipProps) { + return ( + + + + + + +

{content}

+ {query && } +
+
+
+ ) +} + diff --git a/apps/mongo-mp/components/library-content.tsx b/apps/mongo-mp/components/library-content.tsx new file mode 100644 index 0000000..e5bd906 --- /dev/null +++ b/apps/mongo-mp/components/library-content.tsx @@ -0,0 +1,250 @@ +'use client' + +import { useState, useEffect } from 'react' +import { useRouter } from 'next/navigation' +import { Plus, Trash2, Play, Info } from 'lucide-react' +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Card, CardContent } from "@/components/ui/card" +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog" +import { Label } from "@/components/ui/label" +import { ScrollArea } from "@/components/ui/scroll-area" +import { InfoTooltip } from "@/components/info-tooltip" +import { Badge } from "@/components/ui/badge" +import { useUser } from '@/contexts/UserContext' +import { Playlist } from '@/types/playlist' +import { cn } from "@/lib/utils" + +export function LibraryContent() { + const { user } = useUser() + const router = useRouter() + const [playlists, setPlaylists] = useState([]) + const [newPlaylistName, setNewPlaylistName] = useState('') + const [isDialogOpen, setIsDialogOpen] = useState(false) + const [loading, setLoading] = useState(true) + + useEffect(() => { + if (user) { + fetchPlaylists() + } + }, [user]) + + const fetchPlaylists = async () => { + try { + setLoading(true) + const response = await fetch('/api/playlists') + if (response.ok) { + const data = await response.json() + setPlaylists(data) + } else { + console.error('Failed to fetch playlists') + } + } catch (error) { + console.error('Error fetching playlists:', error) + } finally { + setLoading(false) + } + } + + const handleCreatePlaylist = async () => { + if (!newPlaylistName.trim()) return + + try { + const response = await fetch('/api/playlists', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name: newPlaylistName }), + }) + + if (response.ok) { + const newPlaylist = await response.json() + setPlaylists([...playlists, newPlaylist]) + setNewPlaylistName('') + setIsDialogOpen(false) + } else { + console.error('Failed to create playlist') + } + } catch (error) { + console.error('Error creating playlist:', error) + } + } + + const handleDeletePlaylist = async (playlistId: string) => { + try { + const response = await fetch(`/api/playlists/${playlistId}`, { + method: 'DELETE', + }) + + if (response.ok) { + setPlaylists(playlists.filter(playlist => playlist._id !== playlistId)) + } else { + console.error('Failed to delete playlist') + } + } catch (error) { + console.error('Error deleting playlist:', error) + } + } + + const getUniqueGenres = (songs: any[]) => { + return [...new Set(songs.map(song => song.genre))]; + } + + if (!user) { + return
Please log in to view your library.
+ } + + if (loading) { + return
Loading your playlists...
+ } + + return ( +
+
+

Your Library

+ + + + + + + Create New Playlist + + Enter a name for your new playlist. + + +
+
+ + setNewPlaylistName(e.target.value)} + className="col-span-3" + /> +
+
+ + + +
+
+
+
+ {playlists.map((playlist) => { + const genres = getUniqueGenres(playlist.songs); + return ( + + +
+

{playlist.name}

+

{playlist.songs.length} songs

+
+ {genres.map((genre) => ( + + {genre} + + ))} +
+
+ + {playlist.songs.length > 0 ? ( +
    + {playlist.songs.map((song, idx) => ( +
  • + {idx + 1} +
    +

    {song.title}

    +

    {song.artist}

    +
    +
  • + ))} +
+ ) : ( +

No songs in this playlist

+ )} +
+
+ + + +
+
+
+ ); + })} +
+
+ ) +} + diff --git a/apps/mongo-mp/components/navbar.tsx b/apps/mongo-mp/components/navbar.tsx new file mode 100644 index 0000000..32c1fb7 --- /dev/null +++ b/apps/mongo-mp/components/navbar.tsx @@ -0,0 +1,66 @@ +'use client' + +import { useState } from 'react' +import Link from 'next/link' +import { Home, Search, Library, Music, Menu, X } from 'lucide-react' +import { UserMenu } from '@/components/user-menu' +import { useUser } from '@/contexts/UserContext' +import { Button } from "@/components/ui/button" +import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet" + +export function Navbar() { + const { user } = useUser() + const [isOpen, setIsOpen] = useState(false) + + const NavItems = () => ( + <> + + + Home + + + + Search + + + + Library + + + ) + + return ( + + ) +} + diff --git a/apps/mongo-mp/components/notification.tsx b/apps/mongo-mp/components/notification.tsx new file mode 100644 index 0000000..3a5ba36 --- /dev/null +++ b/apps/mongo-mp/components/notification.tsx @@ -0,0 +1,73 @@ +import { useState, useEffect } from 'react' +import { X } from 'lucide-react' +import { cva, type VariantProps } from 'class-variance-authority' +import { cn } from '@/lib/utils' + +const notificationVariants = cva( + "fixed bottom-4 right-4 w-full max-w-sm overflow-hidden rounded-lg shadow-lg", + { + variants: { + variant: { + default: "bg-white", + destructive: "bg-red-600 text-white", + success: "bg-green-600 text-white", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface NotificationProps + extends React.HTMLAttributes, + VariantProps { + title: string + message: string + duration?: number +} + +export function Notification({ + className, + variant, + title, + message, + duration = 5000, + ...props +}: NotificationProps) { + const [isVisible, setIsVisible] = useState(true) + + useEffect(() => { + const timer = setTimeout(() => { + setIsVisible(false) + }, duration) + + return () => clearTimeout(timer) + }, [duration]) + + if (!isVisible) return null + + return ( +
+
+
+
+

{title}

+

{message}

+
+ +
+
+
+ ) +} + diff --git a/apps/mongo-mp/components/playing-song-popup.tsx b/apps/mongo-mp/components/playing-song-popup.tsx new file mode 100644 index 0000000..97f8983 --- /dev/null +++ b/apps/mongo-mp/components/playing-song-popup.tsx @@ -0,0 +1,214 @@ +'use client' + +import { useEffect, useRef, useState, useMemo } from 'react' +import { X, Play, Pause, SkipBack, SkipForward, ChevronDown, ChevronUp } from 'lucide-react' +import { Button } from "@/components/ui/button" +import { Card, CardContent } from "@/components/ui/card" +import { Slider } from "@/components/ui/slider" +import { InfoTooltip } from "@/components/info-tooltip" +import { ScrollArea } from "@/components/ui/scroll-area" +import { formatDuration } from "@/lib/utils" +import { Song } from "@/types/song" +import RetroEqualizer from './RetroEqualizer' + +interface PlayingSongPopupProps { + song: Song + isPlaying: boolean + onTogglePlay: () => void + onClose: () => void + onSelectRandomSong: (currentSongId: string) => void + onSelectSong: (song: Song) => void +} + +export function PlayingSongPopup({ song, isPlaying, onTogglePlay, onClose, onSelectRandomSong, onSelectSong }: PlayingSongPopupProps) { + const [currentTime, setCurrentTime] = useState(0) + const audioRef = useRef(null) + const [playCountIncremented, setPlayCountIncremented] = useState(false) + const [similarSongs, setSimilarSongs] = useState([]) + const [showSimilarSongs, setShowSimilarSongs] = useState(false) + + const gradientStyle = useMemo(() => { + const color1 = `hsl(${Math.random() * 360}, 70%, 60%)` + const color2 = `hsl(${Math.random() * 360}, 70%, 60%)` + return { + backgroundImage: `linear-gradient(135deg, ${color1}, ${color2})` + } + }, [song._id]) + + useEffect(() => { + if (audioRef.current) { + if (isPlaying) { + audioRef.current.play() + } else { + audioRef.current.pause() + } + } + }, [isPlaying, song]) + + useEffect(() => { + const audio = audioRef.current + if (!audio) return + + const updateTime = () => setCurrentTime(audio.currentTime) + audio.addEventListener('timeupdate', updateTime) + + const handlePlay = async () => { + if (!playCountIncremented) { + try { + const response = await fetch('/api/songs/increment-plays', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ songId: song._id }), + }) + if (response.ok) { + setPlayCountIncremented(true) + } + } catch (error) { + console.error('Failed to increment play count:', error) + } + } + } + audio.addEventListener('play', handlePlay) + + return () => { + audio.removeEventListener('timeupdate', updateTime) + audio.removeEventListener('play', handlePlay) + } + }, [song._id, playCountIncremented]) + + useEffect(() => { + const fetchSimilarSongs = async () => { + try { + const response = await fetch(`/api/songs/similar?songId=${song._id}`) + if (response.ok) { + const data = await response.json() + setSimilarSongs(data) + } + } catch (error) { + console.error('Failed to fetch similar songs:', error) + } + } + + fetchSimilarSongs() + }, [song._id]) + + const handleSeek = (value: number[]) => { + if (audioRef.current) { + audioRef.current.currentTime = value[0] + } + } + + const handleNextPrevious = () => { + onSelectRandomSong(song._id) + } + + return ( + + +
+

+ Now Playing + +

+ +
+
+
+
+

{song.title}

+

{song.artist}

+
+
+ +
+
+ ) +} + diff --git a/apps/mongo-mp/components/playlist-player.tsx b/apps/mongo-mp/components/playlist-player.tsx new file mode 100644 index 0000000..0c5fafd --- /dev/null +++ b/apps/mongo-mp/components/playlist-player.tsx @@ -0,0 +1,212 @@ +'use client' + +import { useState, useEffect, useRef } from 'react' +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { Button } from "@/components/ui/button" +import { ScrollArea } from "@/components/ui/scroll-area" +import { Slider } from "@/components/ui/slider" +import { Play, Pause, SkipForward, SkipBack, Volume2 } from 'lucide-react' +import { Song } from "@/types/song" +import { formatDuration } from "@/lib/utils" + +interface PlaylistPlayerProps { + playlistId: string | null; + onClose: () => void; +} + +export function PlaylistPlayer({ playlistId, onClose }: PlaylistPlayerProps) { + const [songs, setSongs] = useState([]) + const [currentSongIndex, setCurrentSongIndex] = useState(0) + const [isPlaying, setIsPlaying] = useState(false) + const [currentTime, setCurrentTime] = useState(0) + const [volume, setVolume] = useState(1) + const audioRef = useRef(null) + + useEffect(() => { + if (playlistId) { + fetchPlaylistSongs(playlistId) + } + }, [playlistId]) + + useEffect(() => { + const audio = audioRef.current + if (!audio) return + + const updateTime = () => setCurrentTime(audio.currentTime) + audio.addEventListener('timeupdate', updateTime) + audio.addEventListener('ended', playNext) + + return () => { + audio.removeEventListener('timeupdate', updateTime) + audio.removeEventListener('ended', playNext) + } + }, []) + + useEffect(() => { + if (audioRef.current) { + audioRef.current.volume = volume + } + }, [volume]) + + const fetchPlaylistSongs = async (id: string) => { + try { + const response = await fetch(`/api/playlists/${id}/songs`) + if (response.ok) { + const data = await response.json() + setSongs(data) + } else { + console.error('Failed to fetch playlist songs') + } + } catch (error) { + console.error('Error fetching playlist songs:', error) + } + } + + const togglePlay = () => { + if (audioRef.current) { + if (isPlaying) { + audioRef.current.pause() + } else { + audioRef.current.play() + } + setIsPlaying(!isPlaying) + } + } + + const playNext = () => { + setCurrentSongIndex((prevIndex) => { + const nextIndex = (prevIndex + 1) % songs.length + if (audioRef.current) { + audioRef.current.src = songs[nextIndex].url + audioRef.current.play() + setIsPlaying(true) + } + return nextIndex + }) + } + + const playPrevious = () => { + setCurrentSongIndex((prevIndex) => { + const nextIndex = (prevIndex - 1 + songs.length) % songs.length + if (audioRef.current) { + audioRef.current.src = songs[nextIndex].url + audioRef.current.play() + setIsPlaying(true) + } + return nextIndex + }) + } + + const handleSeek = (value: number[]) => { + if (audioRef.current) { + audioRef.current.currentTime = value[0] + } + } + + const handleVolumeChange = (value: number[]) => { + setVolume(value[0]) + } + + const currentSong = songs[currentSongIndex] + + if (!playlistId || !currentSong) return null + + return ( + + + + Now Playing + + + + +
+

{currentSong.title}

+

{currentSong.artist}

+
+ +
+
+ ) +} + diff --git a/apps/mongo-mp/components/search-bar.tsx b/apps/mongo-mp/components/search-bar.tsx new file mode 100644 index 0000000..4216d77 --- /dev/null +++ b/apps/mongo-mp/components/search-bar.tsx @@ -0,0 +1,35 @@ +'use client' + +import { useState } from 'react' +import { Input } from "@/components/ui/input" +import { Button } from "@/components/ui/button" +import { Search } from 'lucide-react' + +interface SearchBarProps { + onSearch: (query: string) => void +} + +export function SearchBar({ onSearch }: SearchBarProps) { + const [query, setQuery] = useState('') + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + onSearch(query) + } + + return ( +
+ setQuery(e.target.value)} + /> + +
+ ) +} + diff --git a/apps/mongo-mp/components/song-card.tsx b/apps/mongo-mp/components/song-card.tsx new file mode 100644 index 0000000..9d63bd1 --- /dev/null +++ b/apps/mongo-mp/components/song-card.tsx @@ -0,0 +1,161 @@ +'use client' + +import { useMemo, useState } from 'react' +import { Play, Pause, Heart, Plus } from 'lucide-react' +import { Button } from "@/components/ui/button" +import { Card, CardContent } from "@/components/ui/card" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { Tag } from "@/components/tag" +import { formatDuration } from "@/lib/utils" +import { useUser } from '@/contexts/UserContext' +import { Playlist } from '@/types/playlist' +import { InfoTooltip } from "@/components/info-tooltip" + +interface SongCardProps { + id: string + title: string + artist: string + duration: number + plays?: number + tags: string[] + isPlaying: boolean + isLiked: boolean + onTogglePlay: (id: string) => void + onToggleLike: (id: string) => void + onAddToPlaylist: (songId: string, playlistId: string) => void + playlists: Playlist[] +} + +export function SongCard({ + id, + title, + artist, + duration, + plays, + tags, + isPlaying, + isLiked, + onTogglePlay, + onToggleLike, + onAddToPlaylist, + playlists +}: SongCardProps) { + const { user } = useUser() + const [likeStatus, setLikeStatus] = useState(isLiked) + + const handleTogglePlay = () => { + onTogglePlay(id) + } + + const handleToggleLike = async () => { + if (user) { + setLikeStatus(!likeStatus) + onToggleLike(id) + try { + const response = await fetch('/api/user/toggle-like', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ songId: id }), + }) + if (!response.ok) { + setLikeStatus(likeStatus) // Revert if the API call fails + throw new Error('Failed to toggle like') + } + } catch (error) { + console.error('Error toggling like:', error) + setLikeStatus(likeStatus) // Revert if there's an error + } + } + } + + const gradientStyle = useMemo(() => { + const color1 = `hsl(${Math.random() * 360}, 70%, 60%)` + const color2 = `hsl(${Math.random() * 360}, 70%, 60%)` + return { + backgroundImage: `linear-gradient(135deg, ${color1}, ${color2})` + } + }, []) + + return ( + + +
+ + + + + + + + {playlists.map((playlist) => ( + onAddToPlaylist(id, playlist._id)} + > + Add to {playlist.name} + + + ))} + + +
+
+

{title}

+

{artist}

+
+ {tags.map((tag) => ( + + ))} +
+
+ {plays !== undefined ? `${plays.toLocaleString()} plays` : 'N/A plays'} + {formatDuration(duration)} +
+
+
+
+ ) +} + diff --git a/apps/mongo-mp/components/song-list.tsx b/apps/mongo-mp/components/song-list.tsx new file mode 100644 index 0000000..677eaea --- /dev/null +++ b/apps/mongo-mp/components/song-list.tsx @@ -0,0 +1,111 @@ +'use client' + +import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area" +import { SongCard } from "@/components/song-card" +import { InfoTooltip } from "@/components/info-tooltip" +import { Song } from "@/types/song" +import { Playlist } from "@/types/playlist" +import { ChevronLeft } from 'lucide-react' +import { cn } from '@/lib/utils' +import { useState, useRef, useEffect } from 'react'; + +interface SongListProps { + genre: string + songs: Song[] + currentSong: Song | null + isPlaying: boolean + onTogglePlay: (song: Song) => void + onToggleLike: (songId: string) => void + onAddToPlaylist: (songId: string, playlistId: string) => void + userLikes: string[] + playlists: Playlist[] +} + +export function SongList({ + genre, + songs, + currentSong, + isPlaying, + onTogglePlay, + onToggleLike, + onAddToPlaylist, + userLikes, + playlists +}: SongListProps) { + const [canScrollLeft, setCanScrollLeft] = useState(false) + const scrollAreaRef = useRef(null) + + useEffect(() => { + const checkScroll = () => { + if (scrollAreaRef.current) { + setCanScrollLeft(scrollAreaRef.current.scrollLeft > 0) + } + } + + const scrollArea = scrollAreaRef.current + if (scrollArea) { + scrollArea.addEventListener('scroll', checkScroll) + // Initial check + checkScroll() + } + + return () => { + if (scrollArea) { + scrollArea.removeEventListener('scroll', checkScroll) + } + } + }, []) + + return ( +
+
+
+
+
+

+ {genre} + +

+ +
+ {songs.map((song) => ( + onTogglePlay(song)} + onToggleLike={() => onToggleLike(song._id)} + onAddToPlaylist={onAddToPlaylist} + playlists={playlists} + /> + ))} +
+ +
+ +
+
+
+ ) +} + diff --git a/apps/mongo-mp/components/suggested-songs.tsx b/apps/mongo-mp/components/suggested-songs.tsx new file mode 100644 index 0000000..13e2a7e --- /dev/null +++ b/apps/mongo-mp/components/suggested-songs.tsx @@ -0,0 +1,101 @@ +"use client" + +import { useEffect, useState } from "react" +import { SongCard } from "@/components/song-card" +import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area" +import { InfoTooltip } from "@/components/info-tooltip" +import type { Song } from "@/types/song" +import type { Playlist } from "@/types/playlist" + +interface SuggestedSongsProps { + currentSong: Song | null + isPlaying: boolean + onTogglePlay: (song: Song) => void + onToggleLike: (songId: string) => void + onAddToPlaylist: (songId: string, playlistId: string) => void + userLikes: string[] + playlists: Playlist[] +} + +export function SuggestedSongs({ + currentSong, + isPlaying, + onTogglePlay, + onToggleLike, + onAddToPlaylist, + userLikes, + playlists, +}: SuggestedSongsProps) { + const [suggestedSongs, setSuggestedSongs] = useState([]) + + useEffect(() => { + const fetchSuggestedSongs = async () => { + try { + const response = await fetch("/api/songs/suggested") + if (response.ok) { + const data = await response.json() + setSuggestedSongs(data) + } + } catch (error) { + console.error("Failed to fetch suggested songs:", error) + } + } + + fetchSuggestedSongs() + }, []) + + if (suggestedSongs.length === 0) { + return null + } + + return ( +
+

+ Suggested for You + +

+ +
+ {suggestedSongs.map((song) => ( + onTogglePlay(song)} + onToggleLike={() => onToggleLike(song._id)} + onAddToPlaylist={onAddToPlaylist} + playlists={playlists} + /> + ))} +
+ +
+
+ ) +} + diff --git a/apps/mongo-mp/components/tag.tsx b/apps/mongo-mp/components/tag.tsx new file mode 100644 index 0000000..b80c74f --- /dev/null +++ b/apps/mongo-mp/components/tag.tsx @@ -0,0 +1,14 @@ +import { Badge } from "@/components/ui/badge" + +interface TagProps { + name: string; +} + +export function Tag({ name }: TagProps) { + return ( + + {name} + + ) +} + diff --git a/apps/mongo-mp/components/ui/accordion.tsx b/apps/mongo-mp/components/ui/accordion.tsx new file mode 100644 index 0000000..24c788c --- /dev/null +++ b/apps/mongo-mp/components/ui/accordion.tsx @@ -0,0 +1,58 @@ +"use client" + +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDown } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Accordion = AccordionPrimitive.Root + +const AccordionItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AccordionItem.displayName = "AccordionItem" + +const AccordionTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + +)) +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName + +const AccordionContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +
{children}
+
+)) + +AccordionContent.displayName = AccordionPrimitive.Content.displayName + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/apps/mongo-mp/components/ui/alert-dialog.tsx b/apps/mongo-mp/components/ui/alert-dialog.tsx new file mode 100644 index 0000000..25e7b47 --- /dev/null +++ b/apps/mongo-mp/components/ui/alert-dialog.tsx @@ -0,0 +1,141 @@ +"use client" + +import * as React from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +const AlertDialog = AlertDialogPrimitive.Root + +const AlertDialogTrigger = AlertDialogPrimitive.Trigger + +const AlertDialogPortal = AlertDialogPrimitive.Portal + +const AlertDialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + +)) +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName + +const AlertDialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogHeader.displayName = "AlertDialogHeader" + +const AlertDialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogFooter.displayName = "AlertDialogFooter" + +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName + +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogDescription.displayName = + AlertDialogPrimitive.Description.displayName + +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName + +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/apps/mongo-mp/components/ui/alert.tsx b/apps/mongo-mp/components/ui/alert.tsx new file mode 100644 index 0000000..41fa7e0 --- /dev/null +++ b/apps/mongo-mp/components/ui/alert.tsx @@ -0,0 +1,59 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const alertVariants = cva( + "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)) +Alert.displayName = "Alert" + +const AlertTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertTitle.displayName = "AlertTitle" + +const AlertDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertDescription.displayName = "AlertDescription" + +export { Alert, AlertTitle, AlertDescription } diff --git a/apps/mongo-mp/components/ui/aspect-ratio.tsx b/apps/mongo-mp/components/ui/aspect-ratio.tsx new file mode 100644 index 0000000..d6a5226 --- /dev/null +++ b/apps/mongo-mp/components/ui/aspect-ratio.tsx @@ -0,0 +1,7 @@ +"use client" + +import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" + +const AspectRatio = AspectRatioPrimitive.Root + +export { AspectRatio } diff --git a/apps/mongo-mp/components/ui/avatar.tsx b/apps/mongo-mp/components/ui/avatar.tsx new file mode 100644 index 0000000..51e507b --- /dev/null +++ b/apps/mongo-mp/components/ui/avatar.tsx @@ -0,0 +1,50 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/apps/mongo-mp/components/ui/badge.tsx b/apps/mongo-mp/components/ui/badge.tsx new file mode 100644 index 0000000..690e3de --- /dev/null +++ b/apps/mongo-mp/components/ui/badge.tsx @@ -0,0 +1,37 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } + diff --git a/apps/mongo-mp/components/ui/breadcrumb.tsx b/apps/mongo-mp/components/ui/breadcrumb.tsx new file mode 100644 index 0000000..60e6c96 --- /dev/null +++ b/apps/mongo-mp/components/ui/breadcrumb.tsx @@ -0,0 +1,115 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { ChevronRight, MoreHorizontal } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Breadcrumb = React.forwardRef< + HTMLElement, + React.ComponentPropsWithoutRef<"nav"> & { + separator?: React.ReactNode + } +>(({ ...props }, ref) =>