31 __title__ =
"vimeo_api - Simple-to-use Python interface to the vimeo API (http://vimeo.com)"
32 __author__=
"Marc Poulhiès and modified by R.D. Vaughan"
34 This python script is intended to perform a variety of utility functions to search and access text
35 metadata and video/image URLs from vimeo. These routines are based on the v2 api. Specifications
36 for this api are published at http://vimeo.com/api/docs/advanced-api
55 Python module to interact with Vimeo through its API (version 2)
57 import os, struct, sys, re, time, datetime
58 import urllib.request, urllib.parse, urllib.error, urllib.request, urllib.error, urllib.parse
61 import xml.etree.ElementTree
as ET
63 from .oauth
import oauth_api
as oauth
64 from MythTV
import MythXML
66 from .vimeo_exceptions
import (VimeoUrlError, VimeoHttpError, VimeoResponseError, VimeoVideoNotFound, VimeoRequestTokenError, VimeoAuthorizeTokenError, VimeoVideosSearchError, VimeoAllChannelError, __errmsgs__)
68 from .vimeo_data
import getData
73 REQUEST_TOKEN_URL =
'http://vimeo.com/oauth/request_token'
74 ACCESS_TOKEN_URL =
'http://vimeo.com/oauth/access_token'
75 AUTHORIZATION_URL =
'http://vimeo.com/oauth/authorize'
77 API_REST_URL =
'http://vimeo.com/api/rest/v2/'
78 API_V2_CALL_URL =
'http://vimeo.com/api/v2/'
80 USER_AGENT =
'python-vimeo http://github.com/dkm/python-vimeo'
84 HMAC_SHA1 = oauth.OAuthSignatureMethod_HMAC_SHA1()
89 Exception.__init__(self)
97 Exception.__init__(self)
103 return "Error code: %s, message: %s\nFull message: %s" % (self.
code,
110 A CurlyRequest object is used to send HTTP requests.
111 It's a simple wrapper around basic curl methods.
112 In particular, it can upload files and display a progress bar.
122 Send a simple GET request and interpret the answer as a REST reply.
127 t = ET.fromstring(res)
129 if t.attrib[
'stat'] ==
'fail':
130 err_code = t.find(
'err').attrib[
'code']
131 err_msg = t.find(
'err').attrib[
'msg']
132 raise Exception(err_code, err_msg, ET.tostring(t))
134 except Exception
as e:
135 raise Exception(
'%s' % (e))
142 Send a simple GET request
145 print(
"Request URL:")
151 curl.setopt(pycurl.USERAGENT, USER_AGENT)
152 curl.setopt(curl.URL, url)
160 print(
"Raw response:")
171 self.
pidx = (self.
pidx + 1) % len(TURNING_BAR)
173 done = int(self.
pbar_size * upload_d / upload_t)
176 pstr =
'#'*done +
'>' +
' '*(self.
pbar_size - done - 1)
180 print(
"\r%s[%s] " %(TURNING_BAR[self.
pidx], pstr), end=
' ')
185 Send a simple POST request
190 c.setopt(c.HTTPPOST, args)
191 c.setopt(c.WRITEFUNCTION, self.body_callback)
195 c.setopt(c.NOPROGRESS, 0)
208 Class used for handling authenticated call to the API.
212 server="vimeo.com", port=PORT,
213 request_token_url=REQUEST_TOKEN_URL,
214 access_token_url=ACCESS_TOKEN_URL,
215 authorization_url=AUTHORIZATION_URL,
219 You need to give both key (consumer key) and secret (consumer secret).
220 If you already have an access token (token+secret), you can use it
221 by giving it through token and token_secret parameters.
222 If not, then you need to call both get_request_token(), get_authorize_token_url() and
223 finally get_access_token().
236 if token
is not None and token_secret
is not None:
237 self.
token = oauth.OAuthToken(token, token_secret)
243 Requests a request token and return it on success.
245 oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.
consumer,
248 oauth_request.sign_request(HMAC_SHA1, self.
consumer,
None)
254 Returns a URL used to verify and authorize the application to access
255 user's account. The pointed page should contain a simple 'password' that
256 acts as the 'verifier' in oauth.
259 oauth_request = oauth.OAuthRequest.from_token_and_callback(token=self.
token,
261 return oauth_request.to_url()
266 Should be called after having received the 'verifier' from the authorization page.
267 See 'get_authorize_token_url()' method.
270 self.
token.set_verifier(verifier)
271 oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.
consumer,
275 oauth_request.sign_request(HMAC_SHA1, self.
consumer, self.
token)
280 Sends a requests and interprets the result as a token string.
282 ans = self.
curly.do_request(oauth_request.to_url())
283 return oauth.OAuthToken.from_string(ans)
291 Wrapper to send an authenticated call to vimeo. You first need to have
295 parameters[
'method'] = method
296 oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer,
299 http_url=API_REST_URL,
300 parameters=parameters)
301 oauth_request.sign_request(HMAC_SHA1, self.consumer, self.token)
302 return self.curly.do_rest_call(oauth_request.to_url())
306 Wrapper to send an unauthenticated call to vimeo. You don't need to have
309 parameters[
'method'] = method
310 oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.
consumer,
312 http_url=API_REST_URL,
313 parameters=parameters)
314 oauth_request.sign_request(HMAC_SHA1, self.
consumer,
None)
315 return self.
curly.do_rest_call(oauth_request.to_url())
324 Get a list of a user's albums.
325 This method does not require authentication.
327 params = {
'user_id': user_id}
328 if sort
in (
'newest',
'oldest',
'alphabetical'):
329 params[
'sort'] = sort
330 if per_page
is not None:
331 params[
'per_page'] = per_page
333 params[
'page'] = page
344 Search for matching Videos.
345 This method does not require authentication.
348 if sort
in (
'newest',
'most_played',
'relevant',
'most_liked',
'oldest'):
349 params[
'sort'] = sort
351 params[
'sort'] =
'most_liked'
352 if per_page
is not None:
353 params[
'per_page'] = per_page
355 params[
'page'] = page
356 params[
'full_response'] =
'1'
358 params[
'query'] = query
369 Get a list of all public channels.
370 This method does not require authentication.
373 if sort
in (
'newest',
'oldest',
'alphabetical',
374 'most_videos',
'most_subscribed',
'most_recently_updated'):
375 params[
'sort'] = sort
376 if per_page
is not None:
377 params[
'per_page'] = per_page
379 params[
'page'] = page
388 Get a list of Videos for a specific channels.
389 This method does not require authentication.
393 if channel_id
is not None:
394 params[
'channel_id'] = channel_id
395 if full_response
is not None:
396 params[
'full_response'] = 1
397 if per_page
is not None:
398 params[
'per_page'] = per_page
400 params[
'page'] = page
436 This will just repeat back any parameters that you send.
448 Is the user logged in?
455 This is just a simple null/ping test.
457 You can use this method to make sure that you are properly
458 contacting to the Vimeo API.
482 (from vimeo API documentation)
483 Get the space and number of HD uploads left for a user.
485 Numbers are provided in bytes. It's a good idea to check this
486 method before you upload a video to let the user know if their
487 video will be converted to HD. hd_quota will have a value of 0
488 if the user reached the max number of uploads, 1
489 otherwise. Resets is the number of the day of the week,
490 starting with Sunday.
499 raise VimeoException(
"Sorry, only 'xml' supported. '%s' was requested." %format)
503 ans = curly.do_request(url)
506 return ET.fromstring(ans)
514 url = API_V2_CALL_URL +
'%s/%s.%%s' %(user,info)
519 User info for the specified user
521 return _user_request(user, inspect.stack()[0][3][5:], format)
526 Videos created by user
528 return _user_request(user, inspect.stack()[0][3][5:], format)
532 Videos the user likes
534 return _user_request(user, inspect.stack()[0][3][5:], format)
538 Videos that the user appears in
540 return _user_request(user, inspect.stack()[0][3][5:], format)
544 Videos that the user appears in and created
546 return _user_request(user, inspect.stack()[0][3][5:], format)
550 Videos the user is subscribed to
552 return _user_request(user, inspect.stack()[0][3][5:], format)
556 Albums the user has created
558 return _user_request(user, inspect.stack()[0][3][5:], format)
562 Channels the user has created and subscribed to
564 return _user_request(user, inspect.stack()[0][3][5:], format)
568 Groups the user has created and joined
570 return _user_request(user, inspect.stack()[0][3][5:], format)
574 Videos that the user's contacts created
576 return _user_request(user, inspect.stack()[0][3][5:], format)
580 Videos that the user's contacts like
582 return _user_request(user, inspect.stack()[0][3][5:], format)
589 url = API_V2_CALL_URL +
'video/%s.%%s' %(video)
597 """Wraps a stream with an encoder"""
606 """Wraps the output stream, encoding Unicode strings with the specified encoding"""
607 if isinstance(obj, str):
609 self.
out.buffer.write(obj)
612 """Delegate everything but write to the stream"""
613 return getattr(self.
out, attr)
615 if isinstance(sys.stdout, io.TextIOWrapper):
621 """Main interface to http://vimeo.com/
622 This is done to support a common naming framework for all python Netvision plugins no matter their site
625 Supports search and tree view methods
626 The apikey is a not passed but is created as a session token to access http://vimeo.com/
632 select_first = False,
636 search_all_languages = False,
638 """apikey (str/unicode):
639 Specify the target site API key. Applications need their own key in some cases
642 When True, the returned meta data is being returned has the key and values massaged to match MythTV
643 When False, the returned meta data is being returned matches what target site returned
645 interactive (True/False): (This option is not supported by all target site apis)
646 When True, uses built-in console UI is used to select the correct show.
647 When False, the first search result is used.
649 select_first (True/False): (This option is not supported currently implemented in any grabbers)
650 Automatically selects the first series search result (rather
651 than showing the user a list of more than one series).
652 Is overridden by interactive = False, or specifying a custom_ui
655 shows verbose debugging information
657 custom_ui (xx_ui.BaseUI subclass): (This option is not supported currently implemented in any grabbers)
658 A callable subclass of interactive class (overrides interactive option)
660 language (2 character language abbreviation): (This option is not supported by all target site apis)
661 The language of the returned data. Is also the language search
662 uses. Default is "en" (English). For full list, run..
664 search_all_languages (True/False): (This option is not supported by all target site apis)
665 By default, a Netvision grabber will only search in the language specified using
666 the language option. When this is True, it will search for the
673 self.
config[
'debug_enabled'] = debug
678 self.
config[
'custom_ui'] = custom_ui
682 self.
config[
'select_first'] = select_first
684 self.
config[
'search_all_languages'] = search_all_languages
687 self.
config[
'language'] =
"en"
689 self.
error_messages = {
'VimeoUrlError':
"! Error: The URL (%s) cause the exception error (%s)\n",
'VimeoHttpError':
"! Error: An HTTP communications error with vimeo.com was raised (%s)\n",
'VimeoResponseError':
"! Error: Invalid XML metadata\nwas received from vimeo.com error (%s). Skipping item.\n",
'VimeoVideoNotFound':
"! Error: Video search with vimeo.com did not return any results for (%s)\n",
'VimeoRequestTokenError':
"! Error: Vimeo get request token failed (%s)\n",
'VimeoAuthorizeTokenError':
"! Error: Video get authorise token failed (%s)\n",
'VimeoVideosSearchError':
"! Error: Video search failed (%s)\n",
'VimeoException':
"! Error: VimeoException (%s)\n",
'VimeoAllChannelError':
"! Error: Access Video Channel information failed (%s)\n", }
692 self.
key_translation = [{
'channel_title':
'channel_title',
'channel_link':
'channel_link',
'channel_description':
'channel_description',
'channel_numresults':
'channel_numresults',
'channel_returned':
'channel_returned',
'channel_startindex':
'channel_startindex'}, {
'title':
'item_title',
'display_name':
'item_author',
'upload_date':
'item_pubdate',
'description':
'item_description',
'url':
'item_link',
'thumbnail':
'item_thumbnail',
'url':
'item_url',
'duration':
'item_duration',
'number_of_likes':
'item_rating',
'width':
'item_width',
'height':
'item_height',
'language':
'item_lang'}]
696 self.
config[
'methods'] = {}
698 self.
config[
'methods'][
'channels'] =
None
699 self.
config[
'methods'][
'channels_videos'] =
None
702 self.
config[
'item_parser'] = {}
706 self.
config[
'methods'][
'tree.view'] = {
708 '__all__': [
'channels_videos',
'channels'],
711 '__all__': [
'channels_videos',
'channels'],
715 self.
config[
'image_extentions'] = [
"png",
"jpg",
"bmp"]
717 self.
tree_key_list = [
'newest',
'most_recently_updated',
'most_subscribed']
719 self.
tree_order = [
'N_R_S',
'Everything HD', ]
723 [
'Newest Channels/Most ...',
''],
728 [
'Everything HD: Newest Channels/Most ...', self.
tree_key_list ]
744 'N_R_S': {
'newest':
'Most Recent Channels',
'most_recently_updated':
"This Month's Channels'",
'most_subscribed':
'Most Subscribed Channels',
746 'Everything HD': {
'newest':
'Most Recent Channels',
'most_recently_updated':
"This Month's Channels'",
'most_subscribed':
'Most Subscribed Channels',
752 'N_R_S': {
'newest':
'directories/topics/most_recent',
'most_recently_updated':
'directories/topics/month',
'most_subscribed':
'directories/topics/most_subscribed',
754 'Everything HD': {
'newest':
'directories/topics/most_recent',
'most_recently_updated':
'directories/topics/month',
'most_subscribed':
'directories/topics/most_subscribed',
'Everything HD':
'directories/topics/hd'
761 self.
channel_icon =
'%SHAREDIR%/mythnetvision/icons/vimeo.jpg'
771 '''Removes HTML markup from a text string.
772 @param text The HTML source.
773 @return The plain text. If the HTML source contains non-ASCII
774 entities or character references, this is a Unicode string.
782 if text[:3] ==
"&#x":
783 return chr(int(text[3:-1], 16))
785 return chr(int(text[2:-1]))
788 elif text[:1] ==
"&":
790 entity = html.entities.entitydefs.get(text[1:-1])
792 if entity[:2] ==
"&#":
794 return chr(int(entity[2:-1]))
798 return str(entity,
"iso-8859-1")
800 return self.
ampReplace(re.sub(
r"(?s)<[^>]*>|&#?\w+;", fixup, self.
textUtf8(text))).replace(
'\n',
' ')
805 """Setups a logger using the logging module, returns a log object
807 logger = logging.getLogger(self.
log_name)
808 formatter = logging.Formatter(
'%(asctime)s) %(levelname)s %(message)s')
810 hdlr = logging.StreamHandler(sys.stdout)
812 hdlr.setFormatter(formatter)
813 logger.addHandler(hdlr)
815 if self.
config[
'debug_enabled']:
816 logger.setLevel(logging.DEBUG)
818 logger.setLevel(logging.WARNING)
827 return str(text,
'utf8')
828 except UnicodeDecodeError:
830 except (UnicodeEncodeError, TypeError):
836 '''Replace all "&" characters with "&"
839 return text.replace(
'&',
'~~~~~').replace(
'&',
'&').replace(
'~~~~~',
'&')
844 '''Check if there is a specific generic tree view icon. If not default to the channel icon.
845 return self.tree_dir_icon
856 self.
tree_dir_icon =
'%%SHAREDIR%%/mythnetvision/icons/%s.png' % (dir_icon, )
867 '''Initialize acccess methods for all Vimeo API calls
868 raise errors if there are issues during the initalization steps
873 if self.
config[
'debug_enabled']:
874 self.
client.curly.debug =
True
876 self.
client.get_request_token()
877 except Exception
as msg:
880 self.
client.get_authorize_token_url()
881 except Exception
as msg:
884 self.
config[
'methods'][
'channels'] = self.
client.vimeo_channels_getAll
885 self.
config[
'methods'][
'channels_videos'] = self.
client.vimeo_channels_getVideos
890 playerUrl = self.
mythxml.getInternetContentUrl(
"nv_python_libs/configs/HTML/vimeo.html", \
891 url.replace(
'http://vimeo.com/',
''))
895 '''Key word video search of the vimeo.com web site
896 return an array of matching item dictionaries
908 xml_data = self.
client.vimeo_videos_search(urllib.parse.quote_plus(title.encode(
"utf-8")),
912 except Exception
as msg:
918 if not len(list(xml_data.keys())):
921 if xml_data.tag ==
'rsp':
922 if not xml_data.get(
'stat') ==
'ok':
923 if xml_data.get(
'stat')
in __errmsgs__:
924 errmsg = __errmsg__[xml_data.get(
'stat')]
927 errmsg =
'Unknown error'
931 videos = xml_data.find(
"videos")
933 if videos.get(
'total'):
934 if not int(videos.get(
'total')):
936 self.
channel[
'channel_numresults'] = int(videos.get(
'total'))
939 for video
in xml_data.find(
"videos").getchildren():
942 if video.tag ==
'video':
943 if video.get(
'embed_privacy') ==
"anywhere":
945 if video.get(
'is_hd') ==
"1":
948 for details
in video.getchildren():
949 if details.tag
in [
'tags',
'cast']:
951 if details.tag ==
'width':
953 v_details[
'width'] = details.text.strip()
955 if details.tag ==
'height':
957 v_details[
'height'] = details.text.strip()
959 if details.tag ==
'duration':
961 v_details[
'duration'] = details.text.strip()
963 if details.tag ==
'owner':
965 v_details[
'display_name'] = self.
massageDescription(details.get(
'display_name').strip())
967 v_details[
'display_name'] =
''
969 if details.tag ==
'description':
973 v_details[details.tag] =
''
975 if details.tag ==
'upload_date':
977 pub_time = time.strptime(details.text.strip(),
"%Y-%m-%d %H:%M:%S")
978 v_details[details.tag] = time.strftime(
'%a, %d %b %Y %H:%M:%S GMT', pub_time)
980 v_details[details.tag] =
''
982 if details.tag ==
'urls':
983 for url
in details.getchildren():
984 if url.get(
'type') ==
'video':
989 v_details[url.tag] = self.
ampReplace(url.text.strip())
991 v_details[url.tag] =
''
993 if details.tag ==
'thumbnails':
995 for image
in details.getchildren():
996 if image.tag ==
'thumbnail':
997 height = int(image.get(
'height'))
998 width = int(image.get(
'width'))
999 default = image.text.find(
'default')
1000 if largest < height * width
and not default != -1:
1002 v_details[image.tag] = self.
ampReplace(image.text.strip())
1009 v_details[details.tag] =
''
1010 if hd_flag
and 'width' not in v_details:
1011 v_details[
'width'] = 1280
1012 v_details[
'height'] = 720
1013 elements_final.append(v_details)
1015 if not len(elements_final):
1018 return elements_final
1023 """Common name for a video search. Used to interface with MythTV plugin NetVision
1026 self.
channel = {
'channel_title':
'Vimeo',
'channel_link':
'http://vimeo.com',
'channel_description':
"Vimeo is a respectful community of creative people who are passionate about sharing the videos they make.",
'channel_numresults': 0,
'channel_returned': 1,
'channel_startindex': 0}
1034 data = self.
searchTitle(title, pagenumber, self.page_limit)
1035 except VimeoVideoNotFound
as msg:
1036 sys.stderr.write(
'%s' % msg)
1038 except VimeoUrlError
as msg:
1041 except VimeoHttpError
as msg:
1044 except VimeoResponseError
as msg:
1045 sys.stderr.write(self.
error_messages[
'VimeoResponseError'] % msg)
1047 except VimeoAuthorizeTokenError
as msg:
1048 sys.stderr.write(self.
error_messages[
'VimeoAuthorizeTokenError'] % msg)
1050 except VimeoVideosSearchError
as msg:
1051 sys.stderr.write(self.
error_messages[
'VimeoVideosSearchError'] % msg)
1053 except VimeoRequestTokenError
as msg:
1054 sys.stderr.write(self.
error_messages[
'VimeoRequestTokenError'] % msg)
1056 except VimeoException
as msg:
1059 except Exception
as e:
1060 sys.stderr.write(
"! Error: Unknown error during a Video search (%s)\nError(%s)\n" % (title, e))
1073 item_data[
'item_link'] = match[key]
1074 item_data[
'item_url'] = match[key]
1076 if key
in list(match.keys()):
1080 items.append(item_data)
1082 self.
channel[
'channel_startindex'] = self.page_limit * int(pagenumber)
1083 self.
channel[
'channel_returned'] = len(items)
1086 return [[self.
channel, items]]
1092 '''Get the channel directory information and fill out the tree view directory structures as required
1093 raise exceptions if the there was an issue getting Channel information or no channel data
1094 return True if successful
1102 self.
channel_count[
'N_R_S'] = {
'newest': [10, 2],
'most_recently_updated': [10, 1],
'most_subscribed': [10, 10]}
1103 self.
channel_count[
'Everything HD'] = {
'newest': [10, 2],
'most_recently_updated': [10, 1],
'most_subscribed': [5, 20]}
1117 xml_data = self.
config[
'methods'][
'channels'](sort=sort,
1120 except Exception
as msg:
1123 if xml_data
is None:
1126 if not len(list(xml_data.keys())):
1129 if xml_data.tag ==
'rsp':
1130 if not xml_data.get(
'stat') ==
'ok':
1131 if xml_data.get(
'stat')
in __errmsgs__:
1132 errmsg = __errmsg__[xml_data.get(
'stat')]
1135 errmsg =
'Unknown error'
1138 for channel
in xml_data.find(
'channels'):
1139 index = channel.find(
'name').text.find(
'HD')
1142 if not channel.get(
'id')
in HD_list:
1143 self.
channel_dict[
'Everything HD'][sort].append([channel.get(
'id'), channel.find(
'name').text])
1144 HD_list.append(channel.get(
'id'))
1148 if not channel.get(
'id')
in not_HD_list:
1149 self.
channel_dict[
'N_R_S'][sort].append([channel.get(
'id'), channel.find(
'name').text])
1150 not_HD_list.append(channel.get(
'id'))
1164 '''Gather the Vimeo Groups/Channels...etc then get a max page of videos meta data in each of them
1165 return array of directories and their video metadata
1169 except VimeoAuthorizeTokenError
as msg:
1170 sys.stderr.write(self.
error_messages[
'VimeoAuthorizeTokenError'] % msg)
1172 except VimeoRequestTokenError
as msg:
1173 sys.stderr.write(self.
error_messages[
'VimeoRequestTokenError'] % msg)
1175 except VimeoException
as msg:
1178 except Exception
as msg:
1179 sys.stderr.write(
"! Error: Unknown error during a Vimeo API initialization (%s)\n" % msg)
1183 self.
channel = {
'channel_title':
'Vimeo',
'channel_link':
'http://vimeo.com',
'channel_description':
"Vimeo is a respectful community of creative people who are passionate about sharing the videos they make.",
'channel_numresults': 0,
'channel_returned': 1,
'channel_startindex': 0}
1185 if self.
config[
'debug_enabled']:
1192 except VimeoResponseError
as msg:
1193 sys.stderr.write(self.
error_messages[
'VimeoResponseError'] % msg)
1195 except VimeoAllChannelError
as msg:
1196 sys.stderr.write(self.
error_messages[
'VimeoAllChannelError'] % msg)
1198 except VimeoException
as msg:
1201 except Exception
as msg:
1202 sys.stderr.write(
"! Error: Unknown error while getting all Channels (%s)\n" % msg)
1214 return [[self.
channel, dictionaries]]
1219 '''Parse a list made of category lists and retrieve video meta data
1220 return a dictionary of directory names and categories video metadata
1222 for sets
in dir_dict:
1223 if not isinstance(sets[1], list):
1230 dictionaries.append([
'',
''])
1232 temp_dictionary = []
1233 for self.feed
in sets[1]:
1234 if '__all__' in self.
config[
'methods'][
'tree.view'][self.
tree_key]:
1235 URL = self.
config[
'methods'][
'tree.view'][self.
tree_key][
'__all__']
1237 URL = self.
config[
'methods'][
'tree.view'][self.
tree_key][self.feed]
1238 temp_dictionary = self.
config[
'item_parser'][URL[1]](self.
config[
'methods'][URL[0]], temp_dictionary)
1239 if len(temp_dictionary):
1245 for element
in temp_dictionary:
1246 dictionaries.append(element)
1248 dictionaries.append([
'',
''])
1254 '''Process all channel related directory videos
1255 return dictionary of new video items
1273 except VimeoVideoNotFound
as msg:
1274 sys.stderr.write(self.
error_messages[
'VimeoVideoNotFound'] % msg)
1276 except VimeoVideosSearchError
as msg:
1277 sys.stderr.write(self.
error_messages[
'VimeoVideosSearchError'] % msg)
1279 except VimeoResponseError
as msg:
1280 sys.stderr.write(self.
error_messages[
'VimeoResponseError'] % msg)
1282 except VimeoException
as msg:
1285 except Exception
as e:
1286 sys.stderr.write(
"! Error: Unknown error during while getting all Channels (%s)\nError(%s)\n" % (self.
dir_name, e))
1289 if len(tmp_dictionary):
1291 for element
in tmp_dictionary:
1292 dictionary.append(element)
1293 dictionary.append([
'',
''])
1300 '''Get the video metadata for url search
1301 return the video dictionary of directories and their video mata data
1303 initial_length = len(dictionaries)
1305 xml_data = method(channel_id=self.
channel_id, full_response=1,
1308 except Exception
as msg:
1311 if xml_data
is None:
1314 if not len(list(xml_data.keys())):
1317 if xml_data.tag ==
'rsp':
1318 if not xml_data.get(
'stat') ==
'ok':
1319 if xml_data.get(
'stat')
in __errmsgs__:
1320 errmsg = __errmsg__[xml_data.get(
'stat')]
1323 errmsg =
'Unknown error'
1326 videos = xml_data.find(
"videos")
1328 if videos.get(
'total'):
1329 self.
channel[
'channel_numresults'] = int(videos.get(
'total'))
1332 dictionary_first =
False
1333 for video
in xml_data.find(
"videos").getchildren():
1336 if video.tag ==
'video':
1337 if video.get(
'embed_privacy') ==
"anywhere":
1339 if video.get(
'is_hd') ==
"1":
1342 for details
in video.getchildren():
1343 if details.tag
in [
'tags',
'cast']:
1345 if details.tag ==
'width':
1347 v_details[
'width'] = details.text.strip()
1349 if details.tag ==
'height':
1351 v_details[
'height'] = details.text.strip()
1353 if details.tag ==
'duration':
1355 v_details[
'duration'] = details.text.strip()
1357 if details.tag ==
'owner':
1359 v_details[
'display_name'] = self.
massageDescription(details.get(
'display_name').strip())
1361 v_details[
'display_name'] =
''
1363 if details.tag ==
'description':
1373 if details.tag ==
'upload_date':
1375 pub_time = time.strptime(details.text.strip(),
"%Y-%m-%d %H:%M:%S")
1376 v_details[details.tag] = time.strftime(
'%a, %d %b %Y %H:%M:%S GMT', pub_time)
1378 v_details[details.tag] =
''
1380 if details.tag ==
'urls':
1381 for url
in details.getchildren():
1382 if url.get(
'type') ==
'video':
1387 v_details[url.tag] = self.
ampReplace(url.text.strip())
1389 v_details[url.tag] =
''
1391 if details.tag ==
'thumbnails':
1393 for image
in details.getchildren():
1394 if image.tag ==
'thumbnail':
1395 height = int(image.get(
'height'))
1396 width = int(image.get(
'width'))
1397 default = image.text.find(
'default')
1398 if largest < height * width
and not default != -1:
1400 v_details[image.tag] = self.
ampReplace(image.text.strip())
1407 v_details[details.tag] =
''
1409 if hd_flag
and 'width' not in v_details:
1410 v_details[
'width'] = 1280
1411 v_details[
'height'] = 720
1413 if 'url' not in v_details:
1416 if not dictionary_first
and not self.
tree_list:
1418 dictionary_first =
True
1423 final_item[
'item_link'] = v_details[key]
1424 final_item[
'item_url'] = v_details[key]
1426 if key
in v_details:
1430 dictionaries.append(final_item)
1433 if initial_length < len(dictionaries)
and not self.
tree_list:
1434 dictionaries.append([
'',
''])