Complete code rework, added sources, lists and README updated

master
Meliurwen 4 years ago
parent c13ebc2ac1
commit 92e983d7b5
Signed by: meliurwen
GPG Key ID: 818A8B35E9F1CE10
  1. 20
      README.md
  2. 130
      channels.json
  3. 206
      iptv_network_extract.py

@ -22,14 +22,26 @@ Extracts original m3u8 links from multiple IPTV networks.
## Use ## Use
To extract the link for a _channel_ and put it in `stdout`: To list the supported _sources_:
```sh ```sh
./iptv_network_extract.py -c channelName ./iptv_network_extract.py -l
``` ```
You can also pipe the link to a player like `mpv`: To list the supported _channels_ of a _source_:
```sh ```sh
./iptv_network_extract.py -c channelName | mpv --playlist=- ./iptv_network_extract.py -s SOURCE -l
```
To extract the _link_ for a _channel_:
```sh
./iptv_network_extract.py -s SOURCE -c CHANNEL
```
You can also pipe the link directly to a player like `mpv`:
```sh
./iptv_network_extract.py -s SOURCE -c CHANNEL | mpv --playlist=-
``` ```

@ -1,68 +1,70 @@
{ {
"realtime":{ "dplay-it": {
"url":"https://it.dplay.com/ajax/playbackjson/channel/2", "realtime":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/2",
"referer":"https://it.dplay.com/realtime/" "data":{
} "referer":"https://it.dplay.com/realtime/"
}, }
"nove":{ },
"url":"https://it.dplay.com/ajax/playbackjson/channel/3", "nove":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/3",
"referer":"https://it.dplay.com/nove/" "data":{
} "referer":"https://it.dplay.com/nove/"
}, }
"dmax":{ },
"url":"https://it.dplay.com/ajax/playbackjson/channel/5", "dmax":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/5",
"referer":"https://it.dplay.com/dmax/" "data":{
} "referer":"https://it.dplay.com/dmax/"
}, }
"giallo":{ },
"url":"https://it.dplay.com/ajax/playbackjson/channel/6", "giallo":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/6",
"referer":"https://it.dplay.com/giallo/" "data":{
} "referer":"https://it.dplay.com/giallo/"
}, }
"k-2":{ },
"url":"https://it.dplay.com/ajax/playbackjson/channel/7", "k-2":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/7",
"referer":"https://it.dplay.com/k-2/" "data":{
} "referer":"https://it.dplay.com/k-2/"
}, }
"frisbee":{ },
"url":"https://it.dplay.com/ajax/playbackjson/channel/8", "frisbee":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/8",
"referer":"https://it.dplay.com/frisbee/" "data":{
} "referer":"https://it.dplay.com/frisbee/"
}, }
"motor-trend":{ },
"url":"https://it.dplay.com/ajax/playbackjson/channel/19", "motor-trend":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/19",
"referer":"https://it.dplay.com/motor-trend/" "data":{
} "referer":"https://it.dplay.com/motor-trend/"
}, }
"food-network":{ },
"url":"https://it.dplay.com/ajax/playbackjson/channel/21", "food-network":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/21",
"referer":"https://it.dplay.com/food-network/" "data":{
} "referer":"https://it.dplay.com/food-network/"
}, }
"home-and-garden-tv":{ },
"url":"https://it.dplay.com/ajax/playbackjson/channel/36", "home-and-garden-tv":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/36",
"referer":"https://it.dplay.com/home-and-garden-tv/" "data":{
} "referer":"https://it.dplay.com/home-and-garden-tv/"
}, }
"eurosport1":{ },
"url":"https://it.dplay.com/ajax/playbackjson/channel/49", "eurosport1":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/49",
"referer":"https://it.dplay.com/eurosport1/" "data":{
} "referer":"https://it.dplay.com/eurosport1/"
}, }
"eurosport2":{ },
"url":"https://it.dplay.com/ajax/playbackjson/channel/50", "eurosport2":{
"data":{ "url":"https://it.dplay.com/ajax/playbackjson/channel/50",
"referer":"https://it.dplay.com/eurosport2/" "data":{
"referer":"https://it.dplay.com/eurosport2/"
}
} }
} }
} }

