mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-12 08:27:27 +02:00
feat: comma-separated flags to REQ
This commit is contained in:
@@ -163,7 +163,7 @@ export default function ReqViewer({
|
||||
Authors: {filter.authors.length}
|
||||
</span>
|
||||
{nip05Authors && nip05Authors.length > 0 && (
|
||||
<div className="text-xs text-blue-500 ml-2">
|
||||
<div className="text-xs text-muted-foreground ml-2">
|
||||
{nip05Authors.map((nip05) => (
|
||||
<div key={nip05}>→ {nip05}</div>
|
||||
))}
|
||||
@@ -178,7 +178,7 @@ export default function ReqViewer({
|
||||
#p Tags: {filter["#p"].length}
|
||||
</span>
|
||||
{nip05PTags && nip05PTags.length > 0 && (
|
||||
<div className="text-xs text-blue-500 ml-2">
|
||||
<div className="text-xs text-muted-foreground ml-2">
|
||||
{nip05PTags.map((nip05) => (
|
||||
<div key={nip05}>→ {nip05}</div>
|
||||
))}
|
||||
|
||||
326
src/lib/req-parser.test.ts
Normal file
326
src/lib/req-parser.test.ts
Normal file
@@ -0,0 +1,326 @@
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { parseReqCommand } from "./req-parser";
|
||||
|
||||
describe("parseReqCommand", () => {
|
||||
describe("kind flag (-k, --kind)", () => {
|
||||
it("should parse single kind", () => {
|
||||
const result = parseReqCommand(["-k", "1"]);
|
||||
expect(result.filter.kinds).toEqual([1]);
|
||||
});
|
||||
|
||||
it("should parse comma-separated kinds", () => {
|
||||
const result = parseReqCommand(["-k", "1,3,7"]);
|
||||
expect(result.filter.kinds).toEqual([1, 3, 7]);
|
||||
});
|
||||
|
||||
it("should parse comma-separated kinds with spaces", () => {
|
||||
const result = parseReqCommand(["-k", "1, 3, 7"]);
|
||||
expect(result.filter.kinds).toEqual([1, 3, 7]);
|
||||
});
|
||||
|
||||
it("should deduplicate kinds", () => {
|
||||
const result = parseReqCommand(["-k", "1,3,1,3"]);
|
||||
expect(result.filter.kinds).toEqual([1, 3]);
|
||||
});
|
||||
|
||||
it("should deduplicate across multiple -k flags", () => {
|
||||
const result = parseReqCommand(["-k", "1", "-k", "3", "-k", "1"]);
|
||||
expect(result.filter.kinds).toEqual([1, 3]);
|
||||
});
|
||||
|
||||
it("should handle --kind long form", () => {
|
||||
const result = parseReqCommand(["--kind", "1,3,7"]);
|
||||
expect(result.filter.kinds).toEqual([1, 3, 7]);
|
||||
});
|
||||
|
||||
it("should ignore invalid kinds", () => {
|
||||
const result = parseReqCommand(["-k", "1,invalid,3"]);
|
||||
expect(result.filter.kinds).toEqual([1, 3]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("author flag (-a, --author)", () => {
|
||||
it("should parse hex pubkey", () => {
|
||||
const hex = "a".repeat(64);
|
||||
const result = parseReqCommand(["-a", hex]);
|
||||
expect(result.filter.authors).toEqual([hex]);
|
||||
});
|
||||
|
||||
it("should parse comma-separated hex pubkeys", () => {
|
||||
const hex1 = "a".repeat(64);
|
||||
const hex2 = "b".repeat(64);
|
||||
const result = parseReqCommand(["-a", `${hex1},${hex2}`]);
|
||||
expect(result.filter.authors).toEqual([hex1, hex2]);
|
||||
});
|
||||
|
||||
it("should deduplicate authors", () => {
|
||||
const hex = "a".repeat(64);
|
||||
const result = parseReqCommand(["-a", `${hex},${hex}`]);
|
||||
expect(result.filter.authors).toEqual([hex]);
|
||||
});
|
||||
|
||||
it("should accumulate NIP-05 identifiers for async resolution", () => {
|
||||
const result = parseReqCommand([
|
||||
"-a",
|
||||
"user@domain.com,alice@example.com",
|
||||
]);
|
||||
expect(result.nip05Authors).toEqual(["user@domain.com", "alice@example.com"]);
|
||||
expect(result.filter.authors).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should handle mixed hex and NIP-05", () => {
|
||||
const hex = "a".repeat(64);
|
||||
const result = parseReqCommand(["-a", `${hex},user@domain.com`]);
|
||||
expect(result.filter.authors).toEqual([hex]);
|
||||
expect(result.nip05Authors).toEqual(["user@domain.com"]);
|
||||
});
|
||||
|
||||
it("should deduplicate NIP-05 identifiers", () => {
|
||||
const result = parseReqCommand([
|
||||
"-a",
|
||||
"user@domain.com,user@domain.com",
|
||||
]);
|
||||
expect(result.nip05Authors).toEqual(["user@domain.com"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("event ID flag (-e)", () => {
|
||||
it("should parse hex event ID", () => {
|
||||
const hex = "a".repeat(64);
|
||||
const result = parseReqCommand(["-e", hex]);
|
||||
expect(result.filter["#e"]).toEqual([hex]);
|
||||
});
|
||||
|
||||
it("should parse comma-separated event IDs", () => {
|
||||
const hex1 = "a".repeat(64);
|
||||
const hex2 = "b".repeat(64);
|
||||
const result = parseReqCommand(["-e", `${hex1},${hex2}`]);
|
||||
expect(result.filter["#e"]).toEqual([hex1, hex2]);
|
||||
});
|
||||
|
||||
it("should deduplicate event IDs", () => {
|
||||
const hex = "a".repeat(64);
|
||||
const result = parseReqCommand(["-e", `${hex},${hex}`]);
|
||||
expect(result.filter["#e"]).toEqual([hex]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("pubkey tag flag (-p)", () => {
|
||||
it("should parse hex pubkey for #p tag", () => {
|
||||
const hex = "a".repeat(64);
|
||||
const result = parseReqCommand(["-p", hex]);
|
||||
expect(result.filter["#p"]).toEqual([hex]);
|
||||
});
|
||||
|
||||
it("should parse comma-separated pubkeys", () => {
|
||||
const hex1 = "a".repeat(64);
|
||||
const hex2 = "b".repeat(64);
|
||||
const result = parseReqCommand(["-p", `${hex1},${hex2}`]);
|
||||
expect(result.filter["#p"]).toEqual([hex1, hex2]);
|
||||
});
|
||||
|
||||
it("should accumulate NIP-05 identifiers for #p tags", () => {
|
||||
const result = parseReqCommand(["-p", "user@domain.com,alice@example.com"]);
|
||||
expect(result.nip05PTags).toEqual(["user@domain.com", "alice@example.com"]);
|
||||
expect(result.filter["#p"]).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should deduplicate #p tags", () => {
|
||||
const hex = "a".repeat(64);
|
||||
const result = parseReqCommand(["-p", `${hex},${hex}`]);
|
||||
expect(result.filter["#p"]).toEqual([hex]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("hashtag flag (-t)", () => {
|
||||
it("should parse single hashtag", () => {
|
||||
const result = parseReqCommand(["-t", "nostr"]);
|
||||
expect(result.filter["#t"]).toEqual(["nostr"]);
|
||||
});
|
||||
|
||||
it("should parse comma-separated hashtags", () => {
|
||||
const result = parseReqCommand(["-t", "nostr,bitcoin,lightning"]);
|
||||
expect(result.filter["#t"]).toEqual(["nostr", "bitcoin", "lightning"]);
|
||||
});
|
||||
|
||||
it("should parse comma-separated hashtags with spaces", () => {
|
||||
const result = parseReqCommand(["-t", "nostr, bitcoin, lightning"]);
|
||||
expect(result.filter["#t"]).toEqual(["nostr", "bitcoin", "lightning"]);
|
||||
});
|
||||
|
||||
it("should deduplicate hashtags", () => {
|
||||
const result = parseReqCommand(["-t", "nostr,bitcoin,nostr"]);
|
||||
expect(result.filter["#t"]).toEqual(["nostr", "bitcoin"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("d-tag flag (-d)", () => {
|
||||
it("should parse single d-tag", () => {
|
||||
const result = parseReqCommand(["-d", "article1"]);
|
||||
expect(result.filter["#d"]).toEqual(["article1"]);
|
||||
});
|
||||
|
||||
it("should parse comma-separated d-tags", () => {
|
||||
const result = parseReqCommand(["-d", "article1,article2,article3"]);
|
||||
expect(result.filter["#d"]).toEqual(["article1", "article2", "article3"]);
|
||||
});
|
||||
|
||||
it("should deduplicate d-tags", () => {
|
||||
const result = parseReqCommand(["-d", "article1,article2,article1"]);
|
||||
expect(result.filter["#d"]).toEqual(["article1", "article2"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("limit flag (-l, --limit)", () => {
|
||||
it("should parse limit", () => {
|
||||
const result = parseReqCommand(["-l", "100"]);
|
||||
expect(result.filter.limit).toBe(100);
|
||||
});
|
||||
|
||||
it("should handle --limit long form", () => {
|
||||
const result = parseReqCommand(["--limit", "50"]);
|
||||
expect(result.filter.limit).toBe(50);
|
||||
});
|
||||
});
|
||||
|
||||
describe("time flags (--since, --until)", () => {
|
||||
it("should parse unix timestamp for --since", () => {
|
||||
const result = parseReqCommand(["--since", "1234567890"]);
|
||||
expect(result.filter.since).toBe(1234567890);
|
||||
});
|
||||
|
||||
it("should parse relative time for --since (hours)", () => {
|
||||
const result = parseReqCommand(["--since", "2h"]);
|
||||
expect(result.filter.since).toBeDefined();
|
||||
expect(result.filter.since).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("should parse relative time for --since (days)", () => {
|
||||
const result = parseReqCommand(["--since", "7d"]);
|
||||
expect(result.filter.since).toBeDefined();
|
||||
expect(result.filter.since).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("should parse unix timestamp for --until", () => {
|
||||
const result = parseReqCommand(["--until", "1234567890"]);
|
||||
expect(result.filter.until).toBe(1234567890);
|
||||
});
|
||||
});
|
||||
|
||||
describe("search flag (--search)", () => {
|
||||
it("should parse search query", () => {
|
||||
const result = parseReqCommand(["--search", "bitcoin"]);
|
||||
expect(result.filter.search).toBe("bitcoin");
|
||||
});
|
||||
});
|
||||
|
||||
describe("relay parsing", () => {
|
||||
it("should parse relay with wss:// protocol", () => {
|
||||
const result = parseReqCommand(["wss://relay.example.com"]);
|
||||
expect(result.relays).toEqual(["wss://relay.example.com"]);
|
||||
});
|
||||
|
||||
it("should parse relay domain and add wss://", () => {
|
||||
const result = parseReqCommand(["relay.example.com"]);
|
||||
expect(result.relays).toEqual(["wss://relay.example.com"]);
|
||||
});
|
||||
|
||||
it("should parse multiple relays", () => {
|
||||
const result = parseReqCommand([
|
||||
"wss://relay1.com",
|
||||
"relay2.com",
|
||||
"wss://relay3.com",
|
||||
]);
|
||||
expect(result.relays).toEqual([
|
||||
"wss://relay1.com",
|
||||
"wss://relay2.com",
|
||||
"wss://relay3.com",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("close-on-eose flag", () => {
|
||||
it("should parse --close-on-eose", () => {
|
||||
const result = parseReqCommand(["--close-on-eose"]);
|
||||
expect(result.closeOnEose).toBe(true);
|
||||
});
|
||||
|
||||
it("should default to false when not provided", () => {
|
||||
const result = parseReqCommand(["-k", "1"]);
|
||||
expect(result.closeOnEose).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("complex scenarios", () => {
|
||||
it("should handle multiple flags together", () => {
|
||||
const hex = "a".repeat(64);
|
||||
const result = parseReqCommand([
|
||||
"-k",
|
||||
"1,3",
|
||||
"-a",
|
||||
hex,
|
||||
"-t",
|
||||
"nostr,bitcoin",
|
||||
"-l",
|
||||
"100",
|
||||
"--since",
|
||||
"1h",
|
||||
"relay.example.com",
|
||||
]);
|
||||
|
||||
expect(result.filter.kinds).toEqual([1, 3]);
|
||||
expect(result.filter.authors).toEqual([hex]);
|
||||
expect(result.filter["#t"]).toEqual(["nostr", "bitcoin"]);
|
||||
expect(result.filter.limit).toBe(100);
|
||||
expect(result.filter.since).toBeDefined();
|
||||
expect(result.relays).toEqual(["wss://relay.example.com"]);
|
||||
});
|
||||
|
||||
it("should handle deduplication across multiple flags and commas", () => {
|
||||
const result = parseReqCommand([
|
||||
"-k",
|
||||
"1,3",
|
||||
"-k",
|
||||
"3,7",
|
||||
"-k",
|
||||
"1",
|
||||
"-t",
|
||||
"nostr",
|
||||
"-t",
|
||||
"bitcoin,nostr",
|
||||
]);
|
||||
|
||||
expect(result.filter.kinds).toEqual([1, 3, 7]);
|
||||
expect(result.filter["#t"]).toEqual(["nostr", "bitcoin"]);
|
||||
});
|
||||
|
||||
it("should handle empty comma-separated values", () => {
|
||||
const result = parseReqCommand(["-k", "1,,3,,"]);
|
||||
expect(result.filter.kinds).toEqual([1, 3]);
|
||||
});
|
||||
|
||||
it("should handle whitespace in comma-separated values", () => {
|
||||
const result = parseReqCommand(["-t", " nostr , bitcoin , lightning "]);
|
||||
expect(result.filter["#t"]).toEqual(["nostr", "bitcoin", "lightning"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("edge cases", () => {
|
||||
it("should handle empty args", () => {
|
||||
const result = parseReqCommand([]);
|
||||
expect(result.filter).toEqual({});
|
||||
expect(result.relays).toBeUndefined();
|
||||
expect(result.closeOnEose).toBe(false);
|
||||
});
|
||||
|
||||
it("should handle flag without value", () => {
|
||||
const result = parseReqCommand(["-k"]);
|
||||
expect(result.filter.kinds).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should handle unknown flags gracefully", () => {
|
||||
const result = parseReqCommand(["-x", "value", "-k", "1"]);
|
||||
expect(result.filter.kinds).toEqual([1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -15,6 +15,30 @@ export interface ParsedReqCommand {
|
||||
nip05PTags?: string[]; // NIP-05 identifiers for #p tags that need async resolution
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse comma-separated values and apply a parser function to each
|
||||
* Returns true if at least one value was successfully parsed
|
||||
*/
|
||||
function parseCommaSeparated<T>(
|
||||
value: string,
|
||||
parser: (v: string) => T | null,
|
||||
target: Set<T>
|
||||
): boolean {
|
||||
const values = value.split(',').map(v => v.trim());
|
||||
let addedAny = false;
|
||||
|
||||
for (const val of values) {
|
||||
if (!val) continue;
|
||||
const parsed = parser(val);
|
||||
if (parsed !== null) {
|
||||
target.add(parsed);
|
||||
addedAny = true;
|
||||
}
|
||||
}
|
||||
|
||||
return addedAny;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse REQ command arguments into a Nostr filter
|
||||
* Supports:
|
||||
@@ -27,8 +51,17 @@ export interface ParsedReqCommand {
|
||||
export function parseReqCommand(args: string[]): ParsedReqCommand {
|
||||
const filter: NostrFilter = {};
|
||||
const relays: string[] = [];
|
||||
const nip05Authors: string[] = [];
|
||||
const nip05PTags: string[] = [];
|
||||
const nip05Authors = new Set<string>();
|
||||
const nip05PTags = new Set<string>();
|
||||
|
||||
// Use sets for deduplication during accumulation
|
||||
const kinds = new Set<number>();
|
||||
const authors = new Set<string>();
|
||||
const eventIds = new Set<string>();
|
||||
const pTags = new Set<string>();
|
||||
const tTags = new Set<string>();
|
||||
const dTags = new Set<string>();
|
||||
|
||||
let closeOnEose = false;
|
||||
|
||||
let i = 0;
|
||||
@@ -58,33 +91,47 @@ export function parseReqCommand(args: string[]): ParsedReqCommand {
|
||||
switch (flag) {
|
||||
case "-k":
|
||||
case "--kind": {
|
||||
const kind = parseInt(nextArg, 10);
|
||||
if (!isNaN(kind)) {
|
||||
if (!filter.kinds) filter.kinds = [];
|
||||
filter.kinds.push(kind);
|
||||
i += 2;
|
||||
} else {
|
||||
// Support comma-separated kinds: -k 1,3,7
|
||||
if (!nextArg) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
const addedAny = parseCommaSeparated(
|
||||
nextArg,
|
||||
(v) => {
|
||||
const kind = parseInt(v, 10);
|
||||
return isNaN(kind) ? null : kind;
|
||||
},
|
||||
kinds
|
||||
);
|
||||
i += addedAny ? 2 : 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case "-a":
|
||||
case "--author": {
|
||||
// Check if it's a NIP-05 identifier
|
||||
if (isNip05(nextArg)) {
|
||||
nip05Authors.push(nextArg);
|
||||
i += 2;
|
||||
} else {
|
||||
const pubkey = parseNpubOrHex(nextArg);
|
||||
if (pubkey) {
|
||||
if (!filter.authors) filter.authors = [];
|
||||
filter.authors.push(pubkey);
|
||||
i += 2;
|
||||
// Support comma-separated authors: -a npub1...,npub2...,user@domain.com
|
||||
if (!nextArg) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
let addedAny = false;
|
||||
const values = nextArg.split(',').map(a => a.trim());
|
||||
for (const authorStr of values) {
|
||||
if (!authorStr) continue;
|
||||
// Check if it's a NIP-05 identifier
|
||||
if (isNip05(authorStr)) {
|
||||
nip05Authors.add(authorStr);
|
||||
addedAny = true;
|
||||
} else {
|
||||
i++;
|
||||
const pubkey = parseNpubOrHex(authorStr);
|
||||
if (pubkey) {
|
||||
authors.add(pubkey);
|
||||
addedAny = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
i += addedAny ? 2 : 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -101,41 +148,55 @@ export function parseReqCommand(args: string[]): ParsedReqCommand {
|
||||
}
|
||||
|
||||
case "-e": {
|
||||
const eventId = parseNoteOrHex(nextArg);
|
||||
if (eventId) {
|
||||
if (!filter["#e"]) filter["#e"] = [];
|
||||
filter["#e"].push(eventId);
|
||||
i += 2;
|
||||
} else {
|
||||
// Support comma-separated event IDs: -e id1,id2,id3
|
||||
if (!nextArg) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
const addedAny = parseCommaSeparated(
|
||||
nextArg,
|
||||
parseNoteOrHex,
|
||||
eventIds
|
||||
);
|
||||
i += addedAny ? 2 : 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case "-p": {
|
||||
// Check if it's a NIP-05 identifier
|
||||
if (isNip05(nextArg)) {
|
||||
nip05PTags.push(nextArg);
|
||||
i += 2;
|
||||
} else {
|
||||
const pubkey = parseNpubOrHex(nextArg);
|
||||
if (pubkey) {
|
||||
if (!filter["#p"]) filter["#p"] = [];
|
||||
filter["#p"].push(pubkey);
|
||||
i += 2;
|
||||
// Support comma-separated pubkeys: -p npub1...,npub2...,user@domain.com
|
||||
if (!nextArg) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
let addedAny = false;
|
||||
const values = nextArg.split(',').map(p => p.trim());
|
||||
for (const pubkeyStr of values) {
|
||||
if (!pubkeyStr) continue;
|
||||
// Check if it's a NIP-05 identifier
|
||||
if (isNip05(pubkeyStr)) {
|
||||
nip05PTags.add(pubkeyStr);
|
||||
addedAny = true;
|
||||
} else {
|
||||
i++;
|
||||
const pubkey = parseNpubOrHex(pubkeyStr);
|
||||
if (pubkey) {
|
||||
pTags.add(pubkey);
|
||||
addedAny = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
i += addedAny ? 2 : 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case "-t": {
|
||||
// Hashtag filter
|
||||
// Support comma-separated hashtags: -t nostr,bitcoin,lightning
|
||||
if (nextArg) {
|
||||
if (!filter["#t"]) filter["#t"] = [];
|
||||
filter["#t"].push(nextArg);
|
||||
i += 2;
|
||||
const addedAny = parseCommaSeparated(
|
||||
nextArg,
|
||||
(v) => v, // hashtags are already strings
|
||||
tTags
|
||||
);
|
||||
i += addedAny ? 2 : 1;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
@@ -143,11 +204,14 @@ export function parseReqCommand(args: string[]): ParsedReqCommand {
|
||||
}
|
||||
|
||||
case "-d": {
|
||||
// D-tag filter (for replaceable events)
|
||||
// Support comma-separated d-tags: -d article1,article2,article3
|
||||
if (nextArg) {
|
||||
if (!filter["#d"]) filter["#d"] = [];
|
||||
filter["#d"].push(nextArg);
|
||||
i += 2;
|
||||
const addedAny = parseCommaSeparated(
|
||||
nextArg,
|
||||
(v) => v, // d-tags are already strings
|
||||
dTags
|
||||
);
|
||||
i += addedAny ? 2 : 1;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
@@ -201,16 +265,21 @@ export function parseReqCommand(args: string[]): ParsedReqCommand {
|
||||
}
|
||||
}
|
||||
|
||||
const result = {
|
||||
// Convert accumulated sets to filter arrays (with deduplication)
|
||||
if (kinds.size > 0) filter.kinds = Array.from(kinds);
|
||||
if (authors.size > 0) filter.authors = Array.from(authors);
|
||||
if (eventIds.size > 0) filter["#e"] = Array.from(eventIds);
|
||||
if (pTags.size > 0) filter["#p"] = Array.from(pTags);
|
||||
if (tTags.size > 0) filter["#t"] = Array.from(tTags);
|
||||
if (dTags.size > 0) filter["#d"] = Array.from(dTags);
|
||||
|
||||
return {
|
||||
filter,
|
||||
relays: relays.length > 0 ? relays : undefined,
|
||||
closeOnEose,
|
||||
nip05Authors: nip05Authors.length > 0 ? nip05Authors : undefined,
|
||||
nip05PTags: nip05PTags.length > 0 ? nip05PTags : undefined,
|
||||
nip05Authors: nip05Authors.size > 0 ? Array.from(nip05Authors) : undefined,
|
||||
nip05PTags: nip05PTags.size > 0 ? Array.from(nip05PTags) : undefined,
|
||||
};
|
||||
|
||||
console.log("parseReqCommand result:", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -144,12 +144,12 @@ export const manPages: Record<string, ManPageEntry> = {
|
||||
{
|
||||
flag: "-k, --kind <number>",
|
||||
description:
|
||||
"Filter by event kind (e.g., 0=metadata, 1=note, 7=reaction)",
|
||||
"Filter by event kind (e.g., 0=metadata, 1=note, 7=reaction). Supports comma-separated values: -k 1,3,7",
|
||||
},
|
||||
{
|
||||
flag: "-a, --author <npub|hex|nip05>",
|
||||
description:
|
||||
"Filter by author pubkey (supports npub, hex, NIP-05 identifier, or bare domain)",
|
||||
"Filter by author pubkey (supports npub, hex, NIP-05 identifier, or bare domain). Supports comma-separated values: -a npub1...,user@domain.com",
|
||||
},
|
||||
{
|
||||
flag: "-l, --limit <number>",
|
||||
@@ -157,20 +157,20 @@ export const manPages: Record<string, ManPageEntry> = {
|
||||
},
|
||||
{
|
||||
flag: "-e <id>",
|
||||
description: "Filter by referenced event ID (#e tag)",
|
||||
description: "Filter by referenced event ID (#e tag). Supports comma-separated values: -e id1,id2,id3",
|
||||
},
|
||||
{
|
||||
flag: "-p <npub|hex|nip05>",
|
||||
description:
|
||||
"Filter by mentioned pubkey (#p tag, supports npub, hex, NIP-05, or bare domain)",
|
||||
"Filter by mentioned pubkey (#p tag, supports npub, hex, NIP-05, or bare domain). Supports comma-separated values: -p npub1...,npub2...",
|
||||
},
|
||||
{
|
||||
flag: "-t <hashtag>",
|
||||
description: "Filter by hashtag (#t tag)",
|
||||
description: "Filter by hashtag (#t tag). Supports comma-separated values: -t nostr,bitcoin,lightning",
|
||||
},
|
||||
{
|
||||
flag: "-d <identifier>",
|
||||
description: "Filter by d-tag identifier (replaceable events)",
|
||||
description: "Filter by d-tag identifier (replaceable events). Supports comma-separated values: -d article1,article2",
|
||||
},
|
||||
{
|
||||
flag: "--since <time>",
|
||||
@@ -199,13 +199,15 @@ export const manPages: Record<string, ManPageEntry> = {
|
||||
],
|
||||
examples: [
|
||||
"req -k 1 -l 20 Get 20 recent notes (streams live by default)",
|
||||
"req -k 1,3,7 -l 50 Get notes, contact lists, and reactions",
|
||||
"req -k 0 -a npub1... Get profile for author",
|
||||
"req -k 1 -a user@domain.com Get notes from NIP-05 identifier",
|
||||
"req -k 1 -a dergigi.com Get notes from bare domain (resolves to _@dergigi.com)",
|
||||
"req -k 1 -a npub1...,npub2... Get notes from multiple authors",
|
||||
"req -k 1 -p verbiricha@habla.news Get notes mentioning NIP-05 user",
|
||||
"req -k 1 --since 1h relay.damus.io Get notes from last hour",
|
||||
"req -k 1 --close-on-eose Get recent notes and close after EOSE",
|
||||
"req -t nostr -l 50 Get 50 events tagged #nostr",
|
||||
"req -t nostr,bitcoin -l 50 Get 50 events tagged #nostr or #bitcoin",
|
||||
"req --search bitcoin -k 1 Search notes for 'bitcoin'",
|
||||
"req -k 1 relay1.com relay2.com Query multiple relays",
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user