Example #1
0
    def setup(cls):
        """ Setup IPTV Simple """
        try:
            # Install IPTV Simple
            kodiutils.execute_builtin('InstallAddon', IPTV_SIMPLE_ID)
            addon = kodiutils.get_addon(IPTV_SIMPLE_ID)
        except Exception as exc:  # pylint: disable=broad-except
            _LOGGER.warning('Could not setup IPTV Simple: %s', str(exc))
            return False

        # Deactivate IPTV Simple to hide the "Needs to be restarted" messages
        cls._deactivate()

        # Configure IPTV Simple
        output_dir = kodiutils.addon_profile()
        playlist_path = os.path.join(output_dir, IPTV_SIMPLE_PLAYLIST)
        epg_path = os.path.join(output_dir, IPTV_SIMPLE_EPG)
        logo_path = '/'

        addon.setSetting('m3uPathType', '0')  # Local path
        addon.setSetting('m3uPath', playlist_path)

        addon.setSetting('epgPathType', '0')  # Local path
        addon.setSetting('epgPath', epg_path)

        addon.setSetting('logoPathType', '0')  # Local path
        addon.setSetting('logoPath', logo_path)

        # Activate IPTV Simple
        cls._activate()

        return True
Example #2
0
    def write_playlist(channels):
        """ Write playlist data """
        output_dir = kodiutils.addon_profile()

        # Make sure our output dir exists
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

        playlist_path = os.path.join(output_dir, IPTV_SIMPLE_PLAYLIST)

        with open(playlist_path + '.tmp', 'wb') as fdesc:
            fdesc.write('#EXTM3U\n'.encode('utf-8'))

            for channel in channels:
                if channel.get('radio'):
                    header = '#EXTINF:0 tvg-id="{id}" tvg-logo="{logo}" tvg-name="{name}" radio="true",{name}\n'
                else:
                    header = '#EXTINF:0 tvg-id="{id}" tvg-logo="{logo}" tvg-name="{name}",{name}\n'

                fdesc.write(header.format(id=channel.get('id'), logo=channel.get('logo'), name=channel.get('name')).encode('utf-8'))
                fdesc.write("{url}\n".format(url=channel.get('stream')).encode('utf-8'))
                fdesc.write("\n".encode('utf-8'))

        # Move new file to the right place
        os.rename(playlist_path + '.tmp', playlist_path)
Example #3
0
    def write_playlist(channels):
        """ Write playlist data """
        output_dir = kodiutils.addon_profile()

        # Make sure our output dir exists
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

        playlist_path = os.path.join(output_dir, IPTV_SIMPLE_PLAYLIST)

        with open(playlist_path + '.tmp', 'wb') as fdesc:
            m3u8_data = '#EXTM3U\n'

            for channel in channels:
                m3u8_data += '#EXTINF:-1 tvg-name="{name}"'.format(**channel)
                if channel.get('id'):
                    m3u8_data += ' tvg-id="{id}"'.format(**channel)
                if channel.get('logo'):
                    m3u8_data += ' tvg-logo="{logo}"'.format(**channel)
                if channel.get('preset'):
                    m3u8_data += ' tvg-chno="{preset}"'.format(**channel)
                if channel.get('group'):
                    m3u8_data += ' group-title="{group}"'.format(**channel)
                if channel.get('radio'):
                    m3u8_data += ' radio="true"'
                m3u8_data += ',{name}\n{stream}\n\n'.format(**channel)
            fdesc.write(m3u8_data.encode('utf-8'))

        # Move new file to the right place
        if os.path.isfile(playlist_path):
            os.remove(playlist_path)

        os.rename(playlist_path + '.tmp', playlist_path)
