class Youtube(PlatformOAuth2): # Platform attributes based_on = 'google' name = 'youtube' display_name = 'Youtube' account_url = 'https://youtube.com/channel/{user_id}' optional_user_name = True user_type = 'channel' # Auth attributes auth_url = 'https://accounts.google.com/o/oauth2/auth?access_type=offline' access_token_url = 'https://accounts.google.com/o/oauth2/token' oauth_default_scope = ['https://www.googleapis.com/auth/youtube.readonly'] # API attributes api_format = 'json' api_paginator = query_param_paginator('pageToken', next='nextPageToken', page='items', total=('pageInfo', 'totalResults')) api_url = 'https://www.googleapis.com/youtube/v3' api_user_info_path = '/channels?part=snippet&id={user_id}' api_user_self_info_path = '/channels?part=snippet&mine=true' api_friends_path = '/subscriptions?part=snippet&mine=true' api_search_path = '/search?part=snippet&type=channel&q={query}' # User info extractors x_user_info = key('items') x_user_id = any_key(('snippet', 'resourceId', 'channelId'), 'id') x_display_name = any_key(('snippet', 'title')) x_avatar_url = any_key(('snippet', 'thumbnails', 'medium', 'url')) x_description = any_key(('snippet', 'description'))
class Google(PlatformOAuth2): # Platform attributes name = 'google' display_name = 'Google' fontawesome_name = name account_url = None optional_user_name = True # Auth attributes # https://developers.google.com/identity/protocols/OAuth2WebServer auth_url = 'https://accounts.google.com/o/oauth2/auth?access_type=offline&include_granted_scopes=true' access_token_url = 'https://accounts.google.com/o/oauth2/token' # https://developers.google.com/identity/protocols/googlescopes oauth_default_scope = ['https://www.googleapis.com/auth/userinfo.profile'] oauth_friends_scope = 'https://www.googleapis.com/auth/contacts.readonly' # https://developers.google.com/people/api/rest/v1/people/get person_fields = 'personFields=names,nicknames,photos,taglines' # API attributes api_requires_user_token = True api_format = 'json' api_paginator = query_param_paginator('pageToken', next='nextPageToken', total='totalItems') api_url = 'https://people.googleapis.com/v1' api_user_info_path = '/people/{user_id}?%s' % person_fields api_user_self_info_path = '/people/me?%s' % person_fields api_friends_path = '/people/me/connections?%s' % person_fields # User info extractors x_user_id = key('resourceName', clean=partial(_strip_prefix, 'people/')) x_display_name = any_key(('names', 'displayName')) x_avatar_url = any_key('coverPhotos', 'photos', clean=lambda d: None if d.get('default') else d['url']) x_description = any_key(('taglines', 'value')) def x_user_info(self, extracted, info, *default): """Reduce a Person object to its primary values. Docs: https://developers.google.com/people/api/rest/v1/people#Person """ for k, v in list(info.items()): if type(v) is list: info[k] = get_primary(v) return info
class Google(PlatformOAuth2): # Platform attributes name = 'google' display_name = 'Google' account_url = 'https://plus.google.com/{user_id}' optional_user_name = True # Auth attributes auth_url = 'https://accounts.google.com/o/oauth2/auth' access_token_url = 'https://accounts.google.com/o/oauth2/token' oauth_default_scope = ['https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/plus.login'] # API attributes api_format = 'json' api_paginator = query_param_paginator('pageToken', next='nextPageToken', page='items', total='totalItems') api_url = 'https://www.googleapis.com/plus/v1' api_user_info_path = '/people/{user_id}' api_user_self_info_path = '/people/me' api_friends_path = '/people/{user_id}/people/visible' api_friends_limited = True # User info extractors x_user_id = key('id') x_display_name = key('displayName') x_email = any_key(('emails', 0), clean=lambda d: d.get('value')) x_avatar_url = key('image', clean=lambda d: d.get('url')) def x_user_name(self, extracted, info, *default): url = info.get('url', '') return url[25:] if url.startswith('https://plus.google.com/+') else None
class Bitbucket(PlatformOAuth1): # Platform attributes name = 'bitbucket' display_name = 'Bitbucket' fontawesome_name = name account_url = 'https://bitbucket.org/{user_name}' # Auth attributes auth_url = 'https://bitbucket.org/api/1.0' authorize_path = '/oauth/authenticate' # API attributes api_format = 'json' api_paginator = keys_paginator('values', prev='previous', total='size') api_url = 'https://bitbucket.org/api' api_user_info_path = '/2.0/users/{user_id}' api_user_name_info_path = '/2.0/users/{user_name}' api_user_self_info_path = '/2.0/user' api_team_members_path = '/2.0/teams/{user_name}/members' api_friends_path = '/2.0/users/{user_name}/following' # User info extractors x_user_info = key('user') x_user_id = key('uuid') x_user_name = key('username') x_display_name = key('display_name') x_email = not_available x_avatar_url = any_key('avatar', ('links', 'avatar', 'href')) x_is_team = key('type', lambda v: v == 'team') def api_get(self, domain, path, sess=None, **kw): """Extend to manually retry /users/pypy as /teams/pypy. Bitbucket gives us a 404 where a 30x would be more helpful. """ try: return PlatformOAuth1.api_get(self, domain, path, sess, **kw) except Response as response: if response.code == 404 and ' is a team account' in response.body: assert path.startswith('/2.0/users/') path = '/2.0/teams/' + path[11:] return PlatformOAuth1.api_get(self, domain, path, sess, **kw) else: raise