limontec

afreeca.py

May 7th, 2017
4,031
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.53 KB | None | 0 0
  1. import re
  2.  
  3. from streamlink.plugin import Plugin
  4. from streamlink.plugin import PluginArguments, PluginArgument
  5. from streamlink.plugin.api import validate
  6. from streamlink.stream import HLSStream
  7.  
  8. CHANNEL_API_URL = "http://live.afreecatv.com/afreeca/player_live_api.php"
  9. STREAM_INFO_URLS = "{rmd}/broad_stream_assign.html"
  10.  
  11. CHANNEL_RESULT_ERROR = 0
  12. CHANNEL_RESULT_OK = 1
  13.  
  14. QUALITYS = ["original", "hd", "sd"]
  15.  
  16. QUALITY_WEIGHTS = {
  17.     "original": 1080,
  18.     "hd": 720,
  19.     "sd": 480
  20. }
  21.  
  22. _url_re = re.compile(r"https?://play\.afreecatv\.com/(?P<username>\w+)(?:/\d+)?")
  23.  
  24. _channel_schema = validate.Schema(
  25.     {
  26.         "CHANNEL": {
  27.             "RESULT": validate.transform(int),
  28.             validate.optional("BPWD"): validate.text,
  29.             validate.optional("BNO"): validate.text,
  30.             validate.optional("RMD"): validate.text,
  31.             validate.optional("AID"): validate.text,
  32.             validate.optional("CDN"): validate.text
  33.         }
  34.     },
  35.     validate.get("CHANNEL")
  36. )
  37.  
  38. _stream_schema = validate.Schema(
  39.     {
  40.         validate.optional("view_url"): validate.url(
  41.             scheme=validate.any("rtmp", "http")
  42.         ),
  43.         "stream_status": validate.text
  44.     }
  45. )
  46.  
  47.  
  48. class AfreecaTV(Plugin):
  49.     login_url = "https://member.afreecatv.com:8111/login/LoginAction.php"
  50.  
  51.     arguments = PluginArguments(
  52.         PluginArgument(
  53.             "username",
  54.             requires=["password"],
  55.             metavar="USERNAME",
  56.             help="The username used to register with afreecatv.com."
  57.         ),
  58.         PluginArgument(
  59.             "password",
  60.             sensitive=True,
  61.             metavar="PASSWORD",
  62.             help="A afreecatv.com account password to use with --afreeca-username."
  63.         )
  64.     )
  65.  
  66.     @classmethod
  67.     def can_handle_url(self, url):
  68.         return _url_re.match(url)
  69.  
  70.     @classmethod
  71.     def stream_weight(cls, key):
  72.         weight = QUALITY_WEIGHTS.get(key)
  73.         if weight:
  74.             return weight, "afreeca"
  75.  
  76.         return Plugin.stream_weight(key)
  77.  
  78.     def _get_channel_info(self, username):
  79.         data = {
  80.             "bid": username,
  81.             "mode": "landing",
  82.             "player_type": "html5"
  83.         }
  84.  
  85.         res = self.session.http.post(CHANNEL_API_URL, data=data)
  86.         return self.session.http.json(res, schema=_channel_schema)
  87.  
  88.     def _get_hls_key(self, broadcast, username, quality):
  89.         data = {
  90.             "bid": username,
  91.             "bno": broadcast,
  92.             "pwd": "",
  93.             "quality": quality,
  94.             "type": "pwd"
  95.         }
  96.         res = self.session.http.post(CHANNEL_API_URL, data=data)
  97.         return self.session.http.json(res, schema=_channel_schema)
  98.  
  99.     def _get_stream_info(self, broadcast, quality, cdn, rmd):
  100.         params = {
  101.             "return_type": cdn,
  102.             "broad_key": "{broadcast}-flash-{quality}-hls".format(**locals())
  103.         }
  104.         res = self.session.http.get(STREAM_INFO_URLS.format(rmd=rmd), params=params)
  105.         return self.session.http.json(res, schema=_stream_schema)
  106.  
  107.     def _get_hls_stream(self, broadcast, username, quality, cdn, rmd):
  108.         keyjson = self._get_hls_key(broadcast, username, quality)
  109.  
  110.         if keyjson["RESULT"] != CHANNEL_RESULT_OK:
  111.             return
  112.         key = keyjson["AID"]
  113.  
  114.         info = self._get_stream_info(broadcast, quality, cdn, rmd)
  115.  
  116.         if "view_url" in info:
  117.             return HLSStream(self.session, info["view_url"], params=dict(aid=key))
  118.  
  119.     def _login(self, username, password):
  120.         data = {
  121.             "szWork": "login",
  122.             "szType": "json",
  123.             "szUid": username,
  124.             "szPassword": password,
  125.             "isSaveId": "true",
  126.             "isSavePw": "false",
  127.             "isSaveJoin": "false"
  128.         }
  129.  
  130.         res = self.session.http.post(self.login_url, data=data)
  131.         res = self.session.http.json(res)
  132.         if res["RESULT"] == 1:
  133.             return True
  134.         else:
  135.             return False
  136.  
  137.     def _get_streams(self):
  138.         self.session.http.headers.update({"Referer": self.url})
  139.         if not self.session.get_option("hls-segment-ignore-names"):
  140.             ignore_segment = ["preloading"]
  141.             self.session.set_option("hls-segment-ignore-names", ignore_segment)
  142.  
  143.         login_username = self.get_option("username")
  144.         login_password = self.get_option("password")
  145.         if login_username and login_password:
  146.             self.logger.debug("Attempting login as {0}".format(login_username))
  147.             if self._login(login_username, login_password):
  148.                 self.logger.info("Successfully logged in as {0}".format(login_username))
  149.             else:
  150.                 self.logger.info("Failed to login as {0}".format(login_username))
  151.  
  152.         match = _url_re.match(self.url)
  153.         username = match.group("username")
  154.  
  155.         channel = self._get_channel_info(username)
  156.         if channel.get("BPWD") == "Y":
  157.             self.logger.error("Stream is Password-Protected")
  158.             return
  159.         elif channel.get("RESULT") == -6:
  160.             self.logger.error("Login required")
  161.             return
  162.         elif channel.get("RESULT") != CHANNEL_RESULT_OK:
  163.             return
  164.  
  165.         (broadcast, rmd, cdn) = (channel["BNO"], channel["RMD"], channel["CDN"])
  166.         if not (broadcast and rmd and cdn):
  167.             return
  168.  
  169.         for qkey in QUALITYS:
  170.             hls_stream = self._get_hls_stream(broadcast, username, qkey, cdn, rmd)
  171.             if hls_stream:
  172.                 yield qkey, hls_stream
  173.  
  174.  
  175. __plugin__ = AfreecaTV
Add Comment
Please, Sign In to add comment