Example #4
0
    def setup(cls):
        """ Setup IPTV Simple """
        try:
            # Install IPTV Simple
            kodiutils.execute_builtin('InstallAddon', IPTV_SIMPLE_ID)
            addon = kodiutils.get_addon(IPTV_SIMPLE_ID)
        except:
            raise Exception('Could not enable IPTV Simple.')

        # Deactivate IPTV Simple to hide the "Needs to be restarted" messages
        cls._deactivate()

        # Configure IPTV Simple
        output_dir = kodiutils.addon_profile()
        playlist_path = os.path.join(output_dir, IPTV_SIMPLE_PLAYLIST)
        epg_path = os.path.join(output_dir, IPTV_SIMPLE_EPG)

        addon.setSetting('m3uPathType', '0')  # Local path
        addon.setSetting('m3uPath', playlist_path)

        addon.setSetting('epgPathType', '0')  # Local path
        addon.setSetting('epgPath', epg_path)

        addon.setSetting('logoPathType', '0')  # Local path
        addon.setSetting('logoPath', '/')

        # Activate IPTV Simple
        cls._activate()
    def write_epg(cls, epg_list, channels):
        """Write EPG data"""
        output_dir = kodiutils.addon_profile()

        # Make sure our output dir exists
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

        epg_path = os.path.join(output_dir, IPTV_SIMPLE_EPG)

        # Write XML file by hand
        # The reason for this is that it takes less memory to write the file line by line then to construct an
        # XML object in memory and writing that in one go.
        # We can't depend on lxml.etree.xmlfile, since that's not available as a Kodi module
        with open(epg_path + '.tmp', 'wb') as fdesc:
            fdesc.write(
                '<?xml version="1.0" encoding="UTF-8"?>\n'.encode('utf-8'))
            fdesc.write('<!DOCTYPE tv SYSTEM "xmltv.dtd">\n'.encode('utf-8'))
            fdesc.write('<tv>\n'.encode('utf-8'))

            # Write channel info
            for addon in channels:
                for channel in addon.get('channels'):
                    if isinstance(channel, dict) and channel.get('id'):
                        fdesc.write(
                            '<channel id="{id}">\n'.format(id=cls._xml_encode(
                                channel.get('id'))).encode('utf-8'))
                        fdesc.write(
                            ' <display-name>{name}</display-name>\n'.format(
                                name=cls._xml_encode(channel.get(
                                    'name'))).encode('utf-8'))
                        if channel.get('logo'):
                            fdesc.write(' <icon src="{logo}"/>\n'.format(
                                logo=cls._xml_encode(channel.get(
                                    'logo'))).encode('utf-8'))
                        fdesc.write('</channel>\n'.encode('utf-8'))

            for epg in epg_list:
                # RAW XMLTV data
                if not isinstance(epg, dict):
                    fdesc.write(epg.encode('utf-8'))
                    fdesc.write('\n'.encode('utf-8'))
                    continue

                # Write program info
                for _, key in enumerate(epg):
                    for item in epg[key]:
                        program = cls._construct_epg_program_xml(item, key)
                        fdesc.write(program.encode('utf-8'))

            fdesc.write('</tv>\n'.encode('utf-8'))

        # Move new file to the right place
        if os.path.isfile(epg_path):
            os.remove(epg_path)

        os.rename(epg_path + '.tmp', epg_path)
Example #6
0
 def __get_subtitle_paths():
     """ Get the external subtitles path """
     temp_path = kodiutils.addon_profile() + 'temp/'
     files = None
     if kodiutils.exists(temp_path):
         _, files = kodiutils.listdir(temp_path)
     if files and len(files) >= 1:
         return [temp_path + kodiutils.to_unicode(filename) for filename in files]
     _LOGGER.debug('Player: No subtitle path')
     return None
    def write_channels(channels):
        """Write the channel data to a file."""
        output_dir = kodiutils.addon_profile()

        # Make sure our output dir exists
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

        channels_path = os.path.join(output_dir, CHANNELS_CACHE)
        with open(channels_path, 'w') as fdesc:
            json.dump(channels, fdesc)
    def _get_addons_for_channel(channel):
        """Returns a list of Add-ons that can play this channel."""
        channels_path = os.path.join(kodiutils.addon_profile(), CHANNELS_CACHE)
        with open(channels_path, 'r') as fdesc:
            data = json.load(fdesc)

        matches = {}
        for _addon in data:
            for _channel in _addon.get('channels', []):
                if _channel.get('name').lower() == channel.lower() and _channel.get('vod') is not None:
                    matches.update({_addon.get('addon_name'): _channel.get('vod')})

        return matches
    def write_playlist(channels):
        """Write playlist data"""
        output_dir = kodiutils.addon_profile()

        # Make sure our output dir exists
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

        # Write playlist for IPTV Simple
        playlist_path = os.path.join(output_dir, IPTV_SIMPLE_PLAYLIST)

        with open(playlist_path + '.tmp', 'wb') as fdesc:
            m3u8_data = '#EXTM3U\n'

            for addon in channels:
                m3u8_data += '## {addon_name}\n'.format(**addon)

                # RAW M3U8 data
                if not isinstance(addon['channels'], list):
                    m3u8_data += addon['channels']
                    continue

                # JSON-STREAMS format
                for channel in addon['channels']:
                    m3u8_data += '#EXTINF:-1 tvg-name="{name}"'.format(
                        **channel)
                    if channel.get('id'):
                        m3u8_data += ' tvg-id="{id}"'.format(**channel)
                    if channel.get('logo'):
                        m3u8_data += ' tvg-logo="{logo}"'.format(**channel)
                    if channel.get('preset'):
                        m3u8_data += ' tvg-chno="{preset}"'.format(**channel)
                    if channel.get('group'):
                        m3u8_data += ' group-title="{groups}"'.format(
                            groups=';'.join(channel.get('group')))
                    if channel.get('radio'):
                        m3u8_data += ' radio="true"'
                    m3u8_data += ' catchup="vod",{name}\n'.format(**channel)
                    if channel.get('kodiprops'):
                        for key, value in channel.get('kodiprops').items():
                            m3u8_data += '#KODIPROP:{key}={value}\n'.format(
                                key=key, value=value)
                    m3u8_data += '{stream}\n\n'.format(**channel)

            fdesc.write(m3u8_data.encode('utf-8'))

        # Move new file to the right place
        if os.path.isfile(playlist_path):
            os.remove(playlist_path)

        os.rename(playlist_path + '.tmp', playlist_path)
