You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-31 15:24:23 +03:00
Update Mutual Rooms (MSC2666) support (#3381)
* update mutual rooms support * clarify docs and switch eslint comment with todo * please the holy linter * change query variable names around * add mock tests and fix issue * ye holy linter
This commit is contained in:
@ -14,9 +14,19 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import fetchMock from "fetch-mock-jest";
|
||||||
|
|
||||||
import * as utils from "../test-utils/test-utils";
|
import * as utils from "../test-utils/test-utils";
|
||||||
import { RoomMember, RoomMemberEvent } from "../../src/models/room-member";
|
import { RoomMember, RoomMemberEvent } from "../../src/models/room-member";
|
||||||
import { EventType, RoomState } from "../../src";
|
import {
|
||||||
|
createClient,
|
||||||
|
EventType,
|
||||||
|
MatrixClient,
|
||||||
|
RoomState,
|
||||||
|
UNSTABLE_MSC2666_MUTUAL_ROOMS,
|
||||||
|
UNSTABLE_MSC2666_QUERY_MUTUAL_ROOMS,
|
||||||
|
UNSTABLE_MSC2666_SHARED_ROOMS,
|
||||||
|
} from "../../src";
|
||||||
|
|
||||||
describe("RoomMember", function () {
|
describe("RoomMember", function () {
|
||||||
const roomId = "!foo:bar";
|
const roomId = "!foo:bar";
|
||||||
@ -481,3 +491,125 @@ describe("RoomMember", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("MutualRooms", () => {
|
||||||
|
let client: MatrixClient;
|
||||||
|
const HS_URL = "https://example.com";
|
||||||
|
const TEST_USER_ID = "@alice:localhost";
|
||||||
|
const TEST_DEVICE_ID = "xzcvb";
|
||||||
|
const QUERIED_USER = "@user:example.com";
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
// anything that we don't have a specific matcher for silently returns a 404
|
||||||
|
fetchMock.catch(404);
|
||||||
|
fetchMock.config.warnOnFallback = true;
|
||||||
|
|
||||||
|
client = createClient({
|
||||||
|
baseUrl: HS_URL,
|
||||||
|
userId: TEST_USER_ID,
|
||||||
|
accessToken: "akjgkrgjs",
|
||||||
|
deviceId: TEST_DEVICE_ID,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await client.stopClient();
|
||||||
|
fetchMock.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
function enableFeature(feature: string) {
|
||||||
|
const mapping: Record<string, boolean> = {};
|
||||||
|
|
||||||
|
mapping[feature] = true;
|
||||||
|
|
||||||
|
fetchMock.get(`${HS_URL}/_matrix/client/versions`, {
|
||||||
|
unstable_features: mapping,
|
||||||
|
versions: ["v1.1"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it("supports the initial MSC version (shared rooms)", async () => {
|
||||||
|
enableFeature(UNSTABLE_MSC2666_SHARED_ROOMS);
|
||||||
|
|
||||||
|
fetchMock.get("express:/_matrix/client/unstable/uk.half-shot.msc2666/user/shared_rooms/:user_id", (rawUrl) => {
|
||||||
|
const segments = rawUrl.split("/");
|
||||||
|
const lastSegment = decodeURIComponent(segments[segments.length - 1]);
|
||||||
|
|
||||||
|
expect(lastSegment).toEqual(QUERIED_USER);
|
||||||
|
|
||||||
|
return {
|
||||||
|
joined: ["!test:example.com"],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const rooms = await client._unstable_getSharedRooms(QUERIED_USER);
|
||||||
|
|
||||||
|
expect(rooms).toEqual(["!test:example.com"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("supports the renaming MSC version (mutual rooms)", async () => {
|
||||||
|
enableFeature(UNSTABLE_MSC2666_MUTUAL_ROOMS);
|
||||||
|
|
||||||
|
fetchMock.get("express:/_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms/:user_id", (rawUrl) => {
|
||||||
|
const segments = rawUrl.split("/");
|
||||||
|
const lastSegment = decodeURIComponent(segments[segments.length - 1]);
|
||||||
|
|
||||||
|
expect(lastSegment).toEqual(QUERIED_USER);
|
||||||
|
|
||||||
|
return {
|
||||||
|
joined: ["!test2:example.com"],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const rooms = await client._unstable_getSharedRooms(QUERIED_USER);
|
||||||
|
|
||||||
|
expect(rooms).toEqual(["!test2:example.com"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("can work the latest MSC version (query mutual rooms)", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
enableFeature(UNSTABLE_MSC2666_QUERY_MUTUAL_ROOMS);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("works with a simple response", async () => {
|
||||||
|
fetchMock.get("express:/_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms", (rawUrl) => {
|
||||||
|
const url = new URL(rawUrl);
|
||||||
|
|
||||||
|
expect(url.searchParams.get("user_id")).toEqual(QUERIED_USER);
|
||||||
|
|
||||||
|
return {
|
||||||
|
joined: ["!test3:example.com"],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const rooms = await client._unstable_getSharedRooms(QUERIED_USER);
|
||||||
|
|
||||||
|
expect(rooms).toEqual(["!test3:example.com"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("works with a paginated response", async () => {
|
||||||
|
fetchMock.get("express:/_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms", (rawUrl) => {
|
||||||
|
const url = new URL(rawUrl);
|
||||||
|
|
||||||
|
expect(url.searchParams.get("user_id")).toEqual(QUERIED_USER);
|
||||||
|
|
||||||
|
const token = url.searchParams.get("batch_token");
|
||||||
|
|
||||||
|
if (token == "yahaha") {
|
||||||
|
return {
|
||||||
|
joined: ["!korok:example.com"],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
joined: ["!rock:example.com"],
|
||||||
|
next_batch_token: "yahaha",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const rooms = await client._unstable_getSharedRooms(QUERIED_USER);
|
||||||
|
|
||||||
|
expect(rooms).toEqual(["!rock:example.com", "!korok:example.com"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -500,6 +500,10 @@ export interface IMSC3882GetLoginTokenCapability extends ICapability {}
|
|||||||
|
|
||||||
export const UNSTABLE_MSC3882_CAPABILITY = new UnstableValue("m.get_login_token", "org.matrix.msc3882.get_login_token");
|
export const UNSTABLE_MSC3882_CAPABILITY = new UnstableValue("m.get_login_token", "org.matrix.msc3882.get_login_token");
|
||||||
|
|
||||||
|
export const UNSTABLE_MSC2666_SHARED_ROOMS = "uk.half-shot.msc2666";
|
||||||
|
export const UNSTABLE_MSC2666_MUTUAL_ROOMS = "uk.half-shot.msc2666.mutual_rooms";
|
||||||
|
export const UNSTABLE_MSC2666_QUERY_MUTUAL_ROOMS = "uk.half-shot.msc2666.query_mutual_rooms";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of the capabilities advertised by a homeserver as defined by
|
* A representation of the capabilities advertised by a homeserver as defined by
|
||||||
* [Capabilities negotiation](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3capabilities).
|
* [Capabilities negotiation](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3capabilities).
|
||||||
@ -7148,29 +7152,75 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a set of room IDs in common with another user
|
* Gets a set of room IDs in common with another user.
|
||||||
|
*
|
||||||
|
* Note: This endpoint is unstable, and can throw an `Error`.
|
||||||
|
* Check progress on [MSC2666](https://github.com/matrix-org/matrix-spec-proposals/pull/2666) for more details.
|
||||||
|
*
|
||||||
* @param userId - The userId to check.
|
* @param userId - The userId to check.
|
||||||
* @returns Promise which resolves to a set of rooms
|
* @returns Promise which resolves to an array of rooms
|
||||||
* @returns Rejects: with an error response.
|
* @returns Rejects: with an error response.
|
||||||
*/
|
*/
|
||||||
|
// TODO: on spec release, rename this to getMutualRooms
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
public async _unstable_getSharedRooms(userId: string): Promise<string[]> {
|
public async _unstable_getSharedRooms(userId: string): Promise<string[]> {
|
||||||
const sharedRoomsSupport = await this.doesServerSupportUnstableFeature("uk.half-shot.msc2666");
|
// Initial variant of the MSC
|
||||||
const mutualRoomsSupport = await this.doesServerSupportUnstableFeature("uk.half-shot.msc2666.mutual_rooms");
|
const sharedRoomsSupport = await this.doesServerSupportUnstableFeature(UNSTABLE_MSC2666_SHARED_ROOMS);
|
||||||
|
|
||||||
if (!sharedRoomsSupport && !mutualRoomsSupport) {
|
// Newer variant that renamed shared rooms to mutual rooms
|
||||||
throw Error("Server does not support mutual_rooms API");
|
const mutualRoomsSupport = await this.doesServerSupportUnstableFeature(UNSTABLE_MSC2666_MUTUAL_ROOMS);
|
||||||
}
|
|
||||||
|
|
||||||
const path = utils.encodeUri(
|
// Latest variant that changed from path elements to query elements
|
||||||
`/uk.half-shot.msc2666/user/${mutualRoomsSupport ? "mutual_rooms" : "shared_rooms"}/$userId`,
|
const queryMutualRoomsSupport = await this.doesServerSupportUnstableFeature(
|
||||||
{ $userId: userId },
|
UNSTABLE_MSC2666_QUERY_MUTUAL_ROOMS,
|
||||||
);
|
);
|
||||||
|
|
||||||
const res = await this.http.authedRequest<{ joined: string[] }>(Method.Get, path, undefined, undefined, {
|
if (!sharedRoomsSupport && !mutualRoomsSupport && !queryMutualRoomsSupport) {
|
||||||
prefix: ClientPrefix.Unstable,
|
throw Error("Server does not support the Mutual Rooms API");
|
||||||
});
|
}
|
||||||
return res.joined;
|
|
||||||
|
let path;
|
||||||
|
let query;
|
||||||
|
|
||||||
|
// Cascading unstable support switching.
|
||||||
|
if (queryMutualRoomsSupport) {
|
||||||
|
path = "/uk.half-shot.msc2666/user/mutual_rooms";
|
||||||
|
query = { user_id: userId };
|
||||||
|
} else {
|
||||||
|
path = utils.encodeUri(
|
||||||
|
`/uk.half-shot.msc2666/user/${mutualRoomsSupport ? "mutual_rooms" : "shared_rooms"}/$userId`,
|
||||||
|
{ $userId: userId },
|
||||||
|
);
|
||||||
|
query = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accumulated rooms
|
||||||
|
const rooms: string[] = [];
|
||||||
|
let token = null;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const tokenQuery: Record<string, string> = {};
|
||||||
|
if (token != null && queryMutualRoomsSupport) {
|
||||||
|
tokenQuery["batch_token"] = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await this.http.authedRequest<{
|
||||||
|
joined: string[];
|
||||||
|
next_batch_token?: string;
|
||||||
|
}>(Method.Get, path, { ...query, ...tokenQuery }, undefined, {
|
||||||
|
prefix: ClientPrefix.Unstable,
|
||||||
|
});
|
||||||
|
|
||||||
|
rooms.push(...res.joined);
|
||||||
|
|
||||||
|
if (res.next_batch_token !== undefined) {
|
||||||
|
token = res.next_batch_token;
|
||||||
|
} else {
|
||||||
|
token = null;
|
||||||
|
}
|
||||||
|
} while (token != null);
|
||||||
|
|
||||||
|
return rooms;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user