function requiredString(e: Element, name: string): string { return e.getAttribute(name) as string } function optionalString(e: Element, name: string): string | undefined { return e.hasAttribute(name) ? requiredString(e, name) : undefined } function requiredBoolean(e: Element, name: string): boolean { return (e.getAttribute(name) as string).toLowerCase() === 'true' } function optionalBoolean(e: Element, name: string): boolean | undefined { return e.hasAttribute(name) ? requiredBoolean(e, name) : undefined } function requiredInt(e: Element, name: string): number { return parseInt(e.getAttribute(name) as string) } function optionalInt(e: Element, name: string): number | undefined { return e.hasAttribute(name) ? requiredInt(e, name) : undefined } function requiredFloat(e: Element, name: string): number { return parseFloat(e.getAttribute(name) as string) } function optionalFloat(e: Element, name: string): number | undefined { return e.hasAttribute(name) ? requiredFloat(e, name) : undefined } function requiredDate(e: Element, name: string): Date { return new Date(e.getAttribute(name) as string) } function optionalDate(e: Element, name: string): Date | undefined { return e.hasAttribute(name) ? requiredDate(e, name) : undefined } export class BaseArtistElement { id: string name: string starred?: Date constructor(e: Element) { this.id = requiredString(e, 'id') this.name = requiredString(e, 'name') this.starred = optionalDate(e, 'starred') } } export class ArtistID3Element extends BaseArtistElement { coverArt?: string albumCount?: number constructor(e: Element) { super(e) this.coverArt = optionalString(e, 'coverArt') this.albumCount = optionalInt(e, 'albumCount') } } export class ArtistElement extends BaseArtistElement { userRating?: number averageRating?: number constructor(e: Element) { super(e) this.userRating = optionalInt(e, 'userRating') this.averageRating = optionalFloat(e, 'averageRating') } } export class BaseArtistInfoElement { similarArtists: T[] = [] biography?: string musicBrainzId?: string lastFmUrl?: string smallImageUrl?: string mediumImageUrl?: string largeImageUrl?: string constructor(e: Element, artistType: new (e: Element) => T) { if (e.getElementsByTagName('biography').length > 0) { this.biography = e.getElementsByTagName('biography')[0].textContent as string } if (e.getElementsByTagName('musicBrainzId').length > 0) { this.musicBrainzId = e.getElementsByTagName('musicBrainzId')[0].textContent as string } if (e.getElementsByTagName('lastFmUrl').length > 0) { this.lastFmUrl = e.getElementsByTagName('lastFmUrl')[0].textContent as string } if (e.getElementsByTagName('smallImageUrl').length > 0) { this.smallImageUrl = e.getElementsByTagName('smallImageUrl')[0].textContent as string } if (e.getElementsByTagName('mediumImageUrl').length > 0) { this.mediumImageUrl = e.getElementsByTagName('mediumImageUrl')[0].textContent as string } if (e.getElementsByTagName('largeImageUrl').length > 0) { this.largeImageUrl = e.getElementsByTagName('largeImageUrl')[0].textContent as string } const similarArtistElements = e.getElementsByTagName('similarArtist') for (let i = 0; i < similarArtistElements.length; i++) { this.similarArtists.push(new artistType(similarArtistElements[i])) } } } export class ArtistInfoElement extends BaseArtistInfoElement { constructor(e: Element) { super(e, ArtistElement) } } export class ArtistInfo2Element extends BaseArtistInfoElement { constructor(e: Element) { super(e, ArtistID3Element) } } export class DirectoryElement { id: string parent?: string name: string starred?: Date userRating?: number averageRating?: number playCount?: number constructor(e: Element) { this.id = requiredString(e, 'id') this.parent = optionalString(e, 'parent') this.name = requiredString(e, 'name') this.starred = optionalDate(e, 'starred') this.userRating = optionalInt(e, 'userRating') this.averageRating = optionalFloat(e, 'averageRating') } } export class ChildElement { id: string parent?: string isDir: boolean title: string album?: string artist?: string track?: number year?: number genre?: string coverArt?: string size?: number contentType?: string suffix?: string transcodedContentType?: string transcodedSuffix?: string duration?: number bitRate?: number path?: string isVideo?: boolean userRating?: number averageRating?: number playCount?: number discNumber?: number created?: Date starred?: Date albumId?: string artistId?: string type?: string bookmarkPosition?: number originalWidth?: number originalHeight?: number constructor(e: Element) { this.id = requiredString(e, 'id') this.parent = optionalString(e, 'parent') this.isDir = requiredBoolean(e, 'isDir') this.title = requiredString(e, 'title') this.album = optionalString(e, 'album') this.artist = optionalString(e, 'artist') this.track = optionalInt(e, 'track') this.year = optionalInt(e, 'year') this.genre = optionalString(e, 'genre') this.coverArt = optionalString(e, 'coverArt') this.size = optionalInt(e, 'size') this.contentType = optionalString(e, 'contentType') this.suffix = optionalString(e, 'suffix') this.transcodedContentType = optionalString(e, 'transcodedContentType') this.transcodedSuffix = optionalString(e, 'transcodedSuffix') this.duration = optionalInt(e, 'duration') this.bitRate = optionalInt(e, 'bitRate') this.path = optionalString(e, 'path') this.isVideo = optionalBoolean(e, 'isVideo') this.userRating = optionalInt(e, 'userRating') this.averageRating = optionalFloat(e, 'averageRating') this.playCount = optionalInt(e, 'playCount') this.discNumber = optionalInt(e, 'discNumber') this.created = optionalDate(e, 'created') this.starred = optionalDate(e, 'starred') this.albumId = optionalString(e, 'albumId') this.artistId = optionalString(e, 'artistId') this.type = optionalString(e, 'type') this.bookmarkPosition = optionalInt(e, 'bookmarkPosition') this.originalWidth = optionalInt(e, 'originalWidth') this.originalHeight = optionalInt(e, 'originalHeight') } } export class AlbumID3Element { id: string name: string artist?: string artistId?: string coverArt?: string songCount: number duration: number playCount?: number created: Date starred?: Date year?: number genre?: string constructor(e: Element) { this.id = requiredString(e, 'id') this.name = requiredString(e, 'name') this.artist = optionalString(e, 'artist') this.artistId = optionalString(e, 'artistId') this.coverArt = optionalString(e, 'coverArt') this.songCount = requiredInt(e, 'songCount') this.duration = requiredInt(e, 'duration') this.playCount = optionalInt(e, 'playCount') this.created = requiredDate(e, 'created') this.starred = optionalDate(e, 'starred') this.year = optionalInt(e, 'year') this.genre = optionalString(e, 'genre') } } export class PlaylistElement { allowedUser: string[] = [] id: string name: string comment?: string owner?: string public?: boolean songCount: number duration: number created: Date changed: Date coverArt?: string constructor(e: Element) { for (let i = 0; i < e.getElementsByTagName('allowedUser').length; i++) { this.allowedUser.push(e.getElementsByTagName('allowedUser')[i].textContent as string) } this.id = requiredString(e, 'id') this.name = requiredString(e, 'name') this.comment = optionalString(e, 'comment') this.owner = optionalString(e, 'owner') this.public = optionalBoolean(e, 'public') this.songCount = requiredInt(e, 'songCount') this.duration = requiredInt(e, 'duration') this.created = requiredDate(e, 'created') this.changed = requiredDate(e, 'changed') this.coverArt = optionalString(e, 'coverArt') } } export class PlaylistWithSongsElement extends PlaylistElement { songs: ChildElement[] = [] constructor(e: Element) { super(e) for (let i = 0; i < e.getElementsByTagName('entry').length; i++) { this.songs.push(new ChildElement(e.getElementsByTagName('entry')[i])) } } }