Forked from
sweng-group-15 / drawing-app
17 commits behind the upstream repository.
XMPP.js 3.07 KiB
import { client, xml } from "@xmpp/client"
import uuid from "uuid"
const GROUP_MESSAGE_ID = "I smell JOJO!" // Ur. Ugly.
const XMPP_STATUS_ROOM_CREATED = "201" // 201 Created
export default class XMPPConnection extends EventTarget {
joinChannel() {
const channelIdent = `${this.channel}@conference.xmpp.lets-draw.live/${this.username}`
const presence = xml(
"presence",
{ to: channelIdent },
xml("x", { xmlns: "http://jabber.org/protocol/muc" }),
)
this.sendOrQueue(presence)
}
sendOrQueue(message) {
if (this.online) {
this.xmpp.send(message)
} else {
this.queue.push(message)
}
}
sendChannelMessage(message) {
const channelIdent = `${this.channel}@conference.xmpp.lets-draw.live`
const wrappedMessage = xml(
"message",
{
type: "groupchat",
to: channelIdent,
id: GROUP_MESSAGE_ID,
},
xml("body", {}, message),
)
this.sendOrQueue(wrappedMessage)
}
acceptDefaultRoomConfiguration() {
const channelIdent = `${this.channel}@conference.xmpp.lets-draw.live`
const presence = xml(
"iq",
{ id: GROUP_MESSAGE_ID, to: channelIdent, type: "set" },
xml(
"query",
{ xmlns: "http://jabber.org/protocol/muc#owner" },
xml("x", { xmlns: "jabber:x:data", type: "submit" }),
),
)
this.sendOrQueue(presence)
}
constructor(channel) {
super()
this.username = uuid.v4().toString()
this.channel = channel
this.online = false
this.queue = []
const xmpp = client({
service: "wss://xmpp.lets-draw.live:5281/xmpp-websocket",
domain: "xmpp.lets-draw.live",
username: "beartest",
password: "beartest",
})
this.xmpp = xmpp
xmpp.on("offline", () => {
this.online = false
})
xmpp.on("stanza", (stanza) => {
const stanzaId = stanza.getAttr("id")
if (stanzaId && stanzaId === GROUP_MESSAGE_ID) {
// Messages sent to the room as echoed back
// Ignore our own messages to prevent loops
return
}
if (stanza.is("message")) {
this.dispatchEvent(
new CustomEvent("stanza", {
detail: stanza,
}),
)
} else if (stanza.is("presence")) {
const x = stanza.getChild("x")
if (x === undefined) {
// Uncertain if this element is guaranteed inside a <presence/>
return
}
const created =
x.getChildByAttr("code", XMPP_STATUS_ROOM_CREATED) !== undefined
if (created) {
// Create an "instant room"
this.acceptDefaultRoomConfiguration()
}
}
})
xmpp.on("online", async (address) => {
/*eslint no-unused-vars: ["error", { "args": "none" }]*/
// Makes itself available
await xmpp.send(xml("presence"))
this.online = true
for (const message of this.queue) {
await this.xmpp.send(message)
}
})
xmpp.start().catch(console.error)
this.joinChannel()
}
sneakilySendTheOtherTeamOur(secrets) {
this.sendChannelMessage(secrets)
}
}