Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 1x 1x 5x 5x 5x 27x 27x 5x 5x 5x 5x 5x 5x 5x 5x 12x 12x 12x 12x 5x 5x 4x 4x 1x 1x 2x 2x 2x 18x 12x 6x 6x 6x 2x 18x 3x 24x 3x 1x 2x | import { M3uPlaylist, M3uMedia, M3uAttributes, M3uDirectives, M3U_COMMENT } from "./m3u-playlist"; export class M3uParser { /** * * @param attributesString tvg-id="" group-title="" * @private */ private static getAttributes(attributesString: string): M3uAttributes { const attributeValuePair = attributesString.split('" '); const attributes: M3uAttributes = new M3uAttributes(); attributeValuePair.forEach((item) => { const [key, value] = item.split('="'); attributes[key] = value.replace('"', ''); }); return attributes; } /** * * @param trackInformation -1 tvg-id="" group-title="",Tv Name * @param media * @private */ private static processMedia(trackInformation: string, media: M3uMedia): void { const lastCommaIndex = trackInformation.lastIndexOf(','); const durationAttributes = trackInformation.substring(0, lastCommaIndex); media.name = trackInformation.substring(lastCommaIndex + 1); const firstSpaceIndex = durationAttributes.indexOf(' '); media.duration = Number(durationAttributes.substring(0, firstSpaceIndex)); const attributes = durationAttributes.substring(firstSpaceIndex + 1); media.attributes = this.getAttributes(attributes); } /** * * @param item #EXTINF:-1 tvg-id="" group-title="",Tv Name * @param playlist * @param media * @private */ private static processDirective(item: string, playlist: M3uPlaylist, media: M3uMedia): void { const firstSemicolonIndex = item.indexOf(':'); const directive = item.substring(0, firstSemicolonIndex); const trackInformation = item.substring(firstSemicolonIndex + 1); switch(directive) { case M3uDirectives.EXTINF: { this.processMedia(trackInformation, media); break; } case M3uDirectives.EXTGRP: { media.group = trackInformation; break; } case M3uDirectives.PLAYLIST: { playlist.title = trackInformation; break; } } } private static getPlaylist(lines: string[]): M3uPlaylist { const playlist = new M3uPlaylist(); let media = new M3uMedia(''); lines.forEach(item => { if (this.isDirective(item)) { this.processDirective(item, playlist, media); } else { media.location = item; playlist.medias.push(media); media = new M3uMedia(''); } }); return playlist; } private static isDirective(item: string): boolean { return item[0] === M3U_COMMENT; } private static isValidM3u(firstLine: string[]): boolean { return firstLine[0].replace('\n', '') === M3uDirectives.EXTM3U; } static parse(m3uString: string): M3uPlaylist { const lines = m3uString.split('\n').filter(item => item); if (!this.isValidM3u(lines)) { throw new Error(`Missing ${M3uDirectives.EXTM3U} directive!`); } return this.getPlaylist(lines); } } |