Skip to content
55 linesCodeBlameRaw
1/**
2 * Channel names and direct-message keys. Pure, so they are tested apart
3 * from the service.
4 */
5
6/** The longest channel name. */
7export const MAX_NAME = 80;
8
9/** The most members a direct message may have, the viewer included. */
10export const MAX_DM_MEMBERS = 9;
11
12/** The channel every workspace starts with. */
13export const GENERAL = "general";
14
15const NAME = /^[a-z0-9_-]+$/;
16
17/**
18 * Names the site's chat URLs use beside channel names
19 * (`/<workspace>/-/chat/<name>`), so no channel can take them.
20 */
21export const RESERVED = new Set(["dm", "browse", "live", "api", "new"]);
22
23/**
24 * A channel name as it is kept: lowercase, without a leading `#`, spaces
25 * as dashes. Names are what people type after `#`, so only letters,
26 * digits, `-` and `_`.
27 */
28export function channelName(input: string): { ok: true; name: string } | { ok: false; message: string } {
29 const name = String(input ?? "")
30 .trim()
31 .replace(/^#+/, "")
32 .toLowerCase()
33 .replace(/\s+/g, "-");
34 if (!name) return { ok: false, message: "A channel needs a name." };
35 if (name.length > MAX_NAME) return { ok: false, message: `A channel name is at most ${MAX_NAME} characters.` };
36 if (!NAME.test(name)) {
37 return { ok: false, message: "A channel name can only use lowercase letters, digits, dashes and underscores." };
38 }
39 if (RESERVED.has(name)) return { ok: false, message: `#${name} is reserved. Pick another name.` };
40 return { ok: true, name };
41}
42
43/**
44 * Who is in a direct message: the viewer and `others`, each once, sorted.
45 * Nobody else, or only the viewer, is a direct message with yourself:
46 * a place for notes.
47 */
48export function dmMembers(viewer: string, others: string[]): string[] {
49 return [...new Set([viewer, ...others])].sort();
50}
51
52/** The key that finds a direct message by its members, whatever order they were given in. */
53export function dmKey(members: string[]): string {
54 return [...new Set(members)].sort().join(",");
55}