Skip to content
This repository was archived by the owner on May 6, 2025. It is now read-only.

Commit a116b0c

Browse files
author
Naya Singhania
committed
finish refresh
1 parent 43c527a commit a116b0c

40 files changed

+2395
-62
lines changed

app/api/auth/callback/route.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import crypto from "crypto";
22
import { redirect } from "next/navigation";
33
import { cookies } from "next/headers";
4+
import { db } from "@/db";
5+
import { InsertUser, users } from "@/db/schema";
46

57
export async function GET(request: Request) {
68
const cookieStore = await cookies();
@@ -25,6 +27,10 @@ export async function GET(request: Request) {
2527
.then((data) => {
2628
cookieStore.set("username", data.session.name);
2729
cookieStore.set("session", data.session.key);
30+
const values: InsertUser = {
31+
username: data.session.name,
32+
};
33+
return db.insert(users).values(values);
2834
})
2935
.catch((error) => {
3036
console.log(error);

app/api/auth/delete/route.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { db } from "@/db";
2+
import { users } from "@/db/schema";
3+
import { eq } from "drizzle-orm";
4+
import { redirect } from "next/navigation";
5+
import { cookies } from "next/headers";
6+
7+
export async function GET() {
8+
const cookieStore = await cookies();
9+
const username = cookieStore.get("username")?.value || "";
10+
await db.delete(users).where(eq(users.username, username));
11+
cookieStore.set("username", "", { maxAge: 0 });
12+
cookieStore.set("session", "", { maxAge: 0 });
13+
redirect('/')
14+
}

app/api/auth/logout/route.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { redirect } from "next/navigation";
2+
import { cookies } from "next/headers";
3+
4+
export async function GET() {
5+
const cookieStore = await cookies();
6+
cookieStore.set("username", "", { maxAge: 0 });
7+
cookieStore.set("session", "", { maxAge: 0 });
8+
redirect("/");
9+
}

app/api/persona/route.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
12
import { cookies } from "next/headers";
23
import OpenAI from "openai";
34
import { zodResponseFormat } from "openai/helpers/zod";
45
import { z } from "zod";
56
import fs from "fs";
67
import path from "path";
8+
import { InsertPersona, personas } from "@/db/schema";
9+
import { db } from "@/db";
10+
import { eq } from "drizzle-orm";
711

812
const openai = new OpenAI();
913

@@ -65,11 +69,39 @@ export async function POST() {
6569
});
6670
})
6771
.then((res) => {
68-
vibe = res.choices[0].message.content;
69-
});
72+
vibe = res.choices[0].message.content || "";
73+
const parsedVibe = JSON.parse(vibe.toString());
74+
const data: InsertPersona = {
75+
username: username.toString(),
76+
vibe: parsedVibe.vibe,
77+
mainstream_description: parsedVibe.mainstream.description,
78+
mainstream_percent: parsedVibe.mainstream.percent,
79+
energetic_description: parsedVibe.energetic.description,
80+
energetic_percent: parsedVibe.energetic.percent,
81+
};
82+
return db.insert(personas).values(data);
83+
})
84+
.catch((error) => console.log(error));
7085

7186
return new Response(JSON.stringify(vibe), {
7287
status: 200,
7388
headers: { "Content-Type": "application/json" },
7489
});
7590
}
91+
92+
export async function GET() {
93+
let result;
94+
const cookieStore = await cookies();
95+
const username = cookieStore.get("username")?.value || "";
96+
await db
97+
.select()
98+
.from(personas)
99+
.where(eq(personas.username, username))
100+
.then((response) => {
101+
result = response;
102+
})
103+
.catch((error) => {
104+
console.log(error);
105+
});
106+
return new Response(JSON.stringify(result));
107+
}

app/api/user/profile/route.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import { cookies } from "next/headers";
22

33
export async function GET() {
4-
54
const cookieStore = await cookies();
65
const username = cookieStore.get("username")?.value || "";
7-
6+
87
const params = new URLSearchParams({
98
method: "user.getInfo",
109
user: username.toString(),
@@ -15,9 +14,9 @@ export async function GET() {
1514
let userInfo;
1615

1716
await fetch(`https://ws.audioscrobbler.com/2.0/?${params.toString()}`)
18-
.then((response) => response.json())
19-
.then((data) => {
20-
userInfo = data.user
21-
})
22-
return new Response(JSON.stringify(userInfo))
23-
}
17+
.then((response) => response.json())
18+
.then((data) => {
19+
userInfo = data.user;
20+
});
21+
return new Response(JSON.stringify(userInfo));
22+
}

app/contact/layout.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Metadata } from "next";
2+
3+
export const metadata: Metadata = {
4+
title: "Contact",
5+
};
6+
7+
export default function Layout({ children }: { children: React.ReactNode }) {
8+
return <div>{children}</div>;
9+
}

app/favicon.ico

-25.3 KB
Binary file not shown.

app/home/layout.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Metadata } from "next";
2+
3+
export const metadata: Metadata = {
4+
title: "Home",
5+
};
6+
7+
export default function Layout({ children }: { children: React.ReactNode }) {
8+
return <div>{children}</div>;
9+
}

