Merge pull request #1618 from tpikonen/view-prefs
[gpodder.git] / src / gpodder / vimeo.py
blob3b4a28ad49e0af9c7036988eea3eeb9db3402534
1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2018 The gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 # gpodder.vimeo - Vimeo download magic
22 # Thomas Perl <thp@gpodder.org>; 2012-01-03
26 import logging
27 import re
29 import gpodder
30 from gpodder import registry, util
32 _ = gpodder.gettext
34 logger = logging.getLogger(__name__)
37 VIMEOCOM_RE = re.compile(r'http[s]?://vimeo\.com/(channels/[^/]+|\d+)$', re.IGNORECASE)
38 VIMEOCOM_VIDEO_RE = re.compile(r'http[s]?://vimeo.com/channels/(?:[^/])+/(\d+)$', re.IGNORECASE)
39 MOOGALOOP_RE = re.compile(r'http[s]?://vimeo\.com/moogaloop\.swf\?clip_id=(\d+)$', re.IGNORECASE)
40 SIGNATURE_RE = re.compile(r'"timestamp":(\d+),"signature":"([^"]+)"')
42 # List of qualities, from lowest to highest
43 FILEFORMAT_RANKING = ['270p', '360p', '720p', '1080p']
45 FORMATS = tuple((x, x) for x in FILEFORMAT_RANKING)
48 class VimeoError(BaseException):
49 pass
52 @registry.download_url.register
53 def vimeo_real_download_url(config, episode, allow_partial):
54 fmt = config.vimeo.fileformat if config else None
55 res = get_real_download_url(episode.url, preferred_fileformat=fmt)
56 return None if res == episode.url else res
59 def get_real_download_url(url, preferred_fileformat=None):
60 video_id = get_vimeo_id(url)
62 if video_id is None:
63 return url
65 data_config_url = 'https://player.vimeo.com/video/%s/config' % (video_id,)
67 def get_urls(data_config_url):
68 data_config = util.urlopen(data_config_url).json()
69 for fileinfo in list(data_config['request']['files'].values()):
70 if not isinstance(fileinfo, list):
71 continue
73 for item in fileinfo:
74 yield (item['quality'], item['url'])
76 fileformat_to_url = dict(get_urls(data_config_url))
78 if preferred_fileformat is not None and preferred_fileformat in fileformat_to_url:
79 logger.debug('Picking preferred format: %s', preferred_fileformat)
80 return fileformat_to_url[preferred_fileformat]
82 def fileformat_sort_key_func(fileformat):
83 if fileformat in FILEFORMAT_RANKING:
84 return FILEFORMAT_RANKING.index(fileformat)
86 return 0
88 for fileformat in sorted(fileformat_to_url, key=fileformat_sort_key_func, reverse=True):
89 logger.debug('Picking best format: %s', fileformat)
90 return fileformat_to_url[fileformat]
92 return url
95 def get_vimeo_id(url):
96 result = MOOGALOOP_RE.match(url)
97 if result is not None:
98 return result.group(1)
100 result = VIMEOCOM_RE.match(url)
101 if result is not None:
102 return result.group(1)
104 result = VIMEOCOM_VIDEO_RE.match(url)
105 if result is not None:
106 return result.group(1)
108 return None
111 def is_video_link(url):
112 return (get_vimeo_id(url) is not None)
115 def get_real_channel_url(url):
116 result = VIMEOCOM_RE.match(url)
117 if result is not None:
118 return 'http://vimeo.com/%s/videos/rss' % result.group(1)
120 return url
123 def get_real_cover(url):
124 return None