import { GetInfo, LinkOptions, OntimeView, SessionStats } from 'ontime-types'; import { socket } from '../../adapters/WebsocketAdapter.js'; import { getLastRequest } from '../../api-integration/integration.controller.js'; import { getDataProvider } from '../../classes/data-provider/DataProvider.js'; import { portManager } from '../../classes/port-manager/PortManager.js'; import { password, routerPrefix } from '../../externals.js'; import { ONTIME_VERSION } from '../../ONTIME_VERSION.js'; import { getCurrentProject } from '../../services/project-service/ProjectService.js'; import { runtimeService } from '../../services/runtime-service/runtime.service.js'; import { publicDir } from '../../setup/index.js'; import { hashPassword } from '../../utils/hash.js'; import { getNetworkInterfaces } from '../../utils/network.js'; import { getTimezoneLabel } from '../../utils/time.js'; const startedAt = new Date(); /** Gathers information related to runtime */ export async function getSessionStats(): Promise { const { connectedClients, lastConnection } = socket.getStats(); const lastRequest = getLastRequest(); const { filename } = await getCurrentProject(); const { playback } = runtimeService.getRuntimeState(); return { startedAt: startedAt.toISOString(), connectedClients, lastConnection: lastConnection !== null ? lastConnection.toISOString() : null, lastRequest: lastRequest !== null ? lastRequest.toISOString() : null, projectName: filename, playback, timezone: getTimezoneLabel(startedAt), version: ONTIME_VERSION, }; } /** * Adds business logic to gathering data for the info endpoint */ export function getInfo(): GetInfo { const { version } = getDataProvider().getSettings(); const { port } = portManager.getPort(); // get nif and inject localhost const ni = getNetworkInterfaces(); ni.unshift({ name: 'localhost', address: '127.0.0.1' }); return { networkInterfaces: ni, version, serverPort: port, publicDir: publicDir.root, }; } export const hasPassword = Boolean(password); export const hashedPassword = hasPassword ? hashPassword(password as string) : undefined; /** * Generates a pre-authenticated URL by injecting a token in the URL params */ export function generateShareUrl( baseUrl: string, canonicalPath: string, { authenticate, lockConfig, lockNav, preset, prefix = routerPrefix, hash = hashedPassword }: LinkOptions, ): URL { /** * URL constructor will throw if given an IP address without protocol * for the case of IP addresses, we expect that the base URL provides protocol and port * eg: http://192.168.10.1:4001 */ const url = new URL(baseUrl); // companion links point to the root if (canonicalPath !== '<>') { // if the config is locked and we are in a preset, we hide the canonical path const shouldMaskPath = Boolean(preset) && (canonicalPath === OntimeView.Cuesheet || lockConfig); const maybePresetPath = shouldMaskPath ? `preset/${preset}` : preset || canonicalPath; url.pathname = prefix ? `${prefix}/${maybePresetPath}` : maybePresetPath; if (lockNav) { url.searchParams.append('n', '1'); } } if (authenticate && hash) { url.searchParams.append('token', hash); } return url; }