2014-01-16 20:07:01 -06:00
from __future__ import unicode_literals
2013-06-23 15:31:12 -05:00
from . common import InfoExtractor
2015-10-31 20:08:19 -05:00
from . . compat import compat_urllib_parse
2013-06-23 15:31:12 -05:00
from . . utils import (
2015-11-01 06:38:11 -06:00
ExtractorError ,
2015-10-31 20:08:19 -05:00
int_or_none ,
qualities ,
2013-06-23 15:31:12 -05:00
)
class FlickrIE ( InfoExtractor ) :
2015-10-31 20:08:19 -05:00
_VALID_URL = r ' https?://(?:www \ .|secure \ .)?flickr \ .com/photos/[ \ w \ -_@]+/(?P<id> \ d+) '
2013-06-27 13:46:46 -05:00
_TEST = {
2014-01-16 20:07:01 -06:00
' url ' : ' http://www.flickr.com/photos/forestwander-nature-pictures/5645318632/in/photostream/ ' ,
2015-10-31 20:08:19 -05:00
' md5 ' : ' 164fe3fa6c22e18d448d4d5af2330f31 ' ,
2014-01-16 20:07:01 -06:00
' info_dict ' : {
2014-09-24 03:46:33 -05:00
' id ' : ' 5645318632 ' ,
2015-10-31 20:08:19 -05:00
' ext ' : ' mpg ' ,
' description ' : ' Waterfalls in the Springtime at Dark Hollow Waterfalls. These are located just off of Skyline Drive in Virginia. They are only about 6/10 of a mile hike but it is a pretty steep hill and a good climb back up. ' ,
' title ' : ' Dark Hollow Waterfalls ' ,
' duration ' : 19 ,
' timestamp ' : 1303528740 ,
' upload_date ' : ' 20110423 ' ,
' uploader_id ' : ' 10922353@N03 ' ,
' uploader ' : ' Forest Wander ' ,
' comment_count ' : int ,
2015-12-20 17:20:22 -06:00
' view_count ' : int ,
' tags ' : list ,
2013-06-27 13:46:46 -05:00
}
}
2013-06-23 15:31:12 -05:00
2015-10-31 20:08:19 -05:00
_API_BASE_URL = ' https://api.flickr.com/services/rest? '
2015-04-22 12:24:14 -05:00
2015-11-01 06:23:23 -06:00
def _call_api ( self , method , video_id , api_key , note , secret = None ) :
2015-10-31 20:08:19 -05:00
query = {
' photo_id ' : video_id ,
' method ' : ' flickr. %s ' % method ,
2015-11-01 06:23:23 -06:00
' api_key ' : api_key ,
2015-10-31 20:08:19 -05:00
' format ' : ' json ' ,
' nojsoncallback ' : 1 ,
}
if secret :
query [ ' secret ' ] = secret
2015-11-01 06:38:11 -06:00
data = self . _download_json ( self . _API_BASE_URL + compat_urllib_parse . urlencode ( query ) , video_id , note )
if data [ ' stat ' ] != ' ok ' :
raise ExtractorError ( data [ ' message ' ] )
return data
2013-06-23 15:31:12 -05:00
2015-10-31 20:08:19 -05:00
def _real_extract ( self , url ) :
video_id = self . _match_id ( url )
2013-06-23 15:31:12 -05:00
2015-11-01 06:23:23 -06:00
api_key = self . _download_json ( ' https://www.flickr.com/hermes_error_beacon.gne ' , video_id , ' Downloading api key ' , ) [ ' site_key ' ]
video_info = self . _call_api ( ' photos.getInfo ' , video_id , api_key , ' Downloading video info ' ) [ ' photo ' ]
2015-10-31 20:08:19 -05:00
if video_info [ ' media ' ] == ' video ' :
2015-11-01 06:23:23 -06:00
streams = self . _call_api ( ' video.getStreamInfo ' , video_id , api_key , ' Downloading streams info ' , video_info [ ' secret ' ] ) [ ' streams ' ]
2013-06-23 15:31:12 -05:00
2015-10-31 20:08:19 -05:00
preference = qualities ( [ ' iphone_wifi ' , ' 700 ' , ' appletv ' , ' orig ' ] )
2013-06-23 15:31:12 -05:00
2015-10-31 20:08:19 -05:00
formats = [ ]
for stream in streams [ ' stream ' ] :
stream_type = str ( stream . get ( ' type ' ) )
formats . append ( {
' format_id ' : stream_type ,
' url ' : stream [ ' _content ' ] ,
' preference ' : preference ( stream_type ) ,
} )
self . _sort_formats ( formats )
2013-06-23 15:31:12 -05:00
2015-10-31 20:08:19 -05:00
owner = video_info . get ( ' owner ' , { } )
2013-06-23 15:31:12 -05:00
2015-10-31 20:08:19 -05:00
return {
' id ' : video_id ,
' title ' : video_info [ ' title ' ] [ ' _content ' ] ,
' description ' : video_info . get ( ' description ' , { } ) . get ( ' _content ' ) ,
' formats ' : formats ,
' timestamp ' : int_or_none ( video_info . get ( ' dateuploaded ' ) ) ,
' duration ' : int_or_none ( video_info . get ( ' video ' , { } ) . get ( ' duration ' ) ) ,
' uploader_id ' : owner . get ( ' nsid ' ) ,
' uploader ' : owner . get ( ' realname ' ) ,
' comment_count ' : int_or_none ( video_info . get ( ' comments ' , { } ) . get ( ' _content ' ) ) ,
2015-12-20 17:20:22 -06:00
' view_count ' : int_or_none ( video_info . get ( ' views ' ) ) ,
' tags ' : [ tag . get ( ' _content ' ) for tag in video_info . get ( ' tags ' , { } ) . get ( ' tag ' , [ ] ) ]
2015-10-31 20:08:19 -05:00
}
2015-11-05 11:01:13 -06:00
else :
raise ExtractorError ( ' not a video ' , expected = True )