3 from __future__ 
import unicode_literals
 
   8 from .common 
import InfoExtractor
 
  11     compat_urllib_parse_unquote
, 
  12     compat_urllib_parse_urlencode
, 
  23 class DaumIE(InfoExtractor
): 
  24     _VALID_URL 
= r
'https?://(?:(?:m\.)?tvpot\.daum\.net/v/|videofarm\.daum\.net/controller/player/VodPlayer\.swf\?vid=)(?P<id>[^?#&]+)' 
  28         'url': 'http://tvpot.daum.net/v/vab4dyeDBysyBssyukBUjBz', 
  30             'id': 'vab4dyeDBysyBssyukBUjBz', 
  32             'title': '마크 헌트 vs 안토니오 실바', 
  33             'description': 'Mark Hunt vs Antonio Silva', 
  34             'upload_date': '20131217', 
  35             'thumbnail': 're:^https?://.*\.(?:jpg|png)', 
  41         'url': 'http://m.tvpot.daum.net/v/65139429', 
  45             'title': '1297회, \'아빠 아들로 태어나길 잘 했어\' 민수, 감동의 눈물[아빠 어디가] 20150118', 
  46             'description': 'md5:79794514261164ff27e36a21ad229fc5', 
  47             'upload_date': '20150604', 
  48             'thumbnail': 're:^https?://.*\.(?:jpg|png)', 
  54         'url': 'http://tvpot.daum.net/v/07dXWRka62Y%24', 
  55         'only_matching': True, 
  57         'url': 'http://videofarm.daum.net/controller/player/VodPlayer.swf?vid=vwIpVpCQsT8%24&ref=', 
  61             'title': '01-Korean War ( Trouble on the horizon )', 
  62             'description': '\nKorean War 01\nTrouble on the horizon\n전쟁의 먹구름', 
  63             'upload_date': '20080223', 
  64             'thumbnail': 're:^https?://.*\.(?:jpg|png)', 
  70         # Requires dte_type=WEB (#9972) 
  71         'url': 'http://tvpot.daum.net/v/s3794Uf1NZeZ1qMpGpeqeRU', 
  72         'md5': 'a8917742069a4dd442516b86e7d66529', 
  74             'id': 's3794Uf1NZeZ1qMpGpeqeRU', 
  76             'title': '러블리즈 - Destiny (나의 지구) (Lovelyz - Destiny) [쇼! 음악중심] 508회 20160611', 
  77             'description': '러블리즈 - Destiny (나의 지구) (Lovelyz - Destiny)\n\n[쇼! 음악중심] 20160611, 507회', 
  78             'upload_date': '20160611', 
  82     def _real_extract(self
, url
): 
  83         video_id 
= compat_urllib_parse_unquote(self
._match
_id
(url
)) 
  84         movie_data 
= self
._download
_json
( 
  85             'http://videofarm.daum.net/controller/api/closed/v1_2/IntegratedMovieData.json', 
  86             video_id
, 'Downloading video formats info', query
={'vid': video_id
, 'dte_type': 'WEB'}) 
  88         # For urls like http://m.tvpot.daum.net/v/65139429, where the video_id is really a clipid 
  89         if not movie_data
.get('output_list', {}).get('output_list') and re
.match(r
'^\d+$', video_id
): 
  90             return self
.url_result('http://tvpot.daum.net/clip/ClipView.do?clipid=%s' % video_id
) 
  92         info 
= self
._download
_xml
( 
  93             'http://tvpot.daum.net/clip/ClipInfoXml.do', video_id
, 
  94             'Downloading video info', query
={'vid': video_id
}) 
  97         for format_el 
in movie_data
['output_list']['output_list']: 
  98             profile 
= format_el
['profile'] 
  99             format_query 
= compat_urllib_parse_urlencode({ 
 103             url_doc 
= self
._download
_xml
( 
 104                 'http://videofarm.daum.net/controller/api/open/v1_2/MovieLocation.apixml?' + format_query
, 
 105                 video_id
, note
='Downloading video data for %s format' % profile
) 
 106             format_url 
= url_doc
.find('result/url').text
 
 109                 'format_id': profile
, 
 110                 'width': int_or_none(format_el
.get('width')), 
 111                 'height': int_or_none(format_el
.get('height')), 
 112                 'filesize': int_or_none(format_el
.get('filesize')), 
 114         self
._sort
_formats
(formats
) 
 118             'title': info
.find('TITLE').text
, 
 120             'thumbnail': xpath_text(info
, 'THUMB_URL'), 
 121             'description': xpath_text(info
, 'CONTENTS'), 
 122             'duration': int_or_none(xpath_text(info
, 'DURATION')), 
 123             'upload_date': info
.find('REGDTTM').text
[:8], 
 124             'view_count': str_to_int(xpath_text(info
, 'PLAY_CNT')), 
 125             'comment_count': str_to_int(xpath_text(info
, 'COMMENT_CNT')), 
 129 class DaumClipIE(InfoExtractor
): 
 130     _VALID_URL 
= r
'https?://(?:m\.)?tvpot\.daum\.net/(?:clip/ClipView.(?:do|tv)|mypot/View.do)\?.*?clipid=(?P<id>\d+)' 
 131     IE_NAME 
= 'daum.net:clip' 
 132     _URL_TEMPLATE 
= 'http://tvpot.daum.net/clip/ClipView.do?clipid=%s' 
 135         'url': 'http://tvpot.daum.net/clip/ClipView.do?clipid=52554690', 
 139             'title': 'DOTA 2GETHER 시즌2 6회 - 2부', 
 140             'description': 'DOTA 2GETHER 시즌2 6회 - 2부', 
 141             'upload_date': '20130831', 
 142             'thumbnail': 're:^https?://.*\.(?:jpg|png)', 
 147         'url': 'http://m.tvpot.daum.net/clip/ClipView.tv?clipid=54999425', 
 148         'only_matching': True, 
 152     def suitable(cls
, url
): 
 153         return False if DaumPlaylistIE
.suitable(url
) or DaumUserIE
.suitable(url
) else super(DaumClipIE
, cls
).suitable(url
) 
 155     def _real_extract(self
, url
): 
 156         video_id 
= self
._match
_id
(url
) 
 157         clip_info 
= self
._download
_json
( 
 158             'http://tvpot.daum.net/mypot/json/GetClipInfo.do?clipid=%s' % video_id
, 
 159             video_id
, 'Downloading clip info')['clip_bean'] 
 162             '_type': 'url_transparent', 
 164             'url': 'http://tvpot.daum.net/v/%s' % clip_info
['vid'], 
 165             'title': unescapeHTML(clip_info
['title']), 
 166             'thumbnail': clip_info
.get('thumb_url'), 
 167             'description': clip_info
.get('contents'), 
 168             'duration': int_or_none(clip_info
.get('duration')), 
 169             'upload_date': clip_info
.get('up_date')[:8], 
 170             'view_count': int_or_none(clip_info
.get('play_count')), 
 175 class DaumListIE(InfoExtractor
): 
 176     def _get_entries(self
, list_id
, list_id_type
): 
 179         for pagenum 
in itertools
.count(1): 
 180             list_info 
= self
._download
_json
( 
 181                 'http://tvpot.daum.net/mypot/json/GetClipInfo.do?size=48&init=true&order=date&page=%d&%s=%s' % ( 
 182                     pagenum
, list_id_type
, list_id
), list_id
, 'Downloading list info - %s' % pagenum
) 
 186                     'http://tvpot.daum.net/v/%s' % clip
['vid']) 
 187                 for clip 
in list_info
['clip_list'] 
 191                 name 
= list_info
.get('playlist_bean', {}).get('name') or \
 
 192                     list_info
.get('potInfo', {}).get('name') 
 194             if not list_info
.get('has_more'): 
 199     def _check_clip(self
, url
, list_id
): 
 200         query_dict 
= compat_parse_qs(compat_urlparse
.urlparse(url
).query
) 
 201         if 'clipid' in query_dict
: 
 202             clip_id 
= query_dict
['clipid'][0] 
 203             if self
._downloader
.params
.get('noplaylist'): 
 204                 self
.to_screen('Downloading just video %s because of --no-playlist' % clip_id
) 
 205                 return self
.url_result(DaumClipIE
._URL
_TEMPLATE 
% clip_id
, 'DaumClip') 
 207                 self
.to_screen('Downloading playlist %s - add --no-playlist to just download video' % list_id
) 
 210 class DaumPlaylistIE(DaumListIE
): 
 211     _VALID_URL 
= r
'https?://(?:m\.)?tvpot\.daum\.net/mypot/(?:View\.do|Top\.tv)\?.*?playlistid=(?P<id>[0-9]+)' 
 212     IE_NAME 
= 'daum.net:playlist' 
 213     _URL_TEMPLATE 
= 'http://tvpot.daum.net/mypot/View.do?playlistid=%s' 
 216         'note': 'Playlist url with clipid', 
 217         'url': 'http://tvpot.daum.net/mypot/View.do?playlistid=6213966&clipid=73806844', 
 220             'title': 'Woorissica Official', 
 222         'playlist_mincount': 181 
 224         'note': 'Playlist url with clipid - noplaylist', 
 225         'url': 'http://tvpot.daum.net/mypot/View.do?playlistid=6213966&clipid=73806844', 
 229             'title': '151017 Airport', 
 230             'upload_date': '20160117', 
 234             'skip_download': True, 
 239     def suitable(cls
, url
): 
 240         return False if DaumUserIE
.suitable(url
) else super(DaumPlaylistIE
, cls
).suitable(url
) 
 242     def _real_extract(self
, url
): 
 243         list_id 
= self
._match
_id
(url
) 
 245         clip_result 
= self
._check
_clip
(url
, list_id
) 
 249         name
, entries 
= self
._get
_entries
(list_id
, 'playlistid') 
 251         return self
.playlist_result(entries
, list_id
, name
) 
 254 class DaumUserIE(DaumListIE
): 
 255     _VALID_URL 
= r
'https?://(?:m\.)?tvpot\.daum\.net/mypot/(?:View|Top)\.(?:do|tv)\?.*?ownerid=(?P<id>[0-9a-zA-Z]+)' 
 256     IE_NAME 
= 'daum.net:user' 
 259         'url': 'http://tvpot.daum.net/mypot/View.do?ownerid=o2scDLIVbHc0', 
 261             'id': 'o2scDLIVbHc0', 
 262             'title': '마이 리틀 텔레비전', 
 264         'playlist_mincount': 213 
 266         'url': 'http://tvpot.daum.net/mypot/View.do?ownerid=o2scDLIVbHc0&clipid=73801156', 
 270             'title': '[미공개] 김구라, 오만석이 부릅니다 \'오케피\' - 마이 리틀 텔레비전 20160116', 
 271             'upload_date': '20160117', 
 272             'description': 'md5:5e91d2d6747f53575badd24bd62b9f36' 
 276             'skip_download': True, 
 279         'note': 'Playlist url has ownerid and playlistid, playlistid takes precedence', 
 280         'url': 'http://tvpot.daum.net/mypot/View.do?ownerid=o2scDLIVbHc0&playlistid=6196631', 
 283             'title': '마이 리틀 텔레비전 - 20160109', 
 287         'url': 'http://tvpot.daum.net/mypot/Top.do?ownerid=o2scDLIVbHc0', 
 288         'only_matching': True, 
 290         'url': 'http://m.tvpot.daum.net/mypot/Top.tv?ownerid=45x1okb1If50&playlistid=3569733', 
 291         'only_matching': True, 
 294     def _real_extract(self
, url
): 
 295         list_id 
= self
._match
_id
(url
) 
 297         clip_result 
= self
._check
_clip
(url
, list_id
) 
 301         query_dict 
= compat_parse_qs(compat_urlparse
.urlparse(url
).query
) 
 302         if 'playlistid' in query_dict
: 
 303             playlist_id 
= query_dict
['playlistid'][0] 
 304             return self
.url_result(DaumPlaylistIE
._URL
_TEMPLATE 
% playlist_id
, 'DaumPlaylist') 
 306         name
, entries 
= self
._get
_entries
(list_id
, 'ownerid') 
 308         return self
.playlist_result(entries
, list_id
, name
)