UNPKG

raiden-ts

Version:

Raiden Light Client Typescript/Javascript SDK

97 lines 6.12 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.matrixUpdateCapsEpic = exports.matrixMonitorChannelPresenceEpic = exports.matrixMonitorPresenceEpic = void 0; const isEmpty_1 = __importDefault(require("lodash/isEmpty")); const isEqual_1 = __importDefault(require("lodash/isEqual")); const rxjs_1 = require("rxjs"); const operators_1 = require("rxjs/operators"); const actions_1 = require("../../channels/actions"); const config_1 = require("../../config"); const utils_1 = require("../../services/utils"); const actions_2 = require("../../utils/actions"); const error_1 = require("../../utils/error"); const rx_1 = require("../../utils/rx"); const actions_3 = require("../actions"); const utils_2 = require("../utils"); /** * Fetch peer's presence info from services * * @param address - Address of interest * @param pfs$ - Observable of cached best PFS * @param deps - Epics dependencies * @returns Observable of user with most recent presence */ function searchAddressPresence$(address, pfs$, deps) { return pfs$.pipe((0, operators_1.withLatestFrom)(deps.config$), (0, operators_1.concatMap)(([{ url }, { httpTimeout }]) => (0, utils_1.getPresenceFromService$)(address, url, deps).pipe((0, operators_1.timeout)(httpTimeout), // this catchAndLog will suppress error and retry next PFS only if error is a networkError, // otherwise (e.g. address offline) will error early and become matrixPresence.failure (0, rx_1.catchAndLog)({ onErrors: error_1.networkErrors, log: deps.log.debug }, 'Error fetching presence from service', address, url))), (0, operators_1.first)(), (0, operators_1.catchError)((err) => (0, rxjs_1.of)(actions_3.matrixPresence.failure(err, { address })))); } /** * Handles MatrixRequestMonitorPresenceAction and emits a MatrixPresenceUpdateAction * If presence is already known, emits it, else fetch from user profile * Even if the presence stays the same, we emit a MatrixPresenceUpdateAction, as this may be a * request being waited by a promise or something like that * IOW: every request should be followed by a presence update or a failed action, but presence * updates may happen later without new requests (e.g. when the user goes offline) * * @param action$ - Observable of matrixPresence.request actions * @param state$ - Observable of RaidenStates * @param deps - RaidenEpicDeps members * @param deps.matrix$ - MatrixClient async subject * @param deps.log - Logger instance * @param deps.config$ - Config observable * @returns Observable of presence updates or fail action */ function matrixMonitorPresenceEpic(action$, {}, deps) { const { latest$, config$ } = deps; const cache = new Map(); const pfs$ = (0, utils_1.choosePfs$)(undefined, deps, true).pipe((0, operators_1.shareReplay)()); return action$.pipe((0, operators_1.tap)((action) => { if (actions_3.matrixPresence.success.is(action)) cache.set(action.meta.address, action); else if (actions_3.matrixPresence.failure.is(action)) cache.delete(action.meta.address); }), (0, operators_1.filter)((0, actions_2.isActionOf)(actions_3.matrixPresence.request)), // this mergeMap is like withLatestFrom, but waits until matrix$ emits its only value (0, operators_1.groupBy)((action) => action.meta.address), (0, operators_1.mergeMap)((grouped$) => grouped$.pipe((0, operators_1.withLatestFrom)(latest$, config$), // if we're already fetching presence for this address, no need to fetch again (0, operators_1.exhaustMap)(([action, { rtc }, { pollingInterval }]) => { const { address } = action.meta; const cached = cache.get(address); // we already fetched this peer's presence recently, or there's an RTC channel with them if (cached && (Date.now() - cached.payload.ts < pollingInterval || address in rtc)) return (0, rxjs_1.of)(cached); return searchAddressPresence$(address, pfs$, deps); })))); } exports.matrixMonitorPresenceEpic = matrixMonitorPresenceEpic; /** * Channel monitoring triggers matrix presence monitoring for partner * * @param action$ - Observable of RaidenActions * @returns Observable of matrixPresence.request actions */ function matrixMonitorChannelPresenceEpic(action$) { return action$.pipe((0, operators_1.filter)(actions_1.channelMonitored.is), (0, operators_1.map)((action) => actions_3.matrixPresence.request(undefined, { address: action.meta.partner }))); } exports.matrixMonitorChannelPresenceEpic = matrixMonitorChannelPresenceEpic; /** * Update our matrix's avatarUrl on config.caps on startup and changes * * @param action$ - Observable of RaidenActions * @param state$ - Observable of RaidenStates * @param deps - Epics dependencies * @param deps.matrix$ - MatrixClient async subject * @param deps.config$ - Config object * @param deps.init$ - Init$ subject * @returns Observable which never emits */ function matrixUpdateCapsEpic(action$, {}, { matrix$, config$, init$ }) { return config$.pipe((0, rx_1.completeWith)(action$), (0, operators_1.pluck)('caps'), (0, operators_1.distinctUntilChanged)(isEqual_1.default), (0, operators_1.withLatestFrom)(init$.pipe((0, operators_1.ignoreElements)(), (0, operators_1.startWith)(false), (0, operators_1.endWith)(true))), (0, operators_1.switchMap)(([caps, synced]) => matrix$.pipe((0, rx_1.withMergeFrom)(async (matrix) => matrix.setAvatarUrl(caps && !(0, isEmpty_1.default)(caps) ? (0, utils_2.stringifyCaps)(caps) : '')), (0, operators_1.filter)(() => synced), (0, rx_1.withMergeFrom)(async ([matrix]) => matrix.setPresence({ presence: 'offline', status_msg: '' })), (0, rx_1.withMergeFrom)(async ([[matrix]]) => matrix.setPresence({ presence: 'online', status_msg: Date.now().toString() })), (0, rx_1.retryWhile)((0, config_1.intervalFromConfig)(config$)))), (0, operators_1.ignoreElements)()); } exports.matrixUpdateCapsEpic = matrixUpdateCapsEpic; //# sourceMappingURL=presence.js.map