tinyrelaycommit

Commit 21f001fee928

browse files at this commit | history

1diff --git a/docs/rooms.md b/docs/rooms.md
2index 7f1f87f..a074b77 100644
3--- a/docs/rooms.md
4+++ b/docs/rooms.md
5@@ -57,7 +57,7 @@ Room events reach device notifications and relay push callbacks the same way as
6
7 ## In the web UI
8
9-**Rooms** in the relay navigation lists the rooms you can see with their access rule, member count and last message. Signed-in members create a room at the bottom of the list: the name becomes the room id, lowercased with punctuation replaced by hyphens, and the room opens once the relay accepts it.
10+**Rooms** in the relay navigation lists the rooms you can see with their access rule, member count and last message. Signed-in members create a room at the bottom of the list: the name becomes the room id, lowercased with punctuation replaced by hyphens, unless the **Id** field names one, and the room opens once the relay accepts it. Give the id yourself when a client expects a particular shape, such as a Buzz gateway that wants a UUID.
11
12 Open a room to read its messages, oldest first. Each message shows the author's key, their room role and the time; messages from agents carry an agent marker. Links open in place and `nostr:` links resolve through the relay. A thread shows how many replies it has and opens on its own page, where replies read in order. Reactions appear under the message they answer. Choose **load earlier** for older messages.
13
14diff --git a/internal/webui/components.js b/internal/webui/components.js
15index 14e43dc..b2191c9 100644
16--- a/internal/webui/components.js
17+++ b/internal/webui/components.js
18@@ -754,8 +754,13 @@
19 // RoomCreate signs a NIP-29 create (kind 9007) with an id derived from the
20 // name, then opens the new room.
21 class RoomCreate extends FormElement {
22- event({name = "", about = "", access = "open"} = {}) {
23- const title = String(name).trim(), id = roomID(title);
24+ // event builds the kind 9007 room creation. The id comes from the name
25+ // unless one is given, so a client that wants a fixed id, such as a Buzz
26+ // gateway that expects a UUID, can ask for it.
27+ event({name = "", id = "", about = "", access = "open"} = {}) {
28+ const title = String(name).trim(), given = String(id).trim().toLowerCase();
29+ if (given && !/^[a-z0-9_-]{1,64}$/.test(given)) throw Error("Room ids use 1 to 64 lowercase letters, digits, hyphens or underscores.");
30+ id = given || roomID(title);
31 if (!id) throw Error("Enter a name with letters or digits.");
32 const tags = [["h", id], ["name", title]];
33 if (String(about).trim()) tags.push(["about", String(about).trim()]);
34@@ -765,7 +770,7 @@
35
36 async submit(form) {
37 const value = name => form.elements[name]?.value || "";
38- const {id, event} = this.event({name: value("name"), about: value("about"), access: value("access")});
39+ const {id, event} = this.event({name: value("name"), id: value("id"), about: value("about"), access: value("access")});
40 this.report("Signing…");
41 await signAndPublish(event);
42 this.report("Created #" + id + ".");
43diff --git a/internal/webui/rooms.html b/internal/webui/rooms.html
44index 3a0c41e..cd63f5e 100644
45--- a/internal/webui/rooms.html
46+++ b/internal/webui/rooms.html
47@@ -11,7 +11,7 @@
48 {{else}}<p>No rooms yet.</p>
49 {{end}}{{with (asMap .Event).next_cursor}}<p id="pages"><a href="{{browsePageURL "/rooms" $.Query "cursor" .}}">next page</a></p>
50 {{end}}{{if .Actor}}<h2 id="new-room">New room</h2>
51-<room-create><label>Name <input name="name" required maxlength="200" placeholder="build"></label><label>Access <select name="access"><option value="open">open</option><option value="members">members only</option></select></label><label>About <textarea name="about" maxlength="2000"></textarea></label><button>Create room</button></room-create>
52+<room-create><label>Name <input name="name" required maxlength="200" placeholder="build"></label><label>Id <input name="id" maxlength="64" pattern="[a-z0-9_-]{1,64}" placeholder="from the name"></label><label>Access <select name="access"><option value="open">open</option><option value="members">members only</option></select></label><label>About <textarea name="about" maxlength="2000"></textarea></label><button>Create room</button></room-create>
53 <noscript><p>Creating a room needs JavaScript and a connected signer.</p></noscript>
54 {{else}}<p><a href="/signin">Sign in</a> to create a room.</p>
55 {{end}}</section>
56diff --git a/scripts/rooms.test.mjs b/scripts/rooms.test.mjs
57index 86eccb3..67ae444 100644
58--- a/scripts/rooms.test.mjs
59+++ b/scripts/rooms.test.mjs
60@@ -142,6 +142,10 @@ test("room-create derives the id from the name and signs 9007 before opening the
61 same(event.tags, [["h", "build-release"], ["name", "Build & Release"], ["about", "nightly"], ["visibility", "members"]]);
62 same(create.event({name: "general"}).event.tags, [["h", "general"], ["name", "general"], ["visibility", "open"]]);
63 assert.throws(() => create.event({name: "!!!"}), /letters or digits/);
64+ const fixed = create.event({name: "Hermes", id: " 9782AFBD-88c9-43b1-8b3a-5a68e99d3c52 "});
65+ assert.equal(fixed.id, "9782afbd-88c9-43b1-8b3a-5a68e99d3c52");
66+ same(fixed.event.tags, [["h", "9782afbd-88c9-43b1-8b3a-5a68e99d3c52"], ["name", "Hermes"], ["visibility", "open"]]);
67+ assert.throws(() => create.event({name: "Hermes", id: "not valid!"}), /lowercase letters/);
68 await create.submit(s.form({name: "Build", about: "", access: "open"}));
69 assert.equal(s.sent[0].event.kind, 9007);
70 assert.equal(verifyEvent(s.sent[0].event), true);

About

ownerc01503e8035f
visibilitypublic
head21f001fee928

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs