Skip to content

Commit

Permalink
Initial version of iptv-filter. (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
huxuan authored Jan 2, 2020
1 parent f66b873 commit 4f51c43
Show file tree
Hide file tree
Showing 23 changed files with 460 additions and 294 deletions.
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include LICENSE
include README.md
include config.json
23 changes: 15 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
.PHONY: clean deps lint pycodestyle pyflakes pylint
.PHONY: clean install dev lint pycodestyle pyflakes pylint dist upload

clean:
find . -name '*.pyc' -print0 | xargs -0 rm -f
find . -name '*.swp' -print0 | xargs -0 rm -f
find . -name '.DS_Store' -print0 | xargs -0 rm -rf
find . -name '__pycache__' -print0 | xargs -0 rm -rf
-rm -rf build dist *.egg-info .eggs *.spec

deps:
pip install -r requirements.txt

install:
python setup.py install
pip install .

dev:
pip install .[dev]

lint: pycodestyle pyflakes pylint

pycodestyle:
-pycodestyle --statistics --count *.py
-pycodestyle setup.py iptvtools

pyflakes:
-pyflakes *.py
-pyflakes setup.py iptvtools

pylint:
-pylint *.py
-pylint setup.py iptvtools

dist:
python setup.py sdist bdist_wheel

upload:
twine upload dist/*
62 changes: 20 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,34 @@
# iptv-m3u-filter
# iptvtools

Quite a few publicly available IPTV channels can be found on the Internet, but usually only a part of them is valuable considering accessibility, resolution, latency, bandwidth and some other criteria.
[![PyPI version](https://badge.fury.io/py/iptvtools.svg)](https://badge.fury.io/py/iptvtools)

This script aims to help with the filtering purpose.
IPTVTools aims to provide the following features:

## Prerequisites
- [X] Grab well-maintained playlists from the Internet.
- [X] Filter inaccessible channels.
- [X] Filter channels according width/resolution.
- [X] Simple strategy to unify channels' titles.
- [X] Format url with UDP proxy (Udpxy) if provided.
- [X] Fulfill channels' information by referring to well-maintained template.
- [ ] Scan certain ip and port range to find new channels.
- [ ] Establish a lightweight database for routine maintenance.

```shell
make deps
```
Besides, all scripts should be lightweight and able to keep running regularly after proper configuration.

or
Last but not least, any ideas, comments and suggestions are welcome!

## Installation

```shell
pip install -r requirements.txt
pip install -U iptvtools
```

## Usage
or

```shell
$ python main.py -h
usage: main.py [-h] [--min-height MIN_HEIGHT] [-i INPUT] [-o OUTPUT]
[-p MAX_WORKERS] [-t TIMEOUT]

optional arguments:
-h, --help show this help message and exit
--min-height MIN_HEIGHT
Minimal acceptable height/resolution, defaults to 1080
which means 1080P.
-i INPUT, --input INPUT
Valid M3U playlists, which could be a file or url,
defaults to `https://iptv-
org.github.io/iptv/index.m3u`.
-o OUTPUT, --output OUTPUT
Output file name, defaults to `iptv-m3u-filter.m3u`.
-p MAX_WORKERS, --max-workers MAX_WORKERS
Number of threads to perform the filtering process,
defaults to 16.
-t TIMEOUT, --timeout TIMEOUT
Acceptable timeout when retrieving stream information,
defaults to 2.
pip install .
```

## Roadmap

> Any help is welcome for the following topics.
## Usage

- [ ] Upload to PyPI.
- [ ] Support strategies to unify channel titles. For example, covert `CCTV1`, `CCTV-1HD`, `CCTV-1FHD` to `CCTV-1综合`.
- [ ] Support template combination, such as the [test.m3u](http://epg.51zmt.top:8000/test.m3u) under http://epg.51zmt.top:8000/.
- [ ] Support regular execution, may not by Python code, but usage or documentation instead.
- [ ] Support online deployment, scripts may needed, but still may not by Python code.
- [ ] Support more criteria if possible.
- [ ] Better documentation/docstrings.
- [ ] i18n support.
Please refer to the [wiki](https://github.com/huxuan/iptvtools/wiki) page.
19 changes: 19 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"id_filters": {
"-": "",
"IPTV": "",
"BTV冬奥纪实": "北京纪实",
"BTV北京卫视": "北京卫视",
"BTV卡酷少儿": "卡酷动画",
"CETV1": "中国教育1台",
"CETV2": "中国教育2台",
"CETV3": "中国教育3台",
"CETV4": "中国教育4台",
"纪实频道": "上海纪实"
},
"title_filters": {
"高清": "",
"HD": "",
"+": "+"
}
}
16 changes: 0 additions & 16 deletions defaults.py

This file was deleted.

29 changes: 0 additions & 29 deletions helps.py

This file was deleted.

Empty file added iptvtools/__init__.py
Empty file.
28 changes: 28 additions & 0 deletions iptvtools/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: config.py
Author: huxuan
Email: i(at)huxuan.org
Description: Configuration for iptvtools.
"""
import json
import os
import os.path


class Config():
"""Configuration for iptvtools."""
config = {}

@classmethod
def init(cls, config_file):
"""Initialize configuration."""
if os.path.isfile(config_file):
with open(config_file) as fin:
cls.config = json.load(fin)

@classmethod
def __getattr__(cls, key):
"""Get configuration with key."""
return cls.config.get(key, {})
Empty file added iptvtools/constants/__init__.py
Empty file.
15 changes: 15 additions & 0 deletions iptvtools/constants/defaults.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: constants.py
Author: huxuan
Email: i(at)huxuan.org
Description: Defaults for iptvtools.
"""
CONFIG = 'config.json'
INPUT = 'https://iptv-org.github.io/iptv/index.m3u'
MIN_HEIGHT = 1080
OUTPUT = 'iptvtools.m3u'
TEMPLATE = None # 'http://epg.51zmt.top:8000/test.m3u'
TIMEOUT = 10
UDPXY = None
32 changes: 32 additions & 0 deletions iptvtools/constants/helps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: constants.py
Author: huxuan
Email: i(at)huxuan.org
Description: Helps for iptvtools.
"""
from . import defaults

CONFIG = (
f'Configuration file with title and id filter information, defaults to '
f'`{defaults.CONFIG}`'
)
INPUT = (
f'Valid M3U playlists, which could be a file or url, defaults to '
f'`{defaults.INPUT}`.'
)
MIN_HEIGHT = (
f'Minimal acceptable height/resolution, defaults to '
f'{defaults.MIN_HEIGHT} which means {defaults.MIN_HEIGHT}P.'
)
OUTPUT = f'Output file name, defaults to `{defaults.OUTPUT}`.'
TEMPLATE = f'Template file name, defaults to `{defaults.TEMPLATE}`.'
TIMEOUT = (
f'Acceptable timeout when retrieving stream information, defaults to '
f'{defaults.TIMEOUT}.'
)
UDPXY = (
f'UDP Proxy which will convert the url automatically, defaults to '
f'`{defaults.UDPXY}`.'
)
14 changes: 14 additions & 0 deletions iptvtools/constants/patterns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: constants.py
Author: huxuan
Email: i(at)huxuan.org
Description: Patterns for iptvtools.
"""
import re

PARAMS = re.compile(r'(\S+)="(.*?)"')
EXTINF = re.compile(
r'^#EXTINF:(?P<duration>-?\d+?) ?(?P<params>.*),(?P<title>.*?)$')
EXTM3U = re.compile(r'^#EXTM3U ?(?P<params>.*)$')
10 changes: 10 additions & 0 deletions iptvtools/constants/tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: constants.py
Author: huxuan
Email: i(at)huxuan.org
Description: Tags for iptvtools.
"""
M3U = '#EXTM3U'
INF = '#EXTINF'
50 changes: 50 additions & 0 deletions iptvtools/iptv_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: main.py
Author: huxuan
Email: i(at)huxuan.org
Description: Filter IPTV m3u playlists according to customized criteria.
"""
import argparse

from .config import Config
from .constants import defaults
from .constants import helps
from .models import Playlist


def parse_args():
"""Arguments Parsers."""
parser = argparse.ArgumentParser()
parser.add_argument('--min-height', default=defaults.MIN_HEIGHT, type=int,
help=helps.MIN_HEIGHT)
parser.add_argument('-c', '--config', default=defaults.CONFIG,
help=helps.CONFIG)
parser.add_argument('-i', '--input', default=defaults.INPUT,
help=helps.INPUT)
parser.add_argument('-o', '--output', default=defaults.OUTPUT,
help=helps.OUTPUT)
parser.add_argument('-t', '--template', default=defaults.TEMPLATE,
help=helps.TEMPLATE)
parser.add_argument('-T', '--timeout', default=defaults.TIMEOUT, type=int,
help=helps.TIMEOUT)
parser.add_argument('-u', '--udpxy', default=defaults.UDPXY,
help=helps.UDPXY)
return parser.parse_args()


def main():
"""Main process."""
args = parse_args()
Config.init(args.config)
playlist = Playlist()
playlist.parse(args.input, args.udpxy)
playlist.parse(args.template, is_template=True)
playlist.filter(args.min_height)
print(f'{len(playlist.data)} channels after filtering!')
open(args.output, 'w', encoding='utf-8').write(str(playlist))


if __name__ == '__main__':
main()
Loading

0 comments on commit 4f51c43

Please sign in to comment.