@ -5,76 +5,142 @@ import json
import argparse import argparse
import requests import requests
__author__ = "Meliurwen"
__version__ = "0.1.1"
__license__ = "GPL3"
with open('channels.json', 'r') as myfile: def get_link_m3u(source, channel, chan_dict):
channelsDict = json.loads(myfile.read())
headers = {
parser = argparse.ArgumentParser( "User-Agent": ("Mozilla/5.0 (Windows NT 10.0; rv:75.0) "
prog='IPTV Network Extract', "Gecko/20100101 Firefox/75.0"),
description='Extracts original m3u8 links from multiple IPTV networks.' "Accept-Language": "en-US;q=0.9,en;q=0.8,en-GB;q=0.7",
) "X-Requested-With": "XMLHttpRequest",
parser.add_argument( "Connection": "keep-alive",
"-c", "--channel", "Referer": str(chan_dict[source][channel]["data"]["referer"]),
nargs=1, "cb-enabled": "enabled",
choices=list(channelsDict.keys()), "DNT": "1",
required=True, "Pragma": "no-cache",
help="TV channel name" "Cache-Control": "no-cache"
) }
parser.add_argument(
"--version", content = requests.get(
action="version", chan_dict[source][channel]["url"],
version="%(prog)s 0.1" headers=headers,
) timeout=(3, 300)
args = parser.parse_args()
channel = args.channel[0]
HEADERS: dict = {
"User-Agent": ("Mozilla/5.0 (Windows NT 10.0; rv:75.0) "
"Gecko/20100101 Firefox/75.0"),
"Accept-Language": "en-US;q=0.9,en;q=0.8,en-GB;q=0.7",
"X-Requested-With": "XMLHttpRequest",
"Connection": "keep-alive",
"Referer": str(channelsDict[channel]["data"]["referer"]),
"cb-enabled": "enabled",
"DNT": "1",
"Pragma": "no-cache",
"Cache-Control": "no-cache"
}
content = requests.get(
channelsDict[channel]["url"],
headers=HEADERS,
timeout=(3, 300)
)
content = {
"status_code": content.status_code,
"content": content.content,
"encoding": content.encoding,
"cookies": content.cookies,
"request": content.request,
"url": content.url,
"reason": content.reason,
"headers": content.headers,
"elapsed": content.elapsed,
"history": content.history
}
if content["status_code"] == 200:
uglyPayload = json.loads(content["content"].decode('unicode_escape')[1:-1])
print(
uglyPayload["data"]["attributes"]["streaming"]["hls"]["url"],
sep='',
end='',
file=sys.stdout,
flush=False
)
else:
print(
"[ERROR] Http status code: " + str(content["status_code"]),
sep='',
end='\n',
file=sys.stderr,
) )
content = {
"status_code": content.status_code,
"content": content.content,
"url": content.url
}
if content["status_code"] == 200:
ugly_payload = json.loads(content["content"].decode('unicode_escape')[1:-1])
print(
ugly_payload["data"]["attributes"]["streaming"]["hls"]["url"],
sep='',
end='\n',
file=sys.stdout,
flush=False
)
sys.exit(0)
else:
print(
"[ERROR] Http status code: {stat_code}".format(stat_code=content["status_code"]),
file=sys.stderr
)
sys.exit(1)
def is_supp_source(chan_dict, source):
if source not in chan_dict.keys():
print(
"[ERROR] Source not supported: {source}".format(source=source),
file=sys.stderr
)
sys.exit(1)
def is_supp_channel(chan_dict, source, channel):
if channel not in chan_dict[source].keys():
print(
"[ERROR] Channel not supported: {channel}".format(channel=channel),
file=sys.stderr
)
sys.exit(1)
def get_list(source, chan_dict):
if source:
is_supp_source(chan_dict, source)
print(*chan_dict[source].keys(), sep = "\n")
else:
print(*chan_dict.keys(), sep = "\n")
sys.exit(1) sys.exit(1)
def main(arguments):
source = arguments.source[0] if args.source else None
channel = arguments.channel[0] if args.channel else None
is_list = arguments.list if args.list else False
with open('channels.json', 'r') as myfile:
chan_dict = json.loads(myfile.read())
if source and channel:
is_supp_source(chan_dict, source)
is_supp_channel(chan_dict, source, channel)
get_link_m3u(source, channel, chan_dict)
if is_list:
get_list(source, chan_dict)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog='IPTV Network Extract',
usage='%(prog)s [-h] [[-s SOURCE -c CHANNEL] | [-s SOURCE -l]] [-l] [--version]',
description='Extracts original m3u8 links from multiple IPTV networks.'
)
parser.add_argument(
"-s", "--source",
nargs=1,
required=False,
help="source where getting the channel"
)
parser.add_argument(
"-c", "--channel",
nargs=1,
required=False,
help="TV channel name"
)
parser.add_argument(
"-l", "--list",
required=False,
action='store_true',
help="List supported networks and channels"
)
parser.add_argument(
"--version",
action="version",
version="%(prog)s (version {version})".format(version=__version__)
)
args = parser.parse_args()
if len(sys.argv) <= 1:
parser.error("at least 1 argument is required")
if len(sys.argv) == 3 and args.channel:
parser.error("--source is required for this parameter")
if args.source and not bool(args.channel) ^ bool(args.list):
parser.error("--source requires either --channel CHANNEL or --list")
if args.list and args.channel:
parser.error("--list should either be used singularly or with --source")
main(args)

Loading…
Cancel
Save