Skip to content

Instantly share code, notes, and snippets.

@OpakAlex
Created November 21, 2017 14:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OpakAlex/4d7a9a1860586952f3abfaf316ab7fa0 to your computer and use it in GitHub Desktop.
Save OpakAlex/4d7a9a1860586952f3abfaf316ab7fa0 to your computer and use it in GitHub Desktop.
import XMPP from 'stanza.io'
import Actions from './actions';
import {
buildRoomJid,
buildJid,
buildConfig,
buildMessagesHistory,
createLogger
} from './utils';
const defaultConfig = {
sasl: 'plain',
resource: 'browser',
}
class Mongooseim {
static instance;
constructor({ auth, config, dispatch, onSessionStarted, kind, usersSelector }) {
if (!auth || !auth.id || !auth.token) {
throw new Error("Invalid auth passed to Provider")
}
if (!kind) {
throw new Error("Kind prop is required")
}
if (!config.domain || !config.host || !config.ports) {
throw new Error("Invalid config prop is passed")
}
if (this.instance) {
return this.instance;
}
this.domain = config.domain
this.muc = config.muc
this.auth = auth
this.kind = kind
this.dispatch = dispatch
this.usersSelector = usersSelector
this.config = config
this.logger = createLogger(config)
this.jid = this.buildJid(kind, auth.id)
const client = XMPP.createClient({
jid: this.jid,
password: auth.token,
...buildConfig(config, defaultConfig),
});
client.on('session:started', (data) => {
this.logger('session:started', data)
this.isConnected = true
client.sendPresence();
dispatch(Actions.sessionStarted())
if (onSessionStarted) {
onSessionStarted(this)
}
})
client.on('session:error', (error) => {
this.logger('session error', error)
dispatch(Actions.sessionError(error))
});
const retryAfter = config.retryAfter || 500
client.on('auth:failed', (error) => {
this.logger('auth error', error)
dispatch(Actions.authFailed(true))
setTimeout(() => {
this.logger('try to reconnect')
client.connect()
}, retryAfter)
});
client.on('auth:success', (data) => {
this.logger('auth success', data)
dispatch(Actions.authSuccess(data))
});
client.on('message:error', (data) => {
this.logger('message error', data)
});
client.on('message', (data) => {
this.logger('message', data)
if (data.id) {
dispatch(Actions.message({ ...data, stamp: (new Date()).toString()}))
}
});
client.on('presence', (data) => {
this.logger('presence', data)
if (data.type === 'subscribe') {
client.acceptSubscription(data.from)
}
if (data.from.bare !== this.jid) {
if (data.type === 'available') {
dispatch(Actions.presenceAvailable(data.from.bare))
}
if (data.type === 'unavailable') {
dispatch(Actions.presenceUnavailable(data.from.bare))
}
}
});
client.on('presence:error', (data) => {
this.logger('presence error', data)
});
this.client = client
this.instance = this;
}
connect = () => {
if (!this.isConnected) {
this.client.enableKeepAlive()
this.client.connect()
}
}
disconnect = () => {
if (this.isConnected) {
this.client.disableKeepAlive()
this.client.disconnect()
this.isConnected = false
}
}
buildRoomJid = (roomName) => buildRoomJid(this.domain, this.muc, roomName)
buildActiveRoomJid = () => this.activeRoom ? this.buildRoomJid(this.activeRoom) : null
buildJid = (type, id) => buildJid(type, id, this.domain)
sendMessage = ({ to, body, type }) => {
let recepient = buildJid(to)
let kind = type || 'normal'
if (this.activeRoom) {
recepient = this.buildRoomJid(this.activeRoom)
kind = 'groupchat'
}
this.client.sendMessage({
to: recepient,
type: kind,
body,
})
}
joinRoom = (roomName, options = {}) => {
const roomJid = this.buildRoomJid(roomName)
this.activeRoom = roomName.toString()
this.dispatch(Actions.joinRoom(roomName.toString()))
this.client.joinRoom(roomJid, this.auth.id, options)
this.client.configureRoom(roomJid, {
fields: [
{ name: 'FORM_TYPE', value: 'http://jabber.org/protocol/muc#roomconfig' },
{ name: 'muc#roomconfig_persistentroom', value: '1'}
]
}, (err, data) => {
this.logger('configure room', data)
this.logger('configure room error', err)
});
this.client.searchHistory()
}
closeRoom = () => {
this.activeRoom = null
this.dispatch(Actions.closeRoom())
}
searchHistory = (options = {}) => {
let params = {
...options,
jid: this.auth.jid,
}
if (this.activeRoom) {
params = {
...params,
with: this.buildActiveRoomJid(),
}
}
return this.client.searchHistory(params, (err, data) => {
if (err) {
return this.dispatch(Actions.searchHistoryError(err))
}
const messages = buildMessagesHistory(data)
this.dispatch(Actions.searchHistory(messages))
})
}
subscribe = (type, id) => this.client.subscribe(this.buildJid(type, id))
}
export default Mongooseim
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment