Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions app/api/download/audio-library-ready/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { embedId3Tags } from "@/lib/embed-id3";
import { extractVideoId, getInnertube } from "@/lib/innertube";
import { fetchLyrics } from "@/lib/lyrics";
import { fetchSongMetadata } from "@/lib/metadata";
import { deezerProvider } from "@/lib/metadata/providers/deezer";
import { itunesProvider } from "@/lib/metadata/providers/itunes";
import { youtubeMusicProvider } from "@/lib/metadata/providers/youtube-music";
import { buildContentDisposition, cleanFiles, TEMP_DIR } from "@/lib/route-utils";
import { getServerConf } from "@/lib/server-conf";
import { getYtDlpFullInfo, matchSong } from "@/lib/song-matching";
Expand Down Expand Up @@ -43,9 +46,12 @@ export async function GET(request: Request) {
console.log(`[library-ready] Matched: "${match.artist}" - "${match.title}"`);

try {
const [[meta, lyrics]] = await Promise.all([
const [[meta, itunesMeta, deezerMeta, ytMusicMeta, lyrics]] = await Promise.all([
Promise.all([
fetchSongMetadata({ artist: match.artist, title: match.title }),
itunesProvider.search({ artist: match.artist, title: match.title }),
deezerProvider.search({ artist: match.artist, title: match.title }),
youtubeMusicProvider.search({ artist: match.artist, title: match.title }),
fetchLyrics({
artist: match.artist,
title: match.title,
Expand All @@ -68,12 +74,14 @@ export async function GET(request: Request) {
year: meta?.year,
trackNumber: meta?.trackNumber,
genre: meta?.genre,
coverUrl: meta?.coverUrl ?? ytThumbnail,
coverUrl: meta?.coverUrl, // provider cover only (MusicBrainz CAA or iTunes)
label: meta?.label,
};

await embedId3Tags(mp3Path, {
metadata: songMeta,
coverFallbacks: [itunesMeta?.coverUrl, deezerMeta?.coverUrl, ytMusicMeta?.coverUrl].filter(Boolean) as string[],
ytThumbnail,
sylt: lyrics?.sylt,
plainLyrics: lyrics?.plain,
lyricsLanguage: lyrics?.language,
Expand Down
2 changes: 1 addition & 1 deletion app/api/download/audio/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { NextResponse } from "next/server";
import { guardApiRequest } from "@/lib/api-guard";
import { downloadAudioWithFfmpegTags } from "@/lib/audio-convert";
import { extractVideoId, getInnertube } from "@/lib/innertube";
import { TEMP_DIR, buildContentDisposition, cleanFiles } from "@/lib/route-utils";
import { buildContentDisposition, cleanFiles, TEMP_DIR } from "@/lib/route-utils";
import { getServerConf } from "@/lib/server-conf";

export async function GET(request: Request) {
Expand Down
2 changes: 1 addition & 1 deletion app/api/download/video/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { NextResponse } from "next/server";
import { guardApiRequest } from "@/lib/api-guard";
import { extractVideoId, getInnertube } from "@/lib/innertube";
import { prisma } from "@/lib/prisma";
import { buildContentDisposition, cleanFiles, TEMP_DIR } from "@/lib/route-utils";
import { getServerConf } from "@/lib/server-conf";
import { sanitizeFilename } from "@/lib/serverUtils";
import { TEMP_DIR, buildContentDisposition, cleanFiles } from "@/lib/route-utils";
import type { FormatData, VideoData } from "@/lib/types";
import { downloadStreamsToFiles } from "@/lib/video-download";
import { getVideoFormats } from "@/lib/ytdlp-info";
Expand Down
30 changes: 12 additions & 18 deletions app/fetch/page.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,28 @@
import { CircleCheckBig } from "lucide-react";
import { Suspense } from "react";
import { GetterInput } from "@/components/custom/GetterInput";
import { SkeletonInput } from "@/components/custom/SkeletonInput";
import { VideoLoading } from "@/components/custom/VideoLoading";
import { VideoSelect } from "@/components/custom/VideoSelect";

export default async function QualityVideoSelection() {
export const metadata = {
title: "Download video",
robots: { index: false },
};

export default function QualityVideoSelection() {
return (
<>
<div className="bg-primary py-8">
<h2 className="mx-4 my-4 text-center text-5xl font-bold md:mx-auto md:w-1/3">
Download any youtube video for free !
</h2>
<div className="mx-auto my-4 flex w-1/2 flex-col justify-center md:flex-row">
<div className="mx-auto my-2 flex">
<CircleCheckBig className="my-auto mr-2" size={24} />
<p className="text-center">Unlimited downloads</p>
</div>
<div className="mx-auto my-2 flex">
<CircleCheckBig className="my-auto mr-2 " size={24} />
<p className="text-center">Ads free</p>
</div>
</div>
<section className="bg-stroy-500 px-4 py-8 md:px-14">
{/* URL recap / edit bar */}
<div className="mx-auto mb-10 max-w-5xl">
<Suspense fallback={<SkeletonInput />}>
<GetterInput />
</Suspense>
</div>

{/* Result card + format picker */}
<Suspense fallback={<VideoLoading />}>
<VideoSelect />
</Suspense>
</>
</section>
);
}
82 changes: 36 additions & 46 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@
@theme inline {
--font-satoshi: var(--font-satoshi);

/* StroyGetter petrol-blue design system */
--color-stroy-50: #E6EEF4;
--color-stroy-100: #C7D8E4;
--color-stroy-200: #9BB9CD;
--color-stroy-300: #6E99B5;
--color-stroy-400: #437B9C;
--color-stroy-500: #206083;
--color-stroy-600: #1B5273;
--color-stroy-700: #144059;
--color-stroy-800: #102F42;
--color-stroy-900: #0A1F2C;
--color-stroy-950: #081721;

--color-background: hsl(var(--background));
--color-foreground: hsl(var(--foreground));
--color-card: hsl(var(--card));
Expand Down Expand Up @@ -36,10 +49,16 @@
--radius-sm: calc(var(--radius) - 4px);
}

html {
scroll-behavior: smooth;
}

body {
font-family: sans-serif;
color: rgb(var(--foreground-rgb));
background: rgb(var(--background-rgb));
font-family: var(--font-satoshi), ui-sans-serif, system-ui, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: #102F42; /* stroy-800 — matches last content section, prevents white flash */
color: white;
}

@layer utilities {
Expand All @@ -50,71 +69,42 @@ body {

@layer base {
:root {
--foreground-rgb: 255, 255, 255;
--background-rgb: 32, 96, 131;

/* shadcn/ui tokens — kept for shadcn component compatibility */
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
/* Manually changed */
--primary: 203 61% 16%;
/* primary = stroy-500 #206083 */
--primary: 203 61% 32%;
--primary-foreground: 210 40% 98%;

--secondary: 203 61% 32%;
--secondary-foreground: 222.2 47.4% 11.2%;
/* End */
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
/* secondary = stroy-800 #102F42 */
--secondary: 203 61% 16%;
--secondary-foreground: 210 40% 98%;
--muted: 203 30% 20%;
--muted-foreground: 203 20% 60%;
--accent: 203 40% 25%;
--accent-foreground: 210 40% 98%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--border: 203 30% 25%;
--input: 203 50% 8%;
--ring: 203 61% 60%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
@apply bg-stroy-500 text-white;
}
}
Loading