This is probably enough to log in?

This commit is contained in:
Alex Gleason 2023-03-04 22:10:56 -06:00
parent 7285d71bda
commit 825fed7d21
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
6 changed files with 127 additions and 2 deletions

View File

@ -1,7 +1,47 @@
import { getPublicKey } from '@/deps.ts';
import { LOCAL_DOMAIN } from '../config.ts';
import { fetchUser } from '../client.ts';
import { MetaContent, metaContentSchema } from '../schema.ts';
import type { Context } from '@/deps.ts'; import type { Context } from '@/deps.ts';
function credentialsController(c: Context) { async function credentialsController(c: Context) {
return c.json({}); const authHeader = c.req.headers.get('Authorization') || '';
if (authHeader.startsWith('Bearer ')) {
const token = authHeader.split('Bearer ')[1];
const pubkey = getPublicKey(token);
const event = await fetchUser(pubkey);
const parsed = metaContentSchema.safeParse(JSON.parse(event?.content || ''));
const content: MetaContent = parsed.success ? parsed.data : {};
const { host, origin } = new URL(LOCAL_DOMAIN);
return c.json({
id: pubkey,
acct: pubkey,
avatar: content.picture,
avatar_static: content.picture,
bot: false,
created_at: event ? new Date(event.created_at * 1000).toISOString() : new Date().toISOString(),
display_name: content.name,
emojis: [],
fields: [],
follow_requests_count: 0,
followers_count: 0,
following_count: 0,
statuses_count: 0,
header: content.banner,
header_static: content.banner,
locked: false,
note: content.about,
fqn: `${pubkey}@${host}`,
url: `${origin}/users/${pubkey}`,
username: pubkey,
});
}
return c.json({ error: 'Invalid token' }, 400);
} }
export { credentialsController }; export { credentialsController };

37
src/client.ts Normal file
View File

@ -0,0 +1,37 @@
import { Author, RelayPool } from '@/deps.ts';
import { poolRelays } from './config.ts';
import type { Event } from './event.ts';
const pool = new RelayPool(poolRelays);
/** Fetch a Nostr event by its ID. */
const fetchEvent = async (id: string): Promise<Event | null> => {
const event = await (pool.getEventById(id, poolRelays, 0) as Promise<Event>);
return event?.id === id ? event : null;
};
/** Fetch a Nostr `set_medatadata` event for a user's pubkey. */
const fetchUser = async (pubkey: string): Promise<Event<0> | null> => {
const author = new Author(pool, poolRelays, pubkey);
const event: Event<0> | null = await new Promise((resolve) => author.metaData(resolve, 0));
return event?.pubkey === pubkey ? event : null;
};
/** Fetch users the given pubkey follows. */
const fetchFollows = (pubkey: string): Promise<Event<3> | null> => {
return new Promise((resolve) => {
pool.subscribe(
[{ authors: [pubkey], kinds: [3] }],
poolRelays,
(event: Event<3> | null) => {
resolve(event?.pubkey === pubkey ? event : null);
},
undefined,
undefined,
);
});
};
export { fetchEvent, fetchFollows, fetchUser };

View File

@ -1,2 +1,4 @@
export const LOCAL_DOMAIN = Deno.env.get('LOCAL_DOMAIN') || 'http://localhost:8000'; export const LOCAL_DOMAIN = Deno.env.get('LOCAL_DOMAIN') || 'http://localhost:8000';
export const POST_CHAR_LIMIT = Number(Deno.env.get('POST_CHAR_LIMIT') || 5000); export const POST_CHAR_LIMIT = Number(Deno.env.get('POST_CHAR_LIMIT') || 5000);
export const poolRelays = (Deno.env.get('RELAY_POOL') || '').split(',').filter(Boolean);

View File

@ -1,4 +1,6 @@
import { Context, Hono, validator } from 'https://deno.land/x/hono@v3.0.2/mod.ts'; import { Context, Hono, validator } from 'https://deno.land/x/hono@v3.0.2/mod.ts';
export { Hono, validator }; export { Hono, validator };
export { z } from 'https://deno.land/x/zod@v3.20.5/mod.ts'; export { z } from 'https://deno.land/x/zod@v3.20.5/mod.ts';
export { Author, RelayPool } from 'https://dev.jspm.io/nostr-relaypool@0.5.3';
export { getPublicKey } from 'https://dev.jspm.io/nostr-tools@1.6.0';
export type { Context }; export type { Context };

27
src/event.ts Normal file
View File

@ -0,0 +1,27 @@
enum Kind {
Metadata = 0,
Text = 1,
RecommendRelay = 2,
Contacts = 3,
EncryptedDirectMessage = 4,
EventDeletion = 5,
DeprecatedRepost = 6,
Reaction = 7,
ChannelCreation = 40,
ChannelMetadata = 41,
ChannelMessage = 42,
ChannelHideMessage = 43,
ChannelMuteUser = 44,
}
interface Event<K = Kind> {
id?: string;
sig?: string;
kind: K;
tags: string[][];
pubkey: string;
content: string;
created_at: number;
}
export type { Event, Kind };

17
src/schema.ts Normal file
View File

@ -0,0 +1,17 @@
import { z } from '@/deps.ts';
const optionalString = z.string().optional().catch(undefined);
const metaContentSchema = z.object({
name: optionalString,
about: optionalString,
picture: optionalString,
banner: optionalString,
nip05: optionalString,
lud16: optionalString,
});
type MetaContent = z.infer<typeof metaContentSchema>;
export { metaContentSchema };
export type { MetaContent };