diff options
| author | Li Zhineng <[email protected]> | 2024-07-04 19:23:31 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-07-04 19:23:31 +0800 |
| commit | 9aec9bfbd4d6370423927fdd7b8bc0bb0f8aa811 (patch) | |
| tree | d79819566c994042a9563221788999ece475715a /iptv.sh | |
| parent | d45b437498614d23d2a817e66549818006a64146 (diff) | |
| parent | 6de6d14533b10ed83feff05d79115ac2659ae594 (diff) | |
| download | china-unicom-iptv-gd-9aec9bfbd4d6370423927fdd7b8bc0bb0f8aa811.tar.gz china-unicom-iptv-gd-9aec9bfbd4d6370423927fdd7b8bc0bb0f8aa811.zip | |
Merge pull request #1 from lizhineng/epg
Supports building EPG file
Diffstat (limited to 'iptv.sh')
| -rwxr-xr-x | iptv.sh | 330 |
1 files changed, 200 insertions, 130 deletions
@@ -1,169 +1,239 @@ #!/usr/bin/env bash -# Default values -ip_address="127.0.0.1" -udpxy_endpoint="http://127.0.0.1:4022" -output_file="iptv.M3U8" -curl_args="" -endpoint="http://eds1.unicomgd.com:8082" +step () { echo -e "\033[32m[-]\033[0m $1"; } -while [ $# -gt 0 ]; do - case "$1" in - -u | --user) user_id="$2"; shift 2;; - -p | --password) password="$2"; shift 2;; - -d | --device) device_id="$2"; shift 2;; - --ip) ip_address="$2"; shift 2;; - --mac) mac_address="$2"; shift 2;; - --udpxy) udpxy_endpoint="$2"; shift 2;; - -o | --output) output_file="$2"; shift 2;; - --curl) curl_args="$2"; shift 2;; - *) echo "Unknown option: $1"; exit 1;; - esac -done - -## -## Validate user input -## - -if [[ -z "$user_id" ]]; then - echo "Requires an IPTV user ID with -u or --user" - exit 1 -fi +fatal () { echo -e "\033[31m[!]\033[0m $1"; exit 1; } -if [[ -z "$password" ]]; then - echo "Requires an IPTV password with -p or --password" - exit 1 -fi +ensure_curl_is_installed () { + if ! command -v curl &>/dev/null; then + fatal "The cURL package that handles HTTP requests is not installed." + fi +} -if [[ -z "$device_id" ]]; then - echo "Requires a device ID with -d or --device" - exit 1 -fi +ensure_jq_is_installed () { + if ! command -v jq &>/dev/null; then + fatal "The jq package that handles HTTP JSON response is not installed." + fi +} -if [[ -z "$mac_address" ]]; then - echo "Requires a device MAC address with --mac" - exit 1 -fi +ensure_openssl_is_installed () { + if ! command -v openssl &>/dev/null; then + fatal "The OpenSSL package that handles token computation is not installed." + fi +} -## -## Check dependencies -## +categorize_by_channel_name () { + result="720P" -if ! command -v jq &>/dev/null; then - echo "The jq package that handles HTTP JSON response is not installed." - exit 1 -fi + case "$1" in + *4K*) result="4K" ;; + *"超清"*|*"高清"*) result="1080P" ;; + esac -if ! command -v openssl &>/dev/null; then - echo "The OpenSSL package that handles token computation is not installed." - exit 1 -fi + echo "$result" +} + +make_epg () { + # Check dependencies + ensure_curl_is_installed + ensure_jq_is_installed + + # Default variables + output_file="epg.xml" + endpoint="http://120.87.12.38:8083/epg/api/page/biz_59417088.json" + curl_args="" + + while [ $# -gt 0 ]; do + case "$1" in + -o | --output ) output_file="$2"; shift 2;; + --endpoint ) endpoint="$2"; shift 2;; + --curl ) curl_args="$2"; shift 2;; + *) echo "Unknown option: $1"; exit 1;; + esac + done + + step "Request channel index" + response=$(curl --silent $curl_args "$endpoint") + + step "Create the EPG XML file" + echo '<?xml version="1.0" encoding="UTF-8"?>' > $output_file + echo '<!DOCTYPE tv SYSTEM "xmltv.dtd">' >> $output_file + echo "<tv date=\"$(date +"%Y%m%d%H%M%S %z")\">" >> $output_file + + while read -r item; do + item_title=$(echo "$item" | jq -r '.itemTitle') + item_type=$(echo "$item" | jq -r '.itemType') + data_link=$(echo "$item" | jq -r '.dataLink') + + if [[ "$item_type" == "channel" ]]; then + step "Process: $item_title" + + response=$(curl --silent --interface eth0 "$data_link") + channel_icon=$(echo "$response" | jq -r '.channel.icon') + channel_title=$(echo "$response" | jq -r '.channel.title') + hwcode=$(echo "$response" | jq -r '.channel.params.hwcode') + + echo " <channel id=\"$hwcode\">" >> $output_file + echo " <display-name lang=\"zh\">$channel_title</display-name>" >> $output_file + echo " <icon src=\"$channel_icon\"/>" >> $output_file + echo " </channel>" >> $output_file + + while read -r schedule; do + schedule_title=$(echo "$schedule" | jq -r '.title') + schedule_starttime=$(echo "$schedule" | jq -r '.starttime') + schedule_endtime=$(echo "$schedule" | jq -r '.endtime') + + echo " <programme start=\"$schedule_starttime +0800\" stop=\"$schedule_endtime +0800\" channel=\"$hwcode\">" >> $output_file + echo " <title lang=\"zh\">$schedule_title</title>" >> $output_file + echo " </programme>" >> $output_file + done < <(echo "$response" | jq -c '.schedules[]') + fi + done < <(echo "$response" | jq -c '.areaDatas[].items[]') + + echo '</tv>' >> $output_file + + step "EPG built sucessfully!" + + exit 0 +} + +make_playlist () { + # Check dependencies + ensure_curl_is_installed + ensure_jq_is_installed + ensure_openssl_is_installed + + # Default values + ip_address="127.0.0.1" + udpxy_endpoint="http://127.0.0.1:4022" + output_file="playlist.M3U8" + curl_args="" + endpoint="http://eds1.unicomgd.com:8082" + + while [ $# -gt 0 ]; do + case "$1" in + -u | --user) user_id="$2"; shift 2;; + -p | --password) password="$2"; shift 2;; + -d | --device) device_id="$2"; shift 2;; + --ip) ip_address="$2"; shift 2;; + --mac) mac_address="$2"; shift 2;; + --udpxy) udpxy_endpoint="$2"; shift 2;; + -o | --output) output_file="$2"; shift 2;; + --curl) curl_args="$2"; shift 2;; + *) echo "Unknown option: $1"; exit 1;; + esac + done -## -## Execute the main script -## + # Validate user input + if [[ -z "$user_id" ]]; then + fatal "Requires an IPTV user ID with -u or --user" + fi -echo "[-] Authenticate" + if [[ -z "$password" ]]; then + fatal "Requires an IPTV password with -p or --password" + fi -## -## Retreive Authentication URL -## + if [[ -z "$device_id" ]]; then + fatal "Requires a device ID with -d or --device" + fi -response=$(curl --silent $curl_args \ - "$endpoint/EDS/jsp/AuthenticationURL?Action=Login&UserID=$user_id&return_type=1") + if [[ -z "$mac_address" ]]; then + fatal "Requires a device MAC address with --mac" + fi -epgurl=$(echo "$response" | jq -r '.epgurl') -host="${epgurl#*//}" -host="${host%%/*}" + # Retreive Authentication URL + step "Authenticate" -## -## Retreive token -## + response=$(curl --silent $curl_args \ + "$endpoint/EDS/jsp/AuthenticationURL?Action=Login&UserID=$user_id&return_type=1") -response=$(curl --silent $curl_args \ - "http://$host/EPG/oauth/v2/authorize?response_type=EncryToken&client_id=jiulian&userid=$user_id") + epgurl=$(echo "$response" | jq -r '.epgurl') + host="${epgurl#*//}" + host="${host%%/*}" -encry_token=$(echo "$response" | jq -r '.EncryToken') + # Retreive challenge token + response=$(curl --silent $curl_args \ + "http://$host/EPG/oauth/v2/authorize?response_type=EncryToken&client_id=jiulian&userid=$user_id") -## -## Authenticate -## + encry_token=$(echo "$response" | jq -r '.EncryToken') -pass=$(printf "%-024s" "$password" | tr ' ' 0 | xxd -p) + # Authenticate + pass=$(printf "%-024s" "$password" | tr ' ' 0 | xxd -p) -authinfo=( - $(shuf -i 1-99999999 -n 1) $encry_token - $user_id $device_id - $ip_address $mac_address - "Reserved" "OTT" -) + authinfo=( + $(shuf -i 1-99999999 -n 1) $encry_token + $user_id $device_id + $ip_address $mac_address + "Reserved" "OTT" + ) -authinfo=$(IFS='$'; echo "${authinfo[*]}") + authinfo=$(IFS='$'; echo "${authinfo[*]}") -authinfo=$(echo -n $authinfo | \ + authinfo=$(echo -n $authinfo | \ openssl enc -e -des-ede3 -K $pass -nosalt 2>/dev/null | \ xxd -p -u -c 0) -response=$(curl --silent $curl_args \ + response=$(curl --silent $curl_args \ "http://$host/EPG/oauth/v2/token?grant_type=EncryToken&client_id=jiulian&UserID=$user_id&DeviceType=UNT400G&DeviceVersion=5.5.021&authinfo=$authinfo&issmarthomestb=1&tvdesktopid=") -access_token=$(echo "$response" | jq -r '.access_token') - -echo "[-] Request channel metas" + access_token=$(echo "$response" | jq -r '.access_token') -declare -A logos + step "Request channel metas" + declare -A logos -response=$(curl --silent $curl_args \ - http://120.87.12.38:8083/epg/api/custom/getAllChannel.json) + response=$(curl --silent $curl_args \ + http://120.87.12.38:8083/epg/api/custom/getAllChannel.json) -while read -r channel; do - hwcode=$(echo "$channel" | jq -r '.params.hwcode') - icon=$(echo "$channel" | jq -r '.icon') + while read -r channel; do + hwcode=$(echo "$channel" | jq -r '.params.hwcode') + icon=$(echo "$channel" | jq -r '.icon') - logos["$hwcode"]="$icon" -done < <(echo "$response" | jq -c '.channels[]') + logos["$hwcode"]="$icon" + done < <(echo "$response" | jq -c '.channels[]') -echo "[-] Request channels from the batch API" - -response=$(curl --silent $curl_args \ + step "Request channels from the batch API" + response=$(curl --silent $curl_args \ --data '{"channelcodes":""}' \ --header 'Content-Type: application/json;charset=utf-8' \ --header "Authorization: $access_token" \ http://$host/EPG/interEpg/channellist/batch) -echo "[-] Decode channels from the HTTP response" - -echo "#EXTM3U" > $output_file -echo "#EXT-X-VERSION:3" >> $output_file - -echo "$response" | jq -c '.channellist[]' | while read -r channel; do - channelcode=$(echo "$channel" | jq -r '.channelcode') - channelname=$(echo "$channel" | jq -r '.channelname') - channelurl=$(echo "$channel" | jq -r '.channelurl') - IFS='|' read -ra channelurls <<< "$channelurl" - - echo "[-] Process: $channelname" - - pattern="://([^/]+)" - if [[ "${channelurls[0]}" =~ $pattern ]]; then - host=${BASH_REMATCH[1]} - - group="720P" - case "$channelname" in - *"4K"*) - group="4K" - ;; - *"超清"*|*"高清"*) - group="1080P" - ;; - \?) - group="720P" - ;; - esac + step "Decode channels from the HTTP response" + echo "#EXTM3U" > $output_file + echo "#EXT-X-VERSION:3" >> $output_file - echo "#EXTINF:-1 tvg-id=\"$channelcode\" tvg-name=\"$channelname\" tvg-logo=\"${logos[$channelcode]}\" group-name=\"$group\",$channelname" >> $output_file - echo "$udpxy_endpoint/udp/$host" >> $output_file - fi -done + echo "$response" | jq -c '.channellist[]' | while read -r channel; do + channelcode=$(echo "$channel" | jq -r '.channelcode') + channelname=$(echo "$channel" | jq -r '.channelname') + channelurl=$(echo "$channel" | jq -r '.channelurl') + IFS='|' read -ra channelurls <<< "$channelurl" + + step "Process: $channelname" + + pattern="://([^/]+)" + if [[ "${channelurls[0]}" =~ $pattern ]]; then + host=${BASH_REMATCH[1]} -echo "[-] Extract IPTV channels successfully!" + group=$(categorize_by_channel_name "$channelname") + + echo "#EXTINF:-1 tvg-id=\"$channelcode\" tvg-name=\"$channelname\" tvg-logo=\"${logos[$channelcode]}\" group-name=\"$group\",$channelname" >> $output_file + echo "$udpxy_endpoint/udp/$host" >> $output_file + fi + done + + step "Extract IPTV channels successfully!" + + exit 0 +} + +## +## Main +## + +while [ $# -gt 0 ]; do + case "$1" in + make:playlist) shift 1; make_playlist "$@";; + make:epg) shift 1; make_epg "$@";; + *) echo "Unknown command: $1"; exit 1;; + esac +done |
