-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2905d99
commit 86f8c9e
Showing
5 changed files
with
397 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { NextRequest, NextResponse } from "next/server"; | ||
|
||
export async function POST(request: NextRequest) { | ||
try { | ||
const { url } = await request.json(); | ||
|
||
const response = await fetch( | ||
"https://zylalabs.com/api/4117/spotify+track+download+api/4970/download", | ||
{ | ||
method: "POST", | ||
headers: { | ||
Authorization: `Bearer ${process.env.MUSIC_DOWNLOAD_KEY}`, | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ url }), | ||
}, | ||
); | ||
|
||
const data = await response.json(); | ||
return NextResponse.json(data); | ||
} catch (error) { | ||
return NextResponse.json( | ||
{ error: "Failed to download track" }, | ||
{ status: 500 }, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { NextResponse } from "next/server"; | ||
import type { NextRequest } from "next/server"; | ||
|
||
export async function POST(request: NextRequest) { | ||
try { | ||
const body = await request.json(); | ||
const { name, artists } = body; | ||
|
||
const searchResponse = await fetch( | ||
`https://api.genius.com/search?q=${encodeURIComponent( | ||
`${name} ${artists[0].name}`, | ||
)}`, | ||
{ | ||
headers: { | ||
Authorization: `Bearer ${process.env.GENIUS_ACCESS_TOKEN}`, | ||
}, | ||
}, | ||
); | ||
|
||
const searchData = await searchResponse.json(); | ||
|
||
if (!searchData.response.hits.length) { | ||
return NextResponse.json({ error: "No lyrics found" }); | ||
} | ||
|
||
const songHit = searchData.response.hits.find((hit: any) => { | ||
const result = hit.result; | ||
return ( | ||
result.title.toLowerCase().includes(name.toLowerCase()) || | ||
name.toLowerCase().includes(result.title.toLowerCase()) | ||
); | ||
}); | ||
|
||
if (!songHit) { | ||
return NextResponse.json({ error: "No matching song lyrics found" }); | ||
} | ||
|
||
const hit = songHit.result; | ||
|
||
const lyricsResponse = await fetch(hit.url); | ||
const html = await lyricsResponse.text(); | ||
|
||
const lyricsMatch = html.match( | ||
/data-lyrics-container[^>]*>([\s\S]*?)<\/div>|class="lyrics"[^>]*>([\s\S]*?)<\/div>/g, | ||
); | ||
|
||
if (!lyricsMatch) { | ||
return NextResponse.json({ | ||
lyrics: `Unable to extract lyrics automatically.\nView lyrics at: ${hit.url}`, | ||
title: hit.title, | ||
artist: hit.primary_artist.name, | ||
url: hit.url, | ||
}); | ||
} | ||
|
||
const lyrics = lyricsMatch | ||
.join("\n") | ||
.replace(/<br\s*\/?>/g, "\n") | ||
.replace(/<[^>]*>/g, "") | ||
.replace(/\n{3,}/g, "\n\n") | ||
.replace(/&/g, "&") | ||
.replace(/"/g, '"') | ||
.replace(/'/g, "'") | ||
.replace(/</g, "<") | ||
.replace(/>/g, ">") | ||
.replace(/data-lyrics-container="true" class="Lyrics-sc-[^"]*">/g, "") | ||
.replace(/\[Produced by[^\n]*\]/g, "") | ||
.trim(); | ||
|
||
return NextResponse.json({ | ||
lyrics, | ||
title: hit.title, | ||
artist: hit.primary_artist.name, | ||
url: hit.url, | ||
}); | ||
} catch (error) { | ||
console.error("Lyrics fetch error:", error); | ||
return NextResponse.json( | ||
{ error: "Failed to fetch lyrics" }, | ||
{ status: 500 }, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { NextRequest, NextResponse } from "next/server"; | ||
|
||
async function getSpotifyAccessToken() { | ||
const client_id = process.env.SPOTIFY_CLIENT_ID!; | ||
const client_secret = process.env.SPOTIFY_CLIENT_SECRET!; | ||
|
||
const response = await fetch("https://accounts.spotify.com/api/token", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
Authorization: `Basic ${Buffer.from( | ||
`${client_id}:${client_secret}`, | ||
).toString("base64")}`, | ||
}, | ||
body: new URLSearchParams({ | ||
grant_type: "client_credentials", | ||
}), | ||
}); | ||
|
||
const data = await response.json(); | ||
return data.access_token; | ||
} | ||
|
||
export async function GET(request: NextRequest) { | ||
try { | ||
const query = request.nextUrl.searchParams.get("q"); | ||
if (!query) { | ||
return NextResponse.json( | ||
{ error: "No search query provided" }, | ||
{ status: 400 }, | ||
); | ||
} | ||
|
||
const accessToken = await getSpotifyAccessToken(); | ||
|
||
const response = await fetch( | ||
`https://api.spotify.com/v1/search?q=${encodeURIComponent( | ||
query, | ||
)}&type=track&limit=5`, | ||
{ | ||
headers: { | ||
Authorization: `Bearer ${accessToken}`, | ||
}, | ||
}, | ||
); | ||
|
||
const data = await response.json(); | ||
return NextResponse.json(data); | ||
} catch (error) { | ||
return NextResponse.json( | ||
{ error: "Failed to search tracks" }, | ||
{ status: 500 }, | ||
); | ||
} | ||
} |
Oops, something went wrong.