Example #10
0
    def write_epg(epg):
        """ Write EPG data """
        output_dir = kodiutils.addon_profile()

        # Make sure our output dir exists
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

        epg_path = os.path.join(output_dir, IPTV_SIMPLE_EPG)

        # Write XML file by hand
        # The reason for this is that it takes less memory to write the file line by line then to construct an XML object in memory and writing that in one go.
        # TODO: proper escaping of XML
        with open(epg_path + '.tmp', 'wb') as fdesc:
            fdesc.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n'.encode('utf-8'))
            fdesc.write('<!DOCTYPE tv SYSTEM "xmltv.dtd">\n'.encode('utf-8'))
            fdesc.write('<tv>\n'.encode('utf-8'))

            # Write channel info
            for _, key in enumerate(epg):
                fdesc.write('<channel id="{key}"></channel>\n'.format(key=key).encode('utf-8'))

            # Write program info
            for _, key in enumerate(epg):
                for item in epg[key]:
                    start = dateutil.parser.parse(item.get('start')).strftime('%Y%m%d%H%M%S %z')
                    stop = dateutil.parser.parse(item.get('stop')).strftime('%Y%m%d%H%M%S %z')

                    fdesc.write('<programme start="{start}" stop="{stop}" channel="{channel}">\n'.format(start=start, stop=stop, channel=key).encode('utf8'))
                    fdesc.write(' <title>{title}</title>'.format(title=item.get('title')).encode('utf8'))
                    if item.get('description'):
                        fdesc.write(' <desc>{description}</desc>\n'.format(description=item.get('description')).encode('utf8'))
                    if item.get('subtitle'):
                        fdesc.write(' <sub-title>{subtitle}</sub-title>\n'.format(subtitle=item.get('subtitle')).encode('utf-8'))
                    if item.get('episode'):
                        fdesc.write(' <episode-num system="onscreen">{episode}</episode-num>\n'.format(episode=item.get('episode')).encode('utf-8'))
                    if item.get('image'):
                        fdesc.write(' <icon src="{image}"/>\n'.format(image=item.get('image')).encode('utf-8'))
                    if item.get('date'):
                        fdesc.write(' <date>{date}</date>\n'.format(date=item.get('date')).encode('utf-8'))
                    fdesc.write('</programme>\n'.encode('utf-8'))

            fdesc.write('</tv>\n'.encode('utf-8'))

        # Move new file to the right place
        os.rename(epg_path + '.tmp', epg_path)
