···11-import { type Logger } from '@foxxmd/logging';
22-import { Dayjs, type ManipulateType } from "dayjs";
11+import type { Logger } from '@foxxmd/logging';
22+import type { Dayjs, ManipulateType } from "dayjs";
33import { type Request, type Response } from "express";
44-import { type NextFunction, type ParamsDictionary, type Query } from "express-serve-static-core";
44+import type { NextFunction, ParamsDictionary, Query } from "express-serve-static-core";
55import { FixedSizeList } from 'fixed-size-list';
66import { type ErrorLike, isPlayObject, type PlayMeta, type PlayObject, type PlayObjectMinimal, type UnixTimestamp } from "../../../core/Atomic.js";
77import TupleMap from "../TupleMap.js";
88import { MusicBrainzApi } from 'musicbrainz-api';
99-import { type SourceType } from './config/source/sources.js';
99+import type { SourceType } from './config/source/sources.js';
1010import { type ClientType, clientTypes } from './config/client/clients.js';
1111-import assert, { AssertionError } from 'assert';
1111+import assert from 'assert';
12121313export const lowGranularitySources: SourceType[] = ['subsonic', 'ytmusic'];
1414
+19-19
src/backend/sources/SpotifySource.ts
···3131import { findCauseByFunc } from "../utils/ErrorUtils.js";
3232import { joinedUrl } from "../utils/NetworkUtils.js";
3333import { type RecentlyPlayedOptions } from "./AbstractSource.js";
3434-import AlbumObjectSimplified = SpotifyApi.AlbumObjectSimplified;
3535-import ArtistObjectSimplified = SpotifyApi.ArtistObjectSimplified;
3636-import CurrentlyPlayingObject = SpotifyApi.CurrentlyPlayingObject;
3737-import PlayHistoryObject = SpotifyApi.PlayHistoryObject;
3838-import TrackObjectFull = SpotifyApi.TrackObjectFull;
3939-import UserDevice = SpotifyApi.UserDevice;
3434+// import SpotifyApi.AlbumObjectSimplified = SpotifyApi.SpotifyApi.AlbumObjectSimplified;
3535+// import SpotifyApi.ArtistObjectSimplified = SpotifyApi.SpotifyApi.ArtistObjectSimplified;
3636+// import SpotifyApi.CurrentlyPlayingObject = SpotifyApi.SpotifyApi.CurrentlyPlayingObject;
3737+// import SpotifyApi.PlayHistoryObject = SpotifyApi.SpotifyApi.PlayHistoryObject;
3838+// import SpotifyApi.TrackObjectFull = SpotifyApi.SpotifyApi.TrackObjectFull;
3939+// import SpotifyApi.UserDevice = SpotifyApi.SpotifyApi.UserDevice;
4040import { MemoryPositionalSource } from "./MemoryPositionalSource.js";
4141import { baseFormatPlayObj } from "../utils/PlayTransformUtils.js";
4242import { createGetScrobblesForTimeRangeFunc } from "../utils/ListenFetchUtils.js";
···8181 this.getScrobblesForTimeRange = createGetScrobblesForTimeRangeFunc(this, this.logger);
8282 }
83838484- static formatPlayObj(obj: PlayHistoryObject | CurrentlyPlayingObject, options: FormatPlayObjectOptions = {}): PlayObject {
8484+ static formatPlayObj(obj: SpotifyApi.PlayHistoryObject | SpotifyApi.CurrentlyPlayingObject, options: FormatPlayObjectOptions = {}): PlayObject {
85858686 const {
8787 newFromSource = false
8888 } = options;
89899090- let artists: ArtistObjectSimplified[];
9191- let album: AlbumObjectSimplified;
9090+ let artists: SpotifyApi.ArtistObjectSimplified[];
9191+ let album: SpotifyApi.AlbumObjectSimplified;
9292 let name: string;
9393 let duration_ms: number;
9494 let played_at: Dayjs;
···165165 isrc
166166 } = {},
167167 track_number
168168- } = item as TrackObjectFull;
168168+ } = item as SpotifyApi.TrackObjectFull;
169169170170- delete (obj.item as TrackObjectFull).available_markets;
171171- if((obj.item as TrackObjectFull).album !== undefined) {
172172- delete (obj.item as TrackObjectFull).album.available_markets;
170170+ delete (obj.item as SpotifyApi.TrackObjectFull).available_markets;
171171+ if((obj.item as SpotifyApi.TrackObjectFull).album !== undefined) {
172172+ delete (obj.item as SpotifyApi.TrackObjectFull).album.available_markets;
173173 }
174174175175 scrobbleTsSOC = SCROBBLE_TS_SOC_START;
···196196 images = []
197197 } = album || {};
198198199199- let actualAlbumArtists: ArtistObjectSimplified[] = [];
199199+ let actualAlbumArtists: SpotifyApi.ArtistObjectSimplified[] = [];
200200 if ((artists.length !== albumArtists.length) || !artists.every(artist => albumArtists.some(albumArtist => artist.id === albumArtist.id))) {
201201 // only include album artists if they are not the EXACT same as the track artists
202202 // ...if they aren't the exact same then include all artists, even if they are duplicates of track artists
···438438 const result = await this.callApi<ReturnType<typeof this.spotifyApi.getMyRecentlyPlayedTracks>>((api: SpotifyWebApi) => api.getMyRecentlyPlayedTracks(options));
439439440440 let more = true;
441441- let plays = result.body.items.map((x: PlayHistoryObject) => SpotifySource.formatPlayObj(x)).sort(sortByOldestPlayDate);
441441+ let plays = result.body.items.map((x: SpotifyApi.PlayHistoryObject) => SpotifySource.formatPlayObj(x)).sort(sortByOldestPlayDate);
442442443443 if(to !== undefined) {
444444 const toDate = dayjs.unix(to);
···455455 }
456456457457 return {
458458- data: result.body.items.map((x: PlayHistoryObject) => SpotifySource.formatPlayObj(x)).sort(sortByOldestPlayDate),
458458+ data: result.body.items.map((x: SpotifyApi.PlayHistoryObject) => SpotifySource.formatPlayObj(x)).sort(sortByOldestPlayDate),
459459 meta: {
460460 ...params,
461461 total: result.body.total,
···493493 return undefined;
494494 }
495495496496- getCurrentPlaybackState = async (logError = true): Promise<{device?: UserDevice, playerState?: PlayerStateData}> => {
496496+ getCurrentPlaybackState = async (logError = true): Promise<{device?: SpotifyApi.UserDevice, playerState?: PlayerStateData}> => {
497497 try {
498498 const funcState = (api: SpotifyWebApi) => api.getMyCurrentPlaybackState();
499499 const res = await this.callApi<ReturnType<typeof this.spotifyApi.getMyCurrentPlaybackState>>(funcState);
···634634 protected getBackloggedPlays = async (options: RecentlyPlayedOptions = {}) => await this.getPlayHistory({formatted: true, ...options})
635635}
636636637637-const asPlayHistoryObject = (obj: object): obj is PlayHistoryObject => 'played_at' in obj
637637+const asPlayHistoryObject = (obj: object): obj is SpotifyApi.PlayHistoryObject => 'played_at' in obj
638638639639-const asCurrentlyPlayingObject = (obj: object): obj is CurrentlyPlayingObject => 'is_playing' in obj
639639+const asCurrentlyPlayingObject = (obj: object): obj is SpotifyApi.CurrentlyPlayingObject => 'is_playing' in obj
640640641641const hasApiPermissionError = (e: Error): boolean => findCauseByFunc(e, (err) => err.message.includes('Permissions missing')) !== undefined
642642
+9-9
src/core/Atomic.ts
···11-import { type LogDataPretty, type LogLevel } from "@foxxmd/logging";
22-import { Dayjs } from "dayjs";
33-import { type AdditionalTrackInfoResponse } from "../backend/common/vendor/listenbrainz/interfaces.js";
44-import type { DeepOmit, Merge, RequiredKeys, StrictOmit } from "ts-essentials";
55-import { type ErrorObject } from "serialize-error";
66-import { type PlayPlatformIdStr } from "../backend/common/infrastructure/Atomic.js";
77-import { type FlowControlTerm, type TransformHook } from "../backend/common/infrastructure/Transform.js";
88-import { type Changeset } from "json-diff-ts";
99-import {type IParseBaseOptions } from 'qs';
11+import type { LogDataPretty, LogLevel } from "@foxxmd/logging";
22+import type { Dayjs } from "dayjs";
33+import type { AdditionalTrackInfoResponse } from "../backend/common/vendor/listenbrainz/interfaces.js";
44+import type { Merge, RequiredKeys, StrictOmit } from "ts-essentials";
55+import type { ErrorObject } from "serialize-error";
66+import type { PlayPlatformIdStr } from "../backend/common/infrastructure/Atomic.js";
77+import type { FlowControlTerm, TransformHook } from "../backend/common/infrastructure/Transform.js";
88+import type { Changeset } from "json-diff-ts";
99+import type { IParseBaseOptions } from 'qs';
10101111export type ComponentTypeClient = 'client';
1212export const COMPONENT_TYPE_CLIENT: ComponentTypeClient = 'client';