This is probably enough to log in?
This commit is contained in:
parent
7285d71bda
commit
825fed7d21
|
@ -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 };
|
||||||
|
|
|
@ -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 };
|
|
@ -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);
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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 };
|
|
@ -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 };
|
Loading…
Reference in New Issue