diff --git a/README.md b/README.md index f8d5607..bcf958a 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ You can provide additional parameters to constructor: - `userAgent` - by default `icecast-parser`. - `keepListen` - by default `false`. If you set to `true`, then response from radio station will not be destroyed and you can pipe it to another streams. E.g. piping it to the `speaker` module. - `autoUpdate` - by default `true`. If you set to `false`, then parser will not be listening for recent updates and immediately close the stream. So that, you will get a metadata only once. -- `notifyOnChangeOnly` - by default `false`. If you set both `autoUpdate` and `notifyOnChangeOnly` to `true`, it will keep listening the stream and notifying you about metadata, but it will not notify if metadata did not change from the previous time. +- `notifyOnChangeOnly` - by default `[]`. If you set both `autoUpdate` to `true` and `notifyOnChangeOnly` to include the a list of metadata keys to listen for (`['StreamTitle', 'StreamUrl']`), it will keep listening the stream and notifying you about metadata, but it will not notify if the selected metadata did not change from the previous time. - `errorInterval` - by default 10 minutes. If an error occurred when requesting, the next try will be executed after this interval. Works only if `autoUpdate` is enabled. - `emptyInterval` - by default 5 minutes. If the request was fullfiled but the metadata field was empty, the next try will be executed after this interval. Works only if `autoUpdate` is enabled. - `metadataInterval` - by default 5 seconds. If the request was fullfiled and the metadata was present, the next update will be scheduled after this interval. Works only if `autoUpdate` is enabled. @@ -61,7 +61,7 @@ const radioStation = new Parser({ errorInterval: 10 * 60, keepListen: false, metadataInterval: 5, - notifyOnChangeOnly: false, + notifyOnChangeOnly: [], url: 'https://live.hunter.fm/80s_high', userAgent: 'Custom User Agent', }); diff --git a/package.json b/package.json index 0d159c1..371bd47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "icecast-parser", - "version": "4.0.2", + "version": "4.0.3", "description": "Node.js module for getting and parsing metadata from SHOUTcast/Icecast radio streams", "main": "dist/Parser.js", "license": "MIT", diff --git a/src/Parser.ts b/src/Parser.ts index b7433a0..cbb6c40 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -9,7 +9,7 @@ export interface ParserOptions { errorInterval: number keepListen: boolean metadataInterval: number - notifyOnChangeOnly: boolean + notifyOnChangeOnly: string[] url: string userAgent: string } @@ -35,7 +35,7 @@ export class Parser extends EventEmitter { errorInterval: 10 * 60, keepListen: false, metadataInterval: 5, - notifyOnChangeOnly: false, + notifyOnChangeOnly: [], url: '', userAgent: 'icecast-parser', }; @@ -115,12 +115,22 @@ export class Parser extends EventEmitter { } protected isMetadataChanged (metadata: Map): boolean { - for (const [key, value] of metadata.entries()) { - if (this.previousMetadata.get(key) !== value) { - return true; + if (this.options.notifyOnChangeOnly.length > 0) { + for (const key of this.options.notifyOnChangeOnly) { + const data = metadata.get(key) + if (data) { + if (this.previousMetadata.get(key) !== data) { + return true; + } + } } + } else { + for (const [key, value] of metadata.entries()) { + if (this.previousMetadata.get(key) !== value) { + return true; + } + } } - return false; } } diff --git a/test/Parser.spec.ts b/test/Parser.spec.ts index edd6ff1..fc3112e 100644 --- a/test/Parser.spec.ts +++ b/test/Parser.spec.ts @@ -57,11 +57,40 @@ describe('parser', () => { it('should properly emit metadata event when metadata has been updated', async () => await new Promise((resolve) => { expect.hasAssertions(); - const radio = new Parser({ autoUpdate: false, notifyOnChangeOnly: true, url: 'https://live.hunter.fm/80s_high' }); + const radio = new Parser({ autoUpdate: false, notifyOnChangeOnly: [], url: 'https://live.hunter.fm/80s_high' }); radio.on('metadata', (metadata) => { // @ts-expect-error I want to check that metadata was stored in the private property to later comparsion expect(radio.previousMetadata).toStrictEqual(metadata); resolve(); }); })); + + it('should properly emit metadata event when notifyOnChangeOnly is used and when metadata has been updated', async () => await new Promise((resolve) => { + expect.hasAssertions() + + const radio = new Parser({ autoUpdate: false, notifyOnChangeOnly: ['StreamTitle'], url: 'https://live.hunter.fm/80s_high' }); + radio.on('metadata', (metadata) => { + // @ts-expect-error I want to check that metadata was stored in the private property to later comparsion + expect(radio.previousMetadata).toStrictEqual(metadata); + resolve(); + }); + })) + + it('should not emmit metadata event if notifyOnChangeOnly is incorrect', async () => await new Promise(async (resolve) => { + let triggered = false + const delay = (ms: number) => new Promise(res => setTimeout(res, ms)); + + const radio = new Parser({ autoUpdate: false, notifyOnChangeOnly: ['a'], url: 'https://live.hunter.fm/80s_high' }); + radio.on('metadata', () => { + triggered = true + }); + + await delay(1000) + + if(!triggered) { + resolve() + } else { + throw new Error('metadata event was triggered - Check that the notifyOnChangeOnly data does not exist in the metadata') + } + })) });