stream_data: Get stream id instead of name from slug.

This more closely matches the mobile code.
https://github.com/zulip/zulip/pull/31299#discussion_r1719556337

This shouldn't have any functional changes.
This commit is contained in:
evykassirer
2024-08-17 20:33:38 -07:00
committed by Tim Abbott
parent b6830ff5df
commit 05e58de3f5
3 changed files with 47 additions and 30 deletions

View File

@@ -67,7 +67,13 @@ export function decode_operand(operator: string, operand: string): string {
operand = internal_url.decodeHashComponent(operand); operand = internal_url.decodeHashComponent(operand);
if (util.canonicalize_stream_synonyms(operator) === "stream") { if (util.canonicalize_stream_synonyms(operator) === "stream") {
return stream_data.slug_to_name(operand); const stream_id = stream_data.slug_to_stream_id(operand);
if (stream_id) {
const stream = stream_data.get_sub_by_id(stream_id);
if (stream) {
return stream.name;
}
}
} }
return operand; return operand;

View File

@@ -236,7 +236,7 @@ export function name_to_slug(name: string): string {
return `${stream_id}-${name}`; return `${stream_id}-${name}`;
} }
export function slug_to_name(slug: string): string { export function slug_to_stream_id(slug: string): number | undefined {
/* /*
Modern stream slugs look like this, where 42 Modern stream slugs look like this, where 42
is a stream id: is a stream id:
@@ -244,6 +244,12 @@ export function slug_to_name(slug: string): string {
42 42
42-stream-name 42-stream-name
The ID might point to a stream that's hidden from our user (perhaps
doesn't exist). If so, most likely the user doesn't have permission to
see the stream's existence -- like with a guest user for any stream
they're not in, or any non-admin with a private stream they're not in.
Could be that whoever wrote the link just made something up.
We have legacy slugs that are just the name We have legacy slugs that are just the name
of the stream: of the stream:
@@ -259,29 +265,29 @@ export function slug_to_name(slug: string): string {
If there is any ambiguity about whether a stream slug If there is any ambiguity about whether a stream slug
is old or modern, we prefer modern, as long as the integer is old or modern, we prefer modern, as long as the integer
prefix matches a real stream id. Eventually we will prefix matches a real stream id. We return undefined if the
stop supporting the legacy slugs, which only matter now operand has an unexpected shape, or has the old shape (stream
because people have linked to Zulip threads in things like name but no ID) and we don't know of a stream by the given name.
GitHub conversations. We migrated to modern slugs in
early 2018.
*/ */
const m = /^(\d+)(-.*)?$/.exec(slug);
if (m) { // "New" (2018) format: ${stream_id}-${stream_name} .
const stream_id = Number.parseInt(m[1]!, 10); const match = /^(\d+)(-.*)?$/.exec(slug);
const sub = sub_store.get(stream_id); const newFormatStreamId = match ? Number.parseInt(match[1]!, 10) : null;
if (sub) { if (newFormatStreamId && stream_info.get(newFormatStreamId)) {
return sub.name; return newFormatStreamId;
}
// if nothing was found above, we try to match on the stream
// name in the somewhat unlikely event they had a historical
// link to a stream like 4-horsemen
} }
/* // Old format: just stream name. This case is relevant indefinitely,
We are dealing with a pre-2018 slug that doesn't have the // so that links in old conversations (including off-platform like GitHub)
stream id as a prefix. // continue to work.
*/ const stream = get_sub_by_name(slug);
return slug; if (stream) {
return stream.stream_id;
}
// Unexpected shape, or the old shape and we don't know of a stream with
// the given name.
return undefined;
} }
export function delete_sub(stream_id: number): void { export function delete_sub(stream_id: number): void {

View File

@@ -166,16 +166,21 @@ test("basics", () => {
assert.ok(!stream_data.is_default_stream_id(social.stream_id)); assert.ok(!stream_data.is_default_stream_id(social.stream_id));
assert.ok(!stream_data.is_default_stream_id(999999)); assert.ok(!stream_data.is_default_stream_id(999999));
assert.equal(stream_data.slug_to_name("2-social"), "social"); // "new" correct url formats
assert.equal(stream_data.slug_to_name("2-whatever"), "social"); assert.equal(stream_data.slug_to_stream_id("2-social"), 2);
assert.equal(stream_data.slug_to_name("2"), "social"); assert.equal(stream_data.slug_to_stream_id("2"), 2);
// we still get 2 because it's a valid stream id
assert.equal(stream_data.slug_to_stream_id("2-whatever"), 2);
// invalid stream id
assert.equal(stream_data.slug_to_stream_id("999-social"), undefined);
// legacy // legacy
assert.equal(stream_data.slug_to_name("25-or-6-to-4"), "25-or-6-to-4"); assert.equal(stream_data.slug_to_stream_id("social"), 2);
assert.equal(stream_data.slug_to_name("2something"), "2something");
assert.equal(stream_data.slug_to_name("99-whatever"), "99-whatever"); // invalid formats
assert.equal(stream_data.slug_to_name("99whatever"), "99whatever"); assert.equal(stream_data.slug_to_stream_id("25-or-6-to-4"), undefined);
assert.equal(stream_data.slug_to_stream_id("2something"), undefined);
assert.equal(stream_data.slug_to_stream_id("99-whatever"), undefined);
assert.equal(stream_data.slug_to_stream_id("99whatever"), undefined);
// sub_store // sub_store
assert.equal(sub_store.get(-3), undefined); assert.equal(sub_store.get(-3), undefined);