diff options
author | sualko <klaus@jsxc.org> | 2019-05-24 16:16:57 +0300 |
---|---|---|
committer | sualko <klaus@jsxc.org> | 2019-05-24 16:16:57 +0300 |
commit | c211ff6b85b73d72715ef366f6c0c767d1fb1beb (patch) | |
tree | 89d64c207798159f86fbe15d9a7649a659115ccb | |
parent | 60fdc20b6cb1348f47a4cbef8a0dc6ba31eadfeb (diff) |
fix: mam archive selectionrefactoring
-rw-r--r-- | src/Contact.interface.ts | 4 | ||||
-rw-r--r-- | src/Contact.ts | 8 | ||||
-rw-r--r-- | src/connection/AbstractConnection.ts | 11 | ||||
-rw-r--r-- | src/connection/Connection.interface.ts | 2 | ||||
-rw-r--r-- | src/plugin/PluginAPI.interface.ts | 5 | ||||
-rw-r--r-- | src/plugin/PluginAPI.ts | 8 | ||||
-rw-r--r-- | src/plugins/mam/Archive.ts | 42 | ||||
-rw-r--r-- | src/plugins/mam/Plugin.ts | 113 |
8 files changed, 130 insertions, 63 deletions
diff --git a/src/Contact.interface.ts b/src/Contact.interface.ts index 2be8797f..d601ccaf 100644 --- a/src/Contact.interface.ts +++ b/src/Contact.interface.ts @@ -63,6 +63,10 @@ export interface IContact { getType(): ContactType; + isGroupChat(): boolean; + + isChat(): boolean; + getNumberOfUnreadMessages(): number; hasName(): boolean; diff --git a/src/Contact.ts b/src/Contact.ts index f6675d91..c9b9c315 100644 --- a/src/Contact.ts +++ b/src/Contact.ts @@ -220,6 +220,14 @@ export default class Contact implements IIdentifiable, IContact { return this.data.get('type'); } + public isGroupChat() { + return this.getType() === ContactType.GROUPCHAT; + } + + public isChat() { + return this.getType() === ContactType.CHAT; + } + public getNumberOfUnreadMessages(): number { return this.transcript.getNumberOfUnreadMessages(); } diff --git a/src/connection/AbstractConnection.ts b/src/connection/AbstractConnection.ts index e3f847be..ba68c494 100644 --- a/src/connection/AbstractConnection.ts +++ b/src/connection/AbstractConnection.ts @@ -184,13 +184,14 @@ abstract class AbstractConnection { this.send(presenceStanza); } - public queryArchive(archive: JID, queryId: string, beforeResultId?: string, end?: Date): Promise<Element> { + public queryArchive(archive: JID, version: string, contact: JID, queryId: string, beforeResultId?: string, end?: Date): Promise<Element> { let iq = $iq({ - type: 'set' + type: 'set', + to: archive.bare, }); iq.c('query', { - xmlns: NS.get('MAM'), + xmlns: version, queryid: queryId }); @@ -202,11 +203,11 @@ abstract class AbstractConnection { iq.c('field', { var: 'FORM_TYPE', type: 'hidden' - }).c('value').t(NS.get('MAM')).up().up(); + }).c('value').t(version).up().up(); iq.c('field', { var: 'with' - }).c('value').t(archive.bare).up().up(); + }).c('value').t(contact.bare).up().up(); if (end) { iq.c('field', { diff --git a/src/connection/Connection.interface.ts b/src/connection/Connection.interface.ts index 66abdd87..96860681 100644 --- a/src/connection/Connection.interface.ts +++ b/src/connection/Connection.interface.ts @@ -36,7 +36,7 @@ export interface IConnection { sendPresence(presence?: Presence) - queryArchive(archive: IJID, queryId: string, beforeResultId?: string, end?: Date): Promise<Element> + queryArchive(archive: IJID, version: string, contact: IJID, queryId: string, beforeResultId?: string, end?: Date): Promise<Element> close() } diff --git a/src/plugin/PluginAPI.interface.ts b/src/plugin/PluginAPI.interface.ts index ec46b3f9..a474daef 100644 --- a/src/plugin/PluginAPI.interface.ts +++ b/src/plugin/PluginAPI.interface.ts @@ -8,6 +8,7 @@ import ChatWindow from '@ui/ChatWindow'; import ContactManager from '@src/ContactManager'; import ContactProvider from '@src/ContactProvider'; import { IAvatar } from '@src/Avatar.interface'; +import Pipe from '@util/Pipe'; export interface IPluginAPI { @@ -57,4 +58,8 @@ export interface IPluginAPI { registerContactProvider(source: ContactProvider) getContactManager(): ContactManager + + getAfterReceiveGroupMessagePipe(): Pipe + + getAfterReceiveMessagePipe(): Pipe } diff --git a/src/plugin/PluginAPI.ts b/src/plugin/PluginAPI.ts index bc242ccf..c851065d 100644 --- a/src/plugin/PluginAPI.ts +++ b/src/plugin/PluginAPI.ts @@ -142,4 +142,12 @@ export default class PluginAPI implements IPluginAPI { public getContactManager(): ContactManager { return this.account.getContactManager(); } + + public getAfterReceiveGroupMessagePipe() { + return this.account.getPipe('afterReceiveGroupMessage'); + } + + public getAfterReceiveMessagePipe() { + return this.account.getPipe('afterReceiveMessage'); + } } diff --git a/src/plugins/mam/Archive.ts b/src/plugins/mam/Archive.ts index 9696819e..0318fc41 100644 --- a/src/plugins/mam/Archive.ts +++ b/src/plugins/mam/Archive.ts @@ -8,14 +8,19 @@ import Log from '../../util/Log' import Translation from '../../util/Translation' import * as Namespace from '../../connection/xmpp/namespace' import { IMessage } from '@src/Message.interface'; +import { IJID } from '@src/JID.interface'; +import MultiUserContact from '@src/MultiUserContact'; export default class Archive { private previousMessage: IMessage; private lastMessageId: string; private connected: boolean; + private archiveJid: IJID; constructor(private plugin: MessageArchiveManagementPlugin, private contact: Contact) { + let jid = contact.isGroupChat() ? contact.getJid() : plugin.getConnection().getJID(); + this.archiveJid = new JID(jid.bare); } public clear() { @@ -73,8 +78,13 @@ export default class Archive { } let connection = this.plugin.getConnection(); - connection.queryArchive(this.contact.getJid(), queryId, firstResultId, endDate) - .then(this.onComplete) + this.plugin.determineServerSupport(this.archiveJid).then(version => { + if (!version) { + throw new Error(`Archive JID ${this.archiveJid.full} has no support for MAM.`); + } + + return connection.queryArchive(this.archiveJid, <string> version, this.contact.getJid(), queryId, firstResultId, endDate); + }).then(this.onComplete) .catch((stanza) => { Log.warn('Error while requesting archive', stanza); }); @@ -88,11 +98,10 @@ export default class Archive { return; } - let ownJid = this.plugin.getConnection().getJID(); let from = new JID(messageElement.attr('from')); let to = new JID(messageElement.attr('to')); - if (ownJid.bare !== from.bare && ownJid.bare !== to.bare) { + if (this.archiveJid.bare !== from.bare && this.archiveJid.bare !== to.bare) { return; } @@ -117,7 +126,7 @@ export default class Archive { if (Message.exists(uid)) { message = new Message(uid); } else { - message = new Message({ + let messageProperties = { uid, attrId: messageId, peer: this.contact.getJid(), @@ -126,7 +135,26 @@ export default class Archive { htmlMessage: htmlBody.html(), stamp: stamp.getTime(), unread: false, - }); + sender: undefined, + }; + + if (this.contact.isGroupChat()) { + messageProperties.sender = { + name: from.resource, + }; + + let contact = <MultiUserContact> this.contact; + + messageProperties.direction = contact.getNickname() === from.resource ? Message.DIRECTION.OUT : Message.DIRECTION.IN; + } + + message = new Message(messageProperties); + + if (this.contact.isChat()) { + this.plugin.runAfterReceiveMessagePipe(this.contact, message, messageElement); + } else if (this.contact.isGroupChat()) { + this.plugin.runAfterReceiveGroupMessagePipe(this.contact, message); + } } if (this.previousMessage) { @@ -142,7 +170,7 @@ export default class Archive { public onComplete = (stanza) => { let stanzaElement = $(stanza); - let finElement = stanzaElement.find(`fin` + Namespace.getFilter('MAM')); + let finElement = stanzaElement.find(`fin[xmlns^="urn:xmpp:mam:"]`); if (finElement.length !== 1) { Log.warn('No fin element found'); diff --git a/src/plugins/mam/Plugin.ts b/src/plugins/mam/Plugin.ts index 55c5222e..4d584577 100644 --- a/src/plugins/mam/Plugin.ts +++ b/src/plugins/mam/Plugin.ts @@ -6,11 +6,10 @@ import JID from '../../JID' import { IJID } from '../../JID.interface' import * as Namespace from '../../connection/xmpp/namespace' import Archive from './Archive' -import DiscoInfo from '../../DiscoInfo' -import { Status } from '../../vendor/Strophe' import Contact from '@src/Contact'; import PluginAPI from '@src/plugin/PluginAPI'; import { IContact } from '@src/Contact.interface'; +import { IMessage } from '@src/Message.interface'; /** * XEP-0313: Message Archive Management @@ -25,6 +24,9 @@ const MAX_VERSION = '4.0.0'; const MAM1 = 'urn:xmpp:mam:1'; const MAM2 = 'urn:xmpp:mam:2'; +Namespace.register('MAM1', MAM1); +Namespace.register('MAM2', MAM2); + export default class MessageArchiveManagementPlugin extends AbstractPlugin { public static getName(): string { return 'Message Archive Management'; @@ -34,9 +36,9 @@ export default class MessageArchiveManagementPlugin extends AbstractPlugin { return Translation.t('setting-mam-enable'); } - private enabled = false; private archives: {[key: string]: Archive} = {}; private queryContactRelation: PersistentMap; + private supportCache: {[archiveJid: string]: string | boolean} = {}; constructor(pluginAPI: PluginAPI) { super(MIN_VERSION, MAX_VERSION, pluginAPI); @@ -48,16 +50,14 @@ export default class MessageArchiveManagementPlugin extends AbstractPlugin { }); pluginAPI.registerChatWindowClearedHook((chatWindow: ChatWindow, contact: Contact) => { - if (this.enabled) { + let archiveJid = this.getArchiveJid(contact); + + if (this.supportCache[archiveJid.bare]) { this.getArchive(contact.getJid()).clear(); } }); - pluginAPI.registerConnectionHook((status, condition) => { - if (status === Status.CONNECTED || status === Status.ATTACHED) { - this.determineServerSupport(); - } - }); + this.pluginAPI.getConnection().registerHandler(this.onMamMessage, null, 'message', null); } public getStorage() { @@ -68,6 +68,22 @@ export default class MessageArchiveManagementPlugin extends AbstractPlugin { return this.pluginAPI.getConnection(); } + public runAfterReceiveMessagePipe(contact: IContact, message: IMessage, messageElement) { + let pipe = this.pluginAPI.getAfterReceiveMessagePipe(); + + pipe.run(contact, message, messageElement.get(0)).then(([contact, message]) => { + return message; + }); + } + + public runAfterReceiveGroupMessagePipe(contact: IContact, message: IMessage) { + let pipe = this.pluginAPI.getAfterReceiveGroupMessagePipe(); + + return pipe.run(contact, message).then(([contact, message]) => { + return message; + }); + } + public addQueryContactRelation(queryId: string, contact: IContact) { this.queryContactRelation.set(queryId, contact.getJid().bare); } @@ -76,54 +92,51 @@ export default class MessageArchiveManagementPlugin extends AbstractPlugin { this.queryContactRelation.remove(queryId); } - private determineServerSupport() { - let connection = this.pluginAPI.getConnection(); - let discoInfoRepository = this.pluginAPI.getDiscoInfoRepository(); - let domain = connection.getJID().domain; - - if (!domain) { - this.pluginAPI.Log.debug('Could not get connected JID for MAM'); - return; + public async determineServerSupport(archivingJid: IJID) { + if (typeof this.supportCache[archivingJid.bare] !== 'undefined') { + return this.supportCache[archivingJid.bare]; } - let serverJid = new JID('', domain, '') //@REVIEW - - discoInfoRepository.getCapabilities(serverJid).then((discoInfo: DiscoInfo) => { - if (discoInfo.hasFeature(MAM2)) { - Namespace.register('MAM', MAM2); - return true; - } else if (discoInfo.hasFeature(MAM1)) { - Namespace.register('MAM', MAM1); - return true; - } - return false; - }).then((hasSupport) => { - if (hasSupport) { - this.pluginAPI.Log.debug('Server supports ' + Namespace.get('MAM')); - this.enabled = true; + let discoInfoRepository = this.pluginAPI.getDiscoInfoRepository(); + + let version: string | boolean = false; + try { + let discoInfo = await discoInfoRepository.getCapabilities(archivingJid); - this.pluginAPI.getConnection().registerHandler(this.onMamMessage, null, 'message', null); + if (discoInfo && discoInfo.hasFeature(MAM2)) { + version = MAM2; + } else if (discoInfo && discoInfo.hasFeature(MAM1)) { + version = MAM1; } - }).catch((err) => { + } catch (err) { this.pluginAPI.Log.warn('Could not determine MAM server support:', err); - }); - } + } - private addLoadButtonIfEnabled(chatWindow: ChatWindow, contact: Contact) { - if (!this.enabled) { - let self = this; - - //@REVIEW event based? - setTimeout(function check() { - if (self.enabled) { - self.addLoadButton(chatWindow.getDom(), contact); - } else { - setTimeout(check, 200); - } - }, 200); + if (version) { + this.pluginAPI.Log.debug(archivingJid.bare + ' supports ' + version); } else { - this.addLoadButton(chatWindow.getDom(), contact); + this.pluginAPI.Log.debug(archivingJid.bare + ' has no support for MAM'); } + + this.supportCache[archivingJid.bare] = version; + + return version; + } + + private getArchiveJid(contact: Contact) { + let jid = contact.isGroupChat() ? contact.getJid() : this.getConnection().getJID(); + + return new JID(jid.bare); + } + + private addLoadButtonIfEnabled(chatWindow: ChatWindow, contact: Contact) { + let archivingJid = this.getArchiveJid(contact); + + this.determineServerSupport(archivingJid).then((version) => { + if (version) { + this.addLoadButton(chatWindow.getDom(), contact); + } + }); } private addLoadButton(chatWindowElement: JQuery<HTMLElement>, contact: Contact) { @@ -169,7 +182,7 @@ export default class MessageArchiveManagementPlugin extends AbstractPlugin { private onMamMessage = (stanza: string): boolean => { let stanzaElement = $(stanza); - let resultElement = stanzaElement.find('result' + Namespace.getFilter('MAM')); + let resultElement = stanzaElement.find(`result[xmlns^="urn:xmpp:mam:"]`); let queryId = resultElement.attr('queryid'); if (resultElement.length !== 1 || !queryId) { |