UNPKG

@jellyfin/sdk

Version:
111 lines (108 loc) 4.63 kB
import { RecommendedServerInfoScore } from '../models/recommended-server-info.js'; import { SystemInfoIssue, ProductNameIssue, VersionMissingIssue, VersionUnsupportedIssue, VersionOutdatedIssue, SlowResponseIssue } from '../models/recommended-server-issue.js'; import { getSystemApi } from '../utils/api/system-api.js'; import { isVersionLess } from '../utils/versioning.js'; import { MINIMUM_VERSION, API_VERSION } from '../versions.js'; /** * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** The expected product name in system info. */ const PRODUCT_NAME = 'Jellyfin Server'; /** Requests taking longer than 3s are considered slow. */ const SLOW_RESPONSE_TIME = 3000; /** System info request timeout. */ const HTTP_TIMEOUT = 5000; /** Get the minimum RecommendedServerInfoScore from an array. */ function getMinScore(scores, defaultScore = RecommendedServerInfoScore.GREAT) { return scores.length > 0 ? Math.min(...scores) : defaultScore; } /** Builds a RecommendedServerInfo from a SystemInfoResult. */ function toRecommendedServerInfo(result) { var _a, _b, _c; const issues = []; const scores = []; if (!((_a = result.response) === null || _a === void 0 ? void 0 : _a.data) || result.error) { // The response did not return valid data or returned an error issues.push(new SystemInfoIssue(result.error)); scores.push(RecommendedServerInfoScore.BAD); } else if (result.response.data.ProductName !== PRODUCT_NAME) { // The product name returned was invalid issues.push(new ProductNameIssue(result.response.data.ProductName)); scores.push(RecommendedServerInfoScore.BAD); } const version = (_b = result.response) === null || _b === void 0 ? void 0 : _b.data.Version; try { if (!version) { // No version was returned issues.push(new VersionMissingIssue()); scores.push(RecommendedServerInfoScore.BAD); } else if (isVersionLess(version, MINIMUM_VERSION)) { // Version is less than the minimum supported issues.push(new VersionUnsupportedIssue(version)); scores.push(RecommendedServerInfoScore.OK); } else if (isVersionLess(version, API_VERSION)) { // Version is less than the generated client, but above the minimum issues.push(new VersionOutdatedIssue(version)); scores.push(RecommendedServerInfoScore.GOOD); } } catch (error) { if (error instanceof TypeError) { issues.push(new VersionMissingIssue()); scores.push(RecommendedServerInfoScore.BAD); } } if (result.responseTime > SLOW_RESPONSE_TIME) { // Response was slow issues.push(new SlowResponseIssue(result.responseTime)); scores.push(RecommendedServerInfoScore.GOOD); } return { address: result.address, responseTime: result.responseTime, score: getMinScore(scores), issues, systemInfo: (_c = result.response) === null || _c === void 0 ? void 0 : _c.data }; } /** Class to discover and evaluate potential servers. */ class RecommendedServerDiscovery { constructor(jellyfin) { this.jellyfin = jellyfin; } /** * Fetches the RecommendedServerInfo for a single server address. * @param address The server address. * @returns The resulting RecommendedServerInfo. */ async fetchRecommendedServerInfo(address) { const api = this.jellyfin.createApi(address); const startTime = Date.now(); return getSystemApi(api).getPublicSystemInfo({ timeout: HTTP_TIMEOUT }) .then(response => ({ address, response, responseTime: Date.now() - startTime })) .catch(error => ({ address, error, responseTime: Date.now() - startTime })) .then(result => toRecommendedServerInfo(result)); } /** * Fetches the RecommendedServerInfo for multiple server addresses. * @param servers An array of server addresses. * @returns The RecommendedServerInfo for each address. */ async discover(servers, minimumScore = RecommendedServerInfoScore.BAD) { return (await Promise.all(servers.map(server => this.fetchRecommendedServerInfo(server)))).filter(serverInfo => serverInfo.score >= minimumScore); } } export { RecommendedServerDiscovery };