UNPKG

speedybot

Version:

<p align="center"> <a href="https://github.com/valgaze/speedybot"> <img src="https://img.shields.io/npm/v/speedybot.svg" /> </a> <a href="https://github.com/valgaze/speedybot"> <img src="https://img.shields.io/npm/dm/speedybot.svg" /> </a>

1,011 lines 39.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SpeedyBot = void 0; const index_1 = require("./index"); const cards_1 = require("./cards"); class SpeedyBot { constructor(_token = "", makeRequest = index_1.mainRequester) { this._token = _token; this.makeRequest = makeRequest; this.middlewares = []; this.topMiddleware = null; this.fallbackText = "Your client does not support Adaptive Cards"; this.secrets = {}; this.API = { messages: "https://webexapis.com/v1/messages", attachments: "https://webexapis.com/v1/attachment/actions", user: { self: "https://webexapis.com/v1/people/me", getPersonDetails: "https://webexapis.com/v1/people", }, rooms: "https://webexapis.com/v1/rooms", roomDetails: "https://webexapis.com/v1/rooms", webhooks: "https://webexapis.com/v1/webhooks", }; } addSecret(key, value) { this.secrets[key] = value; } addSecrets(payload) { Object.entries(payload).forEach(([k, v]) => this.addSecret(k, v)); } getSecret(key) { return this.secrets[key]; } setToken(token) { this._token = token; return this; } getToken() { return this._token; } setFallbackText(t) { this.fallbackText = t; } insertStepToFront(middleware) { if (this.topMiddleware) { this.middlewares.unshift(this.topMiddleware); } this.topMiddleware = middleware; } pickRandom(listOrMin, max) { if (Array.isArray(listOrMin)) { const items = listOrMin; return items[Math.floor(Math.random() * items.length)]; } else { const min = listOrMin; return Math.floor(Math.random() * (max - min + 1)) + min; } } addStep(middleware) { this.middlewares.push(middleware); } addStepSequence(middlewares) { this.middlewares.push(...middlewares); } regex(reg, cb) { this.addStep(($) => __awaiter(this, void 0, void 0, function* () { if ($.text) { if (reg instanceof RegExp) { const matched = reg.test($.text.toLowerCase()); if (matched) { return yield cb($); } } } return $.next; })); } onCamera(cb, formats = []) { this.addStep(($) => __awaiter(this, void 0, void 0, function* () { if ($.file) { const { extension } = $.file; const photos = ["png", "jpg", "jpeg", ...formats]; if (photos.includes(extension)) { return yield cb($); } } return $.next; })); } exact(keyword, cb) { this.insertStepToFront(($) => __awaiter(this, void 0, void 0, function* () { if (typeof keyword === "string") { if ($.text === keyword) { return yield cb($); } } return $.next; })); } contains(keyword, cb) { this.addStep(($) => __awaiter(this, void 0, void 0, function* () { var _a, _b; if (typeof keyword === "string") { if ((_a = $.text) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(keyword.toLowerCase())) { return yield cb($); } } else if (Array.isArray(keyword)) { for (const item of keyword) { if ((_b = $.text) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes(item.toLowerCase())) { return yield cb($); } } } return $.next; })); } onReject(e) { if (this.errorHandler) { this.errorHandler(e); } } captureError(func) { this.errorHandler = func; } runMiddleware(env, startingCtx = {}) { return __awaiter(this, void 0, void 0, function* () { const { roomId } = env.data; const botInst = this; try { const messageType = this.detectType(env); let roomType = ""; if ("roomType" in env.data) { roomType = env.data.roomType; } const { details, author: authorData } = yield this.buildDetails(messageType, env); const [authorEmail] = authorData.emails; const [, authorDomain] = authorEmail.toLowerCase().split("@"); let filePayload = undefined; let attachedData = undefined; let textData; let mentionedPeople = []; let messageId = ""; let parentIdVal; const proceed = yield this.checkAuthor(authorData); if (!proceed) { return false; } if (messageType === "card") { const { inputs, messageId: id } = details; attachedData = inputs; messageId = id; const roomData = yield this.getRoom(roomId); roomType = roomData.type; const chipToken = index_1.CONSTANTS.CHIP_LABEL; const isChip = inputs[chipToken]; if (isChip) { textData = inputs[chipToken]; attachedData = undefined; } const isDelete = inputs[index_1.CONSTANTS.submitToken] === index_1.CONSTANTS.action_delete; if (isDelete) { yield this.deleteMessage(id); return true; } } if (messageType === "text" || messageType === "file") { const { parentId, id, roomType: roomType_val, text = textData, files, mentionedPeople: mentionedPeople_val = [], } = details; parentIdVal = parentId; mentionedPeople = mentionedPeople_val; attachedData = undefined; messageId = id; roomType = roomType_val; textData = text !== null && text !== void 0 ? text : ""; textData = roomType === "group" ? textData.split(" ").slice(1).join(" ") || "" : textData; if (files && files.length) { const [targetUrl] = files; try { let fileData = yield this.peekFile(targetUrl); filePayload = Object.assign(Object.assign({}, fileData), { getData() { return __awaiter(this, void 0, void 0, function* () { const { data } = yield botInst.getFile(targetUrl); return data; }); } }); } catch (e) { const err = { message: "There was an issue obtaining file data", error: e, e, roomId, }; this.onReject(err); return false; } } } const $Magic = { next: true, end: false, messageType, id: messageId, author: { domain: authorDomain, email: authorEmail, id: authorData.id, org: authorData.orgId, name: authorData.displayName, type: authorData.type, profilePic: authorData.avatar, }, text: textData, msg: { parentId: parentIdVal, roomId, roomType, mentionedPeople: mentionedPeople.slice(1), }, file: filePayload, data: attachedData, ctx: startingCtx, buildDMLink(target, label) { const url = `webexteams://im?email=${target}`; return this.buildLink(url, label !== null && label !== void 0 ? label : url); }, debug() { var _a; return { messageType: this.messageType, text: (_a = this.text) !== null && _a !== void 0 ? _a : "", data: this.data, messageId: this.id, author: { id: this.author.id, name: this.author.name, email: this.author.email, }, hasFile: !!this.file, msg: { parentId: this.msg.parentId, roomId: this.msg.roomId, roomType: this.msg.roomType, mentionedPeople: this.msg.mentionedPeople, }, }; }, thread(threadData) { return __awaiter(this, void 0, void 0, function* () { let [root, ...messages] = threadData; const maxEntries = Math.min(messages.length, 5); const { id: parentId, roomId } = yield this.send(root); for (let i = 0; i < maxEntries; i++) { const msg = messages[i]; let msgObj = { parentId, }; if (typeof msg === "string") { msgObj["markdown"] = msg; msgObj["text"] = msg; msgObj["roomId"] = roomId; } yield botInst._send(msgObj); } return true; }); }, send(msg) { return botInst.sendTo(roomId, msg); }, reply(msg) { var _a; return botInst.replyTo(roomId, (_a = this.msg.parentId) !== null && _a !== void 0 ? _a : messageId, msg); }, edit(messageObj, msg) { return botInst.editMessage(messageObj.roomId, messageObj.id, msg); }, card(config) { return botInst.card(config); }, buildLink(target, label, noBold = false) { let link = `[${label || target}](${target})`; if (!noBold) { link = `**${link}**`; } return link; }, buildDataSnippet(data, type = "json") { const msg = ` \`\`\`${type} ${type === "json" ? JSON.stringify(data, null, 2) : data} \`\`\``; return msg; }, pickRandom: (listOrMin, max) => { if (Array.isArray(listOrMin)) { const items = listOrMin; return items[Math.floor(Math.random() * items.length)]; } else { const min = listOrMin; return Math.floor(Math.random() * (max - min + 1)) + min; } }, sendFile(data, fileExtension) { return __awaiter(this, void 0, void 0, function* () { return botInst.sendFileTo(roomId, data, fileExtension); }); }, getFile(url, opts) { return __awaiter(this, void 0, void 0, function* () { const fileData = yield botInst.peekFile(url); const filePayload = Object.assign(Object.assign({}, fileData), { getData() { return __awaiter(this, void 0, void 0, function* () { const { data } = yield botInst.getFile(url); return data; }); } }); return filePayload; }); }, fillTemplate(utterances, template) { let payload; if (typeof utterances !== "string") { payload = this.pickRandom(utterances) || ""; } else { payload = utterances; } const replacer = (utterance, target, replacement) => { if (!utterance.includes(`$[${target}]`)) { return utterance; } return replacer(utterance.replace(`$[${target}]`, replacement), target, replacement); }; for (const key in template) { const val = template[key]; payload = replacer(payload, key, val); } return payload; }, clearScreen(repeatCount = 50) { return __awaiter(this, void 0, void 0, function* () { const newLine = "\n"; const repeatClamp = repeatCount > 7000 ? 5000 : repeatCount; const clearScreen = `${newLine.repeat(repeatClamp)}`; const requestOptions = { method: "POST", headers: { Authorization: `Bearer ${botInst.getToken()}`, "content-type": "application/json;charset=UTF-8", }, body: JSON.stringify({ roomId, text: clearScreen, markdown: clearScreen, }), }; const res = yield botInst.makeRequest(botInst.API.messages, {}, { rawInit: requestOptions }); return res; }); }, }; if (this.topMiddleware) { const result = yield this.topMiddleware($Magic); if (result === false || !result) { return false; } } for (const middleware of this.middlewares) { const result = yield middleware($Magic); if (!result) { break; } } } catch (e) { const defaultMessage = `There was a catastrophic error ${e}`; let payload = { message: defaultMessage, status: "00000", e, }; if (typeof e === "object" && e !== null) { const { message = defaultMessage, status = "00000" } = e; payload = { message, status, roomId, e }; } this.onReject(payload); } return true; }); } resolveDestination(candidate) { let target; if (typeof candidate === "string") { if (cards_1.checkers.isEmail(candidate)) { target = { toPersonEmail: candidate }; } else { target = { roomId: candidate }; } } else if (typeof candidate === "object" && "personId" in candidate) { target = { toPersonId: candidate.personId }; } return target; } sendTo(emailOrRoomId, message) { return __awaiter(this, void 0, void 0, function* () { const target = this.resolveDestination(emailOrRoomId); if (typeof message === "string") { const payload = Object.assign(Object.assign({}, target), { markdown: message }); return this._send(payload); } else if (typeof message === "object") { const payload = Object.assign(Object.assign({}, target), { markdown: this.fallbackText, text: this.fallbackText, attachments: [ { contentType: "application/vnd.microsoft.card.adaptive", content: "build" in message && typeof message.build === "function" ? message.build() : message, }, ] }); return this._send(payload); } throw new Error("Invalid message passed to sendTo"); }); } _send(payload) { return __awaiter(this, void 0, void 0, function* () { const res = (yield this.makeRequest(this.API.messages, payload, { method: "POST", token: this.getToken(), })); const json = yield res.json(); return json; }); } validateToken(token) { return __awaiter(this, void 0, void 0, function* () { let valid = false; try { const res = yield this.getSelf(token); if (res.id) { valid = true; } } catch (e) { valid = false; } return valid; }); } card(config) { const card = new cards_1.SpeedyCard(); const { title = "", subTitle = "", image = "", data = {}, chips = [], table = [], choices = [], backgroundImage = "", } = config !== null && config !== void 0 ? config : {}; if (backgroundImage) { card.setBackgroundImage; } if (title) { card.addTitle(title); } if (subTitle) { card.addSubtitle(subTitle); } if (image) { card.setBackgroundImage(image); } if (Object.keys(data).length) { card.attachData(data); } if (chips.length) { card.addChips(chips); } if (choices.length) { card.addPickerDropdown(choices); } if (table) { if (Array.isArray(table) && table.length) { card.addTable(table); } else { if (Object.entries(table).length) { card.addTable(table); } } } return card; } stashCard(secret, message, unwrapLabel = index_1.CONSTANTS.unwrapLabel, destroyLabel = index_1.CONSTANTS.destroyLabel) { return this.card({ title: message || "Info" }) .addDeleteButton(destroyLabel) .addSubcard(this.card().addSubtitle(String(secret)), unwrapLabel); } errorCard(title, message) { return this.card().addBlock(this.card().addTitle(title).addSubtitle(message), { backgroundColor: "Attention" }); } successCard(title, message) { return this.card().addBlock(this.card().addTitle(title).addSubtitle(message), { backgroundColor: "Good" }); } editMessage(roomId, messageId, message) { return __awaiter(this, void 0, void 0, function* () { const url = `https://webexapis.com/v1/messages/${messageId}`; const editPayload = { roomId, markdown: message, }; const res = (yield this.makeRequest(url, editPayload, { token: this.getToken(), method: "PUT", })); const json = yield res.json(); return json; }); } replyTo(roomIdParam, param2, param3) { return __awaiter(this, void 0, void 0, function* () { let roomId; let messageId; let msg; if (typeof roomIdParam === "object") { roomId = roomIdParam.roomId; messageId = roomIdParam.id; msg = param2 || ""; } else { roomId = roomIdParam; messageId = param2 || ""; msg = param3 || ""; } const payload = { markdown: msg, text: msg, parentId: messageId, roomId, }; return this._send(payload); }); } detectType(envelope) { var _a; let type = "text"; if (envelope.resource === "messages") { if ("files" in envelope.data && ((_a = envelope.data.files) === null || _a === void 0 ? void 0 : _a.length)) { const { files = [] } = envelope.data; if (files.length) { type = "file"; } } } else if (envelope.resource === "attachmentActions") { type = "card"; } return type; } deleteMessage(msgId) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.API.messages}/${msgId}`; const res = yield this.makeRequest(url, {}, { token: this.getToken(), method: "DELETE", }); return res; }); } deleteWebhook(webhookId) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.API.webhooks}/${webhookId}`; yield this.makeRequest(url, {}, { token: this.getToken(), method: "DELETE", }); return; }); } getWebhooks() { return __awaiter(this, void 0, void 0, function* () { const url = `${this.API.webhooks}`; const res = (yield this.makeRequest(url, {}, { method: "GET", token: this.getToken(), })); const json = yield res.json(); return json; }); } fetchWebhooks() { return __awaiter(this, void 0, void 0, function* () { const webhooks = (yield this.getWebhooks()) || []; const list = webhooks.items.map((webhook) => { const { id, name, resource, targetUrl } = webhook; return { id, name, resource, targetUrl, }; }); return list; }); } Setup(url, secret) { return Promise.all([ this.createFirehose(url, secret), this.createAttachmentActionsWebhook(url, secret), ]).catch((e) => { throw e; }); } getRecentRooms(limit = 100) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.API.rooms}?max=${limit}&sortBy=lastactivity`; const res = (yield this.makeRequest(url, {}, { method: "GET", token: this.getToken(), })); const json = yield res.json(); return json.items.map((item) => { const { type, title, id } = item; return { type, title, id, }; }); }); } createAttachmentActionsWebhook(url, secret) { return __awaiter(this, void 0, void 0, function* () { const payload = { resource: "attachmentActions", event: "created", targetUrl: url, name: `${new Date().toISOString()}_attachmentActions`, }; if (secret) { payload.secret = secret; } return this.createWebhook(payload); }); } createFirehose(url, secret) { return __awaiter(this, void 0, void 0, function* () { const payload = { resource: "messages", event: "created", targetUrl: url, name: `${new Date().toISOString()}_firehose`, }; if (secret) { payload.secret = secret; } return this.createWebhook(payload); }); } createWebhook(payload) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.API.webhooks}`; const res = (yield this.makeRequest(url, payload, { method: "POST", token: this.getToken(), })); const json = yield res.json(); return json; }); } checkAuthor(authorObj) { return __awaiter(this, void 0, void 0, function* () { const data = yield this.getSelf(); const { id } = data; return id !== authorObj.id; }); } getSelf(token) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const url = (_b = (_a = this.API) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.self; const res = (yield this.makeRequest(url, {}, { method: "GET", token: token !== null && token !== void 0 ? token : this.getToken(), })); const json = (yield res.json()); return json; }); } whoAmI() { return __awaiter(this, void 0, void 0, function* () { const selfData = yield this.getSelf(); const { items: webhooks } = yield this.getWebhooks(); return Object.assign(Object.assign({}, selfData), { webhooks }); }); } buildDetails(type, envelope) { return __awaiter(this, void 0, void 0, function* () { const [author, data] = yield Promise.all([ this.getPerson(envelope.data.personId), this.getData(type, envelope), ]); return { author, details: data, }; }); } getPerson(personId) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.API.user.getPersonDetails}/${personId}`; const res = (yield this.makeRequest(url, {}, { method: "GET", token: this.getToken(), })); const json = yield res.json(); return json; }); } getRoom(roomId) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.API.roomDetails}/${roomId}`.replace(" ", ""); const res = (yield this.makeRequest(url, {}, { method: "GET", token: this.getToken(), })); const json = yield res.json(); return json; }); } getData(type, envelope) { return __awaiter(this, void 0, void 0, function* () { let url = this.API.messages; if (type === "card") { url = this.API.attachments; } const { data } = envelope; const { id } = data; url = `${url}/${id}`; const res = (yield this.makeRequest(url, {}, { method: "GET", token: this.getToken(), })); const json = yield res.json(); if (type === "card") { return json; } if (type === "text") { return json; } if (type === "file") { return json; } return json; }); } generateFileName() { return `${this.rando()}_${this.rando()}`; } rando() { return Math.random().toString(36).slice(2); } handleExtension(input = "") { const hasDot = input.indexOf(".") > -1; let fileName = ""; const [prefix, ext] = input.split("."); if (hasDot) { if (!prefix || prefix === "*") { fileName = `${this.generateFileName()}.${ext}`; } else { fileName = input; } } else { fileName = `${this.generateFileName()}.${prefix}`; } return fileName; } sendFileTo(destination, data, extensionOrFileName, textLabel = "", contentType = null) { return __awaiter(this, void 0, void 0, function* () { const target = this.resolveDestination(destination); if (!extensionOrFileName) { throw new Error(`$(bot).sendDataAsFile: Missing filename/extension parameter, ex "myfile.png" or "*.png"`); } let finalContentType = contentType; if (!finalContentType) { finalContentType = this.guessContentType(extensionOrFileName); if (!finalContentType) { throw new Error(`$(bot).sendDataAsFile: Missing 'content-type' parameter, ex "image/png"`); } } const fullFileName = this.handleExtension(extensionOrFileName); const formData = new FormData(); const isJSON = data && typeof data === "object" && finalContentType.includes("json"); formData.append("files", new Blob([isJSON ? JSON.stringify(data, null, 2) : data], { type: finalContentType, }), fullFileName); const [entry] = Object.entries(target); const [finalDestination, v] = entry; formData.append(finalDestination, v); formData.append("text", textLabel); const requestOptions = { method: "POST", headers: { Authorization: `Bearer ${this.getToken()}`, }, body: formData, }; const res = (yield this.makeRequest(this.API.messages, {}, { rawInit: requestOptions })); const json = yield res.json(); return json; }); } getFile(url, opts = {}) { return __awaiter(this, void 0, void 0, function* () { const res = (yield this.makeRequest(url, {}, { method: "GET", token: this.getToken(), })); const { contentType: type, name: fileName, extension, bytes, } = this.extractFiledata(res); const shouldProbablyBeArrayBuffer = (!type.includes("json") && !type.includes("text")) || type.includes("image"); let data = res; if (opts.responseType === "arraybuffer" || shouldProbablyBeArrayBuffer) { try { data = yield res.arrayBuffer(); } catch (e) { data = {}; } } else { try { if (type.includes("json")) { data = (yield res.json()); } else { data = yield res.text(); } } catch (e) { data = {}; } } const payload = { url: url, name: fileName, extension, contentType: type, data, bytes, }; return payload; }); } extractFiledata(res) { const type = res.headers.get("content-type"); const contentDispo = res.headers.get("content-disposition"); const contentLength = Number(res.headers.get("content-length")); const fileName = contentDispo === null || contentDispo === void 0 ? void 0 : contentDispo.split(";")[1].split("=")[1].replace(/\"/g, ""); const extension = fileName.split(".").pop() || ""; return { bytes: contentLength, contentType: type, extension, name: fileName, }; } peekFile(url) { return __awaiter(this, void 0, void 0, function* () { const res = yield this.makeRequest(url, {}, { method: "HEAD", token: this.getToken(), }); return Object.assign({ url }, this.extractFiledata(res)); }); } guessContentType(extensionOrFileName) { const hasDot = extensionOrFileName.indexOf(".") > -1; let extension = ""; const pieces = extensionOrFileName.split("."); const hasMultipleDots = pieces.length > 2; const [prefix, ext] = pieces; if (hasDot) { if (!prefix || prefix === "*") { extension = ext; } if (hasMultipleDots) { extension = pieces.pop(); } } else { extension = prefix; } const mapping = { doc: "application/msword", docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", xls: "application/vnd.ms-excel", xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ppt: "application/vnd.ms-powerpoint", pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation", pdf: "application/pdf", jpg: "image/jpeg", jpeg: "image/jpeg", bmp: "image/bmp", gif: "image/gif", png: "image/png", txt: "text/plain", csv: "text/csv", html: "text/html", json: "application/json", "*": "application/octet-stream", mp3: "audio/mpeg", mp4: "video/mp4", mpeg: "video/mpeg", mpkg: "application/vnd.apple.installer+xml", vf: "application/json", }; const res = mapping[extension] || null; return res; } fuzzyMatch(candidate, options) { const lowerCaseCandidate = candidate.toLowerCase(); return options.some((option) => option.toLowerCase().includes(lowerCaseCandidate)); } convertToHash(arr) { return arr.reduce((hash, item) => { const [key, value] = item.split("="); hash[key] = value; return hash; }, {}); } appCard(appName, logoUrl, config = {}) { return this.card().addHeader(appName, Object.assign({ iconURL: logoUrl }, config)); } fetchData(url, retries = 3, onChunk) { return __awaiter(this, void 0, void 0, function* () { const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); try { const response = yield fetch(url, { method: "GET", headers: { Authorization: `Bearer ${this._token}`, "Content-Type": "application/json", }, }); if (!response.ok) { if (response.status === 429 && retries > 0) { const retryAfter = parseInt(response.headers.get("Retry-After") || "1", 10) * 1000; yield delay(retryAfter); return yield this.fetchData(url, retries - 1); } else { const text = yield response.text(); throw new Error(`Error fetching messages: ${response.statusText}, ${text}`); } } const { items } = yield response.json(); const data = items; const linkHeader = response.headers.get("Link"); const hasNext = linkHeader ? linkHeader.includes(`rel="next"`) : false; const nextURL = hasNext ? linkHeader.split(";")[0].replace("<", "").replace(">", "") : null; if (onChunk) { yield onChunk(data); } if (hasNext && nextURL) { const nextPageData = yield this.fetchData(nextURL, retries); return data.concat(nextPageData); } return data; } catch (error) { throw new Error(`Error fetching data: ${error}`); } }); } buildQueryURL(target, options) { const queryParams = []; if (options) { Object.entries(options).forEach(([key, value]) => { if (value !== undefined && value !== null) { queryParams.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`); } }); } const queryString = queryParams.length > 0 ? `?${queryParams.join("&")}` : ""; return `${target}${queryString}`; } getAllRooms(options) { return __awaiter(this, void 0, void 0, function* () { const url = this.buildQueryURL(this.API.rooms, options); const collection = yield this.fetchData(url); return collection; }); } } exports.SpeedyBot = SpeedyBot; //# sourceMappingURL=speedybot.js.map