maybe working?
This commit is contained in:
parent
d8f9ea6d40
commit
50329b9e4e
23
app/(app)/(profile)/[npub]/_components/Subscriptions.tsx
Normal file
23
app/(app)/(profile)/[npub]/_components/Subscriptions.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import Subscriptions from "@/containers/Subscriptions";
|
||||||
|
import Spinner from "@/components/spinner";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { NDKEvent } from "@nostr-dev-kit/ndk";
|
||||||
|
import { ReactElement } from "react";
|
||||||
|
export default function ProfileSubscriptions({ pubkey }: { pubkey: string }) {
|
||||||
|
return (
|
||||||
|
<div className="sm:md-feed-cols relative flex flex-col gap-3">
|
||||||
|
<Subscriptions
|
||||||
|
link={true}
|
||||||
|
pubkey={pubkey}
|
||||||
|
loader={() => (
|
||||||
|
<div className="center flex-col gap-y-4 pt-7 text-center">
|
||||||
|
<Spinner />
|
||||||
|
<p className="font-medium text-primary">
|
||||||
|
Fetching Subscriptions...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -8,6 +8,7 @@ import Tabs from "@/components/Tabs";
|
|||||||
import useProfile from "@/lib/hooks/useProfile";
|
import useProfile from "@/lib/hooks/useProfile";
|
||||||
import { getTwoLetters, truncateText } from "@/lib/utils";
|
import { getTwoLetters, truncateText } from "@/lib/utils";
|
||||||
import ProfileFeed from "./_components/Feed";
|
import ProfileFeed from "./_components/Feed";
|
||||||
|
import Subscriptions from "./_components/Subscriptions";
|
||||||
import { nip19 } from "nostr-tools";
|
import { nip19 } from "nostr-tools";
|
||||||
|
|
||||||
export default function ProfilePage({
|
export default function ProfilePage({
|
||||||
@ -114,7 +115,7 @@ export default function ProfilePage({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx-auto max-w-[800px] space-y-6">
|
<div className="mx-auto max-w-[800px] space-y-6">
|
||||||
<div className="flex max-w-2xl flex-col gap-5">
|
<div className="flex max-w-2xl flex-col gap-5 px-5">
|
||||||
{demo.map((e) => (
|
{demo.map((e) => (
|
||||||
<SubscriptionCard key={e.id} {...e} />
|
<SubscriptionCard key={e.id} {...e} />
|
||||||
))}
|
))}
|
||||||
@ -126,10 +127,6 @@ export default function ProfilePage({
|
|||||||
name: "feed",
|
name: "feed",
|
||||||
label: "Feed",
|
label: "Feed",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "media",
|
|
||||||
label: "Media",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "subscriptions",
|
name: "subscriptions",
|
||||||
label: "Subscriptions",
|
label: "Subscriptions",
|
||||||
@ -140,6 +137,7 @@ export default function ProfilePage({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{activeTab === "feed" ? <ProfileFeed pubkey={pubkey} /> : ""}
|
{activeTab === "feed" ? <ProfileFeed pubkey={pubkey} /> : ""}
|
||||||
|
{activeTab === "subscriptions" ? <Subscriptions pubkey={pubkey} /> : ""}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -46,7 +46,8 @@ export default function ListPage({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const noteIds = getTagsValues("e", event.tags).filter(Boolean);
|
const noteIds = getTagsValues("e", event.tags).filter(Boolean);
|
||||||
console.log("notes", event.tags);
|
console.log("notes", noteIds);
|
||||||
|
console.log("tags", event.tags);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative mx-auto max-w-5xl space-y-4 p-2 sm:p-4">
|
<div className="relative mx-auto max-w-5xl space-y-4 p-2 sm:p-4">
|
||||||
|
@ -1,18 +1,119 @@
|
|||||||
|
"use client";
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import Link from "next/link";
|
||||||
import Container from "./components/Container";
|
import Container from "./components/Container";
|
||||||
import { CardTitle, CardDescription } from "@/components/ui/card";
|
import { CardTitle, CardDescription } from "@/components/ui/card";
|
||||||
import { type Event } from "nostr-tools";
|
import { type Event } from "nostr-tools";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { useNDK } from "@/app/_providers/ndk";
|
||||||
|
import { RiArrowRightLine, RiLockLine } from "react-icons/ri";
|
||||||
|
import { decryptMessage } from "@/lib/nostr";
|
||||||
|
import { NDKUser } from "@nostr-dev-kit/ndk";
|
||||||
|
|
||||||
export default function Kind3745({ pubkey }: Event) {
|
import { EventSchema } from "@/types";
|
||||||
|
import KindCard from "@/components/KindCard";
|
||||||
|
import Spinner from "../spinner";
|
||||||
|
|
||||||
|
export default function Kind3745(props: Event) {
|
||||||
|
const { pubkey, content, id } = props;
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
const [fetchingEvent, setFetchingEvent] = useState(false);
|
||||||
|
const [decryptedEvent, setDecryptedEvent] = useState<Event>();
|
||||||
|
const { ndk } = useNDK();
|
||||||
|
useEffect(() => {
|
||||||
|
if (ndk && !fetchingEvent && !decryptedEvent) {
|
||||||
|
void handleFetchEvent();
|
||||||
|
}
|
||||||
|
}, [ndk]);
|
||||||
|
|
||||||
|
async function handleFetchEvent() {
|
||||||
|
setFetchingEvent(true);
|
||||||
|
try {
|
||||||
|
const directMessageEvent = await ndk!.fetchEvent({
|
||||||
|
kinds: [4],
|
||||||
|
authors: [pubkey],
|
||||||
|
["#e"]: [id],
|
||||||
|
});
|
||||||
|
if (directMessageEvent) {
|
||||||
|
await directMessageEvent.decrypt(
|
||||||
|
new NDKUser({ hexpubkey: pubkey }),
|
||||||
|
ndk?.signer,
|
||||||
|
);
|
||||||
|
const passphrase = directMessageEvent.content;
|
||||||
|
if (!passphrase) {
|
||||||
|
setError("Unable to parse event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const decrypedData = await decryptMessage(content, passphrase);
|
||||||
|
console.log("Decrypted", decrypedData);
|
||||||
|
const hiddenEvent = EventSchema.safeParse(
|
||||||
|
JSON.parse(decrypedData ?? ""),
|
||||||
|
);
|
||||||
|
if (hiddenEvent.success) {
|
||||||
|
setDecryptedEvent(hiddenEvent.data);
|
||||||
|
} else {
|
||||||
|
setError("Unable to parse event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setError("Unable to parse event");
|
||||||
|
} finally {
|
||||||
|
setFetchingEvent(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (decryptedEvent) {
|
||||||
|
return <KindCard {...decryptedEvent} />;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Container pubkey={pubkey}>
|
<Container pubkey={pubkey}>
|
||||||
|
<div className="relative ">
|
||||||
|
<div className=" blur">
|
||||||
<CardTitle className="mb-1.5 line-clamp-2 text-lg font-semibold">
|
<CardTitle className="mb-1.5 line-clamp-2 text-lg font-semibold">
|
||||||
The start of the Nostr revolution
|
The start of the Nostr revolution
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription className="line-clamp-4 text-sm">
|
<CardDescription className="line-clamp-4 text-sm">
|
||||||
This is the summary of this artilce. Let's hope that it is a good
|
Here is some secret text. If you are reading this, that means you've
|
||||||
article and that it will end up being worth reading. I don't want to
|
tried some sneaky css tricks to reveal what was hidden 🫣.
|
||||||
waste my time on some random other stuff.
|
Unfourtunatly, CSS won't be able to help you here. In fact, I can't
|
||||||
|
even reveal this if I wanted to. Only the correct private key can
|
||||||
|
reveal it.
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
<div className="center absolute inset-0">
|
||||||
|
{fetchingEvent ? (
|
||||||
|
<div className="center">
|
||||||
|
<Spinner />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Link href={`/`} className="group flex rounded-md shadow-sm">
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex w-14 flex-shrink-0 items-center justify-center rounded-l-md bg-primary text-sm font-medium text-background",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<RiLockLine className="h-5 w-5" aria-hidden="true" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-1 items-center justify-between truncate rounded-r-md border border-b border-r border-t bg-background">
|
||||||
|
<div className="flex-1 truncate px-4 py-2 text-sm">
|
||||||
|
<a className="font-medium text-foreground group-hover:text-primary">
|
||||||
|
Content locked
|
||||||
|
</a>
|
||||||
|
<p className="text-gray-500">Subscribe to reveal</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex-shrink-0 pr-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="inline-flex h-8 w-8 items-center justify-center rounded-full text-muted-foreground group-hover:text-primary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
||||||
|
>
|
||||||
|
<span className="sr-only">Open options</span>
|
||||||
|
<RiArrowRightLine className="h-5 w-5" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -60,10 +60,12 @@ export default function Container({
|
|||||||
<CardContent className="flex grow flex-col px-4 pb-3">
|
<CardContent className="flex grow flex-col px-4 pb-3">
|
||||||
{children}
|
{children}
|
||||||
<div className="mt-auto">
|
<div className="mt-auto">
|
||||||
{!!contentTags?.length && (
|
{!!contentTags?.length ? (
|
||||||
<div className="mb-2.5 mt-1 max-h-[52px] overflow-hidden">
|
<div className="mb-2.5 mt-1 max-h-[52px] overflow-hidden">
|
||||||
<Tags tags={contentTags} />
|
<Tags tags={contentTags} />
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="h-1.5" />
|
||||||
)}
|
)}
|
||||||
<div className="border-t">
|
<div className="border-t">
|
||||||
<Actions />
|
<Actions />
|
||||||
|
@ -77,7 +77,7 @@ export default function ShortTextNoteModal() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log("about to create private event with ", listSigner);
|
||||||
const result = await createEventHandler(
|
const result = await createEventHandler(
|
||||||
ndk,
|
ndk,
|
||||||
{
|
{
|
||||||
|
61
containers/Subscriptions/index.tsx
Normal file
61
containers/Subscriptions/index.tsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
"use client";
|
||||||
|
import KindCard from "@/components/KindCard";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import Link from "next/link";
|
||||||
|
import Spinner from "@/components/spinner";
|
||||||
|
import { Event } from "nostr-tools";
|
||||||
|
import useEvents from "@/lib/hooks/useEvents";
|
||||||
|
import NDK, { NDKEvent, type NDKFilter } from "@nostr-dev-kit/ndk";
|
||||||
|
import ListCard from "@/components/ListCard";
|
||||||
|
|
||||||
|
type SubscriptionsProps = {
|
||||||
|
pubkey: string;
|
||||||
|
link?: boolean;
|
||||||
|
className?: string;
|
||||||
|
loader?: () => JSX.Element;
|
||||||
|
empty?: () => JSX.Element;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Subscriptions({
|
||||||
|
pubkey,
|
||||||
|
link = false,
|
||||||
|
className,
|
||||||
|
loader: Loader,
|
||||||
|
empty: Empty,
|
||||||
|
}: SubscriptionsProps) {
|
||||||
|
const { events, isLoading } = useEvents({
|
||||||
|
filter: {
|
||||||
|
kinds: [30001],
|
||||||
|
["#p"]: [pubkey],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (isLoading) {
|
||||||
|
if (Loader) {
|
||||||
|
return <Loader />;
|
||||||
|
}
|
||||||
|
return <Spinner />;
|
||||||
|
}
|
||||||
|
if (Empty && events.length === 0) {
|
||||||
|
return <Empty />;
|
||||||
|
}
|
||||||
|
if (link) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{events.map((e) => {
|
||||||
|
return (
|
||||||
|
<Link href={`/list/${e.encode()}`}>
|
||||||
|
<ListCard key={e.id} event={e} />;
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{events.map((e) => {
|
||||||
|
return <ListCard key={e.id} event={e} />;
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -58,7 +58,7 @@ export async function createEventHandler(
|
|||||||
}
|
}
|
||||||
const eventToPublish = new NDKEvent(ndk, {
|
const eventToPublish = new NDKEvent(ndk, {
|
||||||
...event,
|
...event,
|
||||||
tags: [...event.tags, ["client", "ordstr"]],
|
tags: [...event.tags, ["client", "flockstr"]],
|
||||||
pubkey,
|
pubkey,
|
||||||
created_at: unixTimeNowInSeconds(),
|
created_at: unixTimeNowInSeconds(),
|
||||||
} as NostrEvent);
|
} as NostrEvent);
|
||||||
@ -68,20 +68,27 @@ export async function createEventHandler(
|
|||||||
let publishedEvent: NDKEvent | null = null;
|
let publishedEvent: NDKEvent | null = null;
|
||||||
// Check if is private event
|
// Check if is private event
|
||||||
if (isPrivate) {
|
if (isPrivate) {
|
||||||
|
console.log("isPrivate");
|
||||||
const rawEventString = JSON.stringify(eventToPublish.rawEvent());
|
const rawEventString = JSON.stringify(eventToPublish.rawEvent());
|
||||||
|
console.log("rawEventString", rawEventString);
|
||||||
const passphrase = generateRandomString();
|
const passphrase = generateRandomString();
|
||||||
|
console.log("passphrase", passphrase);
|
||||||
const encryptedRawEventString = await encryptMessage(
|
const encryptedRawEventString = await encryptMessage(
|
||||||
rawEventString,
|
rawEventString,
|
||||||
passphrase,
|
passphrase,
|
||||||
);
|
);
|
||||||
|
console.log("encryptedRawEventString", encryptedRawEventString);
|
||||||
|
console.log("delegateSigner", delegateSigner);
|
||||||
const signer = delegateSigner ?? ndk.signer!;
|
const signer = delegateSigner ?? ndk.signer!;
|
||||||
const user = await signer.user();
|
const user = await signer.user();
|
||||||
|
console.log("signer user", user);
|
||||||
|
|
||||||
const newEvent = new NDKEvent(ndk, {
|
const newEvent = new NDKEvent(ndk, {
|
||||||
content: encryptedRawEventString,
|
content: encryptedRawEventString,
|
||||||
kind: 3745,
|
kind: 3745,
|
||||||
tags: [
|
tags: [
|
||||||
["kind", event.kind.toString()],
|
["kind", event.kind.toString()],
|
||||||
["client", "ordstr"],
|
["client", "flockstr"],
|
||||||
],
|
],
|
||||||
pubkey: user.pubkey,
|
pubkey: user.pubkey,
|
||||||
} as NostrEvent);
|
} as NostrEvent);
|
||||||
@ -98,7 +105,7 @@ export async function createEventHandler(
|
|||||||
tags: [
|
tags: [
|
||||||
["p", subscriber],
|
["p", subscriber],
|
||||||
["e", newEvent.id],
|
["e", newEvent.id],
|
||||||
["client", "ordstr"],
|
["client", "flockstr"],
|
||||||
],
|
],
|
||||||
pubkey: user.pubkey,
|
pubkey: user.pubkey,
|
||||||
} as NostrEvent);
|
} as NostrEvent);
|
||||||
@ -141,7 +148,7 @@ export async function createEncryptedEventOnPrivateList(
|
|||||||
}
|
}
|
||||||
const eventToPublish = new NDKEvent(ndk, {
|
const eventToPublish = new NDKEvent(ndk, {
|
||||||
...event,
|
...event,
|
||||||
tags: [...event.tags, ["client", "ordstr"]],
|
tags: [...event.tags, ["client", "flockstr"]],
|
||||||
pubkey,
|
pubkey,
|
||||||
created_at: unixTimeNowInSeconds(),
|
created_at: unixTimeNowInSeconds(),
|
||||||
} as NostrEvent);
|
} as NostrEvent);
|
||||||
@ -160,7 +167,7 @@ export async function createEncryptedEventOnPrivateList(
|
|||||||
kind: 3745,
|
kind: 3745,
|
||||||
tags: [
|
tags: [
|
||||||
["kind", event.kind.toString()],
|
["kind", event.kind.toString()],
|
||||||
["client", "ordstr"],
|
["client", "flockstr"],
|
||||||
],
|
],
|
||||||
pubkey: user.pubkey,
|
pubkey: user.pubkey,
|
||||||
} as NostrEvent);
|
} as NostrEvent);
|
||||||
@ -186,7 +193,7 @@ export async function createEncryptedEventOnPrivateList(
|
|||||||
tags: [
|
tags: [
|
||||||
["p", subscriber],
|
["p", subscriber],
|
||||||
["e", newEvent.id],
|
["e", newEvent.id],
|
||||||
["client", "ordstr"],
|
["client", "flockstr"],
|
||||||
],
|
],
|
||||||
pubkey: user.hexpubkey,
|
pubkey: user.hexpubkey,
|
||||||
} as NostrEvent);
|
} as NostrEvent);
|
||||||
|
@ -103,7 +103,7 @@ async function generateTags(mainSigner: NDKSigner, opts: ISaveOpts = {}) {
|
|||||||
const mainUser = await mainSigner.user();
|
const mainUser = await mainSigner.user();
|
||||||
const tags = [
|
const tags = [
|
||||||
["p", mainUser.hexpubkey],
|
["p", mainUser.hexpubkey],
|
||||||
["client", "ordstr"],
|
["client", "flockstr"],
|
||||||
];
|
];
|
||||||
|
|
||||||
if (opts.associatedEvent) {
|
if (opts.associatedEvent) {
|
||||||
|
@ -119,6 +119,7 @@ export function encryptMessage(message: string, password: string) {
|
|||||||
}
|
}
|
||||||
// Function to decrypt a hashed message using a passphrase
|
// Function to decrypt a hashed message using a passphrase
|
||||||
export function decryptMessage(encryptedMessage: string, password: string) {
|
export function decryptMessage(encryptedMessage: string, password: string) {
|
||||||
|
console.log("Attemping decrypto", encryptedMessage, "with", password);
|
||||||
try {
|
try {
|
||||||
const buffer = create32ByteBuffer(password);
|
const buffer = create32ByteBuffer(password);
|
||||||
// Extract IV from the received message
|
// Extract IV from the received message
|
||||||
@ -130,11 +131,15 @@ export function decryptMessage(encryptedMessage: string, password: string) {
|
|||||||
const iv = Buffer.from(ivBase64, "base64");
|
const iv = Buffer.from(ivBase64, "base64");
|
||||||
|
|
||||||
const encryptedText = Buffer.from(encryptedMessage, "base64");
|
const encryptedText = Buffer.from(encryptedMessage, "base64");
|
||||||
|
console.log("at bugger");
|
||||||
const decipher = crypto.createDecipheriv("aes-256-cbc", buffer, iv);
|
const decipher = crypto.createDecipheriv("aes-256-cbc", buffer, iv);
|
||||||
|
console.log("at decipher");
|
||||||
|
|
||||||
const decrypted = decipher.update(encryptedText);
|
const decrypted = decipher.update(encryptedText);
|
||||||
return Buffer.concat([decrypted, decipher.final()]).toString();
|
|
||||||
|
const toReturn = Buffer.concat([decrypted, decipher.final()]).toString();
|
||||||
|
console.log("toReturn", toReturn);
|
||||||
|
return toReturn;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"cmdk": "^0.2.0",
|
"cmdk": "^0.2.0",
|
||||||
|
"crypto": "^1.0.1",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"focus-trap-react": "^10.2.3",
|
"focus-trap-react": "^10.2.3",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user