app/home/page.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@ import Persona from "@/components/persona";
33
export default function Page() {
44
return (
55
<div className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8 px-4">
6-
<h2 className="text-2xl font-semibold mb-6 text-center">
6+
<h2 className="text-2xl font-semibold mb-6 border-none">
77
Welcome back, raspberri05!
88
</h2>
9-
10-
<div className="flex flex-col items-center space-y-6 ">
11-
<Persona />
12-
</div>
9+
<Persona />
1310
</div>
1411
);
1512
}

app/icon.svg

Lines changed: 4 additions & 0 deletions
Loading

app/layout.tsx

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@ import { ThemeProvider } from "@/components/theme-provider";
44
import ModeToggle from "@/components/mode-toggle";
55
import Nav from "@/components/nav";
66
import Footer from "@/components/footer";
7+
import Script from "next/script";
78

89
export const metadata: Metadata = {
9-
title: "Persona.fm",
10-
description: "Generated by create next app",
10+
title: {
11+
template: "%s | Persona.fm",
12+
default: "Persona.fm",
13+
},
14+
description:
15+
"Persona.fm is a new web application that uses the Last.fm API to give users insights into their music listening habits via AI-generated listening personas",
1116
};
1217

1318
export default function RootLayout({
@@ -17,6 +22,30 @@ export default function RootLayout({
1722
}>) {
1823
return (
1924
<html lang="en" suppressHydrationWarning>
25+
<head>
26+
<link
27+
rel="preconnect"
28+
href="https://www.googletagmanager.com"
29+
/>
30+
<link
31+
rel="preconnect"
32+
href="https://www.google-analytics.com"
33+
/>
34+
</head>
35+
<Script
36+
async
37+
src="https://www.googletagmanager.com/gtag/js?id=G-5C6EN7BR23"
38+
strategy="lazyOnload"
39+
></Script>
40+
<Script id="google-analytics" strategy="lazyOnload">
41+
{`
42+
window.dataLayer = window.dataLayer || [];
43+
function gtag(){dataLayer.push(arguments);}
44+
gtag('js', new Date());
45+
46+
gtag('config', 'G-5C6EN7BR23');
47+
`}
48+
</Script>
2049
<body>
2150
<ThemeProvider
2251
attribute="class"

app/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export default function Page() {
1111
Transform your Last.fm listening history into a unique
1212
musical personality.
1313
</p>
14+
<br />
1415
<LogInButton />
1516
</div>
1617
</div>

app/privacy/layout.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Metadata } from "next";
2+
3+
export const metadata: Metadata = {
4+
title: "Privacy",
5+
};
6+
7+
export default function Layout({ children }: { children: React.ReactNode }) {
8+
return <div>{children}</div>;
9+
}

app/robots.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { MetadataRoute } from "next";
2+
3+
export default function robots(): MetadataRoute.Robots {
4+
return {
5+
rules: {
6+
userAgent: "*",
7+
allow: "/",
8+
},
9+
sitemap: "https://personafm.com/sitemap.xml",
10+
};
11+
}

app/settings/layout.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Metadata } from "next";
2+
3+
export const metadata: Metadata = {
4+
title: "Settings",
5+
};
6+
7+
export default function Layout({ children }: { children: React.ReactNode }) {
8+
return <div>{children}</div>;
9+
}

app/sitemap.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import type { MetadataRoute } from "next";
2+
3+
export default function sitemap(): MetadataRoute.Sitemap {
4+
return [
5+
{
6+
url: "https://personafm.com",
7+
lastModified: new Date(),
8+
changeFrequency: "weekly",
9+
priority: 1,
10+
},
11+
{
12+
url: "https://personafm.com/contact",
13+
lastModified: new Date(),
14+
changeFrequency: "monthly",
15+
priority: 0.8,
16+
},
17+
{
18+
url: "https://personafm.com/terms",
19+
lastModified: new Date(),
20+
changeFrequency: "monthly",
21+
priority: 0.5,
22+
},
23+
{
24+
url: "https://personafm.com/privacy",
25+
lastModified: new Date(),
26+
changeFrequency: "monthly",
27+
priority: 0.5,
28+
},
29+
];
30+
}

app/terms/layout.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Metadata } from "next";
2+
3+
export const metadata: Metadata = {
4+
title: "Terms",
5+
};
6+
7+
export default function Layout({ children }: { children: React.ReactNode }) {
8+
return <div>{children}</div>;
9+
}

components/delete-button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function DeleteAccountButton() {
1717
const [isOpen, setIsOpen] = useState(false);
1818

1919
const handleDeleteAccount = async () => {
20-
window.location.href = "/";
20+
window.location.href = "/api/auth/delete";
2121
};
2222

2323
return (

components/footer.tsx

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,22 @@ export default function Footer() {
1010
<Link href="/" className="flex items-center">
1111
<span className="sr-only">Persona.fm</span>
1212
<svg
13-
className="h-8 w-auto"
14-
viewBox="0 0 24 24"
13+
width="24"
14+
height="24"
15+
viewBox="0 0 100 100"
1516
fill="none"
16-
stroke="currentColor"
17-
strokeWidth="2"
18-
strokeLinecap="round"
19-
strokeLinejoin="round"
17+
xmlns="http://www.w3.org/2000/svg"
2018
>
21-
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
19+
<rect
20+
width="100"
21+
height="100"
22+
rx="20"
23+
fill="#276FBF"
24+
/>
25+
<path
26+
d="M53.9375 77.4727V81H27.8105V77.4727H28.877C30.9824 77.4727 32.6504 77.0898 33.8809 76.3242C35.1387 75.5312 35.7676 73.9043 35.7676 71.4434V30.2637C35.7676 27.9121 35.125 26.3809 33.8398 25.6699C32.5547 24.9316 30.9004 24.5625 28.877 24.5625H27.8105V21.0352H51.3945C54.9219 21.0352 57.9844 21.4316 60.582 22.2246C63.1797 23.0176 65.3262 24.1797 67.0215 25.7109C70.3848 28.7187 72.0664 33.0117 72.0664 38.5898C72.0664 41.0781 71.6699 43.4707 70.877 45.7676C70.1113 48.0371 68.8398 50.0605 67.0625 51.8379C65.2852 53.5879 62.9609 54.9961 60.0898 56.0625C57.2188 57.1289 53.7051 57.6621 49.5488 57.6621H44.2578V71.8535C44.2578 74.1777 44.8867 75.6953 46.1445 76.4062C47.4023 77.1172 49.0703 77.4727 51.1484 77.4727H53.9375ZM49.959 25.0547H44.2578V53.6836H48.7285C53.8418 53.6836 57.4922 52.5488 59.6797 50.2793C61.8945 47.9824 63.002 44.1953 63.002 38.918C63.002 36.5664 62.7695 34.5293 62.3047 32.8066C61.8398 31.0566 61.0879 29.6074 60.0488 28.459C57.9707 26.1895 54.6074 25.0547 49.959 25.0547Z"
27+
fill="#D3D0CB"
28+
/>
2229
</svg>
2330
</Link>
2431
<p className="text-sm">&copy; 2024 Persona.fm</p>
@@ -51,13 +58,12 @@ export default function Footer() {
5158
</ul>
5259
</div>
5360

54-
{/* GitHub and Product Hunt Column */}
5561
<div>
5662
<h3 className="font-semibold mb-4">Connect</h3>
5763
<ul className="space-y-2">
5864
<li>
5965
<a
60-
href="https://github.com/persona-fm"
66+
href="https://github.com/personafm/persona.fm"
6167
target="_blank"
6268
rel="noopener noreferrer"
6369
className="flex items-center"
@@ -68,7 +74,7 @@ export default function Footer() {
6874
</li>
6975
<li>
7076
<a
71-
href="https://www.producthunt.com/@persona-fm"
77+
href="https://www.producthunt.com/posts/persona-fm"
7278
target="_blank"
7379
rel="noopener noreferrer"
7480
className="flex items-center"

components/log-in-button.tsx

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
1-
"use client";
2-
31
import { Button } from "@/components/ui/button";
2+
import { cookies } from "next/headers";
3+
4+
export default async function LogInButton() {
5+
const cookieStore = await cookies();
6+
const authenticated = cookieStore.has("username");
47

5-
export default function LogInButton() {
6-
function request() {
7-
window.location.href = `/api/auth/request`;
8-
}
98

109
return (
11-
<Button
12-
className="rounded-xl h-12 px-8 font-medium"
13-
size="lg"
14-
onClick={request}
15-
>
16-
Log with Last.fm
17-
</Button>
10+
<a href={authenticated ? '/home' : '/api/auth/request'}><Button
11+
className="rounded-xl h-12 px-8 font-semibold bg-red-500 hover:bg-red-600">
12+
{authenticated ? 'Go to home' : 'Log In with Last.fm'}
13+
</Button></a>
1814
);
1915
}

0 commit comments

Comments
 (0)