Example #11
0
    def _delay_subtitles(self, subtitles, json_manifest):
        """ Modify the subtitles timings to account for ad breaks.
        :type subtitles: list[string]
        :type json_manifest: dict
        :rtype list[str]
        """
        # Clean up old subtitles
        temp_dir = os.path.join(kodiutils.addon_profile(), 'temp', '')
        _, files = kodiutils.listdir(temp_dir)
        if files:
            for item in files:
                if kodiutils.to_unicode(item).endswith('.vtt'):
                    kodiutils.delete(temp_dir + kodiutils.to_unicode(item))

        # Return if there are no subtitles available
        if not subtitles:
            return None

        import re
        if not kodiutils.exists(temp_dir):
            kodiutils.mkdirs(temp_dir)

        ad_breaks = list()
        delayed_subtitles = list()
        webvtt_timing_regex = re.compile(
            r'\n(\d{2}:\d{2}:\d{2}\.\d{3}) --> (\d{2}:\d{2}:\d{2}\.\d{3})\s')

        # Get advertising breaks info from json manifest
        cues = json_manifest.get('interstitials').get('cues')
        for cue in cues:
            ad_breaks.append(
                dict(start=cue.get('start'),
                     duration=cue.get('break_duration')))

        for subtitle in subtitles:
            output_file = temp_dir + subtitle.get('name') + '.' + subtitle.get(
                'url').split('.')[-1]
            webvtt_content = util.http_get(subtitle.get('url')).text
            webvtt_content = webvtt_timing_regex.sub(
                lambda match: self._delay_webvtt_timing(match, ad_breaks),
                webvtt_content)
            with kodiutils.open_file(output_file, 'w') as webvtt_output:
                webvtt_output.write(kodiutils.from_unicode(webvtt_content))
            delayed_subtitles.append(output_file)
        return delayed_subtitles
    def setup(cls):
        """Setup IPTV Simple"""
        try:
            # Install IPTV Simple
            kodiutils.execute_builtin('InstallAddon', IPTV_SIMPLE_ID)

            # Activate IPTV Simple so we can get the addon to be able to configure it
            cls._activate()
            addon = kodiutils.get_addon(IPTV_SIMPLE_ID)
        except Exception as exc:  # pylint: disable=broad-except
            _LOGGER.warning('Could not setup IPTV Simple: %s', str(exc))
            return False

        # Deactivate IPTV Simple to hide the "Needs to be restarted" messages
        cls._deactivate()

        # Configure IPTV Simple
        output_dir = kodiutils.addon_profile()

        addon.setSetting('m3uPathType', '0')  # Local path
        addon.setSetting('m3uPath',
                         os.path.join(output_dir, IPTV_SIMPLE_PLAYLIST))

        addon.setSetting('epgPathType', '0')  # Local path
        addon.setSetting('epgPath', os.path.join(output_dir, IPTV_SIMPLE_EPG))
        addon.setSetting('epgCache', 'true')
        addon.setSetting('epgTimeShift', '0')

        addon.setSetting('logoPathType', '0')  # Local path
        addon.setSetting('logoPath', '/')

        addon.setSetting('catchupEnabled', 'true')
        addon.setSetting('allChannelsCatchupMode', '1')
        addon.setSetting('catchupOnlyOnFinishedProgrammes', 'false')

        # Activate IPTV Simple
        cls._activate()

        return True
    def _download_subtitles(subtitles):
        # Clean up old subtitles
        temp_dir = os.path.join(kodiutils.addon_profile(), 'temp', '')
        _, files = kodiutils.listdir(temp_dir)
        if files:
            for item in files:
                kodiutils.delete(temp_dir + kodiutils.to_unicode(item))

        # Return if there are no subtitles available
        if not subtitles:
            return None

        if not kodiutils.exists(temp_dir):
            kodiutils.mkdirs(temp_dir)

        downloaded_subtitles = list()
        for subtitle in subtitles:
            output_file = temp_dir + subtitle.get('name')
            webvtt_content = util.http_get(subtitle.get('url')).text
            with kodiutils.open_file(output_file, 'w') as webvtt_output:
                webvtt_output.write(kodiutils.from_unicode(webvtt_content))
            downloaded_subtitles.append(output_file)
        return downloaded_subtitles
