Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/GatewayHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { IBasicProtocolMessage } from "./MessageFormatter";
import { ProfileSync } from "./ProfileSync";
import { IGatewayRoom } from "./bifrost/Gateway";
import { MatrixMembershipEvent } from "./MatrixTypes";
import { XMPP_PROTOCOL } from "./xmppjs/XJSInstance";

const log = Logging.get("GatewayHandler");

Expand Down Expand Up @@ -130,9 +131,21 @@ export class GatewayHandler {
}
const room = await this.getVirtualRoom(context.matrix.getId(), this.bridge.getIntent());
if (this.bridge.getBot().isRemoteUser(event.state_key)) {
const { username } = this.purple.getUsernameFromMxid(event.state_key, this.config.bridge.userPrefix);
// XXX: Hardcoded protocol
const remoteUser = (await this.store.getAccountsForMatrixUser(event.sender, XMPP_PROTOCOL.id))[0];
// This might be a kick or ban.
log.info(`Forwarding remote membership for ${event.state_key} in ${chatName}`);
this.purple.gateway.sendMatrixMembership(chatName, event, room);
this.purple.gateway.sendMatrixMembership(chatName, event, room, {
recipient: {
isRemote: true,
username,
},
sender: {
isRemote: !remoteUser,
username: remoteUser?.username,
}
});
return;
}
const existingMembership = room.membership.find((ev) => ev.stateKey === event.state_key);
Expand All @@ -153,7 +166,7 @@ export class GatewayHandler {
});
}
log.info(`Updating membership for ${event.state_key} in ${chatName} ${room.roomId}`);
this.purple.gateway.sendMatrixMembership(chatName, event, room);
this.purple.gateway.sendMatrixMembership(chatName, event, room, { });
}

