Compare commits

...

10 Commits

Author SHA1 Message Date
zmeyer44
b2dfaa18d1
Merge pull request #16 from tyiu/nip52-updates
Fix RSVPs to use status tag instead of deprecated generic l tag
2024-10-11 12:09:04 -04:00
Terry Yiu
173d5e2bf3
Fix RSVPs to use status tag instead of deprecated generic l tag 2024-08-16 10:55:36 -04:00
zmeyer44
d820d33af0 testing again 2024-05-08 06:51:50 -04:00
zmeyer44
ff6ebb349e crash fix 2024-05-07 20:46:50 -04:00
zmeyer44
866628501c usign title instead of name 2024-04-27 13:28:53 -04:00
zmeyer44
fe66367c1b version changes 2024-01-11 16:10:30 +00:00
zmeyer44
6719fef9e9 test 2024-01-11 16:08:44 +00:00
zmeyer44
c0ac236a5f changign build command 2024-01-11 16:05:49 +00:00
zmeyer44
401d7cdcfe updating schema 2024-01-11 15:52:43 +00:00
zmeyer44
753210b6b2 improving meta tags 2024-01-11 15:47:19 +00:00
15 changed files with 124 additions and 36 deletions

View File

@ -1,18 +1,31 @@
import type { Metadata, ResolvingMetadata } from "next";
import { get } from "@/lib/server-actions/events/cache";
import { getEvent } from "@/lib/server-actions/meta/event";
import { nip19 } from "nostr-tools";
import { getTagValues } from "@/lib/nostr/utils";
export async function generateMetadata(
{ params }: { params: { naddr: string } },
parent: ResolvingMetadata,
): Promise<Metadata> {
const previousImages = (await parent).openGraph?.images || [];
// read route params
const identifier = params.naddr;
const { data, type } = nip19.decode(identifier);
if (type !== "naddr") {
return {
title: "Flockstr Calendar",
openGraph: {
images: previousImages,
},
};
}
// fetch data
const event = await get(identifier);
const event = await getEvent(data.kind, data.pubkey, data.identifier);
// optionally access and extend (rather than replace) parent metadata
const previousImages = (await parent).openGraph?.images || [];
if (!event) {
return {
title: "Flockstr Calendar",
@ -21,21 +34,24 @@ export async function generateMetadata(
},
};
}
const title = `${event.name} | Flockstr`;
const images = event.image
? [event.image, ...previousImages]
: previousImages;
const title = `${getTagValues("name", event.tags as string[][])} | Flockstr`;
const images =
getTagValues("image", event.tags as string[][]) ??
getTagValues("banner", event.tags as string[][]) ??
"";
return {
title: title,
description: event.description,
description: event.content,
openGraph: {
title: title,
description: event.description,
description: event.content,
images: images,
},
twitter: {
title: title,
description: event.description,
description: event.content,
images: images,
card: "summary_large_image",
},

View File

@ -45,7 +45,7 @@ export default function Header({ event }: { event: NDKEvent }) {
const { pubkey, tags } = event;
const { profile } = useProfile(pubkey);
const eventReference = event.tagId();
const title = getTagValues("name", tags) ?? "Untitled";
const title = getTagValues("title", tags) ?? "Untitled";
const image =
getTagValues("image", tags) ??
getTagValues("picture", tags) ??

View File

@ -29,7 +29,7 @@ export default function RSVPButton({ event }: RSVPButtonProps) {
const { currentUser } = useCurrentUser();
const { ndk } = useNDK();
const eventReference = event.tagId();
const name = getTagValues("name", event.tags);
const name = getTagValues("title", event.tags);
const tickets = getTagValues("tickets", event.tags);
const price = getTagAllValues("price", event.tags);
const priceInBTC = parseFloat(getTagValues("price", event.tags) ?? "0");
@ -88,13 +88,14 @@ export default function RSVPButton({ event }: RSVPButtonProps) {
if (!tickets) {
if (rsvpEvent) {
const rsvpResponse = getTagValues("l", rsvpEvent.tags);
const rsvpResponse = getTagValues("status", rsvpEvent.tags);
const rsvpResponseDeprecated = getTagValues("l", rsvpEvent.tags);
return (
<div className="flex items-center gap-2">
<Button disabled>
{rsvpResponse === "accepted"
{rsvpResponse === "accepted" || rsvpResponseDeprecated === "accepted"
? "Going"
: rsvpResponse === "tentative"
: rsvpResponse === "tentative" || rsvpResponseDeprecated === "tentative"
? "Tentative"
: "Not Going"}
</Button>

View File

@ -1,18 +1,29 @@
import type { Metadata, ResolvingMetadata } from "next";
import { get } from "@/lib/server-actions/events/cache";
import { getEvent } from "@/lib/server-actions/meta/event";
import { nip19 } from "nostr-tools";
import { getTagValues } from "@/lib/nostr/utils";
export async function generateMetadata(
{ params }: { params: { naddr: string } },
parent: ResolvingMetadata,
): Promise<Metadata> {
const previousImages = (await parent).openGraph?.images || [];
// read route params
const identifier = params.naddr;
const { data, type } = nip19.decode(identifier);
if (type !== "naddr") {
return {
title: "Flockstr Event",
openGraph: {
images: previousImages,
},
};
}
// fetch data
const event = await get(identifier);
const event = await getEvent(data.kind, data.pubkey, data.identifier);
// optionally access and extend (rather than replace) parent metadata
const previousImages = (await parent).openGraph?.images || [];
if (!event) {
return {
title: "Flockstr Event",
@ -21,22 +32,25 @@ export async function generateMetadata(
},
};
}
const title = `${event.name} | Flockstr`;
const images = event.image
? [event.image, ...previousImages]
: previousImages;
const title = `${getTagValues("title", event.tags as string[][])} | Flockstr`;
const images =
getTagValues("image", event.tags as string[][]) ??
getTagValues("banner", event.tags as string[][]) ??
"";
return {
title: title,
description: event.description,
description: event.content,
openGraph: {
title: title,
description: event.description,
images: images,
description: event.content,
images: [images],
},
twitter: {
title: title,
description: event.description,
images: images,
description: event.content,
images: [images],
card: "summary_large_image",
},
};

View File

@ -44,7 +44,7 @@ export default function EventPage({
useEffect(() => {
if (event) {
const { tags, content } = event;
const name = getTagValues("name", tags) ?? "Untitled";
const name = getTagValues("title", tags) ?? "Untitled";
const image =
getTagValues("image", tags) ??
getTagValues("picture", tags) ??

BIN
bun.lockb

Binary file not shown.

View File

@ -57,7 +57,7 @@ export default function CreateCalendarEventModal() {
}
if (!name) {
setError("Please add a title");
setError("Please add a name");
return;
}
setIsLoading(true);

View File

@ -120,7 +120,7 @@ export default function CreateCalendarEventModal({
const random = randomId();
const tags: string[][] = [
["d", random],
["name", title],
["title", title],
["description", description],
["start", toUnix(convertToTimezone(startDate, timezone)).toString()],
["end", toUnix(convertToTimezone(endDate, timezone)).toString()],

View File

@ -41,8 +41,7 @@ export default function RSVPModal({ eventReference }: RSVPModalProps) {
const tags: string[][] = [
["d", random],
["a", eventReference],
["L", "status"],
["l", statusMap[type], "status"],
["status", statusMap[type]],
];
const event = await createEvent(ndk, {
content: "",

View File

@ -44,8 +44,8 @@ export default function AvatarStack({
}
function User({ pubkey, className }: { pubkey: string; className: string }) {
const { profile } = useProfile(pubkey);
const npub = nip19.npubEncode(pubkey);
const { profile, npub } = useProfile(pubkey);
// const npub = profilenip19.npubEncode(pubkey);
return (
<Avatar

11
db/client.ts Normal file
View File

@ -0,0 +1,11 @@
import { PrismaClient } from "@prisma/client";
declare global {
var prisma: PrismaClient | undefined;
}
const prisma = global.prisma || new PrismaClient();
if (process.env.NODE_ENV === "development") global.prisma = prisma;
export default prisma;

View File

@ -7,7 +7,7 @@ import { type NDKUserProfile } from "@nostr-dev-kit/ndk";
export default function useProfile(key: string) {
const { ndk, getProfile } = useNDK();
const npub = key.length === 64 ? nip19.npubEncode(key) : key;
useEffect(() => {
if (!ndk) return;
if (NOSTR_BECH32_REGEXP.test(key)) {
@ -20,5 +20,5 @@ export default function useProfile(key: string) {
};
}, [key, ndk]);
return { profile: getProfile(key) };
return { profile: getProfile(key), npub: npub };
}

View File

@ -0,0 +1,12 @@
"use server";
import prisma from "@/db/client";
export async function getEvent(kind: number, pubkey: string, d: string) {
return await prisma.nostrEvent.findFirst({
where: {
kind,
pubkey,
d,
},
});
}

View File

@ -4,7 +4,7 @@
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"build": "prisma generate && next build",
"start": "next start",
"lint": "next lint"
},
@ -17,6 +17,7 @@
"@nostr-dev-kit/ndk": "^2.0.0",
"@nostr-dev-kit/ndk-cache-dexie": "^2.0.3",
"@nostr-dev-kit/ndk-react": "^0.1.1",
"@prisma/client": "^5.7.1",
"@radix-ui/react-aspect-ratio": "^1.0.3",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",
@ -88,6 +89,7 @@
"postcss": "^8",
"prettier": "^3.0.3",
"prettier-plugin-tailwindcss": "^0.5.6",
"prisma": "^5.7.1",
"tailwindcss": "^3",
"typescript": "^5",
"webln": "^0.3.2"

33
prisma/schema.prisma Normal file
View File

@ -0,0 +1,33 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// datasource db {
// provider = "postgresql"
// url = env("POSTGRES_PRISMA_URL") // uses connection pooling
// directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection
// }
// generator client {
// provider = "prisma-client-js"
// }
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
generator client {
provider = "prisma-client-js"
}
model NostrEvent {
key Int @id @default(autoincrement())
id String
kind Int
content String @db.Text
created_at Int
pubkey String
tags Json @default("[]")
sig String
d String?
}