import sys import requests import json import datetime from urllib import parse LOGIN_URL = "https://account-api.wavve.com/v0.9/signin/wavve?apikey=E5F3E0D30947AA5440556471321BB6D9&credential=none&device=pc&drm=wm&partner=pooq&pooqzone=none®ion=kor&targetage=all" #LOGIN_URL = "https://apis.wavve.com/login?apikey=E5F3E0D30947AA5440556471321BB6D9&client_version=6.0.1&device=pc&drm=wm&partner=pooq&pooqzone=none®ion=kor&targetage=all" SVC_URL = "https://apis.wavve.com/fz/streaming?device=pc&partner=pooq&apikey=E5F3E0D30947AA5440556471321BB6D9&credential={0}&service=wavve&pooqzone=none®ion=kor&drm=none&targetage=all&contentid={1}&hdr=sdr&videocodec=avc&audiocodec=ac3&issurround=n&format=normal&withinsubtitle=n&contenttype=live&action=hls&protocol=hls&quality=auto&deviceModelId=Windows%2010&guid=1d191e5c-568a-11ed-b37d-92dd5a1cfeb9&lastplayid=46fa3c25a79145d088caebeeebbee4dc&authtype=cookie&isabr=y&ishevc=n" EPG_URL = "https://apis.wavve.com/live/epgs?enddatetime={0}&genre=all&limit=500&offset=0&startdatetime={1}&apikey=E5F3E0D30947AA5440556471321BB6D9&client_version=7.0.40&device=pc&drm=wm&partner=pooq&pooqzone=none®ion=kor&targetage=all" LOGOUT_URL = "https://apis.pooq.co.kr/logout?apikey=E5F3E0D30947AA5440556471321BB6D9&credential={0}&device=pc&drm=wm&partner=pooq&pooqzone=none®ion=kor&targetage=all" #CHDETAIL_URL = "https://apis.pooq.co.kr/live/channels/{0}?device=pc&partner=pooq&pooqzone=none®ion=kor&drm=wm&targetage=all&apikey=E5F3E0D30947AA5440556471321BB6D9&credential=none" CHDETAIL_URL = "https://apis.wavve.com/live/channels/{0}?apikey=E5F3E0D30947AA5440556471321BB6D9&client_version=6.0.1&device=pc&drm=wm&partner=pooq&pooqzone=none®ion=kor&targetage=all" def doLogin(userId,password): try: payloads=json.loads('{{"type": "general","id": "{0}","pushid": "","password":"{1}","profile": "0"}}'.format(userId,password)) response = requests.post(LOGIN_URL, json=payloads) jsonResp = json.loads(response.text) credential=jsonResp.get("credential") payloads = '{{"type": "credential","id": "{0}","pushid": "","password":"","profile": "0"}}'.format(credential) headers = { 'Content-Type':'application/json; charset=UTF-8', 'Wavve-Credential':'{0}'.format(credential) } response = requests.post(LOGIN_URL,data=payloads,headers=headers) jsonResp = json.loads(response.text) if jsonResp.get("needselectprofile") !='n': raise Exception("Unexpected server response.") except Exception as e: print(str(e)) return None else: return credential def doLogout(credential): try: url=LOGOUT_URL.format(parse.quote(credential)) response = requests.options(url) except Exception as e: return False else: return True def getEPG(start,end,credential): headers = { 'Content-Type':'application/json; charset=UTF-8', 'Wavve-Credential':'{0}'.format(credential) } #url=EPG_URL.format(parse.quote(end),parse.quote(start),parse.quote(credential)) url=EPG_URL.format(parse.quote(end),parse.quote(start)) response = requests.get(url,headers=headers) jsonResp = json.loads(response.text) jsonList = jsonResp.get("list") return jsonList def getGenreText(chId): headers = { 'Content-Type':'application/json; charset=UTF-8', 'Wavve-Credential':'{0}'.format(credential) } url=CHDETAIL_URL.format(chId) response = requests.get(url,headers=headers) jsonResp = json.loads(response.text) return jsonResp.get("genretext") def getPlayURL(chId,credential): try: url=SVC_URL.format(parse.quote(credential),chId) response = requests.get(url) jsonResp = json.loads(response.text) playUrl = jsonResp.get("playurl") awsCookie = jsonResp.get("awscookie") awsCookie = jsonResp.get("awscookie").replace(';','&').replace(' ','') except Exception as e: print(str(e)) return None else: return playUrl + '?' + awsCookie finally: pass def createM3U(credential,outpath): try: start=datetime.datetime.today().strftime("%Y-%m-%d %H:%M") end=(datetime.datetime.today() + datetime.timedelta(hours=3)).strftime("%Y-%m-%d %H:%M") channelList = getEPG(start,end,credential) file = open(outpath,'w', encoding='utf8') file.write("#EXTM3U8\n") chNum=0 for channel in channelList: chId = channel["channelid"] playUrl = getPlayURL(chId,credential) if playUrl != None: chName = channel["channelname"] iconUrl = channel["channelimage"] if ( "http" in channel["channelimage"]) else "https://" + channel["channelimage"] groupTitle = getGenreText(chId) file.write('#EXTINF:-1 tvg-id="{0}" tvg-logo="{1}" group-title="{2}" tvg-chno="{3}",{4}\n'.format(chId, iconUrl, groupTitle,chNum, chName)) file.write(playUrl + "\n") chNum = chNum + 1 except Exception as e: print(str(e)) return False else: return True finally: if not file.closed: file.close() def xmlesc(txt): try: txt = txt.replace("&", "&") txt = txt.replace("<", "<") txt = txt.replace(">", ">") txt = txt.replace('"', """) txt = txt.replace("'", "'") except: return "" else: return txt finally: pass def createEPG(credential,outpath): try: start=datetime.datetime.today().strftime("%Y-%m-%d %H:%M") end=(datetime.datetime.today() + datetime.timedelta(hours=3)).strftime("%Y-%m-%d %H:%M") print ("START:",start, "END:",end) channelList = getEPG(start,end,credential) file = open(outpath,'w', encoding='utf8') file.write('\n') file.write('\n') file.write('\n') cn=0 for channel in channelList: chId = channel["channelid"] chName = xmlesc(channel["channelname"]) file.write(' \n'.format(chId)) file.write(' {0}\n'.format(chName)) file.write(' {0}\n'.format("WAVVE")) file.write(' {0}\n'.format(cn)) file.write(' {0} {1}\n'.format(cn, chName)) file.write(' {0} {1}\n'.format(cn, "WAVVE")) chImgUrl = channel["channelimage"] if ("http" in channel["channelimage"]) else "https://" + channel["channelimage"] file.write(' \n'.format(chImgUrl)) file.write(' \n') cn = cn + 1 for channel in channelList: chId = channel["channelid"] pgmList=channel["list"] for pgm in pgmList: sTitle = parse.unquote(pgm["title"]) dtStart = datetime.datetime.strptime(pgm["starttime"], '%Y-%m-%d %H:%M') dtEnd = datetime.datetime.strptime(pgm["endtime"], '%Y-%m-%d %H:%M') sStart = dtStart.strftime("%Y%m%d%H%M%S") sEnd = dtEnd.strftime("%Y%m%d%H%M%S") try: targetAge = int(pgm["targetage"]) except ValueError: targetAge = 0 if targetAge == 0 : sTargetAge ="all" else: sTargetAge ="{0}over age".format(targetAge) file.write(' \n') file.write(' ' + xmlesc(sTitle) + '\n') file.write(' ' + xmlesc(sTitle) + '\n' + sTargetAge + '\n') file.write(' \n') file.write(' {0}\n'.format(sTargetAge)) file.write(' \n') file.write(' \n') file.write('') except Exception as e: print(str(e)) return False else: return True finally: file.close if __name__ == '__main__': if len(sys.argv) < 5 : print('USAGE\n python {0} userId password EPG|M3U "outPath" \n'.format(sys.argv[0])) else: userId = sys.argv[1] password = sys.argv[2] target = sys.argv[3].lower() outPath = sys.argv[4] credential = doLogin(userId,password) if credential != None : if target == 'epg': if createEPG(credential,outPath): print('EPG created!\n') else: print('EPG creation failed!\n') elif 'm3u': if createM3U(credential,outPath): print('M3U created!\n') else: print('M3U creation failed!\n') else: print("Invalid argument - " + target) doLogout(credential) else : print('Login failed! please check userid/password and try again!')