UNPKG

matrix-api

Version:

Matrix API library for the frontend.

748 lines (625 loc) 26.8 kB
"use strict"; function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } Object.defineProperty(exports, "__esModule", { value: true }); exports.Matrix = void 0; var _Uuid = require("curvature/base/Uuid"); var _Mixin = require("curvature/base/Mixin"); var _EventTargetMixin = require("curvature/mixin/EventTargetMixin"); function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var Matrix = function (_Mixin$with) { _inherits(Matrix, _Mixin$with); var _super = _createSuper(Matrix); function Matrix(baseUrl) { var _options$storage, _options$interval; var _this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; _classCallCheck(this, Matrix); _this = _super.call(this); _defineProperty(_assertThisInitialized(_this), "ssoUuid", String(new _Uuid.Uuid())); _defineProperty(_assertThisInitialized(_this), "isLoggedIn", false); _defineProperty(_assertThisInitialized(_this), "loggingIn", null); _this.baseUrl = baseUrl || 'https://matrix.org/_matrix'; _this.clientUrl = "".concat(_this.baseUrl, "/client/v3"); _this.mediaUrl = "".concat(_this.baseUrl, "/media/v3"); _this.profileCache = new Map(); _this.mediaCache = new Map(); _this.storage = (_options$storage = options.storage) !== null && _options$storage !== void 0 ? _options$storage : globalThis.sessionStorage; _this.interval = (_options$interval = options.interval) !== null && _options$interval !== void 0 ? _options$interval : false; return _this; } _createClass(Matrix, [{ key: "isLoggedIn", get: function get() { if (this.isLoggedIn) { this.dispatchEvent(new CustomEvent('logged-in')); } var tokenJson = this.storage.getItem('matrix:access-token') || 'false'; var token = JSON.parse(tokenJson); return this.storage.getItem('matrix:access-token'); } }, { key: "initSso", value: function initSso(redirectUri) { var _this2 = this; var windowRef = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window; if (this.storage.getItem('matrix:access-token')) { this.isLoggedIn = true; this.dispatchEvent(new CustomEvent('logged-in')); return; } var query = new URLSearchParams({ redirectUrl: redirectUri }); var path = "login/sso/redirect?".concat(query); var width = 400; var height = 600; var left = window.screenX + window.outerWidth / 2 + width / 2; var top = window.screenY + window.outerHeight / 2 - height / 2; var options = "width=".concat(width, ",height=").concat(height, ",screenX=").concat(left, ",screenY=").concat(top); var ssoPopup = windowRef.open("".concat(this.clientUrl, "/").concat(path), "matrix-login-".concat(this.ssoUuid), options); var ssoListener = function ssoListener(event) { if (event.origin !== location.origin) { return; } if (event.source === window) { return; } if (typeof event.data !== 'string') { return; } var request = JSON.parse(event.data); if (request.type !== 's.sso.complete') { return; } _this2.storage.setItem('matrix:access-token', JSON.stringify(request.data)); _this2.isLoggedIn = true; _this2.dispatchEvent(new CustomEvent('logged-in')); windowRef.removeEventListener('message', ssoListener); }; windowRef.addEventListener('message', ssoListener); } }, { key: "completeSso", value: function completeSso(loginToken) { var path = 'login'; var body = { type: "m.login.token", token: loginToken, txn_id: (1 / Math.random()).toString(36) }; fetch("".concat(this.clientUrl, "/").concat(path), { method: 'POST', body: JSON.stringify(body) }).then(function (response) { return response.json(); }).then(function (response) { window.opener.postMessage(JSON.stringify({ type: 's.sso.complete', data: response }), location.origin); window.close(); }); } }, { key: "logIn", value: function logIn(redirectUri) { var _this3 = this; var windowRef = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window; if (!this.loggingIn) { this.loggingIn = new Promise(function (accept) { _this3.loggingIn = null; _this3.addEventListener('logged-in', function (event) { accept(event); }, { once: true }); }); } this.initSso(redirectUri, windowRef); return this.loggingIn; } }, { key: "logOut", value: function logOut() { this.storage.removeItem('matrix:access-token'); this.isLoggedIn = false; this.loggingIn = null; this.dispatchEvent(new CustomEvent('logged-out')); } }, { key: "getGuestToken", value: function getGuestToken() { var _this4 = this; var tokenJson = this.storage.getItem('matrix:access-token') || 'false'; var token = JSON.parse(tokenJson); if (token && token.isGuest) { return Promise.resolve(token); } var query = new URLSearchParams({ kind: 'guest' }); var getToken = fetch("".concat(this.clientUrl, "/register?").concat(query), { method: 'POST', body: '{}' }).then(function (response) { return response.json(); }); getToken.then(function (token) { token.isGuest = true; _this4.isLoggedIn = true; _this4.storage.setItem('matrix:access-token', JSON.stringify(token)); }); return getToken; } }, { key: "getToken", value: function getToken() { var tokenJson = this.storage.getItem('matrix:access-token') || 'false'; var token = JSON.parse(tokenJson); if (token) { return Promise.resolve(token); } return matrix.getGuestToken(); } }, { key: "listenForServerEvents", value: function listenForServerEvents() { var _this5 = this; var token = JSON.parse(this.storage.getItem('matrix:access-token') || 'false'); if (!token) { return Promise.reject('No access token found.'); } var query = new URLSearchParams({ access_token: token.access_token }); var listener = "".concat(this.clientUrl, "/events?").concat(query); fetch(listener).then(function (response) { return response.json(); }).then(function (response) { return _this5.streamServerEvents(response); }); } }, { key: "listenForRoomEvents", value: function listenForRoomEvents(room_id, controller) { var _this6 = this; var from = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; if (controller && controller.cancelled) { return; } var token = JSON.parse(this.storage.getItem('matrix:access-token') || 'false'); if (!token) { return Promise.reject('No access token found.'); } var query = new URLSearchParams({ access_token: token.access_token, room_id: room_id, from: from }); var listener = "".concat(this.clientUrl, "/events?").concat(query); controller = controller || { cancelled: false }; fetch(listener).then(function (response) { return response.json(); }).then(function (response) { return _this6.streamServerEvents(response, room_id, controller); }); return controller; } }, { key: "streamServerEvents", value: function streamServerEvents(chunkList, room_id, controller) { var _this7 = this; if (controller && controller.cancelled) { return; } if (!this.interval) { if (room_id) { this.listenForRoomEvents(room_id, controller, chunkList.end); } else { this.listenForServerEvents(); } } else { setTimeout(function () { if (room_id) { _this7.listenForRoomEvents(room_id, controller, chunkList.end); } else { _this7.listenForServerEvents(); } }, this.interval); } chunkList.chunk && chunkList.chunk.forEach(function (event) { var detail = {}; if (!event.event_id) { event.event_id = "local:".concat(new _Uuid.Uuid()); } Object.assign(detail, event); _this7.dispatchEvent(new CustomEvent('matrix-event', { detail: detail })); _this7.dispatchEvent(new CustomEvent(detail.type, { detail: detail })); }); } }, { key: "getUserProfile", value: function getUserProfile(userId) { if (this.profileCache.has(userId)) { return this.profileCache.get(userId); } var getProfile = fetch("".concat(this.clientUrl, "/profile/").concat(userId)).then(function (response) { return response.json(); }); this.profileCache.set(userId, getProfile); return getProfile; } }, { key: "getUserData", value: function getUserData(type) { var token = JSON.parse(this.storage.getItem('matrix:access-token') || 'false'); if (!token) { return Promise.reject('No access token found.'); } var query = new URLSearchParams({ access_token: token.access_token }); return fetch("".concat(this.clientUrl, "/user/").concat(token.user_id, "/account_data/").concat(type, "?").concat(query)).then(function (response) { return response.json(); }); } }, { key: "putUserData", value: function putUserData(type, body) { var token = JSON.parse(this.storage.getItem('matrix:access-token') || 'false'); if (!token) { return; } var query = new URLSearchParams({ access_token: token.access_token }); var endpoint = "".concat(this.clientUrl, "/user/").concat(token.user_id, "/account_data/").concat(type, "?").concat(query); return fetch(endpoint, { method: 'PUT', body: body }).then(function (response) { if (!response.ok) { var error = new Error("HTTP status code: " + response.status); error.status = response.status; error.response = response; throw error; } return response; }).then(function (response) { return response.json(); }); } }, { key: "getMediaUrl", value: function getMediaUrl(mxcUrl) { var url = new URL(mxcUrl); return "".concat(this.mediaUrl, "/download/").concat(url.pathname.substr(2)); } }, { key: "getMedia", value: function getMedia(mxcUrl) { if (this.mediaCache.has(mxcUrl)) { return this.mediaCache.get(mxcUrl); } var getUrl = fetch(this.getMediaUrl(mxcUrl)).then(function (response) { return Promise.all([response.arrayBuffer(), response.headers.get('Content-type')]); }).then(function (_ref) { var _ref2 = _slicedToArray(_ref, 2), buffer = _ref2[0], type = _ref2[1]; return URL.createObjectURL(new Blob([buffer], { type: type })); }); this.mediaCache.set(mxcUrl, getUrl); return getUrl; } }, { key: "postMedia", value: function postMedia(body, filename) { var tokenJson = this.storage.getItem('matrix:access-token') || 'false'; var token = JSON.parse(tokenJson); if (!token) { return; } var query = new URLSearchParams({ access_token: token.access_token }); var url = "".concat(this.mediaUrl, "/upload?").concat(query); var headers = new Headers({ 'Content-Type': body.type }); var method = 'POST'; var options = { method: method, headers: headers, body: body }; return fetch(url, options).then(function (response) { return response.json(); }); } }, { key: "putEvent", value: function putEvent(roomId, type, body) { var tokenJson = this.storage.getItem('matrix:access-token') || 'false'; var token = JSON.parse(tokenJson); if (!token) { return; } var query = new URLSearchParams({ access_token: token.access_token }); var url = "".concat(this.clientUrl, "/rooms/").concat(roomId, "/send/").concat(type, "/").concat(Math.random().toString(36), "?").concat(query); var headers = new Headers({ 'Content-Type': 'application/json' }); var method = 'PUT'; var keepalive = true; var options = _defineProperty({ method: method, headers: headers, keepalive: keepalive, body: JSON.stringify(body) }, "keepalive", keepalive); return fetch(url, options).then(function (response) { return response.json(); }); } }, { key: "getEvent", value: function getEvent(roomId, eventId) { var tokenJson = this.storage.getItem('matrix:access-token') || 'false'; var token = JSON.parse(tokenJson); if (!token) { return; } var query = new URLSearchParams({ access_token: token.access_token }); var url = "".concat(this.clientUrl, "/rooms/").concat(roomId, "/event/").concat(eventId, "?").concat(query); var headers = new Headers({ 'Content-Type': 'application/json' }); var method = 'GET'; var options = { method: method, headers: headers }; return fetch(url, options).then(function (response) { return response.json(); }); } }, { key: "sync", value: function sync() { var tokenJson = this.storage.getItem('matrix:access-token') || 'false'; var token = JSON.parse(tokenJson); if (!token) { return Promise.resolve(); } var query = new URLSearchParams({ full_state: true, access_token: token.access_token }); var syncer = "".concat(this.clientUrl, "/sync?").concat(query); return fetch(syncer).then(function (response) { return response.json(); }); } }, { key: "getRoomState", value: function getRoomState(room_id) { var tokenJson = this.storage.getItem('matrix:access-token') || 'false'; var token = JSON.parse(tokenJson); if (!token) { return Promise.resolve(); } var query = new URLSearchParams({ access_token: token.access_token }); var syncer = "".concat(this.clientUrl, "/rooms/").concat(room_id, "/state?").concat(query); return fetch(syncer).then(function (response) { return response.json(); }); } }, { key: "syncRoom", value: function syncRoom(room_id) { var from = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var filter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; if (!this.isLoggedIn) { return Promise.reject('Logged out.'); } var token = JSON.parse(this.storage.getItem('matrix:access-token') || 'false'); if (!token) { return Promise.reject('No access token found.'); } var query = new URLSearchParams({ access_token: token.access_token, room_id: room_id, dir: 'b', from: from ? from : '', filter: filter ? JSON.stringify(filter) : '' }); var syncer = "".concat(this.clientUrl, "/rooms/").concat(room_id, "/messages?").concat(query); var controller = new AbortController(); var signal = controller.signal; var abort = function abort() { return controller.abort(); }; this.addEventListener('logged-out', abort, { once: true }); var fetchFrame = fetch(syncer, { signal: signal }).then(function (response) { return response.json(); }); fetchFrame["finally"](this.removeEventListener('logged-out', abort)); return fetchFrame; } }, { key: "syncRoomHistory", value: function syncRoomHistory(room) { var _this8 = this; var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var to = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var from = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var filter = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; return this.syncRoom(room, from, filter).then(function (frame) { if (!_this8.isLoggedIn) { return Promise.reject('Logged out.'); } var cancelable = true; var detail = { frame: frame }; var event = new CustomEvent('roomSyncFrame', { detail: detail, cancelable: cancelable }); if (!_this8.dispatchEvent(event)) { return; } if (callback && frame.chunk) { var _iterator = _createForOfIteratorHelper(frame.chunk), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var message = _step.value; if (!_this8.isLoggedIn) { return Promise.reject('Logged out.'); } if (to && message.origin_server_ts <= to) { return Promise.resolve(); } if (callback(message) === false) { return Promise.resolve(); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } return new Promise(function (accept) { var _this8$interval; return setTimeout(function () { return accept(frame.chunk.length && _this8.syncRoomHistory(room, callback, to, frame.end, filter)); }, (_this8$interval = _this8.interval) !== null && _this8$interval !== void 0 ? _this8$interval : 0); }); }); } }, { key: "getCurrentUserId", value: function getCurrentUserId() { var tokenJson = this.storage.getItem('matrix:access-token') || 'false'; var token = JSON.parse(tokenJson); if (!token) { return; } return token.user_id; } }, { key: "createRoom", value: function createRoom(name, topic, visibility) { var initial_state = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; var body = JSON.stringify({ name: name, topic: topic, visibility: visibility, initial_state: initial_state }); var token = JSON.parse(this.storage.getItem('matrix:access-token') || 'false'); if (!token) { return Promise.resolve(); } var query = new URLSearchParams({ access_token: token.access_token }); var url = "".concat(this.clientUrl, "/createRoom?").concat(query); var method = 'POST'; return fetch(url, { body: body, method: method }).then(function (response) { return response.json(); }); } }, { key: "joinRoom", value: function joinRoom(room_id) { var token = JSON.parse(this.storage.getItem('matrix:access-token') || 'false'); if (!token) { return Promise.reject('No access token found.'); } var query = new URLSearchParams({ access_token: token.access_token }); fetch("".concat(this.clientUrl, "/rooms/").concat(room_id, "/join?").concat(query), { method: 'POST' }).then(function (response) { return response.json(); }); } }, { key: "leaveRoom", value: function leaveRoom(room_id) { var token = JSON.parse(this.storage.getItem('matrix:access-token') || 'false'); if (!token) { return Promise.reject('No access token found.'); } var query = new URLSearchParams({ access_token: token.access_token }); fetch("".concat(this.clientUrl, "/rooms/").concat(room_id, "/leave?").concat(query), { method: 'POST' }).then(function (response) { return response.json(); }); } }, { key: "whoAmI", value: function whoAmI() { var token = JSON.parse(this.storage.getItem('matrix:access-token') || 'false'); if (!token) { return Promise.reject('No access token found.'); } var query = new URLSearchParams({ access_token: token.access_token }); return fetch("".concat(this.clientUrl, "/account/whoami?").concat(query)).then(function (response) { return response.json(); }); } }]); return Matrix; }(_Mixin.Mixin["with"](_EventTargetMixin.EventTargetMixin)); exports.Matrix = Matrix;