Typing all the types
This commit is contained in:
parent
edaf5f5c71
commit
46ad9813eb
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
.env
|
.env
|
||||||
users.yaml
|
users.yaml
|
||||||
|
substr
|
||||||
|
42
config.ts
42
config.ts
@ -5,24 +5,24 @@ import { log } from "./log.ts";
|
|||||||
const dirname = new URL(".", import.meta.url).pathname;
|
const dirname = new URL(".", import.meta.url).pathname;
|
||||||
await load({ envPath: `${dirname}/.env`, export: true });
|
await load({ envPath: `${dirname}/.env`, export: true });
|
||||||
|
|
||||||
let staticUsers;
|
let staticUsers: { [key: string]: string } = {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const yamlContent = await Deno.readTextFile(`${dirname}/users.yaml`);
|
const yamlContent = await Deno.readTextFile(`${dirname}/users.yaml`);
|
||||||
staticUsers = parse(yamlContent);
|
const parsedContent = parse(yamlContent);
|
||||||
log(`Serving content for ${Object.keys(staticUsers).length} pubkeys from users.yaml`, "blue");
|
if (parsedContent !== null && typeof parsedContent === "object") {
|
||||||
|
staticUsers = parsedContent as { [key: string]: string };
|
||||||
|
log(`Serving content for pubkeys in users.yaml`, "blue");
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
staticUsers = {};
|
|
||||||
log(`Could not find or parse a users.yaml config`, "yellow");
|
log(`Could not find or parse a users.yaml config`, "yellow");
|
||||||
}
|
}
|
||||||
|
|
||||||
const relay_urls = Deno.env.get("RELAY_URLS")?.split(",");
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
port: Deno.env.get("PORT") || 8000,
|
port: parseInt(Deno.env.get("PORT") || "8000"),
|
||||||
base_url: Deno.env.get("BASE_URL") || `http://localhost:8000`,
|
base_url: Deno.env.get("BASE_URL") || `http://localhost:8000`,
|
||||||
relay_urls,
|
relay_urls: Deno.env.get("RELAY_URLS")?.split(",") || [],
|
||||||
staticUsers: staticUsers,
|
staticUsers,
|
||||||
ldapEnabled: !!Deno.env.get("LDAP_URL"),
|
ldapEnabled: !!Deno.env.get("LDAP_URL"),
|
||||||
ldap: {
|
ldap: {
|
||||||
url: Deno.env.get("LDAP_URL"),
|
url: Deno.env.get("LDAP_URL"),
|
||||||
@ -32,8 +32,21 @@ const config = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (config.ldapEnabled && config.ldap.url) {
|
if (config.relay_urls.length === 0) {
|
||||||
log(`Serving content for pubkeys from ${config.ldap.url}`, "blue");
|
log(`No relays configured. Please add at least one relay to RELAY_URLS.`);
|
||||||
|
Deno.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.ldapEnabled) {
|
||||||
|
if (
|
||||||
|
config.ldap.url && config.ldap.bindDN && config.ldap.password &&
|
||||||
|
config.ldap.searchDN
|
||||||
|
) {
|
||||||
|
log(`Serving content for pubkeys from ${config.ldap.url}`, "blue");
|
||||||
|
} else {
|
||||||
|
log(`The LDAP config is incomplete`);
|
||||||
|
Deno.exit(1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log(`LDAP not enabled`, "blue");
|
log(`LDAP not enabled`, "blue");
|
||||||
}
|
}
|
||||||
@ -43,11 +56,4 @@ if (Object.keys(staticUsers).length === 0 && !config.ldapEnabled) {
|
|||||||
Deno.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.relay_urls?.length > 0) {
|
|
||||||
log(`Relays: ${config.relay_urls.join(", ")}`, "green");
|
|
||||||
} else {
|
|
||||||
log(`No relays configured. Please add at least one relay to RELAY_URLS.`);
|
|
||||||
Deno.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
@ -1,23 +1,21 @@
|
|||||||
import { Context } from "@oak/oak";
|
import { Context } from "@oak/oak";
|
||||||
import { nip19 } from "@nostr/tools";
|
import { nip19 } from "@nostr/tools";
|
||||||
import { log } from "../log.ts";
|
|
||||||
import { lookupUsernameByPubkey } from "../directory.ts";
|
import { lookupUsernameByPubkey } from "../directory.ts";
|
||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import notFoundHandler from "../handlers/not-found.ts";
|
||||||
|
|
||||||
const naddrHandler = async function (ctx: Context) {
|
const naddrHandler = async function (ctx: Context) {
|
||||||
const naddr = ctx.params.path;
|
const naddr = ctx.state.path;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const r = nip19.decode(naddr);
|
const data = nip19.decode(naddr).data as nip19.AddressPointer;
|
||||||
const username = await lookupUsernameByPubkey(r.data.pubkey);
|
const username = await lookupUsernameByPubkey(data.pubkey);
|
||||||
|
|
||||||
if (username && r.data.identifier) {
|
if (username && data.identifier) {
|
||||||
ctx.response.redirect(`/@${username}/${r.data.identifier}`);
|
ctx.response.redirect(`/@${username}/${data.identifier}`);
|
||||||
} else {
|
} else {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (_e) {
|
||||||
log(e, "yellow");
|
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,23 +1,21 @@
|
|||||||
import { Context } from "@oak/oak";
|
import { Context } from "@oak/oak";
|
||||||
import { nip19 } from "@nostr/tools";
|
import { nip19 } from "@nostr/tools";
|
||||||
import { log } from "../log.ts";
|
|
||||||
import { lookupUsernameByPubkey } from "../directory.ts";
|
import { lookupUsernameByPubkey } from "../directory.ts";
|
||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import notFoundHandler from "../handlers/not-found.ts";
|
||||||
|
|
||||||
const nprofileHandler = async function (ctx: Context) {
|
const nprofileHandler = async function (ctx: Context) {
|
||||||
const nprofile = ctx.params.path;
|
const nprofile = ctx.state.path;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const r = nip19.decode(nprofile);
|
const data = nip19.decode(nprofile).data as nip19.ProfilePointer;
|
||||||
const username = await lookupUsernameByPubkey(r.data.pubkey);
|
const username = await lookupUsernameByPubkey(data.pubkey);
|
||||||
|
|
||||||
if (username) {
|
if (username) {
|
||||||
ctx.response.redirect(`/@${username}`);
|
ctx.response.redirect(`/@${username}`);
|
||||||
} else {
|
} else {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (_e) {
|
||||||
log(e, "yellow");
|
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,23 +1,21 @@
|
|||||||
import { Context } from "@oak/oak";
|
import { Context } from "@oak/oak";
|
||||||
import { nip19 } from "@nostr/tools";
|
import { nip19 } from "@nostr/tools";
|
||||||
import { log } from "../log.ts";
|
|
||||||
import { lookupUsernameByPubkey } from "../directory.ts";
|
import { lookupUsernameByPubkey } from "../directory.ts";
|
||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import notFoundHandler from "../handlers/not-found.ts";
|
||||||
|
|
||||||
const npubHandler = async function (ctx: Context) {
|
const npubHandler = async function (ctx: Context) {
|
||||||
const npub = ctx.params.path;
|
const npub = ctx.state.path;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const r = nip19.decode(npub);
|
const pubkey = nip19.decode(npub).data as string;
|
||||||
const username = await lookupUsernameByPubkey(r.data);
|
const username = await lookupUsernameByPubkey(pubkey);
|
||||||
|
|
||||||
if (username) {
|
if (username) {
|
||||||
ctx.response.redirect(`/@${username}`);
|
ctx.response.redirect(`/@${username}`);
|
||||||
} else {
|
} else {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (_e) {
|
||||||
log(e, "yellow");
|
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Context } from "@oak/oak";
|
import { Context } from "@oak/oak";
|
||||||
import { log } from "../log.ts";
|
|
||||||
import { lookupPubkeyByUsername } from "../directory.ts";
|
import { lookupPubkeyByUsername } from "../directory.ts";
|
||||||
import { fetchArticlesByAuthor, fetchProfileEvent } from "../nostr.ts";
|
import { fetchArticlesByAuthor, fetchProfileEvent } from "../nostr.ts";
|
||||||
import { profileAtomFeed } from "../feeds.ts";
|
import { profileAtomFeed } from "../feeds.ts";
|
||||||
@ -8,8 +7,8 @@ import Profile from "../models/profile.ts";
|
|||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import notFoundHandler from "../handlers/not-found.ts";
|
||||||
|
|
||||||
const userAtomFeedHandler = async function (ctx: Context) {
|
const userAtomFeedHandler = async function (ctx: Context) {
|
||||||
const username = ctx.params.user.replace(/^(@|~)/, "");
|
const username = ctx.state.username;
|
||||||
const pubkey = await lookupPubkeyByUsername(username);
|
const pubkey = await lookupPubkeyByUsername(ctx.state.username);
|
||||||
|
|
||||||
if (!pubkey) {
|
if (!pubkey) {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
@ -18,21 +17,22 @@ const userAtomFeedHandler = async function (ctx: Context) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const profileEvent = await fetchProfileEvent(pubkey);
|
const profileEvent = await fetchProfileEvent(pubkey);
|
||||||
const profile = new Profile(profileEvent, username);
|
|
||||||
|
|
||||||
if (profileEvent && profile.nip05) {
|
if (profileEvent) {
|
||||||
const articleEvents = await fetchArticlesByAuthor(pubkey);
|
const profile = new Profile(profileEvent, username);
|
||||||
const articles = articleEvents.map((a) => new Article(a));
|
|
||||||
const atom = profileAtomFeed(profile, articles);
|
|
||||||
|
|
||||||
ctx.response.headers.set("Content-Type", "application/atom+xml");
|
if (profile.nip05) {
|
||||||
ctx.response.body = atom;
|
const articleEvents = await fetchArticlesByAuthor(pubkey);
|
||||||
} else {
|
const articles = articleEvents.map((a) => new Article(a));
|
||||||
ctx.response.status = 404;
|
const atom = profileAtomFeed(profile, articles);
|
||||||
ctx.response.body = "Not Found";
|
|
||||||
|
ctx.response.headers.set("Content-Type", "application/atom+xml");
|
||||||
|
ctx.response.body = atom;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
notFoundHandler(ctx);
|
||||||
log(e, "yellow");
|
} catch (_e) {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Context } from "@oak/oak";
|
import { Context } from "@oak/oak";
|
||||||
import { log } from "../log.ts";
|
|
||||||
import { lookupPubkeyByUsername } from "../directory.ts";
|
import { lookupPubkeyByUsername } from "../directory.ts";
|
||||||
import { fetchProfileEvent, fetchReplaceableEvent } from "../nostr.ts";
|
import { fetchProfileEvent, fetchReplaceableEvent } from "../nostr.ts";
|
||||||
import Article from "../models/article.ts";
|
import Article from "../models/article.ts";
|
||||||
@ -8,8 +7,8 @@ import { articleHtml } from "../html.ts";
|
|||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import notFoundHandler from "../handlers/not-found.ts";
|
||||||
|
|
||||||
const userEventHandler = async function (ctx: Context) {
|
const userEventHandler = async function (ctx: Context) {
|
||||||
const username = ctx.params.user.replace(/^(@|~)/, "");
|
const username = ctx.state.username.replace(/^(@|~)/, "");
|
||||||
const identifier = ctx.params.identifier;
|
const identifier = ctx.state.identifier;
|
||||||
const pubkey = await lookupPubkeyByUsername(username);
|
const pubkey = await lookupPubkeyByUsername(username);
|
||||||
|
|
||||||
if (!pubkey) {
|
if (!pubkey) {
|
||||||
@ -33,8 +32,7 @@ const userEventHandler = async function (ctx: Context) {
|
|||||||
} else {
|
} else {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (_e) {
|
||||||
log(e, "yellow");
|
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Context } from "@oak/oak";
|
import { Context } from "@oak/oak";
|
||||||
import { log } from "../log.ts";
|
|
||||||
import { lookupPubkeyByUsername } from "../directory.ts";
|
import { lookupPubkeyByUsername } from "../directory.ts";
|
||||||
import { fetchArticlesByAuthor, fetchProfileEvent } from "../nostr.ts";
|
import { fetchArticlesByAuthor, fetchProfileEvent } from "../nostr.ts";
|
||||||
import Article from "../models/article.ts";
|
import Article from "../models/article.ts";
|
||||||
@ -8,7 +7,7 @@ import { profilePageHtml } from "../html.ts";
|
|||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import notFoundHandler from "../handlers/not-found.ts";
|
||||||
|
|
||||||
const userProfileHandler = async function (ctx: Context) {
|
const userProfileHandler = async function (ctx: Context) {
|
||||||
const username = ctx.params.path.replace(/^(@|~)/, "");
|
const username = ctx.state.path.replace(/^(@|~)/, "");
|
||||||
const pubkey = await lookupPubkeyByUsername(username);
|
const pubkey = await lookupPubkeyByUsername(username);
|
||||||
|
|
||||||
if (!pubkey) {
|
if (!pubkey) {
|
||||||
@ -27,11 +26,9 @@ const userProfileHandler = async function (ctx: Context) {
|
|||||||
|
|
||||||
ctx.response.body = html;
|
ctx.response.body = html;
|
||||||
} else {
|
} else {
|
||||||
log(`No profile event found for @${username}`, "yellow");
|
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (_e) {
|
||||||
log(e, "yellow");
|
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
21
ldap.ts
21
ldap.ts
@ -1,28 +1,27 @@
|
|||||||
import { Client } from "ldapts";
|
import { Client } from "ldapts";
|
||||||
import { log } from "./log.ts";
|
|
||||||
import config from "./config.ts";
|
import config from "./config.ts";
|
||||||
|
|
||||||
const { ldap, ldapEnabled } = config;
|
const { ldap, ldapEnabled } = config;
|
||||||
|
|
||||||
let client: Client;
|
let client: Client;
|
||||||
if (ldapEnabled) {
|
if (ldapEnabled) {
|
||||||
client = new Client({ url: ldap.url });
|
client = new Client({ url: ldap.url as string });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function lookupPubkeyByUsername(username: string) {
|
export async function lookupPubkeyByUsername(username: string) {
|
||||||
let pubkey;
|
let pubkey;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await client.bind(ldap.bindDN, ldap.password);
|
await client.bind(ldap.bindDN as string, ldap.password as string);
|
||||||
|
|
||||||
const { searchEntries } = await client.search(ldap.searchDN, {
|
const { searchEntries } = await client.search(ldap.searchDN as string, {
|
||||||
filter: `(cn=${username})`,
|
filter: `(cn=${username})`,
|
||||||
attributes: ["nostrKey"],
|
attributes: ["nostrKey"],
|
||||||
});
|
});
|
||||||
|
|
||||||
pubkey = searchEntries[0]?.nostrKey;
|
pubkey = searchEntries[0]?.nostrKey as string;
|
||||||
} catch (ex) {
|
} catch (e) {
|
||||||
log(ex, "red");
|
console.error(e);
|
||||||
} finally {
|
} finally {
|
||||||
await client.unbind();
|
await client.unbind();
|
||||||
}
|
}
|
||||||
@ -34,16 +33,16 @@ export async function lookupUsernameByPubkey(pubkey: string) {
|
|||||||
let username;
|
let username;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await client.bind(ldap.bindDN, ldap.password);
|
await client.bind(ldap.bindDN as string, ldap.password as string);
|
||||||
|
|
||||||
const { searchEntries } = await client.search(ldap.searchDN, {
|
const { searchEntries } = await client.search(ldap.searchDN as string, {
|
||||||
filter: `(nostrKey=${pubkey})`,
|
filter: `(nostrKey=${pubkey})`,
|
||||||
attributes: ["cn"],
|
attributes: ["cn"],
|
||||||
});
|
});
|
||||||
|
|
||||||
username = searchEntries[0]?.cn;
|
username = searchEntries[0]?.cn;
|
||||||
} catch (ex) {
|
} catch (e) {
|
||||||
log(ex, "red");
|
console.error(e);
|
||||||
} finally {
|
} finally {
|
||||||
await client.unbind();
|
await client.unbind();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { render as renderMarkdown } from "@deno/gfm";
|
import { render as renderMarkdown } from "@deno/gfm";
|
||||||
import { nip19 } from "@nostr/tools";
|
import { nip19 } from "@nostr/tools";
|
||||||
import { NEvent } from "../nostr.ts";
|
import { NostrEvent as NEvent } from "@nostrify/nostrify";
|
||||||
import config from "../config.ts";
|
import config from "../config.ts";
|
||||||
|
|
||||||
export default class Article {
|
export default class Article {
|
||||||
@ -51,7 +51,7 @@ export default class Article {
|
|||||||
identifier: this.identifier,
|
identifier: this.identifier,
|
||||||
pubkey: this.event.pubkey,
|
pubkey: this.event.pubkey,
|
||||||
kind: this.event.kind,
|
kind: this.event.kind,
|
||||||
relays: [config.home_relay_url],
|
relays: [config.relay_urls[0]],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { nip19 } from "@nostr/tools";
|
import { nip19, NostrEvent as NEvent } from "@nostr/tools";
|
||||||
import { NEvent } from "../nostr.ts";
|
// import { NEvent } from "../nostr.ts";
|
||||||
|
|
||||||
export interface ProfileData {
|
export interface ProfileData {
|
||||||
name?: string;
|
name?: string;
|
||||||
@ -12,8 +12,8 @@ export interface ProfileData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class Profile {
|
export default class Profile {
|
||||||
event: NEvent;
|
|
||||||
private data: ProfileData;
|
private data: ProfileData;
|
||||||
|
event: NEvent;
|
||||||
username?: string;
|
username?: string;
|
||||||
|
|
||||||
constructor(event: NEvent, username?: string) {
|
constructor(event: NEvent, username?: string) {
|
||||||
|
20
nostr.ts
20
nostr.ts
@ -1,21 +1,15 @@
|
|||||||
import { NPool, NRelay1 } from "@nostrify/nostrify";
|
import { NPool, NRelay1 } from "@nostrify/nostrify";
|
||||||
import config from "./config.ts";
|
import config from "./config.ts";
|
||||||
|
|
||||||
export interface NEvent {
|
|
||||||
content: string;
|
|
||||||
created_at: number;
|
|
||||||
id: string;
|
|
||||||
kind: number;
|
|
||||||
pubkey: string;
|
|
||||||
sig: string;
|
|
||||||
tags: Array<[string, string, string?]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const relayPool = new NPool({
|
const relayPool = new NPool({
|
||||||
open: (url) => new NRelay1(url),
|
open: (url) => new NRelay1(url),
|
||||||
reqRouter: async (filters) => new Map(
|
// deno-lint-ignore require-await
|
||||||
config.relay_urls.map(url => [ url, filters ])
|
reqRouter: async (filters) =>
|
||||||
)
|
new Map(
|
||||||
|
config.relay_urls.map((url) => [url, filters]),
|
||||||
|
),
|
||||||
|
// deno-lint-ignore require-await
|
||||||
|
eventRouter: async (_event) => [],
|
||||||
});
|
});
|
||||||
|
|
||||||
export async function fetchReplaceableEvent(
|
export async function fetchReplaceableEvent(
|
||||||
|
25
server.ts
25
server.ts
@ -1,4 +1,4 @@
|
|||||||
import { Application, Context, Router, send } from "@oak/oak";
|
import { Application, Router, send } from "@oak/oak";
|
||||||
import config from "./config.ts";
|
import config from "./config.ts";
|
||||||
import naddrHandler from "./handlers/naddr.ts";
|
import naddrHandler from "./handlers/naddr.ts";
|
||||||
import nprofileHandler from "./handlers/nprofile.ts";
|
import nprofileHandler from "./handlers/nprofile.ts";
|
||||||
@ -10,8 +10,8 @@ import notFoundHandler from "./handlers/not-found.ts";
|
|||||||
|
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.get("/:path", async (ctx: Context) => {
|
router.get("/:path", async (ctx) => {
|
||||||
const { path } = ctx.params;
|
const path = ctx.state.path = ctx.params.path;
|
||||||
|
|
||||||
if (path.startsWith("naddr")) {
|
if (path.startsWith("naddr")) {
|
||||||
await naddrHandler(ctx);
|
await naddrHandler(ctx);
|
||||||
@ -26,12 +26,14 @@ router.get("/:path", async (ctx: Context) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/:user/:kind.atom", async (ctx: Context) => {
|
router.get("/:username/:kind.atom", async (ctx) => {
|
||||||
const { user, kind } = ctx.params;
|
ctx.state.username = ctx.params.username.replace(/^(@|~)/, "");
|
||||||
|
ctx.state.kind = ctx.params.kind;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
kind === "articles" &&
|
ctx.state.kind === "articles" &&
|
||||||
(user.startsWith("@") || user.startsWith("~"))
|
(ctx.params.username.startsWith("@") ||
|
||||||
|
ctx.params.username.startsWith("~"))
|
||||||
) {
|
) {
|
||||||
await userAtomFeedHandler(ctx);
|
await userAtomFeedHandler(ctx);
|
||||||
} else {
|
} else {
|
||||||
@ -39,10 +41,11 @@ router.get("/:user/:kind.atom", async (ctx: Context) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/:user/:identifier", async (ctx: Context) => {
|
router.get("/:username/:identifier", async (ctx) => {
|
||||||
const { user } = ctx.params;
|
const username = ctx.state.username = ctx.params.username;
|
||||||
|
ctx.state.identifier = ctx.params.identifier;
|
||||||
|
|
||||||
if (user.startsWith("@") || user.startsWith("~")) {
|
if (username.startsWith("@") || username.startsWith("~")) {
|
||||||
await userEventHandler(ctx);
|
await userEventHandler(ctx);
|
||||||
} else {
|
} else {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
@ -51,7 +54,7 @@ router.get("/:user/:identifier", async (ctx: Context) => {
|
|||||||
|
|
||||||
router.get("/assets/:path*", async (ctx) => {
|
router.get("/assets/:path*", async (ctx) => {
|
||||||
try {
|
try {
|
||||||
const filePath = ctx.params.path || '';
|
const filePath = ctx.params.path || "";
|
||||||
|
|
||||||
await send(ctx, filePath, {
|
await send(ctx, filePath, {
|
||||||
root: `${Deno.cwd()}/assets`,
|
root: `${Deno.cwd()}/assets`,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { beforeAll, describe, it } from "@std/testing/bdd";
|
import { beforeAll, describe, it } from "@std/testing/bdd";
|
||||||
import { expect } from "@std/expect";
|
import { expect } from "@std/expect";
|
||||||
import { NEvent } from "../../nostr.ts";
|
import { NostrEvent as NEvent } from "@nostrify/nostrify";
|
||||||
import Article from "../../models/article.ts";
|
import Article from "../../models/article.ts";
|
||||||
|
|
||||||
describe("Article", () => {
|
describe("Article", () => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { beforeAll, describe, it } from "@std/testing/bdd";
|
import { beforeAll, describe, it } from "@std/testing/bdd";
|
||||||
import { expect } from "@std/expect";
|
import { expect } from "@std/expect";
|
||||||
import { NEvent } from "../../nostr.ts";
|
import { NostrEvent as NEvent } from "@nostrify/nostrify";
|
||||||
import Profile from "../../models/profile.ts";
|
import Profile from "../../models/profile.ts";
|
||||||
|
|
||||||
describe("Profile", () => {
|
describe("Profile", () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user