Skip to content

Commit

Permalink
Handle mediated muc invites that include legacy reason.
Browse files Browse the repository at this point in the history
  • Loading branch information
legastero committed Sep 9, 2019
1 parent 003628a commit 54286ed
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 31 deletions.
2 changes: 2 additions & 0 deletions src/jxt/Definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export interface DefinitionUpdateOptions {
exporters: Map<FieldName, FieldExporter>;
contexts: Map<string, PathContext>;
optionalNamespaces: Map<string, string>;
typeOrder?: number;
}

export interface DefinitionOptions {
Expand All @@ -81,6 +82,7 @@ export interface DefinitionOptions {
aliases?: Array<string | LinkPath>;
childrenExportOrder?: { [key: string]: number };
optionalNamespaces?: { [prefix: string]: string };
typeOrder?: number;
}

export interface LinkPath {
Expand Down
10 changes: 7 additions & 3 deletions src/jxt/Registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ export default class Registry {
this.languageResolver = resolver;
}

public import(xml: XMLElement, context: TranslationContext = {}): JSONData | undefined {
public import(
xml: XMLElement,
context: TranslationContext = { registry: this }
): JSONData | undefined {
if (!this.hasTranslator(xml.getNamespace(), xml.getName())) {
return;
}
Expand Down Expand Up @@ -62,7 +65,7 @@ export default class Registry {
public export<T extends JSONData = JSONData>(
path: string,
data: T,
context: TranslationContext = {}
context: TranslationContext = { registry: this }
): XMLElement | undefined {
if (!context.acceptLanguages) {
context.acceptLanguages = [];
Expand Down Expand Up @@ -220,7 +223,8 @@ export default class Registry {
importers,
namespace: definition.namespace,
optionalNamespaces,
type: definition.type
type: definition.type,
typeOrder: definition.typeOrder
});

for (const link of aliases) {
Expand Down
26 changes: 22 additions & 4 deletions src/jxt/Translator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default class Translator {
public placeholder: boolean;
public typeField: FieldName;
public typeValues: Map<XName, Type>;
public typeOrders: Map<Type, number>;
public defaultType: Type;
public languageField: FieldName;
public importers: Map<XName, Importer>;
Expand All @@ -33,6 +34,7 @@ export default class Translator {
this.defaultType = '';
this.languageField = 'lang';
this.typeValues = new Map();
this.typeOrders = new Map();
this.importers = new Map();
this.exporters = new Map();
this.children = new Map();
Expand Down Expand Up @@ -207,6 +209,9 @@ export default class Translator {

if (opts.type) {
this.typeValues.set(xid, opts.type);
if (opts.typeOrder) {
this.typeOrders.set(opts.type, opts.typeOrder);
}
} else if (this.typeField && !opts.type) {
for (const [, imp] of this.importers) {
for (const [fieldName, fieldImporter] of opts.importers) {
Expand Down Expand Up @@ -251,7 +256,7 @@ export default class Translator {
this.parents = new Set();
}

public import(xml: XMLElement, parentContext: TranslationContext = {}): JSONData | undefined {
public import(xml: XMLElement, parentContext: TranslationContext): JSONData | undefined {
const xid = `{${xml.getNamespace()}}${xml.getName()}`;
const output: JSONData = {};

Expand Down Expand Up @@ -330,8 +335,13 @@ export default class Translator {
output[fieldName] = [];
}
output[fieldName].push(childOutput);
} else {
} else if (!output[fieldName]) {
output[fieldName] = childOutput;
} else {
output[fieldName] = translator.resolveCollision(
output[fieldName],
childOutput
);
}
}
}
Expand All @@ -350,7 +360,7 @@ export default class Translator {
return output;
}

public export(data: JSONData, parentContext: TranslationContext = {}): XMLElement | undefined {
public export(data: JSONData, parentContext: TranslationContext): XMLElement | undefined {
if (!data) {
return;
}
Expand Down Expand Up @@ -410,7 +420,7 @@ export default class Translator {
keys.sort((key1, key2) => {
const a = exporter.fieldOrders.get(key1) || 100000;
const b = exporter.fieldOrders.get(key2) || 100000;
return a < b ? -1 : a > b ? 1 : 0;
return a - b;
});
for (const key of keys) {
if (key === this.languageField) {
Expand Down Expand Up @@ -454,4 +464,12 @@ export default class Translator {

return output;
}

private resolveCollision(existingData: JSONData, newData: JSONData): JSONData {
const existingOrder =
this.typeOrders.get(existingData[this.typeField] || this.defaultType) || 0;
const newOrder = this.typeOrders.get(newData[this.typeField] || this.defaultType) || 0;

return existingOrder <= newOrder ? existingData : newData;
}
}
11 changes: 6 additions & 5 deletions src/plugins/muc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,14 @@ export default function(client: Agent) {
return;
}

if (msg.muc.type === 'direct-invite') {
if (msg.muc.type === 'direct-invite' || (!msg.muc.invite && msg.legacyMUC)) {
const invite = msg.muc.type === 'direct-invite' ? msg.muc : msg.legacyMUC!;
client.emit('muc:invite', {
from: msg.from,
password: msg.muc.password,
reason: msg.muc.reason,
room: msg.muc.jid!,
thread: msg.muc.thread,
password: invite.password,
reason: invite.reason,
room: invite.jid!,
thread: invite.thread,
type: 'direct'
});
return;
Expand Down
60 changes: 42 additions & 18 deletions src/protocol/xep0045.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import {
dateAttribute,
deepChildText,
DefinitionOptions,
extendMessage,
findAll,
integerAttribute,
JIDAttribute,
multipleChildAttribute,
Expand All @@ -58,6 +60,7 @@ declare module './' {

export interface Message {
muc?: MUCInfo | MUCDirectInvite;
legacyMUC?: MUCDirectInvite;
}

export interface IQPayload {
Expand Down Expand Up @@ -126,6 +129,7 @@ export interface MUCDirectInvite {
reason?: string;
thread?: string;
continue?: boolean;
legacyReason?: string;
}

export interface MUCDecline {
Expand Down Expand Up @@ -156,9 +160,6 @@ export interface MUCUnique {
name?: string;
}

const reasonAttribute = attribute('reason');
const reasonText = text();

const Protocol: DefinitionOptions[] = [
addAlias(NS_DATAFORM, 'x', [{ path: 'iq.muc.form', selector: 'configure' }]),
{
Expand Down Expand Up @@ -203,7 +204,8 @@ const Protocol: DefinitionOptions[] = [
},
namespace: NS_MUC_USER,
type: 'info',
typeField: 'type'
typeField: 'type',
typeOrder: 1
},
{
element: 'actor',
Expand Down Expand Up @@ -299,24 +301,15 @@ const Protocol: DefinitionOptions[] = [
action: staticValue('invite'),
continue: booleanAttribute('continue'),
jid: JIDAttribute('jid'),
legacyReason: text(),
password: attribute('password'),
reason: {
importer(xml, context) {
const attr = reasonAttribute.importer(xml, context);
if (attr) {
return attr;
}
return reasonText.importer(xml, context);
},
exporter(xml, data, context) {
reasonAttribute.exporter(xml, data, context);
}
},
reason: attribute('reason'),
thread: attribute('thread')
},
namespace: NS_MUC_DIRECT_INVITE,
path: 'message.muc',
type: 'direct-invite'
type: 'direct-invite',
typeOrder: 2
},

// XEP-0307
Expand All @@ -328,6 +321,37 @@ const Protocol: DefinitionOptions[] = [
namespace: NS_MUC_UNIQUE,
path: 'iq.muc',
type: 'unique'
}
},

extendMessage({
legacyMUC: {
exporter(xml, value, context) {
const out = context.registry
? context.registry.export('message.muc', { ...value, type: 'direct-invite' })
: undefined;
if (out) {
xml.appendChild(out);
}
},
exportOrder: 100001,
importer(xml, context) {
const mucElement = findAll(xml, NS_MUC_USER, 'x')[0];
if (!mucElement) {
return;
}
const confElement = findAll(xml, NS_MUC_DIRECT_INVITE, 'x')[0];
if (!confElement) {
return;
}
return context.registry
? context.registry.import(confElement, {
...context,
path: 'message'
})
: undefined;
},
importOrder: -1
}
})
];
export default Protocol;
62 changes: 62 additions & 0 deletions test/protocol-cases/xep0045/mediated-invite-legacy-reason.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
[
"message",
{
"body": "admin@domain/QfQz53QX invited you to the room call-rb8j8seq@conference.quobis (You've been added to the conference's chat room)",
"from": "call-rb8j8seq@conference.domain",
"id": "4fd708bd0eb29b7e",
"legacyMUC": {
"jid": "call-rb8j8seq@domain.quobis",
"legacyReason": "You've been added to the conference's chat room"
},
"muc": {
"invite": [
{
"from": "admin@domain/QfQz53QX",
"reason": "You've been added to the conference's chat room"
}
]
},
"stanzaIds": [
{
"by": "dev6@domain",
"id": "1dHg6QfzhDdy2oXP"
}
],
"to": "dev6@domain"
},
{
"alternateLanguageBodies": [
{
"lang": "",
"value": "admin@domain/QfQz53QX invited you to the room call-rb8j8seq@conference.quobis (You've been added to the conference's chat room)"
}
],
"body": "admin@domain/QfQz53QX invited you to the room call-rb8j8seq@conference.quobis (You've been added to the conference's chat room)",
"from": "call-rb8j8seq@conference.domain",
"id": "4fd708bd0eb29b7e",
"lang": "",
"legacyMUC": {
"action": "invite",
"legacyReason": "You've been added to the conference's chat room",
"jid": "call-rb8j8seq@domain.quobis",
"type": "direct-invite"
},
"muc": {
"action": "invite",
"invite": [
{
"from": "admin@domain/QfQz53QX",
"reason": "You've been added to the conference's chat room"
}
],
"statusCodes": []
},
"stanzaIds": [
{
"by": "dev6@domain",
"id": "1dHg6QfzhDdy2oXP"
}
],
"to": "dev6@domain"
}
]
10 changes: 10 additions & 0 deletions test/protocol-cases/xep0045/mediated-invite-legacy-reason.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<message id="4fd708bd0eb29b7e" to="dev6@domain" xmlns="jabber:client" from="call-rb8j8seq@conference.domain">
<body>admin@domain/QfQz53QX invited you to the room call-rb8j8seq@conference.quobis (You've been added to the conference's chat room)</body>
<x xmlns="http://jabber.org/protocol/muc#user">
<invite from="admin@domain/QfQz53QX">
<reason>You've been added to the conference's chat room</reason>
</invite>
</x>
<stanza-id id="1dHg6QfzhDdy2oXP" xmlns="urn:xmpp:sid:0" by="dev6@domain" />
<x xmlns="jabber:x:conference" jid="call-rb8j8seq@domain.quobis">You've been added to the conference's chat room</x>
</message>
34 changes: 34 additions & 0 deletions test/protocol-cases/xep0045/private-message-direct-invite.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
"message",
{
"from": "crone1@shakespeare.lit/desktop",
"legacyMUC": {
"action": "invite",
"continue": true,
"jid": "darkcave@macbeth.shakespeare.lit",
"password": "cauldronburn",
"reason": "Hey Hecate, this is the place for all good witches!",
"thread": "e0ffe42b28561960c6b12b944a092794b9683a38",
"type": "direct-invite"
},
"muc": {},
"to": "hecate@shakespeare.lit"
},
{
"from": "crone1@shakespeare.lit/desktop",
"lang": "",
"legacyMUC": {
"action": "invite",
"continue": true,
"jid": "darkcave@macbeth.shakespeare.lit",
"password": "cauldronburn",
"reason": "Hey Hecate, this is the place for all good witches!",
"thread": "e0ffe42b28561960c6b12b944a092794b9683a38",
"type": "direct-invite"
},
"muc": {
"statusCodes": []
},
"to": "hecate@shakespeare.lit"
}
]
11 changes: 11 additions & 0 deletions test/protocol-cases/xep0045/private-message-direct-invite.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<message
from='crone1@shakespeare.lit/desktop'
to='hecate@shakespeare.lit'>
<x xmlns="http://jabber.org/protocol/muc#user" />
<x xmlns='jabber:x:conference'
continue='1'
jid='darkcave@macbeth.shakespeare.lit'
password='cauldronburn'
reason='Hey Hecate, this is the place for all good witches!'
thread='e0ffe42b28561960c6b12b944a092794b9683a38'/>
</message>
12 changes: 12 additions & 0 deletions test/protocol-cases/xep0045/status-code-change.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
"message",
{
"from": "test@muc.example.com",
"lang": "",
"muc": {
"statusCodes": ["104"]
},
"to": "user@example.net/conn1",
"type": "groupchat"
}
]
Loading

0 comments on commit 54286ed

Please sign in to comment.