Skip to content

Commit

Permalink
Channel/Group filter. (#11)
Browse files Browse the repository at this point in the history
* Simplify udpxy parameter.

* Add log level arg.

* Add group/channel include/exclude param.

* Implement group/channel include/exclude.

* Add docs.
  • Loading branch information
huxuan authored May 19, 2021
1 parent 96d9c9e commit 24aebee
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 5 deletions.
24 changes: 24 additions & 0 deletions docs/parameters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,30 @@ Selected Parameters

Here is some further explanation for those not so obvious parameters.

GROUP_EXCLUDE
-------------

Filter the playlist depends on the group title with a blacklist (regular expression).
Note that, it has higher priority than the whitelist ``GROUP_INCLUDE``.

GROUP_INCLUDE
-------------

Filter the playlist depends on the group title with a whitelist (regular expression).
Note that, if set, only groups match the pattern will be included.

CHANNEL_EXCLUDE
---------------

Filter the playlist depends on the channel title by a blacklist (regular expression).
Note that, it has higher priority than the whitelist ``CHANNEL_INCLUDE``.

CHANNEL_INCLUDE
---------------

Filter the playlist depends on the channel title by a whitelist (regular expression).
Note that, if set, only channels match the pattern will be included.

MIN_HEIGHT
----------

Expand Down
1 change: 1 addition & 0 deletions iptvtools/constants/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
CONFIG = 'config.json'
INPUTS = ['https://iptv-org.github.io/iptv/index.m3u']
INTERVAL = 1
LOG_LEVEL = 'INFO'
MIN_HEIGHT = 0
OUTPUT = 'iptvtools.m3u'
SORT_KEYS = ['tvg-id', 'height', 'title']
Expand Down
17 changes: 17 additions & 0 deletions iptvtools/constants/helps.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,29 @@
CONFIG = (
'Configuration file to unify title and id.'
)
CHANNEL_EXCLUDE = (
'Channels to exclude with regex. '
'Note: Blacklist has higher priority than whitelist.'
)
CHANNEL_INCLUDE = (
'Channels to include with regex. '
'Note: Only channels in the whitelist will be included if set.'
)
GROUP_EXCLUDE = (
'Groups to exclude with regex.'
'Note: Blacklist has higher priority than whitelist.'
)
GROUP_INCLUDE = (
'Groups to include with regex.'
'Note: Only groups in the whitelist will be included if set.'
)
INPUTS = (
'One or more input m3u playlist files/urls.'
)
INTERVAL = (
'Interval in seconds between successive fetching requests.'
)
LOG_LEVEL = 'Log level.'
MIN_HEIGHT = (
'Minimum height/resolution to accept, 0 means no resolution filtering.'
)
Expand Down
8 changes: 7 additions & 1 deletion iptvtools/iptv_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def parse_args():
"""Arguments Parsers."""
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--channel-exclude', help=helps.CHANNEL_EXCLUDE)
parser.add_argument('--channel-include', help=helps.CHANNEL_INCLUDE)
parser.add_argument('--group-exclude', help=helps.GROUP_EXCLUDE)
parser.add_argument('--group-include', help=helps.GROUP_INCLUDE)
parser.add_argument('--min-height', default=defaults.MIN_HEIGHT, type=int,
help=helps.MIN_HEIGHT)
parser.add_argument('-c', '--config', default=defaults.CONFIG,
Expand All @@ -31,6 +35,8 @@ def parse_args():
help=helps.INPUTS)
parser.add_argument('-I', '--interval', default=defaults.INTERVAL,
type=int, help=helps.INTERVAL)
parser.add_argument('-L', '--log-level', default=defaults.LOG_LEVEL,
help=helps.LOG_LEVEL)
parser.add_argument('-o', '--output', default=defaults.OUTPUT,
help=helps.OUTPUT)
parser.add_argument('-r', '--replace-group-by-source', action='store_true',
Expand All @@ -54,7 +60,7 @@ def main():
"""Filter m3u playlists."""
args = parse_args()

logging.basicConfig(level=logging.INFO)
logging.basicConfig(level=args.log_level.upper())

if args.min_height or args.resolution_on_title:
if shutil.which('ffprobe') is None:
Expand Down
43 changes: 39 additions & 4 deletions iptvtools/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
Author: huxuan
Email: i(at)huxuan.org
"""
import logging
import os.path
import random
import re
import sys
import time

Expand Down Expand Up @@ -63,10 +65,12 @@ def export(self):

def parse(self):
"""Parse contents."""
self._parse(self.args.inputs, udpxy=self.args.udpxy)
self._parse(self.args.inputs)
logging.debug(self.data)
self._parse(self.args.templates, is_template=True)
logging.debug(self.data)

def _parse(self, sources, udpxy=None, is_template=False):
def _parse(self, sources, is_template=False):
"""Parse playlist sources."""
for source in sources:
lines = parsers.parse_content_to_lines(source)
Expand All @@ -79,23 +83,54 @@ def _parse(self, sources, udpxy=None, is_template=False):
lines = lines[1:]

current_item = {}
skip = False
for line in lines:
line = line.strip()
if not line:
continue
if skip:
skip = False
continue
if line.startswith(tags.INF):
current_item = parsers.parse_tag_inf(line)
current_item = utils.unify_title_and_id(current_item)
current_id = current_item['id']

if not skip and current_item.get('params') and \
current_item['params'].get('group-title'):
group = current_item['params']['group-title']
if not skip and self.args.group_include:
if re.search(self.args.group_include, group):
logging.debug(f'Group to include: `{group}`.')
else:
skip = True
if not skip and self.args.group_exclude and \
re.search(self.args.group_exclude, group):
skip = True
logging.debug(f'Group to exclude: `{group}`.')

if not skip and current_item.get('title'):
title = current_item['title']
if not skip and self.args.channel_include:
if re.search(self.args.channel_include, title):
logging.debug(f'Channel to include: `{title}`.')
else:
skip = True
if not skip and self.args.channel_exclude and \
re.search(self.args.channel_exclude, title):
skip = True
logging.debug(f'Channel to exclude: `{title}`.')

else:
if is_template:
for url in self.id_url.get(current_id, []):
current_params = current_item['params']
self.data[url]['params'].update(current_params)
self.data[url]['title'] = current_item['title']
else:
if udpxy:
line = utils.convert_url_with_udpxy(line, udpxy)
if self.args.udpxy:
line = utils.convert_url_with_udpxy(
line, self.args.udpxy)
current_item['source'] = source_name
self.data[line] = current_item

Expand Down

0 comments on commit 24aebee

Please sign in to comment.