Example #14
0
    def write_epg(cls, epg):
        """Write EPG data"""
        output_dir = kodiutils.addon_profile()

        # Make sure our output dir exists
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

        epg_path = os.path.join(output_dir, IPTV_SIMPLE_EPG)

        # Write XML file by hand
        # The reason for this is that it takes less memory to write the file line by line then to construct an
        # XML object in memory and writing that in one go.
        # We can't depend on lxml.etree.xmlfile, since that's not available as a Kodi module
        with open(epg_path + '.tmp', 'wb') as fdesc:
            fdesc.write('<?xml version="1.0" encoding="UTF-8"?>\n'.encode('utf-8'))
            fdesc.write('<!DOCTYPE tv SYSTEM "xmltv.dtd">\n'.encode('utf-8'))
            fdesc.write('<tv>\n'.encode('utf-8'))

            # Write channel info
            for _, key in enumerate(epg):
                fdesc.write('<channel id="{key}"></channel>\n'.format(key=cls._xml_encode(key)).encode('utf-8'))

            # Write program info
            for _, key in enumerate(epg):
                for item in epg[key]:
                    program = cls._construct_epg_program_xml(item, key)
                    fdesc.write(program.encode('utf-8'))

            fdesc.write('</tv>\n'.encode('utf-8'))

        # Move new file to the right place
        if os.path.isfile(epg_path):
            os.remove(epg_path)

        os.rename(epg_path + '.tmp', epg_path)
    def write_epg(cls, epg):
        """Write EPG data"""
        output_dir = kodiutils.addon_profile()

        # Make sure our output dir exists
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

        epg_path = os.path.join(output_dir, IPTV_SIMPLE_EPG)

        # Write XML file by hand
        # The reason for this is that it takes less memory to write the file line by line then to construct an
        # XML object in memory and writing that in one go.
        # We can't depend on lxml.etree.xmlfile, since that's not available as a Kodi module
        with open(epg_path + '.tmp', 'wb') as fdesc:
            fdesc.write(
                '<?xml version="1.0" encoding="UTF-8"?>\n'.encode('utf-8'))
            fdesc.write('<!DOCTYPE tv SYSTEM "xmltv.dtd">\n'.encode('utf-8'))
            fdesc.write('<tv>\n'.encode('utf-8'))

            # Write channel info
            for _, key in enumerate(epg):
                fdesc.write('<channel id="{key}"></channel>\n'.format(
                    key=cls._xml_encode(key)).encode('utf-8'))

            # Write program info
            for _, key in enumerate(epg):
                for item in epg[key]:
                    start = dateutil.parser.parse(
                        item.get('start')).strftime('%Y%m%d%H%M%S %z')
                    stop = dateutil.parser.parse(
                        item.get('stop')).strftime('%Y%m%d%H%M%S %z')
                    title = item.get('title', '')

                    # Add an icon ourselves in Kodi 18
                    if kodiutils.kodi_version_major() < 19 and item.get(
                            'stream'):
                        # We use a clever way to hide the direct URI in the label so Kodi 18 can access the it
                        title = '%s [COLOR green]•[/COLOR][COLOR vod="%s"][/COLOR]' % (
                            title, item.get('stream'))

                    program = '<programme start="{start}" stop="{stop}" channel="{channel}"{vod}>\n'.format(
                        start=start,
                        stop=stop,
                        channel=cls._xml_encode(key),
                        vod=' catchup-id="%s"' %
                        cls._xml_encode(item.get('stream'))
                        if item.get('stream') else '')

                    program += ' <title>{title}</title>\n'.format(
                        title=cls._xml_encode(title))

                    if item.get('description'):
                        program += ' <desc>{description}</desc>\n'.format(
                            description=cls._xml_encode(item.get(
                                'description')))

                    if item.get('subtitle'):
                        program += ' <sub-title>{subtitle}</sub-title>\n'.format(
                            subtitle=cls._xml_encode(item.get('subtitle')))

                    if item.get('episode'):
                        program += ' <episode-num system="onscreen">{episode}</episode-num>\n'.format(
                            episode=cls._xml_encode(item.get('episode')))

                    if item.get('image'):
                        program += ' <icon src="{image}"/>\n'.format(
                            image=cls._xml_encode(item.get('image')))

                    if item.get('date'):
                        program += ' <date>{date}</date>\n'.format(
                            date=cls._xml_encode(item.get('date')))

                    if item.get('genre'):
                        if isinstance(item.get('genre'), list):
                            for genre in item.get('genre'):
                                program += ' <category>{genre}</category>\n'.format(
                                    genre=cls._xml_encode(genre))
                        else:
                            program += ' <category>{genre}</category>\n'.format(
                                genre=cls._xml_encode(item.get('genre')))

                    program += '</programme>\n'

                    fdesc.write(program.encode('utf-8'))

            fdesc.write('</tv>\n'.encode('utf-8'))

        # Move new file to the right place
        if os.path.isfile(epg_path):
            os.remove(epg_path)

        os.rename(epg_path + '.tmp', epg_path)