Socket
Socket
Sign inDemoInstall

mx-puppet-bridge

Package Overview
Dependencies
267
Maintainers
1
Versions
112
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.19 to 0.0.20

lib/structures/delayedfunction.d.ts

1

lib/channelsyncroniser.d.ts

@@ -29,2 +29,3 @@ /// <reference types="node" />

getPartsFromMxid(mxid: string): IRemoteChan | null;
maybeLeaveGhost(chanMxid: string, userMxid: string): Promise<void>;
delete(data: IRemoteChan, keepUsers?: boolean): Promise<void>;

@@ -31,0 +32,0 @@ deleteForMxid(mxid: string): Promise<void>;

@@ -242,2 +242,43 @@ "use strict";

}
maybeLeaveGhost(chanMxid, userMxid) {
return __awaiter(this, void 0, void 0, function* () {
log.info(`Maybe leaving ghost ${userMxid} from ${chanMxid}`);
const ghosts = yield this.bridge.puppetStore.getGhostsInChan(chanMxid);
if (!ghosts.includes(userMxid)) {
log.verbose("Ghost not in room!");
return; // not in chan, nothing to do
}
if (ghosts.length === 1) {
log.verbose("Ghost is the only one in the room!");
return; // we are the last ghost in the chan, we can't leave
}
const intent = this.bridge.AS.getIntentForUserId(userMxid);
const client = intent.underlyingClient;
const oldOp = yield this.chanStore.getChanOp(chanMxid);
if (oldOp === userMxid) {
// we need to get a new OP!
log.verbose("We are the OP in the room, we need to pass on OP");
const newOp = ghosts.find((element) => element !== userMxid);
if (!newOp) {
log.verbose("Noone to pass OP to!");
return; // we can't make a new OP, sorry
}
log.verbose(`Giving OP to ${newOp}...`);
try {
// give the user OP
const powerLevels = yield client.getRoomStateEvent(chanMxid, "m.room.power_levels", "");
powerLevels.users[newOp] = powerLevels.users[oldOp];
yield client.sendStateEvent(chanMxid, "m.room.power_levels", "", powerLevels);
yield this.chanStore.setChanOp(chanMxid, newOp);
}
catch (err) {
log.error("Couldn't set new chan OP", err);
return;
}
}
// and finally we passed all checks and can leave
yield intent.leaveRoom(chanMxid);
yield this.bridge.puppetStore.leaveGhostFromChan(userMxid, chanMxid);
});
}
delete(data, keepUsers = false) {

@@ -306,3 +347,3 @@ return __awaiter(this, void 0, void 0, function* () {

try {
yield intent.underlyingClient.leaveRoom(entry.mxid);
yield intent.leaveRoom(entry.mxid);
}

@@ -309,0 +350,0 @@ catch (err) {

12

lib/db/chanstore.js

@@ -130,9 +130,13 @@ "use strict";

return __awaiter(this, void 0, void 0, function* () {
const row = yield this.db.Get("SELECT * FROM chan_op WHERE chan_mxid=$chan AND user_mxid=$user", {
const row = yield this.db.Get("SELECT * FROM chan_op WHERE chan_mxid=$chan", {
chan: chanMxid,
user: userMxid,
});
if (row) {
// nothing to do, we are already one
return;
if (row.user_mxid === userMxid) {
// nothing to do, we are already set
return;
}
yield this.db.Run("DELETE FROM chan_op WHERE chan_mxid=$chan", {
chan: chanMxid,
});
}

@@ -139,0 +143,0 @@ yield this.db.Run("INSERT INTO chan_op (chan_mxid, user_mxid) VALUES ($chan, $user)", {

@@ -32,6 +32,8 @@ import { IDatabaseConnector } from "./connector";

delete(puppetId: number): Promise<void>;
isGhostInChan(ghostMxid: string, chanMxid: string): Promise<boolean>;
joinGhostToChan(ghostMxid: string, chanMxid: string): Promise<void>;
getGhostsInChan(chan: string): Promise<string[]>;
emptyGhostsInChan(chan: string): Promise<void>;
leaveGhostFromChan(ghostMxid: string, chanMxid: string): Promise<void>;
private getRow;
}

@@ -195,3 +195,3 @@ "use strict";

}
joinGhostToChan(ghostMxid, chanMxid) {
isGhostInChan(ghostMxid, chanMxid) {
return __awaiter(this, void 0, void 0, function* () {

@@ -202,4 +202,9 @@ const exists = yield this.db.Get("SELECT * FROM ghosts_joined_chans WHERE ghost_mxid = $ghostMxid AND chan_mxid = $chanMxid", {

});
if (exists) {
return; // nothing to do
return exists ? true : false;
});
}
joinGhostToChan(ghostMxid, chanMxid) {
return __awaiter(this, void 0, void 0, function* () {
if (yield this.isGhostInChan(ghostMxid, chanMxid)) {
return;
}

@@ -227,2 +232,11 @@ yield this.db.Run("INSERT INTO ghosts_joined_chans (ghost_mxid, chan_mxid) VALUES ($ghostMxid, $chanMxid)", {

}
leaveGhostFromChan(ghostMxid, chanMxid) {
return __awaiter(this, void 0, void 0, function* () {
yield this.db.Run("DELETE FROM ghosts_joined_chans " +
"WHERE ghost_mxid = $g AND chan_mxid = $c", {
g: ghostMxid,
c: chanMxid,
});
});
}
getRow(row) {

@@ -229,0 +243,0 @@ try {

@@ -109,2 +109,3 @@ /// <reference types="node" />

private memberInfoCache;
private delayedFunction;
constructor(registrationPath: string, configPath: string, features: IPuppetBridgeFeatures);

@@ -111,0 +112,0 @@ readConfig(): void;

@@ -30,5 +30,7 @@ "use strict";

const typinghandler_1 = require("./typinghandler");
const delayedfunction_1 = require("./structures/delayedfunction");
const log = new log_1.Log("PuppetBridge");
// tslint:disable-next-line:no-magic-numbers
// tslint:disable no-magic-numbers
const PUPPET_INVITE_CACHE_LIFETIME = 1000 * 60 * 60 * 24;
const GHOST_PUPPET_LEAVE_TIMEOUT = 1000 * 60 * 60;
const DEFAULT_TYPING_TIMEOUT = 30000;

@@ -43,2 +45,3 @@ class PuppetBridge extends events_1.EventEmitter {

this.hooks = {};
this.delayedFunction = new delayedfunction_1.DelayedFunction();
}

@@ -699,3 +702,4 @@ readConfig() {

log.verbose(`Preparing send parameters`, params);
const puppetMxid = yield this.provisioner.getMxid(params.chan.puppetId);
const puppetData = yield this.provisioner.get(params.chan.puppetId);
const puppetMxid = puppetData ? puppetData.puppetMxid : "";
const client = yield this.userSync.getClient(params.user);

@@ -718,2 +722,8 @@ const userId = yield client.getUserId();

yield intent.ensureRegisteredAndJoined(mxid);
if (puppetData && puppetData.userId === params.user.userId) {
const delayedKey = `${userId}_${mxid}`;
this.delayedFunction.set(delayedKey, () => __awaiter(this, void 0, void 0, function* () {
yield this.chanSync.maybeLeaveGhost(mxid, userId);
}), GHOST_PUPPET_LEAVE_TIMEOUT);
}
}

@@ -955,5 +965,2 @@ // ensure our puppeted user is in the room

return __awaiter(this, void 0, void 0, function* () {
if (ghostId === this.appservice.botIntent.userId) {
return; // we don't handle ghost user here
}
// we CAN'T check for if the room exists here, as if we create a new room

@@ -963,2 +970,4 @@ // the m.room.member event triggers before the room is incerted into the store

yield this.store.puppetStore.joinGhostToChan(ghostId, roomId);
// maybe remove the bot user, if it is present
yield this.chanSync.maybeLeaveGhost(roomId, this.appservice.botIntent.userId);
});

@@ -1015,2 +1024,3 @@ }

if (this.appservice.isNamespacedUser(userId)) {
yield this.store.puppetStore.leaveGhostFromChan(userId, roomId);
if (userId !== event.sender) {

@@ -1017,0 +1027,0 @@ // puppet got kicked, unbridging room

{
"name": "mx-puppet-bridge",
"version": "0.0.19",
"version": "0.0.20",
"description": "Matrix Puppeting Bridge library",

@@ -5,0 +5,0 @@ "repository": {

@@ -270,2 +270,45 @@ import { PuppetBridge } from "./puppetbridge";

public async maybeLeaveGhost(chanMxid: string, userMxid: string) {
log.info(`Maybe leaving ghost ${userMxid} from ${chanMxid}`);
const ghosts = await this.bridge.puppetStore.getGhostsInChan(chanMxid);
if (!ghosts.includes(userMxid)) {
log.verbose("Ghost not in room!");
return; // not in chan, nothing to do
}
if (ghosts.length === 1) {
log.verbose("Ghost is the only one in the room!");
return; // we are the last ghost in the chan, we can't leave
}
const intent = this.bridge.AS.getIntentForUserId(userMxid);
const client = intent.underlyingClient;
const oldOp = await this.chanStore.getChanOp(chanMxid);
if (oldOp === userMxid) {
// we need to get a new OP!
log.verbose("We are the OP in the room, we need to pass on OP");
const newOp = ghosts.find((element: string) => element !== userMxid);
if (!newOp) {
log.verbose("Noone to pass OP to!");
return; // we can't make a new OP, sorry
}
log.verbose(`Giving OP to ${newOp}...`);
try {
// give the user OP
const powerLevels = await client.getRoomStateEvent(
chanMxid, "m.room.power_levels", "",
);
powerLevels.users[newOp] = powerLevels.users[oldOp];
await client.sendStateEvent(
chanMxid, "m.room.power_levels", "", powerLevels,
);
await this.chanStore.setChanOp(chanMxid, newOp);
} catch (err) {
log.error("Couldn't set new chan OP", err);
return;
}
}
// and finally we passed all checks and can leave
await intent.leaveRoom(chanMxid);
await this.bridge.puppetStore.leaveGhostFromChan(userMxid, chanMxid);
}
public async delete(data: IRemoteChan, keepUsers: boolean = false) {

@@ -332,3 +375,3 @@ const chan = await this.maybeGet(data);

try {
await intent.underlyingClient.leaveRoom(entry.mxid);
await intent.leaveRoom(entry.mxid);
} catch (err) {

@@ -335,0 +378,0 @@ log.warn("Failed to trigger client leave room", err);

@@ -143,9 +143,13 @@ import { IDatabaseConnector, ISqlRow } from "./connector";

public async setChanOp(chanMxid: string, userMxid: string) {
const row = await this.db.Get("SELECT * FROM chan_op WHERE chan_mxid=$chan AND user_mxid=$user", {
const row = await this.db.Get("SELECT * FROM chan_op WHERE chan_mxid=$chan", {
chan: chanMxid,
user: userMxid,
});
if (row) {
// nothing to do, we are already one
return;
if ((row.user_mxid as string) === userMxid) {
// nothing to do, we are already set
return;
}
await this.db.Run("DELETE FROM chan_op WHERE chan_mxid=$chan", {
chan: chanMxid,
});
}

@@ -152,0 +156,0 @@ await this.db.Run("INSERT INTO chan_op (chan_mxid, user_mxid) VALUES ($chan, $user)", {

@@ -197,3 +197,3 @@ import { IDatabaseConnector, ISqlRow } from "./connector";

public async joinGhostToChan(ghostMxid: string, chanMxid: string) {
public async isGhostInChan(ghostMxid: string, chanMxid: string): Promise<boolean> {
const exists = await this.db.Get(

@@ -205,4 +205,8 @@ "SELECT * FROM ghosts_joined_chans WHERE ghost_mxid = $ghostMxid AND chan_mxid = $chanMxid"

});
if (exists) {
return; // nothing to do
return exists ? true : false;
}
public async joinGhostToChan(ghostMxid: string, chanMxid: string) {
if (await this.isGhostInChan(ghostMxid, chanMxid)) {
return;
}

@@ -228,2 +232,10 @@ await this.db.Run("INSERT INTO ghosts_joined_chans (ghost_mxid, chan_mxid) VALUES ($ghostMxid, $chanMxid)", {

public async leaveGhostFromChan(ghostMxid: string, chanMxid: string) {
await this.db.Run("DELETE FROM ghosts_joined_chans " +
"WHERE ghost_mxid = $g AND chan_mxid = $c", {
g: ghostMxid,
c: chanMxid,
});
}
private getRow(row: ISqlRow): IPuppet | null {

@@ -230,0 +242,0 @@ try {

@@ -30,8 +30,11 @@ import * as fs from "fs";

import { TypingHandler } from "./typinghandler";
import { DelayedFunction } from "./structures/delayedfunction";
const log = new Log("PuppetBridge");
// tslint:disable-next-line:no-magic-numbers
// tslint:disable no-magic-numbers
const PUPPET_INVITE_CACHE_LIFETIME = 1000 * 60 * 60 * 24;
const GHOST_PUPPET_LEAVE_TIMEOUT = 1000 * 60 * 60;
const DEFAULT_TYPING_TIMEOUT = 30000;
// tslint:enable no-magic-numbers

@@ -153,2 +156,3 @@ interface ISendInfo {

private memberInfoCache: { [roomId: string]: { [userId: string]: IMemberInfo } };
private delayedFunction: DelayedFunction;

@@ -163,2 +167,3 @@ constructor(

this.hooks = {} as IPuppetBridgeHooks;
this.delayedFunction = new DelayedFunction();
}

@@ -806,3 +811,4 @@

log.verbose(`Preparing send parameters`, params);
const puppetMxid = await this.provisioner.getMxid(params.chan.puppetId);
const puppetData = await this.provisioner.get(params.chan.puppetId);
const puppetMxid = puppetData ? puppetData.puppetMxid : "";
const client = await this.userSync.getClient(params.user);

@@ -825,2 +831,8 @@ const userId = await client.getUserId();

await intent.ensureRegisteredAndJoined(mxid);
if (puppetData && puppetData.userId === params.user.userId) {
const delayedKey = `${userId}_${mxid}`;
this.delayedFunction.set(delayedKey, async () => {
await this.chanSync.maybeLeaveGhost(mxid, userId);
}, GHOST_PUPPET_LEAVE_TIMEOUT);
}
}

@@ -1058,6 +1070,2 @@

private async handleGhostJoinEvent(roomId: string, ghostId: string) {
if (ghostId === this.appservice.botIntent.userId) {
return; // we don't handle ghost user here
}
// we CAN'T check for if the room exists here, as if we create a new room

@@ -1068,2 +1076,5 @@ // the m.room.member event triggers before the room is incerted into the store

await this.store.puppetStore.joinGhostToChan(ghostId, roomId);
// maybe remove the bot user, if it is present
await this.chanSync.maybeLeaveGhost(roomId, this.appservice.botIntent.userId);
}

@@ -1118,2 +1129,3 @@

if (this.appservice.isNamespacedUser(userId)) {
await this.store.puppetStore.leaveGhostFromChan(userId, roomId);
if (userId !== event.sender) {

@@ -1120,0 +1132,0 @@ // puppet got kicked, unbridging room

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc