[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
0

Configure Feed

Select the types of activity you want to include in your feed.

Convert all relative backend endings to js

FoxxMD (Jan 18, 2024, 1:58 PM EST) 396c3da2 0591b900

+542 -525
+2 -2
codeshift/transform.ts
··· 77 77 if(hasNoExt) { 78 78 const dirFiles = fs.readdirSync(dir) 79 79 filenameFromDir = dirFiles.find(x => path.parse(x).name === pathInfo.name); 80 - if(filenameFromDir !== undefined) { 80 + if(filenameFromDir === undefined) { 81 81 fileExists = false; 82 82 isRelative = false; 83 83 } else { ··· 159 159 } 160 160 break; 161 161 default: 162 - transformedImport = combineDirFile(pathInfo.dir, `.${derivedTT}`); // path.join(pathInfo.root, dir, pathInfo.name, `.${derivedTT}`); 162 + transformedImport = combineDirFile(pathInfo.dir, `${path.parse(filenameFromDir).name}.${derivedTT}`); // path.join(pathInfo.root, dir, pathInfo.name, `.${derivedTT}`); 163 163 break; 164 164 } 165 165
+2 -2
src/backend/common/errors/NodeErrors.ts
··· 1 - import {isArbitraryObject} from "../infrastructure/Atomic"; 1 + import { isArbitraryObject } from "../infrastructure/Atomic.js"; 2 2 import ErrnoException = NodeJS.ErrnoException; 3 - import {findCauseByFunc} from "../../utils"; 3 + import { findCauseByFunc } from "../../utils.js"; 4 4 5 5 export type NodeNetworkErrorCode = 'ENOTFOUND' | 'ETIMEDOUT' | 'EAI_AGAIN' | 'ECONNRESET' | 'ECONNREFUSED' | 'ERRADDRINUSE' | 'EADDRNOTAVAIL' | 'ECONNABORTED' | 'EHOSTUNREACH'; 6 6 export const NETWORK_ERROR_CODES = ['ENOTFOUND', 'ETIMEDOUT', 'EAI_AGAIN', 'ECONNRESET', 'ECONNREFUSED', 'ERRADDRINUSE', 'EADDRNOTAVAIL', 'ECONNABORTED', 'EHOSTUNREACH'];
+1 -1
src/backend/common/errors/UpstreamError.ts
··· 1 1 import {ErrorWithCause} from "pony-cause"; 2 - import {findCauseByFunc} from "../../utils"; 2 + import { findCauseByFunc } from "../../utils.js"; 3 3 4 4 export class UpstreamError<T = undefined> extends ErrorWithCause<T> { 5 5
+2 -2
src/backend/common/infrastructure/Atomic.ts
··· 1 1 import {Dayjs} from "dayjs"; 2 2 import {FixedSizeList} from 'fixed-size-list'; 3 3 import {Logger} from '@foxxmd/winston'; 4 - import TupleMap from "../TupleMap"; 4 + import TupleMap from "../TupleMap.js"; 5 5 import {Request, Response} from "express"; 6 6 import {NextFunction, ParamsDictionary, Query} from "express-serve-static-core"; 7 - import {LogLevel, logLevels, PlayMeta, PlayObject} from "../../../core/Atomic"; 7 + import { LogLevel, logLevels, PlayMeta, PlayObject } from "../../../core/Atomic.js"; 8 8 9 9 export type SourceType = 'spotify' | 'plex' | 'tautulli' | 'subsonic' | 'jellyfin' | 'lastfm' | 'deezer' | 'ytmusic' | 'mpris' | 'mopidy' | 'listenbrainz' | 'jriver' | 'kodi' | 'webscrobbler' | 'chromecast'; 10 10 export const sourceTypes: SourceType[] = ['spotify', 'plex', 'tautulli', 'subsonic', 'jellyfin', 'lastfm', 'deezer', 'ytmusic', 'mpris', 'mopidy', 'listenbrainz', 'jriver', 'kodi', 'webscrobbler', 'chromecast'];
+6 -6
src/backend/common/infrastructure/config/aioConfig.ts
··· 1 - import { CommonSourceOptions, ScrobbleThresholds, SourceRetryOptions } from "./source/index"; 2 - import { RequestRetryOptions } from "./common"; 3 - import { SourceAIOConfig } from "./source/sources"; 4 - import { ClientAIOConfig } from "./client/clients"; 5 - import { WebhookConfig } from "./health/webhooks"; 6 - import { LogOptions } from "../Atomic"; 1 + import { CommonSourceOptions, ScrobbleThresholds, SourceRetryOptions } from "./source/index.js"; 2 + import { RequestRetryOptions } from "./common.js"; 3 + import { SourceAIOConfig } from "./source/sources.js"; 4 + import { ClientAIOConfig } from "./client/clients.js"; 5 + import { WebhookConfig } from "./health/webhooks.js"; 6 + import { LogOptions } from "../Atomic.js"; 7 7 8 8 export interface SourceDefaults extends SourceRetryOptions { 9 9 /**
+3 -3
src/backend/common/infrastructure/config/client/clients.ts
··· 1 - import { MalojaClientAIOConfig, MalojaClientConfig } from "./maloja"; 2 - import { LastfmClientAIOConfig, LastfmClientConfig } from "./lastfm"; 3 - import { ListenBrainzClientAIOConfig, ListenBrainzClientConfig } from "./listenbrainz"; 1 + import { MalojaClientAIOConfig, MalojaClientConfig } from "./maloja.js"; 2 + import { LastfmClientAIOConfig, LastfmClientConfig } from "./lastfm.js"; 3 + import { ListenBrainzClientAIOConfig, ListenBrainzClientConfig } from "./listenbrainz.js"; 4 4 5 5 export type ClientConfig = MalojaClientConfig | LastfmClientConfig | ListenBrainzClientConfig; 6 6
+2 -2
src/backend/common/infrastructure/config/client/index.ts
··· 1 - import { CommonConfig, CommonData } from "../common"; 1 + import { CommonConfig, CommonData } from "../common.js"; 2 2 3 3 /** 4 4 * Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging. ··· 70 70 * @default 1 71 71 * @examples [1] 72 72 * */ 73 - deadLetterRetries?: boolean 73 + deadLetterRetries?: number 74 74 } 75 75 } 76 76
+2 -2
src/backend/common/infrastructure/config/client/lastfm.ts
··· 1 - import { CommonClientConfig, CommonClientData } from "./index"; 2 - import { RequestRetryOptions } from "../common"; 1 + import { CommonClientConfig, CommonClientData } from "./index.js"; 2 + import { RequestRetryOptions } from "../common.js"; 3 3 4 4 export interface LastfmData extends RequestRetryOptions { 5 5 /**
+2 -2
src/backend/common/infrastructure/config/client/listenbrainz.ts
··· 1 - import { CommonClientConfig, CommonClientData } from "./index"; 2 - import { RequestRetryOptions } from "../common"; 1 + import { CommonClientConfig, CommonClientData } from "./index.js"; 2 + import { RequestRetryOptions } from "../common.js"; 3 3 4 4 export interface ListenBrainzData extends RequestRetryOptions{ 5 5 /**
+2 -2
src/backend/common/infrastructure/config/client/maloja.ts
··· 1 - import { CommonClientConfig, CommonClientData } from "./index"; 2 - import { RequestRetryOptions } from "../common"; 1 + import { CommonClientConfig, CommonClientData } from "./index.js"; 2 + import { RequestRetryOptions } from "../common.js"; 3 3 4 4 export interface MalojaClientData extends RequestRetryOptions, CommonClientData { 5 5 /**
+1 -1
src/backend/common/infrastructure/config/source/chromecast.ts
··· 1 - import {CommonSourceConfig, CommonSourceData} from "./index"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 2 3 3 export interface ChromecastData extends CommonSourceData { 4 4 /**
+1 -1
src/backend/common/infrastructure/config/source/deezer.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 2 3 3 export interface DeezerData extends CommonSourceData { 4 4 /**
+1 -1
src/backend/common/infrastructure/config/source/index.ts
··· 1 - import { CommonConfig, CommonData, RequestRetryOptions } from "../common"; 1 + import { CommonConfig, CommonData, RequestRetryOptions } from "../common.js"; 2 2 3 3 export interface SourceRetryOptions extends RequestRetryOptions { 4 4 /**
+1 -1
src/backend/common/infrastructure/config/source/jellyfin.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 2 3 3 export interface JellyData extends CommonSourceData { 4 4 /**
+2 -2
src/backend/common/infrastructure/config/source/jriver.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 2 - import { PollingOptions } from "../common"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 + import { PollingOptions } from "../common.js"; 3 3 4 4 export interface JRiverData extends CommonSourceData, PollingOptions { 5 5 /**
+2 -2
src/backend/common/infrastructure/config/source/kodi.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 2 - import { PollingOptions } from "../common"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 + import { PollingOptions } from "../common.js"; 3 3 4 4 5 5 export interface KodiData extends CommonSourceData, PollingOptions {
+3 -3
src/backend/common/infrastructure/config/source/lastfm.ts
··· 1 - import { LastfmData } from "../client/lastfm"; 2 - import { CommonSourceConfig, CommonSourceData } from "./index"; 3 - import {PollingOptions} from "../common"; 1 + import { LastfmData } from "../client/lastfm.js"; 2 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 3 + import { PollingOptions } from "../common.js"; 4 4 5 5 export interface LastFmSourceData extends CommonSourceData, PollingOptions, LastfmData{} 6 6
+3 -3
src/backend/common/infrastructure/config/source/listenbrainz.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 2 - import { ListenBrainzData } from "../client/listenbrainz"; 3 - import {PollingOptions} from "../common"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 + import { ListenBrainzData } from "../client/listenbrainz.js"; 3 + import { PollingOptions } from "../common.js"; 4 4 5 5 export interface ListenBrainzSourceData extends ListenBrainzData, CommonSourceData, PollingOptions { 6 6 }
+2 -2
src/backend/common/infrastructure/config/source/mopidy.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 2 - import { PollingOptions } from "../common"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 + import { PollingOptions } from "../common.js"; 3 3 4 4 export interface MopidyData extends CommonSourceData, PollingOptions { 5 5 /**
+1 -1
src/backend/common/infrastructure/config/source/mpris.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 2 3 3 export const PLAYBACK_STATUS_PLAYING = 'Playing'; 4 4 export const PLAYBACK_STATUS_PAUSED = 'Paused';
+1 -1
src/backend/common/infrastructure/config/source/plex.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 2 3 3 export interface PlexSourceData extends CommonSourceData { 4 4 /**
+15 -15
src/backend/common/infrastructure/config/source/sources.ts
··· 1 - import { SpotifySourceAIOConfig, SpotifySourceConfig } from "./spotify"; 2 - import { PlexSourceAIOConfig, PlexSourceConfig } from "./plex"; 3 - import { TautulliSourceAIOConfig, TautulliSourceConfig } from "./tautulli"; 4 - import { DeezerSourceAIOConfig, DeezerSourceConfig } from "./deezer"; 5 - import { SubsonicSourceAIOConfig, SubSonicSourceConfig } from "./subsonic"; 6 - import { JellySourceAIOConfig, JellySourceConfig } from "./jellyfin"; 7 - import { LastFmSouceAIOConfig, LastfmSourceConfig } from "./lastfm"; 8 - import { YTMusicSourceAIOConfig, YTMusicSourceConfig } from "./ytmusic"; 9 - import { MPRISSourceAIOConfig, MPRISSourceConfig } from "./mpris"; 10 - import { MopidySourceAIOConfig, MopidySourceConfig } from "./mopidy"; 11 - import { ListenBrainzSourceAIOConfig, ListenBrainzSourceConfig } from "./listenbrainz"; 12 - import { JRiverSourceAIOConfig, JRiverSourceConfig } from "./jriver"; 13 - import { KodiSourceAIOConfig, KodiSourceConfig } from "./kodi"; 14 - import { WebScrobblerSourceAIOConfig, WebScrobblerSourceConfig } from "./webscrobbler"; 15 - import { ChromecastSourceConfig, ChromecastSourceAIOConfig } from "./chromecast"; 1 + import { SpotifySourceAIOConfig, SpotifySourceConfig } from "./spotify.js"; 2 + import { PlexSourceAIOConfig, PlexSourceConfig } from "./plex.js"; 3 + import { TautulliSourceAIOConfig, TautulliSourceConfig } from "./tautulli.js"; 4 + import { DeezerSourceAIOConfig, DeezerSourceConfig } from "./deezer.js"; 5 + import { SubsonicSourceAIOConfig, SubSonicSourceConfig } from "./subsonic.js"; 6 + import { JellySourceAIOConfig, JellySourceConfig } from "./jellyfin.js"; 7 + import { LastFmSouceAIOConfig, LastfmSourceConfig } from "./lastfm.js"; 8 + import { YTMusicSourceAIOConfig, YTMusicSourceConfig } from "./ytmusic.js"; 9 + import { MPRISSourceAIOConfig, MPRISSourceConfig } from "./mpris.js"; 10 + import { MopidySourceAIOConfig, MopidySourceConfig } from "./mopidy.js"; 11 + import { ListenBrainzSourceAIOConfig, ListenBrainzSourceConfig } from "./listenbrainz.js"; 12 + import { JRiverSourceAIOConfig, JRiverSourceConfig } from "./jriver.js"; 13 + import { KodiSourceAIOConfig, KodiSourceConfig } from "./kodi.js"; 14 + import { WebScrobblerSourceAIOConfig, WebScrobblerSourceConfig } from "./webscrobbler.js"; 15 + import { ChromecastSourceConfig, ChromecastSourceAIOConfig } from "./chromecast.js"; 16 16 17 17 18 18 export type SourceConfig = SpotifySourceConfig | PlexSourceConfig | TautulliSourceConfig | DeezerSourceConfig | SubSonicSourceConfig | JellySourceConfig | LastfmSourceConfig | YTMusicSourceConfig | MPRISSourceConfig | MopidySourceConfig | ListenBrainzSourceConfig | JRiverSourceConfig | KodiSourceConfig | WebScrobblerSourceConfig | ChromecastSourceConfig;
+2 -2
src/backend/common/infrastructure/config/source/spotify.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 2 - import { PollingOptions } from "../common"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 + import { PollingOptions } from "../common.js"; 3 3 4 4 export interface SpotifySourceData extends CommonSourceData, PollingOptions { 5 5 /**
+2 -2
src/backend/common/infrastructure/config/source/subsonic.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 2 - import { PollingOptions } from "../common"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 + import { PollingOptions } from "../common.js"; 3 3 4 4 export interface SubsonicData extends CommonSourceData, PollingOptions { 5 5 /**
+1 -1
src/backend/common/infrastructure/config/source/tautulli.ts
··· 1 - import { PlexSourceConfig } from "./plex"; 1 + import { PlexSourceConfig } from "./plex.js"; 2 2 3 3 export interface TautulliSourceConfig extends PlexSourceConfig { 4 4 }
+1 -1
src/backend/common/infrastructure/config/source/webscrobbler.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 2 3 3 export interface WebScrobblerData extends CommonSourceData { 4 4 /**
+2 -2
src/backend/common/infrastructure/config/source/ytmusic.ts
··· 1 - import { CommonSourceConfig, CommonSourceData } from "./index"; 2 - import { PollingOptions } from "../common"; 1 + import { CommonSourceConfig, CommonSourceData } from "./index.js"; 2 + import { PollingOptions } from "../common.js"; 3 3 4 4 export interface YTMusicData extends CommonSourceData, PollingOptions { 5 5 /**
+5 -5
src/backend/common/logging.ts
··· 1 1 import path from "path"; 2 - import { projectDir } from "./index"; 2 + import { projectDir } from "./index.js"; 3 3 import * as winstonNs from '@foxxmd/winston'; 4 4 import winstonDef from '@foxxmd/winston'; 5 5 import {DuplexTransport} from "winston-duplex"; 6 - import { asLogOptions, LogConfig, LogOptions } from "./infrastructure/Atomic"; 6 + import { asLogOptions, LogConfig, LogOptions } from "./infrastructure/Atomic.js"; 7 7 import process from "process"; 8 - import {fileOrDirectoryIsWriteable, mergeArr, parseBool} from "../utils"; 8 + import { fileOrDirectoryIsWriteable, mergeArr, parseBool } from "../utils.js"; 9 9 import {ErrorWithCause, stackWithCauses} from "pony-cause"; 10 10 import {NullTransport} from 'winston-null'; 11 11 import DailyRotateFile from 'winston-daily-rotate-file'; 12 12 import dayjs from "dayjs"; 13 13 import stringify from 'safe-stable-stringify'; 14 14 import {SPLAT, LEVEL, MESSAGE} from 'triple-beam'; 15 - import { LogInfo, LogLevel } from "../../core/Atomic"; 15 + import { LogInfo, LogLevel } from "../../core/Atomic.js"; 16 16 import TransportStream from "winston-transport"; 17 17 import {format} from 'logform'; 18 18 ··· 157 157 ...rest 158 158 }) => { 159 159 const keys = Object.keys(rest); 160 - let stringifyValue = keys.length > 0 && !keys.every(x => causeKeys.some(y => y == x)) ? stringify(rest) : ''; 160 + let stringifyValue = keys.length > 0 && !keys.every(x => causeKeys.some(y => y == x)) ? stringify.default(rest) : ''; 161 161 let msg = message; 162 162 let stackMsg = ''; 163 163 if (stack !== undefined) {
+4 -4
src/backend/common/vendor/AbstractApiClient.ts
··· 1 - import { mergeArr } from "../../utils"; 1 + import { mergeArr } from "../../utils.js"; 2 2 import {Logger} from '@foxxmd/winston'; 3 - import { FormatPlayObjectOptions } from "../infrastructure/Atomic"; 3 + import { FormatPlayObjectOptions } from "../infrastructure/Atomic.js"; 4 4 import winston from '@foxxmd/winston'; 5 - import { PlayObject } from "../../../core/Atomic"; 6 - import {capitalize} from "../../../core/StringUtils"; 5 + import { PlayObject } from "../../../core/Atomic.js"; 6 + import { capitalize } from "../../../core/StringUtils.js"; 7 7 8 8 export default abstract class AbstractApiClient { 9 9 name: string;
+3 -3
src/backend/common/vendor/JRiverApiClient.ts
··· 1 - import AbstractApiClient from "./AbstractApiClient"; 2 - import {JRiverData} from "../infrastructure/config/source/jriver"; 1 + import AbstractApiClient from "./AbstractApiClient.js"; 2 + import {JRiverData} from "../infrastructure/config/source/jriver.js"; 3 3 import request, {Request, Response} from 'superagent'; 4 4 import xml2js from 'xml2js'; 5 5 import {ErrorWithCause} from "pony-cause"; 6 - import {DEFAULT_RETRY_MULTIPLIER} from "../infrastructure/Atomic"; 6 + import {DEFAULT_RETRY_MULTIPLIER} from "../infrastructure/Atomic.js"; 7 7 8 8 const parser = new xml2js.Parser({'async': true}); 9 9
+5 -5
src/backend/common/vendor/KodiApiClient.ts
··· 1 - import AbstractApiClient from "./AbstractApiClient"; 1 + import AbstractApiClient from "./AbstractApiClient.js"; 2 2 import {ErrorWithCause} from "pony-cause"; 3 - import { KodiData } from "../infrastructure/config/source/kodi"; 3 + import { KodiData } from "../infrastructure/config/source/kodi.js"; 4 4 import { KodiClient } from 'kodi-api' 5 5 import normalizeUrl from "normalize-url"; 6 6 import {URL} from "url"; 7 - import { RecentlyPlayedOptions } from "../../sources/AbstractSource"; 8 - import { FormatPlayObjectOptions } from "../infrastructure/Atomic"; 7 + import { RecentlyPlayedOptions } from "../../sources/AbstractSource.js"; 8 + import { FormatPlayObjectOptions } from "../infrastructure/Atomic.js"; 9 9 import dayjs from "dayjs"; 10 - import { PlayObject } from "../../../core/Atomic"; 10 + import { PlayObject } from "../../../core/Atomic.js"; 11 11 12 12 interface KodiDuration { 13 13 hours: number
+7 -7
src/backend/common/vendor/LastfmApiClient.ts
··· 1 1 import LastFm, {AuthGetSessionResponse, TrackObject, UserGetInfoResponse} from "lastfm-node-client"; 2 - import AbstractApiClient from "./AbstractApiClient"; 2 + import AbstractApiClient from "./AbstractApiClient.js"; 3 3 import dayjs from "dayjs"; 4 - import { readJson, sleep, writeFile } from "../../utils"; 5 - import {DEFAULT_RETRY_MULTIPLIER, FormatPlayObjectOptions} from "../infrastructure/Atomic"; 6 - import { LastfmData } from "../infrastructure/config/client/lastfm"; 7 - import { PlayObject } from "../../../core/Atomic"; 8 - import {isNodeNetworkException} from "../errors/NodeErrors"; 9 - import {nonEmptyStringOrDefault, splitByFirstFound} from "../../../core/StringUtils"; 4 + import { readJson, sleep, writeFile } from "../../utils.js"; 5 + import { DEFAULT_RETRY_MULTIPLIER, FormatPlayObjectOptions } from "../infrastructure/Atomic.js"; 6 + import { LastfmData } from "../infrastructure/config/client/lastfm.js"; 7 + import { PlayObject } from "../../../core/Atomic.js"; 8 + import { isNodeNetworkException } from "../errors/NodeErrors.js"; 9 + import { nonEmptyStringOrDefault, splitByFirstFound } from "../../../core/StringUtils.js"; 10 10 import {source} from "common-tags"; 11 11 12 12 const badErrors = [
+13 -13
src/backend/common/vendor/ListenbrainzApiClient.ts
··· 1 - import AbstractApiClient from "./AbstractApiClient"; 1 + import AbstractApiClient from "./AbstractApiClient.js"; 2 2 import request, {Request} from 'superagent'; 3 - import { ListenBrainzClientData } from "../infrastructure/config/client/listenbrainz"; 4 - import {DEFAULT_RETRY_MULTIPLIER, FormatPlayObjectOptions} from "../infrastructure/Atomic"; 3 + import { ListenBrainzClientData } from "../infrastructure/config/client/listenbrainz.js"; 4 + import { DEFAULT_RETRY_MULTIPLIER, FormatPlayObjectOptions } from "../infrastructure/Atomic.js"; 5 5 import dayjs from "dayjs"; 6 6 import { stringSameness } from '@foxxmd/string-sameness'; 7 - import { 8 - combinePartsToString, 9 - } from "../../utils"; 10 - import { PlayObject } from "../../../core/Atomic"; 11 - import { slice } from "../../../core/StringUtils"; 7 + import { combinePartsToString } from "../../utils.js"; 8 + import { PlayObject } from "../../../core/Atomic.js"; 9 + import { slice } from "../../../core/StringUtils.js"; 12 10 import { 13 11 findDelimiters, 14 - normalizeStr, parseArtistCredits, parseCredits, 12 + normalizeStr, 13 + parseArtistCredits, 14 + parseCredits, 15 15 parseTrackCredits, 16 - uniqueNormalizedStrArr 17 - } from "../../utils/StringUtils"; 18 - import {UpstreamError} from "../errors/UpstreamError"; 19 - import {getScrobbleTsSOCDate} from "../../utils/TimeUtils"; 16 + uniqueNormalizedStrArr, 17 + } from "../../utils/StringUtils.js"; 18 + import { UpstreamError } from "../errors/UpstreamError.js"; 19 + import { getScrobbleTsSOCDate } from "../../utils/TimeUtils.js"; 20 20 21 21 22 22 export interface ArtistMBIDMapping {
+3 -3
src/backend/common/vendor/chromecast/ChromecastClientUtils.ts
··· 1 - import {MdnsDeviceInfo, REPORTED_PLAYER_STATUSES, ReportedPlayerStatus} from "../../infrastructure/Atomic"; 2 - import {PlatformApplication, PlatformType} from "./interfaces"; 1 + import { MdnsDeviceInfo, REPORTED_PLAYER_STATUSES, ReportedPlayerStatus } from "../../infrastructure/Atomic.js"; 2 + import { PlatformApplication, PlatformType } from "./interfaces.js"; 3 3 import {connect, createPlatform, Media, MediaController, PersistentClient, Result} from "@foxxmd/chromecast-client"; 4 4 import {ErrorWithCause} from "pony-cause"; 5 5 import {Client as CastClient} from 'castv2'; 6 6 import objectHash from "object-hash"; 7 - import {PlayObject} from "../../../../core/Atomic"; 7 + import { PlayObject } from "../../../../core/Atomic.js"; 8 8 9 9 export const chromePlayerStateToReported = (state: string): ReportedPlayerStatus => { 10 10 switch (state) {
+1 -1
src/backend/common/vendor/chromecast/interfaces.ts
··· 1 1 import {createPlatform, MediaController, PersistentClient} from "@foxxmd/chromecast-client"; 2 2 import {Service} from "bonjour-service"; 3 - import {FormatPlayObjectOptions} from "../../infrastructure/Atomic"; 3 + import { FormatPlayObjectOptions } from "../../infrastructure/Atomic.js"; 4 4 import {Dayjs} from "dayjs"; 5 5 import {Logger} from "@foxxmd/winston"; 6 6
+2 -2
src/backend/common/vendor/maloja/interfaces.ts
··· 1 1 import {ResponseError} from "superagent"; 2 - import {findCauseByFunc} from "../../../utils"; 3 - import {isSuperAgentResponseError} from "../../errors/ErrorUtils"; 2 + import { findCauseByFunc } from "../../../utils.js"; 3 + import { isSuperAgentResponseError } from "../../errors/ErrorUtils.js"; 4 4 5 5 export interface MalojaV2ScrobbleData { 6 6 artists: string[]
+10 -14
src/backend/index.ts
··· 6 6 import relativeTime from 'dayjs/plugin/relativeTime.js'; 7 7 import duration from 'dayjs/plugin/duration.js'; 8 8 import timezone from 'dayjs/plugin/timezone.js'; 9 - import { 10 - parseBool, 11 - readJson, 12 - sleep 13 - } from "./utils"; 9 + import { parseBool, readJson, sleep } from "./utils.js"; 14 10 import * as path from "path"; 15 - import {projectDir} from "./common/index"; 16 - import SpotifySource from "./sources/SpotifySource"; 17 - import { AIOConfig } from "./common/infrastructure/config/aioConfig"; 18 - import { getRoot } from "./ioc"; 19 - import {getLogger} from "./common/logging"; 20 - import {LogInfo} from "../core/Atomic"; 21 - import {initServer} from "./server/index"; 11 + import { projectDir } from "./common/index.js"; 12 + import SpotifySource from "./sources/SpotifySource.js"; 13 + import { AIOConfig } from "./common/infrastructure/config/aioConfig.js"; 14 + import { getRoot } from "./ioc.js"; 15 + import { getLogger } from "./common/logging.js"; 16 + import { LogInfo } from "../core/Atomic.js"; 17 + import { initServer } from "./server/index.js"; 22 18 import {SimpleIntervalJob, ToadScheduler} from "toad-scheduler"; 23 - import {createHeartbeatSourcesTask} from "./tasks/heartbeatSources"; 24 - import {createHeartbeatClientsTask} from "./tasks/heartbeatClients"; 19 + import { createHeartbeatSourcesTask } from "./tasks/heartbeatSources.js"; 20 + import { createHeartbeatClientsTask } from "./tasks/heartbeatClients.js"; 25 21 26 22 27 23 dayjs.extend(utc)
+6 -6
src/backend/ioc.ts
··· 1 1 import {createContainer} from "iti"; 2 2 import path from "path"; 3 - import {configDir, projectDir} from "./common/index"; 4 - import ScrobbleClients from "./scrobblers/ScrobbleClients"; 5 - import ScrobbleSources from "./sources/ScrobbleSources"; 6 - import {Notifiers} from "./notifier/Notifiers"; 3 + import { configDir, projectDir } from "./common/index.js"; 4 + import ScrobbleClients from "./scrobblers/ScrobbleClients.js"; 5 + import ScrobbleSources from "./sources/ScrobbleSources.js"; 6 + import { Notifiers } from "./notifier/Notifiers.js"; 7 7 import {EventEmitter} from "events"; 8 - import {logPath} from "./common/logging"; 9 - import { WildcardEmitter } from "./common/WildcardEmitter"; 8 + import { logPath } from "./common/logging.js"; 9 + import { WildcardEmitter } from "./common/WildcardEmitter.js"; 10 10 import normalizeUrl from 'normalize-url'; 11 11 import fs from 'fs'; 12 12
+2 -2
src/backend/notifier/AbstractWebhookNotifier.ts
··· 1 - import { GotifyConfig, NtfyConfig, WebhookPayload } from "../common/infrastructure/config/health/webhooks"; 1 + import { GotifyConfig, NtfyConfig, WebhookPayload } from "../common/infrastructure/config/health/webhooks.js"; 2 2 import {Logger} from '@foxxmd/winston'; 3 - import { mergeArr } from "../utils"; 3 + import { mergeArr } from "../utils.js"; 4 4 5 5 export abstract class AbstractWebhookNotifier { 6 6
+2 -2
src/backend/notifier/GotifyWebhookNotifier.ts
··· 1 - import { AbstractWebhookNotifier } from "./AbstractWebhookNotifier"; 2 - import { GotifyConfig, PrioritiesConfig, WebhookPayload } from "../common/infrastructure/config/health/webhooks"; 1 + import { AbstractWebhookNotifier } from "./AbstractWebhookNotifier.js"; 2 + import { GotifyConfig, PrioritiesConfig, WebhookPayload } from "../common/infrastructure/config/health/webhooks.js"; 3 3 import {gotify} from 'gotify'; 4 4 import request from 'superagent'; 5 5 import {HTTPError} from "got";
+5 -5
src/backend/notifier/Notifiers.ts
··· 1 1 import winston, {config, format, Logger} from '@foxxmd/winston'; 2 - import { mergeArr } from "../utils"; 3 - import { GotifyConfig, NtfyConfig, WebhookConfig, WebhookPayload } from "../common/infrastructure/config/health/webhooks"; 4 - import { AbstractWebhookNotifier } from "./AbstractWebhookNotifier"; 5 - import { GotifyWebhookNotifier } from "./GotifyWebhookNotifier"; 6 - import { NtfyWebhookNotifier } from "./NtfyWebhookNotifier"; 2 + import { mergeArr } from "../utils.js"; 3 + import { GotifyConfig, NtfyConfig, WebhookConfig, WebhookPayload } from "../common/infrastructure/config/health/webhooks.js"; 4 + import { AbstractWebhookNotifier } from "./AbstractWebhookNotifier.js"; 5 + import { GotifyWebhookNotifier } from "./GotifyWebhookNotifier.js"; 6 + import { NtfyWebhookNotifier } from "./NtfyWebhookNotifier.js"; 7 7 import {EventEmitter} from "events"; 8 8 9 9 export class Notifiers {
+3 -3
src/backend/notifier/NtfyWebhookNotifier.ts
··· 1 - import { AbstractWebhookNotifier } from "./AbstractWebhookNotifier"; 2 - import { NtfyConfig, PrioritiesConfig, WebhookPayload } from "../common/infrastructure/config/health/webhooks"; 1 + import { AbstractWebhookNotifier } from "./AbstractWebhookNotifier.js"; 2 + import { NtfyConfig, PrioritiesConfig, WebhookPayload } from "../common/infrastructure/config/health/webhooks.js"; 3 3 import {publish} from 'ntfy'; 4 4 import request from "superagent"; 5 5 import {Logger} from '@foxxmd/winston'; 6 - import {Config} from "ntfy/interfaces"; 6 + import {Config} from "ntfy/interfaces.js"; 7 7 8 8 export class NtfyWebhookNotifier extends AbstractWebhookNotifier { 9 9
+29 -19
src/backend/scrobblers/AbstractScrobbleClient.ts
··· 2 2 import { 3 3 comparingMultipleArtists, 4 4 mergeArr, 5 - playObjDataMatch, pollingBackoff, 6 - setIntersection, sleep, sortByOldestPlayDate, 7 - } from "../utils"; 5 + playObjDataMatch, 6 + pollingBackoff, 7 + setIntersection, 8 + sleep, 9 + sortByOldestPlayDate, 10 + } from "../utils.js"; 8 11 import { 9 - ARTIST_WEIGHT, Authenticatable, 10 - ClientType, DEFAULT_RETRY_MULTIPLIER, DUP_SCORE_THRESHOLD, 12 + ARTIST_WEIGHT, 13 + Authenticatable, 14 + ClientType, 15 + DEFAULT_RETRY_MULTIPLIER, 16 + DUP_SCORE_THRESHOLD, 11 17 FormatPlayObjectOptions, 12 18 INITIALIZED, 13 19 INITIALIZING, 14 20 InitState, 15 - NOT_INITIALIZED, REFERENCE_WEIGHT, 16 - ScrobbledPlayObject, TIME_WEIGHT, TITLE_WEIGHT, 17 - } from "../common/infrastructure/Atomic"; 21 + NOT_INITIALIZED, 22 + REFERENCE_WEIGHT, 23 + ScrobbledPlayObject, 24 + TIME_WEIGHT, 25 + TITLE_WEIGHT, 26 + } from "../common/infrastructure/Atomic.js"; 18 27 import {Logger} from '@foxxmd/winston'; 19 - import { CommonClientConfig } from "../common/infrastructure/config/client/index"; 20 - import { Notifiers } from "../notifier/Notifiers"; 28 + import { CommonClientConfig } from "../common/infrastructure/config/client/index.js"; 29 + import { Notifiers } from "../notifier/Notifiers.js"; 21 30 import {FixedSizeList} from 'fixed-size-list'; 22 31 import { 23 32 DeadLetterScrobble, 24 33 PlayObject, 25 34 QueuedScrobble, 26 - TA_CLOSE, TA_FUZZY, 27 - TrackStringOptions 28 - } from "../../core/Atomic"; 29 - import {buildTrackString, capitalize, truncateStringToLength} from "../../core/StringUtils"; 35 + TA_CLOSE, 36 + TA_FUZZY, 37 + TrackStringOptions, 38 + } from "../../core/Atomic.js"; 39 + import { buildTrackString, capitalize, truncateStringToLength } from "../../core/StringUtils.js"; 30 40 import EventEmitter from "events"; 31 - import {compareScrobbleArtists, compareScrobbleTracks, normalizeStr} from "../utils/StringUtils"; 32 - import {hasUpstreamError, UpstreamError} from "../common/errors/UpstreamError"; 41 + import { compareScrobbleArtists, compareScrobbleTracks, normalizeStr } from "../utils/StringUtils.js"; 42 + import { hasUpstreamError, UpstreamError } from "../common/errors/UpstreamError.js"; 33 43 import {nanoid} from "nanoid"; 34 44 import {ErrorWithCause, messageWithCauses} from "pony-cause"; 35 - import {hasNodeNetworkException} from "../common/errors/NodeErrors"; 45 + import { hasNodeNetworkException } from "../common/errors/NodeErrors.js"; 36 46 import { 37 47 comparePlayTemporally, 38 48 temporalAccuracyIsAtLeast, 39 49 temporalAccuracyToString, 40 - temporalPlayComparisonSummary 41 - } from "../utils/TimeUtils"; 50 + temporalPlayComparisonSummary, 51 + } from "../utils/TimeUtils.js"; 42 52 43 53 export default abstract class AbstractScrobbleClient implements Authenticatable { 44 54
+11 -11
src/backend/scrobblers/LastfmScrobbler.ts
··· 1 - import AbstractScrobbleClient from "./AbstractScrobbleClient"; 1 + import AbstractScrobbleClient from "./AbstractScrobbleClient.js"; 2 2 import dayjs from 'dayjs'; 3 3 4 4 import { ··· 7 7 setIntersection, 8 8 sleep, 9 9 sortByOldestPlayDate, 10 - } from "../utils"; 11 - import LastfmApiClient from "../common/vendor/LastfmApiClient"; 12 - import { FormatPlayObjectOptions, INITIALIZING, ScrobbledPlayObject } from "../common/infrastructure/Atomic"; 13 - import { LastfmClientConfig } from "../common/infrastructure/config/client/lastfm"; 10 + } from "../utils.js"; 11 + import LastfmApiClient from "../common/vendor/LastfmApiClient.js"; 12 + import { FormatPlayObjectOptions, INITIALIZING, ScrobbledPlayObject } from "../common/infrastructure/Atomic.js"; 13 + import { LastfmClientConfig } from "../common/infrastructure/config/client/lastfm.js"; 14 14 import {TrackScrobblePayload, TrackScrobbleResponse, UserGetRecentTracksResponse} from "lastfm-node-client"; 15 - import { Notifiers } from "../notifier/Notifiers"; 15 + import { Notifiers } from "../notifier/Notifiers.js"; 16 16 import {Logger} from '@foxxmd/winston'; 17 - import { PlayObject, TrackStringOptions } from "../../core/Atomic"; 18 - import {buildTrackString, capitalize} from "../../core/StringUtils"; 17 + import { PlayObject, TrackStringOptions } from "../../core/Atomic.js"; 18 + import { buildTrackString, capitalize } from "../../core/StringUtils.js"; 19 19 import EventEmitter from "events"; 20 - import {UpstreamError} from "../common/errors/UpstreamError"; 21 - import {isNodeNetworkException} from "../common/errors/NodeErrors"; 22 - import {getScrobbleTsSOCDate} from "../utils/TimeUtils"; 20 + import { UpstreamError } from "../common/errors/UpstreamError.js"; 21 + import { isNodeNetworkException } from "../common/errors/NodeErrors.js"; 22 + import { getScrobbleTsSOCDate } from "../utils/TimeUtils.js"; 23 23 24 24 export default class LastfmScrobbler extends AbstractScrobbleClient { 25 25
+9 -9
src/backend/scrobblers/ListenbrainzScrobbler.ts
··· 1 1 import dayjs from 'dayjs'; 2 2 3 - import AbstractScrobbleClient from "./AbstractScrobbleClient"; 4 - import { FormatPlayObjectOptions, INITIALIZING } from "../common/infrastructure/Atomic"; 5 - import { Notifiers } from "../notifier/Notifiers"; 3 + import AbstractScrobbleClient from "./AbstractScrobbleClient.js"; 4 + import { FormatPlayObjectOptions, INITIALIZING } from "../common/infrastructure/Atomic.js"; 5 + import { Notifiers } from "../notifier/Notifiers.js"; 6 6 import {Logger} from '@foxxmd/winston'; 7 - import { ListenBrainzClientConfig } from "../common/infrastructure/config/client/listenbrainz"; 8 - import {ListenbrainzApiClient, ListenPayload} from "../common/vendor/ListenbrainzApiClient"; 9 - import { PlayObject, TrackStringOptions } from "../../core/Atomic"; 10 - import {buildTrackString, capitalize} from "../../core/StringUtils"; 7 + import { ListenBrainzClientConfig } from "../common/infrastructure/config/client/listenbrainz.js"; 8 + import { ListenbrainzApiClient, ListenPayload } from "../common/vendor/ListenbrainzApiClient.js"; 9 + import { PlayObject, TrackStringOptions } from "../../core/Atomic.js"; 10 + import { buildTrackString, capitalize } from "../../core/StringUtils.js"; 11 11 import EventEmitter from "events"; 12 - import {UpstreamError} from "../common/errors/UpstreamError"; 13 - import {isNodeNetworkException} from "../common/errors/NodeErrors"; 12 + import { UpstreamError } from "../common/errors/UpstreamError.js"; 13 + import { isNodeNetworkException } from "../common/errors/NodeErrors.js"; 14 14 import {ErrorWithCause} from "pony-cause"; 15 15 16 16 export default class ListenbrainzScrobbler extends AbstractScrobbleClient {
+18 -18
src/backend/scrobblers/MalojaScrobbler.ts
··· 1 - import AbstractScrobbleClient from "./AbstractScrobbleClient"; 1 + import AbstractScrobbleClient from "./AbstractScrobbleClient.js"; 2 2 import request, {ResponseError, SuperAgentRequest} from 'superagent'; 3 3 import dayjs from 'dayjs'; 4 4 import compareVersions from 'compare-versions'; 5 - import { 6 - sleep, 7 - parseRetryAfterSecsFromObj, 8 - 9 - } from "../utils"; 10 - import {DEFAULT_RETRY_MULTIPLIER, FormatPlayObjectOptions, INITIALIZING} from "../common/infrastructure/Atomic"; 11 - import { MalojaClientConfig } from "../common/infrastructure/config/client/maloja"; 12 - import { Notifiers } from "../notifier/Notifiers"; 5 + import { sleep, parseRetryAfterSecsFromObj } from "../utils.js"; 6 + import { DEFAULT_RETRY_MULTIPLIER, FormatPlayObjectOptions, INITIALIZING } from "../common/infrastructure/Atomic.js"; 7 + import { MalojaClientConfig } from "../common/infrastructure/config/client/maloja.js"; 8 + import { Notifiers } from "../notifier/Notifiers.js"; 13 9 import {Logger} from '@foxxmd/winston'; 14 10 import { 15 11 getMalojaResponseError, 16 - isMalojaAPIErrorBody, MalojaResponseV3CommonData, 12 + isMalojaAPIErrorBody, 13 + MalojaResponseV3CommonData, 17 14 MalojaScrobbleData, 18 15 MalojaScrobbleRequestData, 19 16 MalojaScrobbleV2RequestData, 20 - MalojaScrobbleV3RequestData, MalojaScrobbleV3ResponseData, MalojaV2ScrobbleData, MalojaV3ScrobbleData 21 - } from "../common/vendor/maloja/interfaces"; 22 - import { PlayObject, TrackStringOptions } from "../../core/Atomic"; 23 - import {buildTrackString, capitalize} from "../../core/StringUtils"; 17 + MalojaScrobbleV3RequestData, 18 + MalojaScrobbleV3ResponseData, 19 + MalojaV2ScrobbleData, 20 + MalojaV3ScrobbleData, 21 + } from "../common/vendor/maloja/interfaces.js"; 22 + import { PlayObject, TrackStringOptions } from "../../core/Atomic.js"; 23 + import { buildTrackString, capitalize } from "../../core/StringUtils.js"; 24 24 import EventEmitter from "events"; 25 25 import normalizeUrl from "normalize-url"; 26 - import {UpstreamError} from "../common/errors/UpstreamError"; 26 + import { UpstreamError } from "../common/errors/UpstreamError.js"; 27 27 import {ErrorWithCause} from "pony-cause"; 28 - import {getScrobbleTsSOCDate, getScrobbleTsSOCDateWithContext} from "../utils/TimeUtils"; 28 + import { getScrobbleTsSOCDate, getScrobbleTsSOCDateWithContext } from "../utils/TimeUtils.js"; 29 29 import e from "express"; 30 - import {isNodeNetworkException} from "../common/errors/NodeErrors"; 31 - import {isSuperAgentResponseError} from "../common/errors/ErrorUtils"; 30 + import { isNodeNetworkException } from "../common/errors/NodeErrors.js"; 31 + import { isSuperAgentResponseError } from "../common/errors/ErrorUtils.js"; 32 32 33 33 const feat = ["ft.", "ft", "feat.", "feat", "featuring", "Ft.", "Ft", "Feat.", "Feat", "Featuring"]; 34 34
+15 -15
src/backend/scrobblers/ScrobbleClients.ts
··· 6 6 readJson, 7 7 returnDuplicateStrings, 8 8 validateJson, 9 - } from "../utils"; 10 - import MalojaScrobbler from "./MalojaScrobbler"; 11 - import LastfmScrobbler from "./LastfmScrobbler"; 12 - import { clientTypes, ConfigMeta } from "../common/infrastructure/Atomic"; 13 - import { AIOConfig } from "../common/infrastructure/config/aioConfig"; 9 + } from "../utils.js"; 10 + import MalojaScrobbler from "./MalojaScrobbler.js"; 11 + import LastfmScrobbler from "./LastfmScrobbler.js"; 12 + import { clientTypes, ConfigMeta } from "../common/infrastructure/Atomic.js"; 13 + import { AIOConfig } from "../common/infrastructure/config/aioConfig.js"; 14 14 import * as aioSchema from '../common/schema/aio-client.json'; 15 15 import * as clientSchema from '../common/schema/client.json'; 16 - import { ClientAIOConfig, ClientConfig } from "../common/infrastructure/config/client/clients"; 17 - import { MalojaClientConfig } from "../common/infrastructure/config/client/maloja"; 18 - import { LastfmClientConfig } from "../common/infrastructure/config/client/lastfm"; 19 - import { Notifiers } from "../notifier/Notifiers"; 20 - import AbstractScrobbleClient from "./AbstractScrobbleClient"; 16 + import { ClientAIOConfig, ClientConfig } from "../common/infrastructure/config/client/clients.js"; 17 + import { MalojaClientConfig } from "../common/infrastructure/config/client/maloja.js"; 18 + import { LastfmClientConfig } from "../common/infrastructure/config/client/lastfm.js"; 19 + import { Notifiers } from "../notifier/Notifiers.js"; 20 + import AbstractScrobbleClient from "./AbstractScrobbleClient.js"; 21 21 import {EventEmitter} from "events"; 22 22 import winston, {Logger} from '@foxxmd/winston'; 23 - import ListenbrainzScrobbler from "./ListenbrainzScrobbler"; 24 - import { ListenBrainzClientConfig } from "../common/infrastructure/config/client/listenbrainz"; 23 + import ListenbrainzScrobbler from "./ListenbrainzScrobbler.js"; 24 + import { ListenBrainzClientConfig } from "../common/infrastructure/config/client/listenbrainz.js"; 25 25 import {ErrorWithCause} from "pony-cause"; 26 - import { PlayObject } from "../../core/Atomic"; 27 - import { buildTrackString } from "../../core/StringUtils"; 28 - import { WildcardEmitter } from "../common/WildcardEmitter"; 26 + import { PlayObject } from "../../core/Atomic.js"; 27 + import { buildTrackString } from "../../core/StringUtils.js"; 28 + import { WildcardEmitter } from "../common/WildcardEmitter.js"; 29 29 30 30 type groupedNamedConfigs = {[key: string]: ParsedConfig[]}; 31 31
+20 -18
src/backend/server/api.ts
··· 1 1 import {ExpressWithAsync} from "@awaitjs/express"; 2 - import {getRoot} from "../ioc"; 3 - import {makeClientCheckMiddle, makeSourceCheckMiddle} from "./middleware"; 4 - import AbstractSource from "../sources/AbstractSource"; 2 + import { getRoot } from "../ioc.js"; 3 + import { makeClientCheckMiddle, makeSourceCheckMiddle } from "./middleware.js"; 4 + import AbstractSource from "../sources/AbstractSource.js"; 5 5 import { 6 - ClientStatusData, DeadLetterScrobble, 6 + ClientStatusData, 7 + DeadLetterScrobble, 7 8 LogInfo, 8 9 LogInfoJson, 9 10 LogLevel, 10 - LogOutputConfig, PlayObject, 11 + LogOutputConfig, 12 + PlayObject, 11 13 SourceStatusData, 12 - } from "../../core/Atomic"; 14 + } from "../../core/Atomic.js"; 13 15 import {Logger} from "@foxxmd/winston"; 14 - import {formatLogToHtml, getLogger, isLogLevelMinLevel, isLogLineMinLevel} from "../common/logging"; 16 + import { formatLogToHtml, getLogger, isLogLevelMinLevel, isLogLineMinLevel } from "../common/logging.js"; 15 17 import {MESSAGE} from "triple-beam"; 16 18 import {Transform} from "stream"; 17 19 //import {createSession} from "better-sse"; 18 20 import * as bsse from 'better-sse'; 19 - import {setupTautulliRoutes} from "./tautulliRoutes"; 20 - import {setupPlexRoutes} from "./plexRoutes"; 21 - import {setupJellyfinRoutes} from "./jellyfinRoutes"; 22 - import {setupDeezerRoutes} from "./deezerRoutes"; 23 - import {setupAuthRoutes} from "./auth"; 24 - import {ExpressHandler, ScrobbledPlayObject} from "../common/infrastructure/Atomic"; 25 - import MemorySource from "../sources/MemorySource"; 26 - import {capitalize} from "../../core/StringUtils"; 21 + import { setupTautulliRoutes } from "./tautulliRoutes.js"; 22 + import { setupPlexRoutes } from "./plexRoutes.js"; 23 + import { setupJellyfinRoutes } from "./jellyfinRoutes.js"; 24 + import { setupDeezerRoutes } from "./deezerRoutes.js"; 25 + import { setupAuthRoutes } from "./auth.js"; 26 + import { ExpressHandler, ScrobbledPlayObject } from "../common/infrastructure/Atomic.js"; 27 + import MemorySource from "../sources/MemorySource.js"; 28 + import { capitalize } from "../../core/StringUtils.js"; 27 29 import {source} from "common-tags"; 28 - import AbstractScrobbleClient from "../scrobblers/AbstractScrobbleClient"; 29 - import {sortByNewestPlayDate} from "../utils"; 30 + import AbstractScrobbleClient from "../scrobblers/AbstractScrobbleClient.js"; 31 + import { sortByNewestPlayDate } from "../utils.js"; 30 32 import bodyParser from "body-parser"; 31 - import {setupWebscrobblerRoutes} from "./webscrobblerRoutes"; 33 + import { setupWebscrobblerRoutes } from "./webscrobblerRoutes.js"; 32 34 import {FixedSizeList} from 'fixed-size-list'; 33 35 34 36 const maxBufferSize = 300;
+6 -6
src/backend/server/auth.ts
··· 1 1 import {ExpressWithAsync} from "@awaitjs/express"; 2 2 import {Logger} from "@foxxmd/winston"; 3 - import ScrobbleSources from "../sources/ScrobbleSources"; 3 + import ScrobbleSources from "../sources/ScrobbleSources.js"; 4 4 import passport from "passport"; 5 - import { ExpressHandler } from "../common/infrastructure/Atomic"; 6 - import ScrobbleClients from "../scrobblers/ScrobbleClients"; 7 - import LastfmScrobbler from "../scrobblers/LastfmScrobbler"; 8 - import LastfmSource from "../sources/LastfmSource"; 9 - import SpotifySource from "../sources/SpotifySource"; 5 + import { ExpressHandler } from "../common/infrastructure/Atomic.js"; 6 + import ScrobbleClients from "../scrobblers/ScrobbleClients.js"; 7 + import LastfmScrobbler from "../scrobblers/LastfmScrobbler.js"; 8 + import LastfmSource from "../sources/LastfmSource.js"; 9 + import SpotifySource from "../sources/SpotifySource.js"; 10 10 11 11 export const setupAuthRoutes = (app: ExpressWithAsync, logger: Logger, sourceMiddle: ExpressHandler, clientMiddle: ExpressHandler, scrobbleSources: ScrobbleSources, scrobbleClients: ScrobbleClients) => { 12 12 app.use('/api/client/auth', clientMiddle);
+6 -6
src/backend/server/deezerRoutes.ts
··· 1 - import { ExpressHandler } from "../common/infrastructure/Atomic"; 2 - import { mergeArr, parseBool, sleep } from "../utils"; 1 + import { ExpressHandler } from "../common/infrastructure/Atomic.js"; 2 + import { mergeArr, parseBool, sleep } from "../utils.js"; 3 3 import {ExpressWithAsync} from "@awaitjs/express"; 4 4 import {Logger} from "@foxxmd/winston"; 5 - import ScrobbleSources from "../sources/ScrobbleSources"; 6 - import PlexSource, { plexRequestMiddle } from "../sources/PlexSource"; 7 - import { PlexNotifier } from "../sources/ingressNotifiers/PlexNotifier"; 8 - import DeezerSource from "../sources/DeezerSource"; 5 + import ScrobbleSources from "../sources/ScrobbleSources.js"; 6 + import PlexSource, { plexRequestMiddle } from "../sources/PlexSource.js"; 7 + import { PlexNotifier } from "../sources/ingressNotifiers/PlexNotifier.js"; 8 + import DeezerSource from "../sources/DeezerSource.js"; 9 9 import passport from "passport"; 10 10 11 11 export const setupDeezerRoutes = (app: ExpressWithAsync, logger: Logger, scrobbleSources: ScrobbleSources) => {
+4 -4
src/backend/server/index.ts
··· 5 5 import passport from 'passport'; 6 6 import session from 'express-session'; 7 7 import path from "path"; 8 - import { getRoot } from "../ioc"; 8 + import { getRoot } from "../ioc.js"; 9 9 import {Logger} from "@foxxmd/winston"; 10 - import { LogInfo } from "../../core/Atomic"; 11 - import { setupApi } from "./api"; 12 - import { getAddress, mergeArr, parseBool } from "../utils"; 10 + import { LogInfo } from "../../core/Atomic.js"; 11 + import { setupApi } from "./api.js"; 12 + import { getAddress, mergeArr, parseBool } from "../utils.js"; 13 13 import {stripIndents} from "common-tags"; 14 14 import {ErrorWithCause} from "pony-cause"; 15 15
+4 -4
src/backend/server/jellyfinRoutes.ts
··· 1 - import { parseBool, remoteHostIdentifiers } from "../utils"; 1 + import { parseBool, remoteHostIdentifiers } from "../utils.js"; 2 2 import {ExpressWithAsync} from "@awaitjs/express"; 3 3 import {Logger} from "@foxxmd/winston"; 4 - import ScrobbleSources from "../sources/ScrobbleSources"; 4 + import ScrobbleSources from "../sources/ScrobbleSources.js"; 5 5 import bodyParser from "body-parser"; 6 - import { JellyfinNotifier } from "../sources/ingressNotifiers/JellyfinNotifier"; 7 - import JellyfinSource from "../sources/JellyfinSource"; 6 + import { JellyfinNotifier } from "../sources/ingressNotifiers/JellyfinNotifier.js"; 7 + import JellyfinSource from "../sources/JellyfinSource.js"; 8 8 9 9 export const setupJellyfinRoutes = (app: ExpressWithAsync, logger: Logger, scrobbleSources: ScrobbleSources) => { 10 10
+1 -1
src/backend/server/middleware.ts
··· 1 - import { ExpressHandler } from "../common/infrastructure/Atomic"; 1 + import { ExpressHandler } from "../common/infrastructure/Atomic.js"; 2 2 import {Logger} from "@foxxmd/winston"; 3 3 4 4 export const makeSourceCheckMiddle = (sources: any) => (required: boolean ): ExpressHandler => (req: any, res: any, next: any) => {
+5 -5
src/backend/server/plexRoutes.ts
··· 1 - import { ExpressHandler } from "../common/infrastructure/Atomic"; 2 - import { mergeArr, parseBool } from "../utils"; 1 + import { ExpressHandler } from "../common/infrastructure/Atomic.js"; 2 + import { mergeArr, parseBool } from "../utils.js"; 3 3 import {ExpressWithAsync} from "@awaitjs/express"; 4 4 import {Logger} from "@foxxmd/winston"; 5 - import ScrobbleSources from "../sources/ScrobbleSources"; 6 - import PlexSource, { plexRequestMiddle } from "../sources/PlexSource"; 7 - import { PlexNotifier } from "../sources/ingressNotifiers/PlexNotifier"; 5 + import ScrobbleSources from "../sources/ScrobbleSources.js"; 6 + import PlexSource, { plexRequestMiddle } from "../sources/PlexSource.js"; 7 + import { PlexNotifier } from "../sources/ingressNotifiers/PlexNotifier.js"; 8 8 9 9 export const setupPlexRoutes = (app: ExpressWithAsync, logger: Logger, scrobbleSources: ScrobbleSources) => { 10 10
+5 -5
src/backend/server/tautulliRoutes.ts
··· 1 - import { TautulliNotifier } from "../sources/ingressNotifiers/TautulliNotifier"; 2 - import { ExpressHandler } from "../common/infrastructure/Atomic"; 3 - import TautulliSource from "../sources/TautulliSource"; 4 - import { parseBool } from "../utils"; 1 + import { TautulliNotifier } from "../sources/ingressNotifiers/TautulliNotifier.js"; 2 + import { ExpressHandler } from "../common/infrastructure/Atomic.js"; 3 + import TautulliSource from "../sources/TautulliSource.js"; 4 + import { parseBool } from "../utils.js"; 5 5 import {ExpressWithAsync} from "@awaitjs/express"; 6 6 import {Logger} from "@foxxmd/winston"; 7 - import ScrobbleSources from "../sources/ScrobbleSources"; 7 + import ScrobbleSources from "../sources/ScrobbleSources.js"; 8 8 9 9 export const setupTautulliRoutes = (app: ExpressWithAsync, logger: Logger, scrobbleSources: ScrobbleSources) => { 10 10
+6 -6
src/backend/server/webscrobblerRoutes.ts
··· 1 - import {mergeArr, parseBool, remoteHostIdentifiers} from "../utils"; 1 + import { mergeArr, parseBool, remoteHostIdentifiers } from "../utils.js"; 2 2 import {ExpressWithAsync} from "@awaitjs/express"; 3 3 import {Logger} from "@foxxmd/winston"; 4 - import ScrobbleSources from "../sources/ScrobbleSources"; 4 + import ScrobbleSources from "../sources/ScrobbleSources.js"; 5 5 import bodyParser from "body-parser"; 6 - import {WebScrobblerPayload} from "../common/vendor/webscrobbler/interfaces"; 7 - import {WebhookNotifier} from "../sources/ingressNotifiers/WebhookNotifier"; 8 - import {nonEmptyBody} from "./middleware"; 9 - import {WebScrobblerSource} from "../sources/WebScrobblerSource"; 6 + import { WebScrobblerPayload } from "../common/vendor/webscrobbler/interfaces.js"; 7 + import { WebhookNotifier } from "../sources/ingressNotifiers/WebhookNotifier.js"; 8 + import { nonEmptyBody } from "./middleware.js"; 9 + import { WebScrobblerSource } from "../sources/WebScrobblerSource.js"; 10 10 import path from "path"; 11 11 12 12 export const setupWebscrobblerRoutes = (app: ExpressWithAsync, parentLogger: Logger, scrobbleSources: ScrobbleSources) => {
+14 -10
src/backend/sources/AbstractSource.ts
··· 7 7 pollingBackoff, 8 8 sleep, 9 9 sortByNewestPlayDate, 10 - sortByOldestPlayDate, findCauseByFunc, formatNumber, 11 - } from "../utils"; 10 + sortByOldestPlayDate, 11 + findCauseByFunc, 12 + formatNumber, 13 + } from "../utils.js"; 12 14 import { 13 15 Authenticatable, 14 - DEFAULT_POLLING_INTERVAL, DEFAULT_POLLING_MAX_INTERVAL, DEFAULT_RETRY_MULTIPLIER, 16 + DEFAULT_POLLING_INTERVAL, 17 + DEFAULT_POLLING_MAX_INTERVAL, 18 + DEFAULT_RETRY_MULTIPLIER, 15 19 DeviceId, 16 20 GroupedFixedPlays, 17 21 GroupedPlays, ··· 23 27 ProgressAwarePlayObject, 24 28 SINGLE_USER_PLATFORM_ID, 25 29 SourceType, 26 - } from "../common/infrastructure/Atomic"; 30 + } from "../common/infrastructure/Atomic.js"; 27 31 import {Logger} from '@foxxmd/winston'; 28 - import { SourceConfig } from "../common/infrastructure/config/source/sources"; 32 + import { SourceConfig } from "../common/infrastructure/config/source/sources.js"; 29 33 import {EventEmitter} from "events"; 30 34 import {FixedSizeList} from "fixed-size-list"; 31 - import TupleMap from "../common/TupleMap"; 32 - import {PlayObject, TA_CLOSE} from "../../core/Atomic"; 33 - import {buildTrackString, capitalize} from "../../core/StringUtils"; 34 - import {isNodeNetworkException} from "../common/errors/NodeErrors"; 35 + import TupleMap from "../common/TupleMap.js"; 36 + import { PlayObject, TA_CLOSE } from "../../core/Atomic.js"; 37 + import { buildTrackString, capitalize } from "../../core/StringUtils.js"; 38 + import { isNodeNetworkException } from "../common/errors/NodeErrors.js"; 35 39 import {ErrorWithCause} from "pony-cause"; 36 - import {comparePlayTemporally, temporalAccuracyIsAtLeast} from "../utils/TimeUtils"; 40 + import { comparePlayTemporally, temporalAccuracyIsAtLeast } from "../utils/TimeUtils.js"; 37 41 38 42 export interface RecentlyPlayedOptions { 39 43 limit?: number
+20 -20
src/backend/sources/ChromecastSource.ts
··· 1 - import MemorySource from "./MemorySource"; 2 - import {ChromecastSourceConfig} from "../common/infrastructure/config/source/chromecast"; 1 + import MemorySource from "./MemorySource.js"; 2 + import { ChromecastSourceConfig } from "../common/infrastructure/config/source/chromecast.js"; 3 3 import { 4 4 FormatPlayObjectOptions, 5 - InternalConfig, MdnsDeviceInfo, NO_USER, 5 + InternalConfig, 6 + MdnsDeviceInfo, 7 + NO_USER, 6 8 PlayerStateData, 7 - SourceData 8 - } from "../common/infrastructure/Atomic"; 9 + SourceData, 10 + } from "../common/infrastructure/Atomic.js"; 9 11 import {EventEmitter} from "events"; 10 12 import {MediaController, PersistentClient, Media, connect, createPlatform} from "@foxxmd/chromecast-client"; 11 13 import {Client as CastClient} from 'castv2'; 12 14 import {ErrorWithCause, findCauseByReference} from "pony-cause"; 13 - import {PlayObject} from "../../core/Atomic"; 15 + import { PlayObject } from "../../core/Atomic.js"; 14 16 import dayjs from "dayjs"; 15 - import {RecentlyPlayedOptions} from "./AbstractSource"; 16 - import {difference, genGroupIdStr, isIPv4, mergeArr, parseBool, sleep} from "../utils"; 17 - import { 18 - PlatformApplication, 19 - PlatformApplicationWithContext, 20 - PlatformType 21 - } from "../common/vendor/chromecast/interfaces"; 17 + import { RecentlyPlayedOptions } from "./AbstractSource.js"; 18 + import { difference, genGroupIdStr, isIPv4, mergeArr, parseBool, sleep } from "../utils.js"; 19 + import { PlatformApplication, PlatformApplicationWithContext, PlatformType } from "../common/vendor/chromecast/interfaces.js"; 22 20 import { 23 - chromePlayerStateToReported, genDeviceId, 24 - getCurrentPlatformApplications, getMediaStatus, 25 - genPlayHash 26 - } from "../common/vendor/chromecast/ChromecastClientUtils"; 21 + chromePlayerStateToReported, 22 + genDeviceId, 23 + getCurrentPlatformApplications, 24 + getMediaStatus, 25 + genPlayHash, 26 + } from "../common/vendor/chromecast/ChromecastClientUtils.js"; 27 27 import {config, Logger} from "@foxxmd/winston"; 28 - import {ContextualValidationError} from "@foxxmd/chromecast-client/dist/cjs/src/utils"; 29 - import {buildTrackString} from "../../core/StringUtils"; 30 - import {discoveryAvahi, discoveryNative} from "../utils/MDNSUtils"; 28 + import {ContextualValidationError} from "@foxxmd/chromecast-client/dist/cjs/src/utils.js"; 29 + import { buildTrackString } from "../../core/StringUtils.js"; 30 + import { discoveryAvahi, discoveryNative } from "../utils/MDNSUtils.js"; 31 31 32 32 interface ChromecastDeviceInfo { 33 33 mdns: MdnsDeviceInfo
+5 -5
src/backend/sources/DeezerSource.ts
··· 6 6 sleep, 7 7 sortByOldestPlayDate, 8 8 writeFile, 9 - } from "../utils"; 9 + } from "../utils.js"; 10 10 import {Strategy as DeezerStrategy} from 'passport-deezer'; 11 - import AbstractSource, { RecentlyPlayedOptions } from "./AbstractSource"; 11 + import AbstractSource, { RecentlyPlayedOptions } from "./AbstractSource.js"; 12 12 import dayjs from "dayjs"; 13 - import { DeezerSourceConfig } from "../common/infrastructure/config/source/deezer"; 14 - import {DEFAULT_RETRY_MULTIPLIER, FormatPlayObjectOptions, InternalConfig} from "../common/infrastructure/Atomic"; 13 + import { DeezerSourceConfig } from "../common/infrastructure/config/source/deezer.js"; 14 + import { DEFAULT_RETRY_MULTIPLIER, FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic.js"; 15 15 import EventEmitter from "events"; 16 - import { PlayObject } from "../../core/Atomic"; 16 + import { PlayObject } from "../../core/Atomic.js"; 17 17 18 18 export default class DeezerSource extends AbstractSource { 19 19 workingCredsPath;
+6 -6
src/backend/sources/JRiverSource.ts
··· 1 - import MemorySource from "./MemorySource"; 2 - import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic"; 1 + import MemorySource from "./MemorySource.js"; 2 + import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic.js"; 3 3 import dayjs from "dayjs"; 4 4 import {URL} from "url"; 5 5 import normalizeUrl from 'normalize-url'; 6 6 import {EventEmitter} from "events"; 7 - import { RecentlyPlayedOptions } from "./AbstractSource"; 8 - import { JRiverSourceConfig } from "../common/infrastructure/config/source/jriver"; 9 - import { Info, JRiverApiClient, PLAYER_STATE } from "../common/vendor/JRiverApiClient"; 10 - import { PlayObject } from "../../core/Atomic"; 7 + import { RecentlyPlayedOptions } from "./AbstractSource.js"; 8 + import { JRiverSourceConfig } from "../common/infrastructure/config/source/jriver.js"; 9 + import { Info, JRiverApiClient, PLAYER_STATE } from "../common/vendor/JRiverApiClient.js"; 10 + import { PlayObject } from "../../core/Atomic.js"; 11 11 12 12 export class JRiverSource extends MemorySource { 13 13 declare config: JRiverSourceConfig;
+10 -10
src/backend/sources/JellyfinSource.ts
··· 1 - import MemorySource from "./MemorySource"; 1 + import MemorySource from "./MemorySource.js"; 2 2 import dayjs, {Dayjs} from "dayjs"; 3 3 import { 4 4 combinePartsToString, ··· 6 6 parseDurationFromTimestamp, 7 7 playObjDataMatch, 8 8 doubleReturnNewline, 9 - } from "../utils"; 10 - import { JellySourceConfig } from "../common/infrastructure/config/source/jellyfin"; 11 - import { FormatPlayObjectOptions, InternalConfig, PlayPlatformId } from "../common/infrastructure/Atomic"; 9 + } from "../utils.js"; 10 + import { JellySourceConfig } from "../common/infrastructure/config/source/jellyfin.js"; 11 + import { FormatPlayObjectOptions, InternalConfig, PlayPlatformId } from "../common/infrastructure/Atomic.js"; 12 12 import EventEmitter from "events"; 13 - import { PlayerStateOptions } from "./PlayerState/AbstractPlayerState"; 13 + import { PlayerStateOptions } from "./PlayerState/AbstractPlayerState.js"; 14 14 import {Logger} from "@foxxmd/winston"; 15 - import { JellyfinPlayerState } from "./PlayerState/JellyfinPlayerState"; 16 - import {PlayObject, TA_CLOSE} from "../../core/Atomic"; 17 - import {buildTrackString, splitByFirstFound, truncateStringToLength} from "../../core/StringUtils"; 15 + import { JellyfinPlayerState } from "./PlayerState/JellyfinPlayerState.js"; 16 + import { PlayObject, TA_CLOSE } from "../../core/Atomic.js"; 17 + import { buildTrackString, splitByFirstFound, truncateStringToLength } from "../../core/StringUtils.js"; 18 18 import {source} from "common-tags"; 19 19 import { 20 20 comparePlayTemporally, 21 21 temporalAccuracyIsAtLeast, 22 - temporalPlayComparisonSummary 23 - } from "../utils/TimeUtils"; 22 + temporalPlayComparisonSummary, 23 + } from "../utils/TimeUtils.js"; 24 24 25 25 const shortDeviceId = truncateStringToLength(10, ''); 26 26
+6 -6
src/backend/sources/KodiSource.ts
··· 1 - import MemorySource from "./MemorySource"; 2 - import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic"; 1 + import MemorySource from "./MemorySource.js"; 2 + import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic.js"; 3 3 import {EventEmitter} from "events"; 4 - import { RecentlyPlayedOptions } from "./AbstractSource"; 5 - import { KodiSourceConfig } from "../common/infrastructure/config/source/kodi"; 6 - import { KodiApiClient } from "../common/vendor/KodiApiClient"; 7 - import { PlayObject } from "../../core/Atomic"; 4 + import { RecentlyPlayedOptions } from "./AbstractSource.js"; 5 + import { KodiSourceConfig } from "../common/infrastructure/config/source/kodi.js"; 6 + import { KodiApiClient } from "../common/vendor/KodiApiClient.js"; 7 + import { PlayObject } from "../../core/Atomic.js"; 8 8 9 9 export class KodiSource extends MemorySource { 10 10 declare config: KodiSourceConfig;
+8 -8
src/backend/sources/LastfmSource.ts
··· 1 - import { RecentlyPlayedOptions } from "./AbstractSource"; 2 - import LastfmApiClient from "../common/vendor/LastfmApiClient"; 3 - import { sortByOldestPlayDate } from "../utils"; 4 - import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic"; 1 + import { RecentlyPlayedOptions } from "./AbstractSource.js"; 2 + import LastfmApiClient from "../common/vendor/LastfmApiClient.js"; 3 + import { sortByOldestPlayDate } from "../utils.js"; 4 + import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic.js"; 5 5 import {TrackObject, UserGetRecentTracksResponse} from "lastfm-node-client"; 6 6 import EventEmitter from "events"; 7 - import { PlayObject } from "../../core/Atomic"; 8 - import MemorySource from "./MemorySource"; 9 - import {LastfmSourceConfig} from "../common/infrastructure/config/source/lastfm"; 7 + import { PlayObject } from "../../core/Atomic.js"; 8 + import MemorySource from "./MemorySource.js"; 9 + import { LastfmSourceConfig } from "../common/infrastructure/config/source/lastfm.js"; 10 10 import dayjs from "dayjs"; 11 - import {isNodeNetworkException} from "../common/errors/NodeErrors"; 11 + import { isNodeNetworkException } from "../common/errors/NodeErrors.js"; 12 12 import {ErrorWithCause} from "pony-cause"; 13 13 14 14 export default class LastfmSource extends MemorySource {
+5 -5
src/backend/sources/ListenbrainzSource.ts
··· 1 - import AbstractSource, { RecentlyPlayedOptions } from "./AbstractSource"; 2 - import { FormatPlayObjectOptions, INITIALIZING, InternalConfig } from "../common/infrastructure/Atomic"; 1 + import AbstractSource, { RecentlyPlayedOptions } from "./AbstractSource.js"; 2 + import { FormatPlayObjectOptions, INITIALIZING, InternalConfig } from "../common/infrastructure/Atomic.js"; 3 3 import EventEmitter from "events"; 4 - import { ListenBrainzSourceConfig } from "../common/infrastructure/config/source/listenbrainz"; 5 - import { ListenbrainzApiClient } from "../common/vendor/ListenbrainzApiClient"; 6 - import MemorySource from "./MemorySource"; 4 + import { ListenBrainzSourceConfig } from "../common/infrastructure/config/source/listenbrainz.js"; 5 + import { ListenbrainzApiClient } from "../common/vendor/ListenbrainzApiClient.js"; 6 + import MemorySource from "./MemorySource.js"; 7 7 import {ErrorWithCause} from "pony-cause"; 8 8 9 9 export default class ListenbrainzSource extends MemorySource {
+6 -6
src/backend/sources/MPRISSource.ts
··· 9 9 PlaybackStatus, 10 10 PlayerInfo, 11 11 PROPERTIES_IFACE, 12 - } from "../common/infrastructure/config/source/mpris"; 13 - import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic"; 14 - import MemorySource from "./MemorySource"; 15 - import { RecentlyPlayedOptions } from "./AbstractSource"; 16 - import { removeDuplicates } from "../utils"; 12 + } from "../common/infrastructure/config/source/mpris.js"; 13 + import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic.js"; 14 + import MemorySource from "./MemorySource.js"; 15 + import { RecentlyPlayedOptions } from "./AbstractSource.js"; 16 + import { removeDuplicates } from "../utils.js"; 17 17 import EventEmitter from "events"; 18 18 import {ErrorWithCause} from "pony-cause"; 19 - import { PlayObject } from "../../core/Atomic"; 19 + import { PlayObject } from "../../core/Atomic.js"; 20 20 21 21 22 22 export class MPRISSource extends MemorySource {
+18 -14
src/backend/sources/MemorySource.ts
··· 1 - import AbstractSource from "./AbstractSource"; 1 + import AbstractSource from "./AbstractSource.js"; 2 2 import { 3 3 playObjDataMatch, 4 4 sortByOldestPlayDate, ··· 7 7 thresholdResultSummary, 8 8 genGroupId, 9 9 genGroupIdStr, 10 - getPlatformIdFromData, formatNumber, 11 - } from "../utils"; 10 + getPlatformIdFromData, 11 + formatNumber, 12 + } from "../utils.js"; 12 13 import dayjs from "dayjs"; 13 14 import { 14 - asPlayerStateData, CALCULATED_PLAYER_STATUSES, 15 + asPlayerStateData, 16 + CALCULATED_PLAYER_STATUSES, 15 17 DeviceId, 16 - GroupedPlays, InternalConfig, 18 + GroupedPlays, 19 + InternalConfig, 17 20 PlayerStateData, 18 21 PlayPlatformId, 19 22 PlayUserId, 20 23 ProgressAwarePlayObject, 21 - ScrobbleThresholdResult, SourceType, 22 - } from "../common/infrastructure/Atomic"; 23 - import TupleMap from "../common/TupleMap"; 24 - import { AbstractPlayerState, PlayerStateOptions } from "./PlayerState/AbstractPlayerState"; 25 - import { GenericPlayerState } from "./PlayerState/GenericPlayerState"; 24 + ScrobbleThresholdResult, 25 + SourceType, 26 + } from "../common/infrastructure/Atomic.js"; 27 + import TupleMap from "../common/TupleMap.js"; 28 + import { AbstractPlayerState, PlayerStateOptions } from "./PlayerState/AbstractPlayerState.js"; 29 + import { GenericPlayerState } from "./PlayerState/GenericPlayerState.js"; 26 30 import {Logger} from "@foxxmd/winston"; 27 - import {PlayObject, SourcePlayerObj} from "../../core/Atomic"; 28 - import { buildTrackString } from "../../core/StringUtils"; 31 + import { PlayObject, SourcePlayerObj } from "../../core/Atomic.js"; 32 + import { buildTrackString } from "../../core/StringUtils.js"; 29 33 import {SimpleIntervalJob, Task, ToadScheduler} from "toad-scheduler"; 30 - import {SourceConfig} from "../common/infrastructure/config/source/sources"; 34 + import { SourceConfig } from "../common/infrastructure/config/source/sources.js"; 31 35 import {EventEmitter} from "events"; 32 36 import objectHash from 'object-hash'; 33 - import {timePassesScrobbleThreshold} from "../utils/TimeUtils"; 37 + import { timePassesScrobbleThreshold } from "../utils/TimeUtils.js"; 34 38 35 39 export default class MemorySource extends AbstractSource { 36 40
+6 -6
src/backend/sources/MopidySource.ts
··· 1 - import MemorySource from "./MemorySource"; 2 - import { MopidySourceConfig } from "../common/infrastructure/config/source/mopidy"; 1 + import MemorySource from "./MemorySource.js"; 2 + import { MopidySourceConfig } from "../common/infrastructure/config/source/mopidy.js"; 3 3 import { 4 4 FormatPlayObjectOptions, 5 5 InternalConfig, 6 6 PlayerStateData, 7 7 SINGLE_USER_PLATFORM_ID, 8 - } from "../common/infrastructure/Atomic"; 8 + } from "../common/infrastructure/Atomic.js"; 9 9 import dayjs from "dayjs"; 10 10 import Mopidy, {models} from "mopidy"; 11 11 import {URL} from "url"; ··· 13 13 import {EventEmitter} from "events"; 14 14 import pEvent from 'p-event'; 15 15 import winston from '@foxxmd/winston'; 16 - import { RecentlyPlayedOptions } from "./AbstractSource"; 17 - import { PlayObject } from "../../core/Atomic"; 18 - import { buildTrackString } from "../../core/StringUtils"; 16 + import { RecentlyPlayedOptions } from "./AbstractSource.js"; 17 + import { PlayObject } from "../../core/Atomic.js"; 18 + import { buildTrackString } from "../../core/StringUtils.js"; 19 19 20 20 export class MopidySource extends MemorySource { 21 21 declare config: MopidySourceConfig;
+6 -6
src/backend/sources/PlayerState/AbstractPlayerState.ts
··· 4 4 PlayPlatformId, 5 5 REPORTED_PLAYER_STATUSES, 6 6 ReportedPlayerStatus, 7 - } from "../../common/infrastructure/Atomic"; 7 + } from "../../common/infrastructure/Atomic.js"; 8 8 import dayjs, {Dayjs} from "dayjs"; 9 - import { formatNumber, genGroupIdStr, playObjDataMatch, progressBar } from "../../utils"; 9 + import { formatNumber, genGroupIdStr, playObjDataMatch, progressBar } from "../../utils.js"; 10 10 import {Logger} from "@foxxmd/winston"; 11 - import { ListenProgress } from "./ListenProgress"; 12 - import {PlayObject, Second, SourcePlayerObj} from "../../../core/Atomic"; 13 - import { buildTrackString } from "../../../core/StringUtils"; 14 - import {ListenRange} from "./ListenRange"; 11 + import { ListenProgress } from "./ListenProgress.js"; 12 + import { PlayObject, Second, SourcePlayerObj } from "../../../core/Atomic.js"; 13 + import { buildTrackString } from "../../../core/StringUtils.js"; 14 + import { ListenRange } from "./ListenRange.js"; 15 15 import {id} from "common-tags"; 16 16 17 17 export interface PlayerStateIntervals {
+2 -2
src/backend/sources/PlayerState/GenericPlayerState.ts
··· 1 - import { AbstractPlayerState, PlayerStateOptions } from "./AbstractPlayerState"; 1 + import { AbstractPlayerState, PlayerStateOptions } from "./AbstractPlayerState.js"; 2 2 import {Logger} from "@foxxmd/winston"; 3 - import { PlayPlatformId } from "../../common/infrastructure/Atomic"; 3 + import { PlayPlatformId } from "../../common/infrastructure/Atomic.js"; 4 4 5 5 export class GenericPlayerState extends AbstractPlayerState { 6 6 constructor(logger: Logger, platformId: PlayPlatformId, opts?: PlayerStateOptions) {
+4 -4
src/backend/sources/PlayerState/JellyfinPlayerState.ts
··· 1 - import { GenericPlayerState } from "./GenericPlayerState"; 1 + import { GenericPlayerState } from "./GenericPlayerState.js"; 2 2 import {Logger} from "@foxxmd/winston"; 3 - import { PlayPlatformId, ReportedPlayerStatus } from "../../common/infrastructure/Atomic"; 4 - import { PlayerStateOptions } from "./AbstractPlayerState"; 5 - import { PlayObject } from "../../../core/Atomic"; 3 + import { PlayPlatformId, ReportedPlayerStatus } from "../../common/infrastructure/Atomic.js"; 4 + import { PlayerStateOptions } from "./AbstractPlayerState.js"; 5 + import { PlayObject } from "../../../core/Atomic.js"; 6 6 7 7 export class JellyfinPlayerState extends GenericPlayerState { 8 8 constructor(logger: Logger, platformId: PlayPlatformId, opts?: PlayerStateOptions) {
+1 -1
src/backend/sources/PlayerState/ListenProgress.ts
··· 1 1 import dayjs, {Dayjs} from "dayjs"; 2 2 3 - import {PlayProgress, Second} from "../../../core/Atomic"; 3 + import { PlayProgress, Second } from "../../../core/Atomic.js"; 4 4 5 5 export class ListenProgress implements PlayProgress { 6 6
+2 -2
src/backend/sources/PlayerState/ListenRange.ts
··· 1 - import {ListenProgress} from "./ListenProgress"; 1 + import { ListenProgress } from "./ListenProgress.js"; 2 2 import dayjs, {Dayjs} from "dayjs"; 3 - import {ListenRangeData, Second} from "../../../core/Atomic"; 3 + import { ListenRangeData, Second } from "../../../core/Atomic.js"; 4 4 5 5 export class ListenRange implements ListenRangeData { 6 6
+6 -6
src/backend/sources/PlexSource.ts
··· 1 1 import dayjs from "dayjs"; 2 - import { combinePartsToString, mergeArr } from "../utils"; 3 - import AbstractSource from "./AbstractSource"; 2 + import { combinePartsToString, mergeArr } from "../utils.js"; 3 + import AbstractSource from "./AbstractSource.js"; 4 4 import formidable from 'formidable'; 5 5 import concatStream from 'concat-stream'; 6 - import { PlexSourceConfig } from "../common/infrastructure/config/source/plex"; 7 - import { FormatPlayObjectOptions, InternalConfig, SourceType } from "../common/infrastructure/Atomic"; 6 + import { PlexSourceConfig } from "../common/infrastructure/config/source/plex.js"; 7 + import { FormatPlayObjectOptions, InternalConfig, SourceType } from "../common/infrastructure/Atomic.js"; 8 8 import EventEmitter from "events"; 9 9 import winston from '@foxxmd/winston'; 10 - import { PlayObject } from "../../core/Atomic"; 11 - import { truncateStringToLength } from "../../core/StringUtils"; 10 + import { PlayObject } from "../../core/Atomic.js"; 11 + import { truncateStringToLength } from "../../core/StringUtils.js"; 12 12 13 13 const shortDeviceId = truncateStringToLength(10, ''); 14 14
+38 -38
src/backend/sources/ScrobbleSources.ts
··· 1 - import { mergeArr, parseBool, readJson, validateJson } from "../utils"; 2 - import SpotifySource from "./SpotifySource"; 3 - import PlexSource from "./PlexSource"; 4 - import TautulliSource from "./TautulliSource"; 5 - import { SubsonicSource } from "./SubsonicSource"; 6 - import JellyfinSource from "./JellyfinSource"; 7 - import LastfmSource from "./LastfmSource"; 8 - import DeezerSource from "./DeezerSource"; 9 - import { ConfigMeta, InternalConfig, SourceType, sourceTypes } from "../common/infrastructure/Atomic"; 10 - import { configDir as defaultConfigDir } from "../common/index"; 1 + import { mergeArr, parseBool, readJson, validateJson } from "../utils.js"; 2 + import SpotifySource from "./SpotifySource.js"; 3 + import PlexSource from "./PlexSource.js"; 4 + import TautulliSource from "./TautulliSource.js"; 5 + import { SubsonicSource } from "./SubsonicSource.js"; 6 + import JellyfinSource from "./JellyfinSource.js"; 7 + import LastfmSource from "./LastfmSource.js"; 8 + import DeezerSource from "./DeezerSource.js"; 9 + import { ConfigMeta, InternalConfig, SourceType, sourceTypes } from "../common/infrastructure/Atomic.js"; 10 + import { configDir as defaultConfigDir } from "../common/index.js"; 11 11 import winston, {Logger} from '@foxxmd/winston'; 12 - import { SourceAIOConfig, SourceConfig } from "../common/infrastructure/config/source/sources"; 13 - import { DeezerData, DeezerSourceConfig } from "../common/infrastructure/config/source/deezer"; 14 - import { LastfmClientConfig } from "../common/infrastructure/config/client/lastfm"; 15 - import { JellyData, JellySourceConfig } from "../common/infrastructure/config/source/jellyfin"; 16 - import { SubsonicData, SubSonicSourceConfig } from "../common/infrastructure/config/source/subsonic"; 17 - import { TautulliSourceConfig } from "../common/infrastructure/config/source/tautulli"; 18 - import { PlexSourceConfig } from "../common/infrastructure/config/source/plex"; 19 - import { SpotifySourceConfig, SpotifySourceData } from "../common/infrastructure/config/source/spotify"; 20 - import AbstractSource from "./AbstractSource"; 21 - import { AIOConfig, SourceDefaults } from "../common/infrastructure/config/aioConfig"; 12 + import { SourceAIOConfig, SourceConfig } from "../common/infrastructure/config/source/sources.js"; 13 + import { DeezerData, DeezerSourceConfig } from "../common/infrastructure/config/source/deezer.js"; 14 + import { LastfmClientConfig } from "../common/infrastructure/config/client/lastfm.js"; 15 + import { JellyData, JellySourceConfig } from "../common/infrastructure/config/source/jellyfin.js"; 16 + import { SubsonicData, SubSonicSourceConfig } from "../common/infrastructure/config/source/subsonic.js"; 17 + import { TautulliSourceConfig } from "../common/infrastructure/config/source/tautulli.js"; 18 + import { PlexSourceConfig } from "../common/infrastructure/config/source/plex.js"; 19 + import { SpotifySourceConfig, SpotifySourceData } from "../common/infrastructure/config/source/spotify.js"; 20 + import AbstractSource from "./AbstractSource.js"; 21 + import { AIOConfig, SourceDefaults } from "../common/infrastructure/config/aioConfig.js"; 22 22 import * as aioSchema from "../common/schema/aio-source.json"; 23 23 import * as sourceSchema from "../common/schema/source.json"; 24 - import { LastfmSourceConfig } from "../common/infrastructure/config/source/lastfm"; 25 - import YTMusicSource from "./YTMusicSource"; 26 - import { YTMusicSourceConfig } from "../common/infrastructure/config/source/ytmusic"; 27 - import { MPRISData, MPRISSourceConfig } from "../common/infrastructure/config/source/mpris"; 28 - import { MPRISSource } from "./MPRISSource"; 24 + import { LastfmSourceConfig } from "../common/infrastructure/config/source/lastfm.js"; 25 + import YTMusicSource from "./YTMusicSource.js"; 26 + import { YTMusicSourceConfig } from "../common/infrastructure/config/source/ytmusic.js"; 27 + import { MPRISData, MPRISSourceConfig } from "../common/infrastructure/config/source/mpris.js"; 28 + import { MPRISSource } from "./MPRISSource.js"; 29 29 import EventEmitter from "events"; 30 - import { MopidySource } from "./MopidySource"; 31 - import { MopidySourceConfig } from "../common/infrastructure/config/source/mopidy"; 32 - import ListenbrainzSource from "./ListenbrainzSource"; 33 - import { ListenBrainzSourceConfig } from "../common/infrastructure/config/source/listenbrainz"; 34 - import { JRiverSource } from "./JRiverSource"; 35 - import { JRiverData, JRiverSourceConfig } from "../common/infrastructure/config/source/jriver"; 36 - import { KodiSource } from "./KodiSource"; 37 - import { KodiData, KodiSourceConfig } from "../common/infrastructure/config/source/kodi"; 38 - import { WildcardEmitter } from "../common/WildcardEmitter"; 39 - import {WebScrobblerSource} from "./WebScrobblerSource"; 40 - import {WebScrobblerSourceConfig} from "../common/infrastructure/config/source/webscrobbler"; 41 - import {ChromecastSource} from "./ChromecastSource"; 42 - import {ChromecastSourceConfig} from "../common/infrastructure/config/source/chromecast"; 30 + import { MopidySource } from "./MopidySource.js"; 31 + import { MopidySourceConfig } from "../common/infrastructure/config/source/mopidy.js"; 32 + import ListenbrainzSource from "./ListenbrainzSource.js"; 33 + import { ListenBrainzSourceConfig } from "../common/infrastructure/config/source/listenbrainz.js"; 34 + import { JRiverSource } from "./JRiverSource.js"; 35 + import { JRiverData, JRiverSourceConfig } from "../common/infrastructure/config/source/jriver.js"; 36 + import { KodiSource } from "./KodiSource.js"; 37 + import { KodiData, KodiSourceConfig } from "../common/infrastructure/config/source/kodi.js"; 38 + import { WildcardEmitter } from "../common/WildcardEmitter.js"; 39 + import { WebScrobblerSource } from "./WebScrobblerSource.js"; 40 + import { WebScrobblerSourceConfig } from "../common/infrastructure/config/source/webscrobbler.js"; 41 + import { ChromecastSource } from "./ChromecastSource.js"; 42 + import { ChromecastSourceConfig } from "../common/infrastructure/config/source/chromecast.js"; 43 43 44 44 type groupedNamedConfigs = {[key: string]: ParsedConfig[]}; 45 45
+13 -11
src/backend/sources/SpotifySource.ts
··· 5 5 sortByOldestPlayDate, 6 6 sleep, 7 7 parseRetryAfterSecsFromObj, 8 - combinePartsToString, findCauseByFunc, 9 - } from "../utils"; 8 + combinePartsToString, 9 + findCauseByFunc, 10 + } from "../utils.js"; 10 11 import SpotifyWebApi from "spotify-web-api-node"; 11 - import AbstractSource, { RecentlyPlayedOptions } from "./AbstractSource"; 12 - import { SpotifySourceConfig } from "../common/infrastructure/config/source/spotify"; 12 + import AbstractSource, { RecentlyPlayedOptions } from "./AbstractSource.js"; 13 + import { SpotifySourceConfig } from "../common/infrastructure/config/source/spotify.js"; 13 14 import { 14 15 DEFAULT_POLLING_INTERVAL, 15 16 FormatPlayObjectOptions, 16 - InternalConfig, NO_DEVICE, 17 + InternalConfig, 18 + NO_DEVICE, 17 19 NO_USER, 18 20 PlayerStateData, 19 21 ReportedPlayerStatus, 20 22 SourceData, 21 - } from "../common/infrastructure/Atomic"; 23 + } from "../common/infrastructure/Atomic.js"; 22 24 import PlayHistoryObject = SpotifyApi.PlayHistoryObject; 23 25 import EventEmitter from "events"; 24 26 import CurrentlyPlayingObject = SpotifyApi.CurrentlyPlayingObject; ··· 26 28 import ArtistObjectSimplified = SpotifyApi.ArtistObjectSimplified; 27 29 import AlbumObjectSimplified = SpotifyApi.AlbumObjectSimplified; 28 30 import UserDevice = SpotifyApi.UserDevice; 29 - import MemorySource from "./MemorySource"; 31 + import MemorySource from "./MemorySource.js"; 30 32 import {ErrorWithCause} from "pony-cause"; 31 - import {PlayObject, SCROBBLE_TS_SOC_END, SCROBBLE_TS_SOC_START, ScrobbleTsSOC} from "../../core/Atomic"; 32 - import { buildTrackString, truncateStringToLength } from "../../core/StringUtils"; 33 - import {isNodeNetworkException} from "../common/errors/NodeErrors"; 34 - import {hasUpstreamError, UpstreamError} from "../common/errors/UpstreamError"; 33 + import { PlayObject, SCROBBLE_TS_SOC_END, SCROBBLE_TS_SOC_START, ScrobbleTsSOC } from "../../core/Atomic.js"; 34 + import { buildTrackString, truncateStringToLength } from "../../core/StringUtils.js"; 35 + import { isNodeNetworkException } from "../common/errors/NodeErrors.js"; 36 + import { hasUpstreamError, UpstreamError } from "../common/errors/UpstreamError.js"; 35 37 36 38 const scopes = ['user-read-recently-played', 'user-read-currently-playing', 'user-read-playback-state', 'user-read-playback-position']; 37 39 const state = 'random';
+6 -6
src/backend/sources/SubsonicSource.ts
··· 2 2 import * as crypto from 'crypto'; 3 3 import dayjs from "dayjs"; 4 4 import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js"; 5 - import { parseRetryAfterSecsFromObj, removeDuplicates, sleep } from "../utils"; 6 - import MemorySource from "./MemorySource"; 7 - import { SubSonicSourceConfig } from "../common/infrastructure/config/source/subsonic"; 8 - import {DEFAULT_RETRY_MULTIPLIER, FormatPlayObjectOptions, InternalConfig} from "../common/infrastructure/Atomic"; 9 - import { RecentlyPlayedOptions } from "./AbstractSource"; 5 + import { parseRetryAfterSecsFromObj, removeDuplicates, sleep } from "../utils.js"; 6 + import MemorySource from "./MemorySource.js"; 7 + import { SubSonicSourceConfig } from "../common/infrastructure/config/source/subsonic.js"; 8 + import { DEFAULT_RETRY_MULTIPLIER, FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic.js"; 9 + import { RecentlyPlayedOptions } from "./AbstractSource.js"; 10 10 import EventEmitter from "events"; 11 - import { PlayObject } from "../../core/Atomic"; 11 + import { PlayObject } from "../../core/Atomic.js"; 12 12 13 13 dayjs.extend(isSameOrAfter); 14 14
+6 -6
src/backend/sources/TautulliSource.ts
··· 1 1 import dayjs from "dayjs"; 2 - import PlexSource from "./PlexSource"; 3 - import { TautulliSourceConfig } from "../common/infrastructure/config/source/tautulli"; 4 - import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic"; 5 - import { combinePartsToString } from "../utils"; 2 + import PlexSource from "./PlexSource.js"; 3 + import { TautulliSourceConfig } from "../common/infrastructure/config/source/tautulli.js"; 4 + import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic.js"; 5 + import { combinePartsToString } from "../utils.js"; 6 6 import EventEmitter from "events"; 7 7 import {Request} from "express"; 8 - import { PlayObject } from "../../core/Atomic"; 9 - import { truncateStringToLength } from "../../core/StringUtils"; 8 + import { PlayObject } from "../../core/Atomic.js"; 9 + import { truncateStringToLength } from "../../core/StringUtils.js"; 10 10 11 11 const shortDeviceId = truncateStringToLength(10, ''); 12 12
+8 -7
src/backend/sources/WebScrobblerSource.ts
··· 1 - import MemorySource from "./MemorySource"; 1 + import MemorySource from "./MemorySource.js"; 2 2 import { 3 3 FormatPlayObjectOptions, 4 4 InternalConfig, 5 5 NO_USER, 6 - PlayerStateData, REPORTED_PLAYER_STATUSES, 7 - ReportedPlayerStatus 8 - } from "../common/infrastructure/Atomic"; 6 + PlayerStateData, 7 + REPORTED_PLAYER_STATUSES, 8 + ReportedPlayerStatus, 9 + } from "../common/infrastructure/Atomic.js"; 9 10 import EventEmitter from "events"; 10 - import {PlayObject} from "../../core/Atomic"; 11 - import {WebScrobblerHookEvent, WebScrobblerPayload, WebScrobblerSong} from "../common/vendor/webscrobbler/interfaces"; 11 + import { PlayObject } from "../../core/Atomic.js"; 12 + import { WebScrobblerHookEvent, WebScrobblerPayload, WebScrobblerSong } from "../common/vendor/webscrobbler/interfaces.js"; 12 13 import dayjs from "dayjs"; 13 - import {WebScrobblerSourceConfig} from "../common/infrastructure/config/source/webscrobbler"; 14 + import { WebScrobblerSourceConfig } from "../common/infrastructure/config/source/webscrobbler.js"; 14 15 15 16 export class WebScrobblerSource extends MemorySource { 16 17
+5 -5
src/backend/sources/YTMusicSource.ts
··· 1 1 import YouTubeMusic from "youtube-music-ts-api"; 2 2 3 - import AbstractSource, { RecentlyPlayedOptions } from "./AbstractSource"; 4 - import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic"; 3 + import AbstractSource, { RecentlyPlayedOptions } from "./AbstractSource.js"; 4 + import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructure/Atomic.js"; 5 5 // @ts-ignore 6 6 import {IYouTubeMusicAuthenticated} from "youtube-music-ts-api/interfaces-primary"; 7 7 import dayjs from "dayjs"; 8 - import { parseDurationFromTimestamp, playObjDataMatch } from "../utils"; 8 + import { parseDurationFromTimestamp, playObjDataMatch } from "../utils.js"; 9 9 // @ts-ignore 10 10 import {IPlaylistDetail, ITrackDetail} from "youtube-music-ts-api/interfaces-supplementary"; 11 - import { YTMusicSourceConfig } from "../common/infrastructure/config/source/ytmusic"; 11 + import { YTMusicSourceConfig } from "../common/infrastructure/config/source/ytmusic.js"; 12 12 import EventEmitter from "events"; 13 - import { PlayObject } from "../../core/Atomic"; 13 + import { PlayObject } from "../../core/Atomic.js"; 14 14 15 15 export default class YTMusicSource extends AbstractSource { 16 16 apiInstance?: IYouTubeMusicAuthenticated
+2 -2
src/backend/sources/ingressNotifiers/IngressNotifier.ts
··· 1 1 import winston, {Logger} from '@foxxmd/winston'; 2 - import { mergeArr, remoteHostIdentifiers, remoteHostStr } from "../../utils"; 2 + import { mergeArr, remoteHostIdentifiers, remoteHostStr } from "../../utils.js"; 3 3 import {Request} from "express"; 4 - import { RemoteIdentityParts } from "../../common/infrastructure/Atomic"; 4 + import { RemoteIdentityParts } from "../../common/infrastructure/Atomic.js"; 5 5 6 6 7 7 export abstract class IngressNotifier {
+3 -3
src/backend/sources/ingressNotifiers/JellyfinNotifier.ts
··· 1 - import { IngressNotifier } from "./IngressNotifier"; 1 + import { IngressNotifier } from "./IngressNotifier.js"; 2 2 import {Request} from "express"; 3 - import JellyfinSource from "../JellyfinSource"; 4 - import { remoteHostIdentifiers, remoteHostStr } from "../../utils"; 3 + import JellyfinSource from "../JellyfinSource.js"; 4 + import { remoteHostIdentifiers, remoteHostStr } from "../../utils.js"; 5 5 6 6 export class JellyfinNotifier extends IngressNotifier { 7 7
+2 -2
src/backend/sources/ingressNotifiers/PlexNotifier.ts
··· 1 - import { IngressNotifier } from "./IngressNotifier"; 1 + import { IngressNotifier } from "./IngressNotifier.js"; 2 2 import {Request} from "express"; 3 - import PlexSource from "../PlexSource"; 3 + import PlexSource from "../PlexSource.js"; 4 4 5 5 export class PlexNotifier extends IngressNotifier { 6 6
+3 -3
src/backend/sources/ingressNotifiers/TautulliNotifier.ts
··· 1 - import { IngressNotifier } from "./IngressNotifier"; 1 + import { IngressNotifier } from "./IngressNotifier.js"; 2 2 import {Request} from "express"; 3 - import PlexSource from "../PlexSource"; 4 - import TautulliSource from "../TautulliSource"; 3 + import PlexSource from "../PlexSource.js"; 4 + import TautulliSource from "../TautulliSource.js"; 5 5 6 6 export class TautulliNotifier extends IngressNotifier { 7 7
+1 -1
src/backend/sources/ingressNotifiers/WebhookNotifier.ts
··· 1 - import {IngressNotifier} from "./IngressNotifier"; 1 + import { IngressNotifier } from "./IngressNotifier.js"; 2 2 import {Request} from "express"; 3 3 import path from "path"; 4 4
+2 -2
src/backend/tasks/heartbeatClients.ts
··· 1 1 import {config, Logger} from "@foxxmd/winston"; 2 - import {mergeArr} from "../utils"; 2 + import { mergeArr } from "../utils.js"; 3 3 import {AsyncTask} from "toad-scheduler"; 4 4 import {PromisePool} from "@supercharge/promise-pool"; 5 - import ScrobbleClients from "../scrobblers/ScrobbleClients"; 5 + import ScrobbleClients from "../scrobblers/ScrobbleClients.js"; 6 6 7 7 export const createHeartbeatClientsTask = (clients: ScrobbleClients, parentLogger: Logger) => { 8 8 const logger = parentLogger.child({labels: ['Heartbeat', 'Clients']}, mergeArr);
+3 -3
src/backend/tasks/heartbeatSources.ts
··· 1 1 import {config, Logger} from "@foxxmd/winston"; 2 - import {mergeArr} from "../utils"; 2 + import { mergeArr } from "../utils.js"; 3 3 import {AsyncTask} from "toad-scheduler"; 4 4 import {PromisePool} from "@supercharge/promise-pool"; 5 - import ScrobbleSources from "../sources/ScrobbleSources"; 6 - import {ChromecastSource} from "../sources/ChromecastSource"; 5 + import ScrobbleSources from "../sources/ScrobbleSources.js"; 6 + import { ChromecastSource } from "../sources/ChromecastSource.js"; 7 7 8 8 export const createHeartbeatSourcesTask = (sources: ScrobbleSources, parentLogger: Logger) => { 9 9 const logger = parentLogger.child({labels: ['Heartbeat', 'Sources']}, mergeArr);
+3 -3
src/backend/tests/jellyfin/jellyfin.test.ts
··· 2 2 import {assert} from 'chai'; 3 3 import samplePayload from './playbackProgressSample.json'; 4 4 5 - import JellyfinSource from "../../sources/JellyfinSource"; 5 + import JellyfinSource from "../../sources/JellyfinSource.js"; 6 6 import EventEmitter from "events"; 7 - import {getLogger} from "../../common/logging"; 8 - import {JsonPlayObject, PlayObject} from "../../../core/Atomic"; 7 + import { getLogger } from "../../common/logging.js"; 8 + import { JsonPlayObject, PlayObject } from "../../../core/Atomic.js"; 9 9 10 10 const dataAsFixture = (data: any): TestFixture => { 11 11 return data as TestFixture;
+5 -5
src/backend/tests/listenbrainz/listenbrainz.test.ts
··· 13 13 import incorrectMultiArtistsTrackName from './incorrectlyMapped/multiArtistsInTrackName.json'; 14 14 import veryWrong from './incorrectlyMapped/veryWrong.json'; 15 15 16 - import {ListenbrainzApiClient, ListenResponse} from "../../common/vendor/ListenbrainzApiClient"; 17 - import {PlayObject} from "../../../core/Atomic"; 16 + import { ListenbrainzApiClient, ListenResponse } from "../../common/vendor/ListenbrainzApiClient.js"; 17 + import { PlayObject } from "../../../core/Atomic.js"; 18 18 import dayjs from "dayjs"; 19 - import {withRequestInterception} from "../utils/networking"; 19 + import { withRequestInterception } from "../utils/networking.js"; 20 20 import {http, HttpResponse} from "msw"; 21 - import {UpstreamError} from "../../common/errors/UpstreamError"; 22 - import {ExpectedResults} from "../utils/interfaces"; 21 + import { UpstreamError } from "../../common/errors/UpstreamError.js"; 22 + import { ExpectedResults } from "../utils/interfaces.js"; 23 23 24 24 interface LZTestFixture { 25 25 data: ListenResponse
+5 -10
src/backend/tests/player/player.test.ts
··· 1 1 import {describe, it} from 'mocha'; 2 2 import {assert} from 'chai'; 3 - import {generatePlay} from "../utils/PlayTestUtils"; 4 - import {GenericPlayerState} from "../../sources/PlayerState/GenericPlayerState"; 5 - import {getLogger} from "../../common/logging"; 6 - import { 7 - CALCULATED_PLAYER_STATUSES, 8 - NO_DEVICE, 9 - NO_USER, 10 - REPORTED_PLAYER_STATUSES 11 - } from "../../common/infrastructure/Atomic"; 12 - import {playObjDataMatch} from "../../utils"; 3 + import { generatePlay } from "../utils/PlayTestUtils.js"; 4 + import { GenericPlayerState } from "../../sources/PlayerState/GenericPlayerState.js"; 5 + import { getLogger } from "../../common/logging.js"; 6 + import { CALCULATED_PLAYER_STATUSES, NO_DEVICE, NO_USER, REPORTED_PLAYER_STATUSES } from "../../common/infrastructure/Atomic.js"; 7 + import { playObjDataMatch } from "../../utils.js"; 13 8 import dayjs from "dayjs"; 14 9 import clone from "clone"; 15 10
+4 -4
src/backend/tests/scrobbler/TestScrobbler.ts
··· 1 - import AbstractScrobbleClient from "../../scrobblers/AbstractScrobbleClient"; 2 - import {PlayObject} from "../../../core/Atomic"; 3 - import {getLogger} from "../../common/logging"; 4 - import {Notifiers} from "../../notifier/Notifiers"; 1 + import AbstractScrobbleClient from "../../scrobblers/AbstractScrobbleClient.js"; 2 + import { PlayObject } from "../../../core/Atomic.js"; 3 + import { getLogger } from "../../common/logging.js"; 4 + import { Notifiers } from "../../notifier/Notifiers.js"; 5 5 import EventEmitter from "events"; 6 6 import request from "superagent"; 7 7
+5 -5
src/backend/tests/scrobbler/scrobblers.test.ts
··· 7 7 import withDuration from '../plays/withDuration.json'; 8 8 import mixedDuration from '../plays/mixedDuration.json'; 9 9 10 - import {TestScrobbler} from "./TestScrobbler"; 11 - import {asPlays, generatePlay, normalizePlays} from "../utils/PlayTestUtils"; 10 + import { TestScrobbler } from "./TestScrobbler.js"; 11 + import { asPlays, generatePlay, normalizePlays } from "../utils/PlayTestUtils.js"; 12 12 import dayjs from "dayjs"; 13 - import {sleep} from "../../utils"; 14 - import {MockNetworkError, withRequestInterception} from "../utils/networking"; 15 - import {PlayObject} from "../../../core/Atomic"; 13 + import { sleep } from "../../utils.js"; 14 + import { MockNetworkError, withRequestInterception } from "../utils/networking.js"; 15 + import { PlayObject } from "../../../core/Atomic.js"; 16 16 17 17 const firstPlayDate = dayjs().subtract(1, 'hour'); 18 18 const olderFirstPlayDate = dayjs().subtract(4, 'hour');
+1 -1
src/backend/tests/utils/PlayTestUtils.ts
··· 1 - import {JsonPlayObject, ObjectPlayData, PlayData, PlayMeta, PlayObject} from "../../../core/Atomic"; 1 + import { JsonPlayObject, ObjectPlayData, PlayData, PlayMeta, PlayObject } from "../../../core/Atomic.js"; 2 2 import dayjs, {Dayjs} from "dayjs"; 3 3 import utc from "dayjs/plugin/utc.js"; 4 4 import isBetween from "dayjs/plugin/isBetween.js";
+1 -1
src/backend/tests/utils/networking.ts
··· 1 - import {NodeNetworkErrorCode, NodeNetworkException} from "../../common/errors/NodeErrors"; 1 + import { NodeNetworkErrorCode, NodeNetworkException } from "../../common/errors/NodeErrors.js"; 2 2 import { setupServer, SetupServer } from 'msw/node'; 3 3 4 4 export class MockNetworkError extends Error implements NodeNetworkException {
+3 -3
src/backend/tests/utils/strings.test.ts
··· 1 1 import {describe, it} from 'mocha'; 2 2 import {assert} from 'chai'; 3 - import {compareNormalizedStrings, parseTrackCredits, uniqueNormalizedStrArr} from "../../utils/StringUtils"; 3 + import { compareNormalizedStrings, parseTrackCredits, uniqueNormalizedStrArr } from "../../utils/StringUtils.js"; 4 4 import testData from './playTestData.json'; 5 - import {ExpectedResults} from "./interfaces"; 6 - import {intersect} from "../../utils"; 5 + import { ExpectedResults } from "./interfaces.js"; 6 + import { intersect } from "../../utils.js"; 7 7 8 8 interface PlayTestFixture { 9 9 caseHints: string[]
+4 -4
src/backend/utils.ts
··· 18 18 RegExResult, 19 19 RemoteIdentityParts, 20 20 ScrobbleThresholdResult, 21 - } from "./common/infrastructure/Atomic"; 21 + } from "./common/infrastructure/Atomic.js"; 22 22 import {Request} from "express"; 23 23 import pathUtil from "path"; 24 24 import {ErrorWithCause, getErrorCause} from "pony-cause"; 25 25 import backoffStrategies from '@kenyip/backoff-strategies'; 26 26 import {replaceResultTransformer, stripIndentTransformer, TemplateTag, trimResultTransformer} from 'common-tags'; 27 27 import {Duration} from "dayjs/plugin/duration.js"; 28 - import {PlayObject} from "../core/Atomic"; 28 + import { PlayObject } from "../core/Atomic.js"; 29 29 import address from "address"; 30 30 31 31 //const { default: Ajv } = AjvNS; ··· 350 350 }); 351 351 } 352 352 353 - export const createAjvFactory = (logger: Logger): Ajv => { 354 - const validator = new AjvNS.default({logger: logger, verbose: true, strict: "log", allowUnionTypes: true}); 353 + export const createAjvFactory = (logger: Logger): AjvNS.default => { 354 + const validator = new Ajv.default({logger: logger, verbose: true, strict: "log", allowUnionTypes: true}); 355 355 // https://ajv.js.org/strict-mode.html#unknown-keywords 356 356 validator.addKeyword('deprecationMessage'); 357 357 return validator;
+3 -3
src/backend/utils/MDNSUtils.ts
··· 1 1 import {Logger} from "@foxxmd/winston"; 2 2 import AvahiBrowser from 'avahi-browse'; 3 - import {MaybeLogger} from "../common/logging"; 4 - import {sleep} from "../utils"; 3 + import { MaybeLogger } from "../common/logging.js"; 4 + import { sleep } from "../utils.js"; 5 5 import {ErrorWithCause} from "pony-cause"; 6 - import {MdnsDeviceInfo} from "../common/infrastructure/Atomic"; 6 + import { MdnsDeviceInfo } from "../common/infrastructure/Atomic.js"; 7 7 import {Browser, Service, ServiceType} from "@astronautlabs/mdns"; 8 8 9 9 export interface AvahiService {
+3 -3
src/backend/utils/StringUtils.ts
··· 1 - import {DELIMITERS} from "../common/infrastructure/Atomic"; 2 - import {parseRegexSingleOrFail} from "../utils"; 3 - import {PlayObject} from "../../core/Atomic"; 1 + import { DELIMITERS } from "../common/infrastructure/Atomic.js"; 2 + import { parseRegexSingleOrFail } from "../utils.js"; 3 + import { PlayObject } from "../../core/Atomic.js"; 4 4 import {stringSameness, StringSamenessResult} from "@foxxmd/string-sameness"; 5 5 import {strategies} from '@foxxmd/string-sameness'; 6 6
+11 -8
src/backend/utils/TimeUtils.ts
··· 1 1 import { 2 - PlayObject, SCROBBLE_TS_SOC_END, SCROBBLE_TS_SOC_START, ScrobbleTsSOC, 2 + PlayObject, 3 + SCROBBLE_TS_SOC_END, 4 + SCROBBLE_TS_SOC_START, 5 + ScrobbleTsSOC, 3 6 TA_CLOSE, 4 7 TA_EXACT, 5 8 TA_FUZZY, 6 9 TA_NONE, 7 10 TemporalAccuracy, 8 - TemporalPlayComparison 9 - } from "../../core/Atomic"; 11 + TemporalPlayComparison, 12 + } from "../../core/Atomic.js"; 10 13 import { 11 14 DEFAULT_SCROBBLE_DURATION_THRESHOLD, 12 15 DEFAULT_SCROBBLE_PERCENT_THRESHOLD, 13 16 lowGranularitySources, 14 - ScrobbleThresholdResult 15 - } from "../common/infrastructure/Atomic"; 16 - import {formatNumber} from "../utils"; 17 - import {ScrobbleThresholds} from "../common/infrastructure/config/source"; 18 - import {capitalize} from "../../core/StringUtils"; 17 + ScrobbleThresholdResult, 18 + } from "../common/infrastructure/Atomic.js"; 19 + import { formatNumber } from "../utils.js"; 20 + import { ScrobbleThresholds } from "../common/infrastructure/config/source/index.js"; 21 + import { capitalize } from "../../core/StringUtils.js"; 19 22 import dayjs, {Dayjs} from "dayjs"; 20 23 21 24 export const temporalPlayComparisonSummary = (data: TemporalPlayComparison, existingPlay?: PlayObject, candidatePlay?: PlayObject) => {
+1 -1
src/core/Atomic.ts
··· 1 1 import {Dayjs} from "dayjs"; 2 2 import {MESSAGE} from "triple-beam"; 3 - import {ListenProgress} from "../backend/sources/PlayerState/ListenProgress"; 3 + import {ListenProgress} from "../backend/sources/PlayerState/ListenProgress.js"; 4 4 5 5 export interface SourceStatusData { 6 6 status: string;
+1 -1
src/core/StringUtils.ts
··· 4 4 import relativeTime from "dayjs/plugin/relativeTime.js"; 5 5 import duration from "dayjs/plugin/duration.js"; 6 6 import timezone from "dayjs/plugin/timezone.js"; 7 - import {AmbPlayObject, SCROBBLE_TS_SOC_END, SCROBBLE_TS_SOC_START, ScrobbleTsSOC, TrackStringOptions} from "./Atomic"; 7 + import {AmbPlayObject, SCROBBLE_TS_SOC_END, SCROBBLE_TS_SOC_START, ScrobbleTsSOC, TrackStringOptions} from "./Atomic.js"; 8 8 9 9 dayjs.extend(utc) 10 10 dayjs.extend(isBetween);