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.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
|
||||
import * as utils from "../test-utils/test-utils";
|
||||
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 () {
|
||||
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_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
|
||||
* [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.
|
||||
* @returns Promise which resolves to a set of rooms
|
||||
* @returns Promise which resolves to an array of rooms
|
||||
* @returns Rejects: with an error response.
|
||||
*/
|
||||
// TODO: on spec release, rename this to getMutualRooms
|
||||
// eslint-disable-next-line
|
||||
public async _unstable_getSharedRooms(userId: string): Promise<string[]> {
|
||||
const sharedRoomsSupport = await this.doesServerSupportUnstableFeature("uk.half-shot.msc2666");
|
||||
const mutualRoomsSupport = await this.doesServerSupportUnstableFeature("uk.half-shot.msc2666.mutual_rooms");
|
||||
// Initial variant of the MSC
|
||||
const sharedRoomsSupport = await this.doesServerSupportUnstableFeature(UNSTABLE_MSC2666_SHARED_ROOMS);
|
||||
|
||||
if (!sharedRoomsSupport && !mutualRoomsSupport) {
|
||||
throw Error("Server does not support mutual_rooms API");
|
||||
// Newer variant that renamed shared rooms to mutual rooms
|
||||
const mutualRoomsSupport = await this.doesServerSupportUnstableFeature(UNSTABLE_MSC2666_MUTUAL_ROOMS);
|
||||
|
||||
// Latest variant that changed from path elements to query elements
|
||||
const queryMutualRoomsSupport = await this.doesServerSupportUnstableFeature(
|
||||
UNSTABLE_MSC2666_QUERY_MUTUAL_ROOMS,
|
||||
);
|
||||
|
||||
if (!sharedRoomsSupport && !mutualRoomsSupport && !queryMutualRoomsSupport) {
|
||||
throw Error("Server does not support the Mutual Rooms API");
|
||||
}
|
||||
|
||||
const path = utils.encodeUri(
|
||||
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 = {};
|
||||
}
|
||||
|
||||
const res = await this.http.authedRequest<{ joined: string[] }>(Method.Get, path, undefined, undefined, {
|
||||
// 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,
|
||||
});
|
||||
return res.joined;
|
||||
|
||||
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