105 lines
3.4 KiB
TypeScript
105 lines
3.4 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { prisma } from '@/lib/prisma';
|
|
import type { ResolveShareResponse, SongShareContent, PlaylistShareContent, AlbumShareContent, ApiError, ShareType } from '@/types/api-types';
|
|
|
|
export async function GET(
|
|
request: NextRequest,
|
|
{ params }: { params: Promise<{ token: string }> }
|
|
) {
|
|
try {
|
|
const { token } = await params;
|
|
|
|
const share = await prisma.share.findUnique({
|
|
where: { token },
|
|
});
|
|
|
|
if (!share) {
|
|
return NextResponse.json<ApiError>(
|
|
{ error: 'Share not found' },
|
|
{ status: 404 }
|
|
);
|
|
}
|
|
|
|
let content: SongShareContent | PlaylistShareContent | AlbumShareContent;
|
|
|
|
if (share.type === 'SONG') {
|
|
const song = await prisma.song.findUnique({
|
|
where: { id: share.targetId },
|
|
include: { artist: true },
|
|
});
|
|
if (!song) {
|
|
return NextResponse.json<ApiError>({ error: 'Content not found' }, { status: 404 });
|
|
}
|
|
content = {
|
|
id: song.id,
|
|
title: song.title,
|
|
duration: song.duration,
|
|
coverArtUrl: song.coverUrl || '',
|
|
fileUrl: song.audioUrl,
|
|
artist: { id: song.artist.id, stage_name: song.artist.name },
|
|
};
|
|
} else if (share.type === 'PLAYLIST') {
|
|
const playlist = await prisma.playlist.findUnique({
|
|
where: { id: share.targetId },
|
|
include: {
|
|
user: true,
|
|
songs: { include: { song: { include: { artist: true } } } }
|
|
},
|
|
});
|
|
if (!playlist) {
|
|
return NextResponse.json<ApiError>({ error: 'Content not found' }, { status: 404 });
|
|
}
|
|
content = {
|
|
id: playlist.id,
|
|
name: playlist.title,
|
|
description: playlist.description || '',
|
|
coverImageUrl: playlist.coverUrl || '',
|
|
songCount: playlist.songs.length,
|
|
curator: { id: playlist.user.id, name: playlist.user.displayName || playlist.user.username },
|
|
songs: playlist.songs.map(ps => ({
|
|
id: ps.song.id,
|
|
title: ps.song.title,
|
|
duration: ps.song.duration,
|
|
cover_art_url: ps.song.coverUrl || '',
|
|
play_count: ps.song.playCount,
|
|
})),
|
|
};
|
|
} else {
|
|
const album = await prisma.album.findUnique({
|
|
where: { id: share.targetId },
|
|
include: { artist: true, songs: true },
|
|
});
|
|
if (!album) {
|
|
return NextResponse.json<ApiError>({ error: 'Content not found' }, { status: 404 });
|
|
}
|
|
content = {
|
|
id: album.id,
|
|
title: album.title,
|
|
description: album.description || '',
|
|
coverArtUrl: album.coverUrl || '',
|
|
releaseDate: album.releaseDate?.toISOString() || '',
|
|
artist: { id: album.artist.id, stage_name: album.artist.name },
|
|
songs: album.songs.map(s => ({
|
|
id: s.id,
|
|
title: s.title,
|
|
duration: s.duration,
|
|
cover_art_url: s.coverUrl || '',
|
|
play_count: s.playCount,
|
|
})),
|
|
};
|
|
}
|
|
|
|
const response: ResolveShareResponse = {
|
|
type: share.type as ShareType,
|
|
targetId: share.targetId,
|
|
content,
|
|
shareUrl: `${process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000'}/s/${token}`,
|
|
};
|
|
|
|
return NextResponse.json(response);
|
|
} catch (error) {
|
|
console.error('Resolve share error:', error);
|
|
return NextResponse.json<ApiError>({ error: 'Failed to resolve share' }, { status: 500 });
|
|
}
|
|
}
|