public async rejoinRemoteUser(mxid: string, roomid: string) {
Expand Down
5 changes: 3 additions & 2 deletions src/MatrixEventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,12 @@ export class MatrixEventHandler {
} catch (e) {
log.error("Failed to handle invite for bot:", e);
}
} else if (event.content.is_direct && bridgeBot.isRemoteUser(event.state_key)) {
} else if (event.state_key && event.content.is_direct && bridgeBot.isRemoteUser(event.state_key)) {
log.debug("Got request to PM", event.state_key);
const {
username,
protocol,
} = this.purple.getUsernameFromMxid(event.state_key!, this.config.bridge.userPrefix);
} = this.purple.getUsernameFromMxid(event.state_key, this.config.bridge.userPrefix);
log.debug("Mapped username to", username);
const remoteData = {
matrixUser: event.sender,
Expand Down Expand Up @@ -624,6 +624,7 @@ Say \`help\` for more commands.
const name: string = context.remote.get("room_name");
const roomProtocol: string = context.remote.get("protocol_id");
if (isGateway) {
const ghostDetails = this.purple.getUsernameFromMxid(event.state_key, this.config.bridge.userPrefix);
await this.gatewayHandler.sendMatrixMembership(
name, context, event,
);
Expand Down
13 changes: 12 additions & 1 deletion src/bifrost/Gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface IGateway extends IProfileProvider {
sender: string, body: IBasicProtocolMessage, room: IGatewayRoom,
): void;
sendMatrixMembership(
chatName: string, event: MatrixMembershipEvent, room: IGatewayRoom,
chatName: string, event: MatrixMembershipEvent, room: IGatewayRoom, context: MatrixMembershipContext,
): void;
sendStateChange(
chatName: string, sender: string, type: "topic"|"name"|"avatar", room: IGatewayRoom,
Expand All @@ -34,3 +34,14 @@ export interface IGatewayRoom {
}[];
// remotes: string[];
}

export interface MatrixMembershipContext {
recipient?: {
isRemote: boolean;
username: string;
};
sender?: {
isRemote: boolean;
username: string;
}
}
7 changes: 5 additions & 2 deletions src/xmppjs/GatewayMUCMembership.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ import { JID, jid } from "@xmpp/jid";
interface IGatewayMember {
type: "xmpp"|"matrix";
anonymousJid: JID;
matrixId: string;
}

export interface IGatewayMemberXmpp extends IGatewayMember {
type: "xmpp";
realJid: JID;
devices: Set<string>;
matrixId: string;
}

export interface IGatewayMemberMatrix extends IGatewayMember {
type: "matrix";
matrixId: string;
}

const FLAT_SUPPORTED = [].flat !== undefined;
Expand All @@ -37,6 +36,10 @@ export class GatewayMUCMembership {
return this.getMembers(chatName).find((user) => user.anonymousJid.toString() === anonJid) as G;
}

public getMemberByMatrixId(chatName: string, matrixId: string): IGatewayMember|undefined {
return this.getMembers(chatName).find((user) => user.matrixId === matrixId);
}

public getMatrixMemberByMatrixId(chatName: string, matrixId: string): IGatewayMemberMatrix|undefined {
return this.getMatrixMembers(chatName).find((user) => user.matrixId === matrixId);
}
Expand Down
21 changes: 18 additions & 3 deletions src/xmppjs/GatewayStateResolve.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import jid from "@xmpp/jid";
import { Logging } from "matrix-appservice-bridge";
import { MatrixMembershipContext } from "../bifrost/Gateway";
import { MatrixMembershipEvent } from "../MatrixTypes";
import { GatewayMUCMembership } from "./GatewayMUCMembership";
import { IStza, PresenceAffiliation, PresenceRole, StzaBase, StzaPresenceItem } from "./Stanzas";
import { IStza, PresenceAffiliation, PresenceRole, StzaBase, StzaMessageInvite, StzaPresenceItem } from "./Stanzas";
import { XMPPStatusCode } from "./XMPPConstants";

const log = Logging.get("GatewayStateResolve");
Expand All @@ -24,7 +25,7 @@ function sendToAllDevices(presence: StzaPresenceItem, devices: Set<string>) {
}

export class GatewayStateResolve {
static resolveMatrixStateToXMPP(chatName: string, members: GatewayMUCMembership, event: MatrixMembershipEvent): IStza[] {
static resolveMatrixStateToXMPP(chatName: string, members: GatewayMUCMembership, event: MatrixMembershipEvent, context: MatrixMembershipContext= {}): IStza[] {
const membership = event.content.membership;
let stanzas: IStza[] = [];
const allDevices = members.getXmppMembersDevices(chatName);
Expand Down Expand Up @@ -139,7 +140,21 @@ export class GatewayStateResolve {
return [];
}
} else if (membership === "invite") {
// TODO: Invites
if (!existingMember || !context.recipient || !context.sender) {
// Cannot handle an invite from someone not in the room.
return [];
}
if (context.recipient?.isRemote) {
stanzas = [new StzaMessageInvite(
context.sender.username,
context.recipient.username,
chatName,
event.content.reason,
event.event_id
)];
} else {
// XXX: Somehow reflect to the room that the user was invited.
}
}
return stanzas;
}
Expand Down
23 changes: 23 additions & 0 deletions src/xmppjs/Stanzas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,29 @@ export class StzaMessageSubject extends StzaBase {
}
}

export class StzaMessageInvite extends StzaBase {
constructor(from: string,
to: string,
public chatName: string,
public reason?: string,
id?: string) {
super(from, to, id);
}

get xml() {
const reason = this.reason ? `<reason>${he.encode(this.reason)}</reason>` : "";
return `<message
from='${this.from}'
id='${this.id}'
to='${this.to}'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<invite to='${this.chatName}'>${reason}
</invite>
</x>
</message>`;
}
}

export class StzaIqPing extends StzaBase {
protected extraContent: string = "";
constructor(
Expand Down
2 changes: 1 addition & 1 deletion src/xmppjs/XJSAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ export class XmppJsAccount implements IBifrostAccount {
}
resolve(true);
});
Metrics.remoteCall("xmpp.iq.ping");
});
Metrics.remoteCall("xmpp.iq.ping");
}

public reconnectToRooms() {
Expand Down
6 changes: 3 additions & 3 deletions src/xmppjs/XJSGateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Logging } from "matrix-appservice-bridge";
import { IConfigBridge } from "../Config";
import { IBasicProtocolMessage } from "..//MessageFormatter";
import { IGatewayJoin, IUserStateChanged, IStoreRemoteUser, IUserInfo } from "../bifrost/Events";
import { IGatewayRoom } from "../bifrost/Gateway";
import { IGatewayRoom, MatrixMembershipContext } from "../bifrost/Gateway";
import { PresenceCache } from "./PresenceCache";
import { XHTMLIM } from "./XHTMLIM";
import { BifrostRemoteUser } from "../store/BifrostRemoteUser";
Expand Down Expand Up @@ -231,11 +231,11 @@ export class XmppJsGateway implements IGateway {
}

public async sendMatrixMembership(
chatName: string, event: MatrixMembershipEvent,
chatName: string, event: MatrixMembershipEvent, room: IGatewayRoom, context: MatrixMembershipContext,
) {
log.info(`Got new ${event.content.membership} for ${event.state_key} (from: ${event.sender}) in ${chatName}`);
// Iterate around each joined member and add the new presence step.
const presenceEvents = GatewayStateResolve.resolveMatrixStateToXMPP(chatName, this.members, event);
const presenceEvents = GatewayStateResolve.resolveMatrixStateToXMPP(chatName, this.members, event, context);
if (presenceEvents.length === 0) {
log.info(`Nothing to do for ${event.event_id}`);
return;
Expand Down