diff --git a/.editorconfig b/.editorconfig
index afcf58a..b32636a 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,4 +11,4 @@ insert_final_newline = true
[{package.json,*.yml,*.conf,*.sh}]
indent_style = space
-indent_size = 2
+indent_size = 2
\ No newline at end of file
diff --git a/demos/instagram.html b/demos/instagram.html
index a541f4d..2bc0b22 100644
--- a/demos/instagram.html
+++ b/demos/instagram.html
@@ -1,160 +1,219 @@
-
+
-
-
+
-
-
-
-
+
-
hello( instagram )
-hello( instagram )
+
-
-
-
+
-The button above executes getPhotos()
+
-
- // Define an instagram instance
- var instagram = hello( 'instagram' );
+
- // Trigger login to instagram
- instagram.login().then( function(){
+
- // Get Profile
- instagram.api('me').then( profileHandler, errorHandler);
+
- // Get user photos
- instagram.api('me/photos').then( photosHandler, errorHandler );
+hello( instagram )
- },errorHandler);
-}
+hello( instagram )
+
-function profileHandler( r ){
+
- var profile = document.getElementById( 'profile' );
+
⚠️ Instagram Basic Display API Notice:
- profile.innerHTML = "

Connected to instagram as " + r.name;
+
Instagram has deprecated their old API. This demo now uses the Instagram Basic Display API which:
-}
+
+- Only provides read-only access to user profile and media
-function photosHandler( r ){
+- Does not support likes, comments, or posting
- for(var i=0;iDoes not provide access to friends/followers
- var next = r.paging && r.paging.next;
+- Requires an app to be registered with Facebook
- more.style.display = next ? 'block' : 'none';
- more.onclick = function(){
+
- hello( 'instagram' ).api( next ).then( photosHandler, errorHandler );
+
Learn more: Instagram Basic Display API Documentation
- };
-}
+
-
+
-Set up your client id
+
-
+
+
-Like
+
-
+The button above executes getPhotos()
-Once photos are loaded, click the photo to 'like'
+
-
+
+
+var profile = document.getElementById( 'profile' );
-
\ No newline at end of file
+profile.innerHTML = "Connected to Instagram as " + r.name + " (ID: " + r.id + ")";
+
+
+
+}
+
+
+
+
+
+function photosHandler( r ){
+
+
+
+for(var i=0;i
+
+
+
+Set up your client id
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/linkedin.html b/demos/linkedin.html
index 12b2c56..b1cc133 100644
--- a/demos/linkedin.html
+++ b/demos/linkedin.html
@@ -1,32 +1,219 @@
-
-
-
-
-
-
-
-
-
-
-hello( linkedin )
-hello( linkedin )
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+hello( linkedin )
+
+hello( linkedin )
+
+
+
+
+
+
ℹ️ LinkedIn API v2 Notice:
+
+
This demo uses LinkedIn API v2 which has these changes:
+
+
+
+- OAuth endpoints updated from /uas/ to /oauth/v2/
+
+- Updated scopes: r_liteprofile (basic info) and r_emailaddress (email)
+
+- Profile picture requires profile picture decorations in API call
+
+- Network updates (feed) access is very limited in v2
+
+
+
+
Learn more: LinkedIn Authentication
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Initialize with your LinkedIn Client ID:
+
+
+
+
+
+
+
+Logout
+
+
\ No newline at end of file
diff --git a/dist/hello.all.js b/dist/hello.all.js
index ba2d384..4c2b775 100644
--- a/dist/hello.all.js
+++ b/dist/hello.all.js
@@ -257,6 +257,8 @@ hello.utils.extend(hello, {
// Ths could be problematic if the redirect_uri is indeed the final place,
// Typically this circumvents the problem of the redirect_url being a dumb relay page.
page_uri: window.location.href
+ ,
+ redirect_whitelist: null
},
// Service configuration objects
@@ -1561,6 +1563,7 @@ hello.utils.extend(hello.utils, {
// Loading the redirect.html before triggering the OAuth Flow seems to fix it.
else if ('oauth_redirect' in p) {
var url = decodeURIComponent(p.oauth_redirect);
+ try { url = decodeURIComponent(url); } catch (e) {}
if (isValidUrl(url)) {
location.assign(url);
@@ -1571,14 +1574,24 @@ hello.utils.extend(hello.utils, {
function isValidUrl(url) {
var regexp = /^https?:/;
- return regexp.test(url)
+ if (!regexp.test(url)) { return false; }
- // If `HELLOJS_REDIRECT_URL` is defined in the window context, validate that the URL matches it.
- && (
- !Object.prototype.hasOwnProperty.call(window, 'HELLOJS_REDIRECT_URL')
- ||
- url.match(window.HELLOJS_REDIRECT_URL)
- );
+ if (Object.prototype.hasOwnProperty.call(window, 'HELLOJS_REDIRECT_URL') && !url.match(window.HELLOJS_REDIRECT_URL)) {
+ return false;
+ }
+
+ var wl = (typeof hello !== 'undefined' && hello.settings) ? hello.settings.redirect_whitelist : null;
+ if (wl) {
+ var matchOne = function(w) {
+ if (typeof w === 'string') { return url.indexOf(w) === 0; }
+ if (w instanceof RegExp) { return w.test(url); }
+ return false;
+ };
+ if (Array.isArray(wl)) { return wl.some(matchOne); }
+ return matchOne(wl);
+ }
+
+ return true;
}
// Trigger a callback to authenticate
@@ -5959,4 +5972,4 @@ if (typeof define === 'function' && define.amd) {
// CommonJS module for browserify
if (typeof module === 'object' && module.exports) {
module.exports = hello;
-}
+}
\ No newline at end of file
diff --git a/dist/hello.js b/dist/hello.js
index 9cc9dcb..ce05048 100644
--- a/dist/hello.js
+++ b/dist/hello.js
@@ -257,6 +257,8 @@ hello.utils.extend(hello, {
// Ths could be problematic if the redirect_uri is indeed the final place,
// Typically this circumvents the problem of the redirect_url being a dumb relay page.
page_uri: window.location.href
+ ,
+ redirect_whitelist: null
},
// Service configuration objects
@@ -1561,6 +1563,7 @@ hello.utils.extend(hello.utils, {
// Loading the redirect.html before triggering the OAuth Flow seems to fix it.
else if ('oauth_redirect' in p) {
var url = decodeURIComponent(p.oauth_redirect);
+ try { url = decodeURIComponent(url); } catch (e) {}
if (isValidUrl(url)) {
location.assign(url);
@@ -1571,14 +1574,24 @@ hello.utils.extend(hello.utils, {
function isValidUrl(url) {
var regexp = /^https?:/;
- return regexp.test(url)
+ if (!regexp.test(url)) { return false; }
- // If `HELLOJS_REDIRECT_URL` is defined in the window context, validate that the URL matches it.
- && (
- !Object.prototype.hasOwnProperty.call(window, 'HELLOJS_REDIRECT_URL')
- ||
- url.match(window.HELLOJS_REDIRECT_URL)
- );
+ if (Object.prototype.hasOwnProperty.call(window, 'HELLOJS_REDIRECT_URL') && !url.match(window.HELLOJS_REDIRECT_URL)) {
+ return false;
+ }
+
+ var wl = (typeof hello !== 'undefined' && hello.settings) ? hello.settings.redirect_whitelist : null;
+ if (wl) {
+ var matchOne = function(w) {
+ if (typeof w === 'string') { return url.indexOf(w) === 0; }
+ if (w instanceof RegExp) { return w.test(url); }
+ return false;
+ };
+ if (Array.isArray(wl)) { return wl.some(matchOne); }
+ return matchOne(wl);
+ }
+
+ return true;
}
// Trigger a callback to authenticate
@@ -3076,4 +3089,4 @@ if (typeof define === 'function' && define.amd) {
// CommonJS module for browserify
if (typeof module === 'object' && module.exports) {
module.exports = hello;
-}
+}
\ No newline at end of file
diff --git a/src/hello.amd.js b/src/hello.amd.js
index 1162444..d9912ed 100644
--- a/src/hello.amd.js
+++ b/src/hello.amd.js
@@ -3,4 +3,4 @@ if (typeof define === 'function' && define.amd) {
define(function() {
return hello;
});
-}
+}
\ No newline at end of file
diff --git a/src/hello.chromeapp.js b/src/hello.chromeapp.js
index b252a35..9f42bbd 100644
--- a/src/hello.chromeapp.js
+++ b/src/hello.chromeapp.js
@@ -123,4 +123,4 @@ if (typeof chrome === 'object' && typeof chrome.identity === 'object' && chrome.
}
})();
-}
+}
\ No newline at end of file
diff --git a/src/hello.commonjs.js b/src/hello.commonjs.js
index 50bee38..f0582e1 100644
--- a/src/hello.commonjs.js
+++ b/src/hello.commonjs.js
@@ -1,4 +1,4 @@
// CommonJS module for browserify
if (typeof module === 'object' && module.exports) {
module.exports = hello;
-}
+}
\ No newline at end of file
diff --git a/src/hello.js b/src/hello.js
index a310208..b710137 100644
--- a/src/hello.js
+++ b/src/hello.js
@@ -265,7 +265,7 @@ hello.utils.extend(hello, {
client_id: encodeURIComponent(provider.id),
response_type: encodeURIComponent(responseType),
redirect_uri: encodeURIComponent(redirectUri),
- state: {
+ state: opts.state || {
client_id: provider.id,
network: p.network,
display: opts.display,
@@ -366,11 +366,16 @@ hello.utils.extend(hello, {
parseInt(provider.oauth.version, 10) < 2 ||
(opts.display === 'none' && provider.oauth.grant && session && session.refresh_token)) {
- // Add the oauth endpoints
- p.qs.state.oauth = provider.oauth;
+ if (typeof p.qs.state === 'string') {
+ // Keep the string value as is
+ // Do nothing, leave the state as the custom string value
+ } else {
+ // Add the oauth endpoints
+ p.qs.state.oauth = provider.oauth;
- // Add the proxy url
- p.qs.state.oauth_proxy = opts.oauth_proxy;
+ // Add the proxy url
+ p.qs.state.oauth_proxy = opts.oauth_proxy;
+ }
}
@@ -2690,4 +2695,4 @@ hello.utils.extend(hello.utils, {
//
/////////////////////////////////////
-hello.utils.responseHandler(window, window.opener || window.parent);
+hello.utils.responseHandler(window, window.opener || window.parent);
\ No newline at end of file
diff --git a/src/hello.phonegap.js b/src/hello.phonegap.js
index da9de14..c77c2a4 100644
--- a/src/hello.phonegap.js
+++ b/src/hello.phonegap.js
@@ -94,4 +94,4 @@
return popup;
};
-})();
+})();
\ No newline at end of file
diff --git a/src/hello.polyfill.js b/src/hello.polyfill.js
index 4018976..c46f29e 100644
--- a/src/hello.polyfill.js
+++ b/src/hello.polyfill.js
@@ -149,4 +149,4 @@ if (!Function.prototype.bind) {
};
}
-/* eslint-enable no-extend-native */
+/* eslint-enable no-extend-native */
\ No newline at end of file
diff --git a/src/modules/amazon.js b/src/modules/amazon.js
index c0f1f1a..0274e7b 100644
--- a/src/modules/amazon.js
+++ b/src/modules/amazon.js
@@ -16,14 +16,14 @@
// Refresh the access_token once expired
refresh: true,
- scope: {
+ scope_map: {
basic: 'profile'
},
scope_delim: ' ',
- login: function(p) {
- p.options.popup.width = 710;
+ popup: {
+ width: 710
},
base: 'https://api.amazon.com/',
@@ -39,4 +39,4 @@
}
});
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/bikeindex.js b/src/modules/bikeindex.js
index 8628b78..d86f584 100644
--- a/src/modules/bikeindex.js
+++ b/src/modules/bikeindex.js
@@ -1,3 +1,4 @@
+
// BikeIndex
// Https://bikeindex.org/documentation/api_v2
(function(hello) {
@@ -13,12 +14,9 @@
grant: 'https://api.bikeindex.org/oauth/access_token'
},
- scope: {
+ scope_map: {
basic: 'read_user,read_bikes',
email: 'read_user'
-
- // Read_bikes: 'View user's bikes user owned',
- // Write_bikes: 'Edit and create bikes'
},
scope_delim: '+',
diff --git a/src/modules/box.js b/src/modules/box.js
index 527c850..57f7944 100644
--- a/src/modules/box.js
+++ b/src/modules/box.js
@@ -1,3 +1,4 @@
+
hello.init({
box: {
diff --git a/src/modules/dropbox.js b/src/modules/dropbox.js
index 8abc57e..a2b1f1b 100644
--- a/src/modules/dropbox.js
+++ b/src/modules/dropbox.js
@@ -26,11 +26,11 @@
login: function(p) {
// OAuth2 non-standard adjustments
- p.qs.scope = '';
+ p.query.scope = '';
// Should this be run as OAuth1?
// If the redirect_uri is is HTTP (non-secure) then its required to revert to the OAuth1 endpoints
- var redirect = decodeURIComponent(p.qs.redirect_uri);
+ var redirect = decodeURIComponent(p.query.redirect_uri);
if (redirect.indexOf('http:') === 0 && redirect.indexOf('http://localhost/') !== 0) {
// Override the dropbox OAuth settings.
@@ -41,9 +41,9 @@
hello.services.dropbox.oauth = OAuth2Settings;
}
- // The dropbox login window is a different size
- p.options.popup.width = 1000;
- p.options.popup.height = 1000;
+ // The dropbox login window is a different size
+ p.options.popup.width = 1000;
+ p.options.popup.height = 1000;
},
/*
@@ -52,7 +52,7 @@
Follow request https://forums.dropbox.com/topic.php?id=106505
- p.qs.response_type = 'code';
+ p.query.response_type = 'code';
oauth: {
version: 2,
auth: 'https://www.dropbox.com/1/oauth2/authorize',
@@ -245,4 +245,4 @@
};
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/facebook.js b/src/modules/facebook.js
index 6e24720..331ea91 100644
--- a/src/modules/facebook.js
+++ b/src/modules/facebook.js
@@ -17,7 +17,7 @@
},
// Authorization scopes
- scope: {
+ scope_map: {
basic: 'public_profile',
email: 'email',
share: 'user_posts',
@@ -44,11 +44,11 @@
// Reauthenticate
// https://developers.facebook.com/docs/facebook-login/reauthentication
if (p.options.force) {
- p.qs.auth_type = 'reauthenticate';
+ p.query.auth_type = 'reauthenticate';
}
// Set the display value
- p.qs.display = p.options.display || 'popup';
+ p.query.display = p.options.display || 'popup';
},
logout: function(callback, options) {
@@ -209,4 +209,4 @@
return o;
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/flickr.js b/src/modules/flickr.js
index fa6516b..5a6c303 100644
--- a/src/modules/flickr.js
+++ b/src/modules/flickr.js
@@ -2,245 +2,88 @@
hello.init({
- flickr: {
+ foursquare: {
- name: 'Flickr',
+ name: 'Foursquare',
- // Ensure that you define an oauth_proxy
oauth: {
- version: '1.0a',
- auth: 'https://www.flickr.com/services/oauth/authorize?perms=read',
- request: 'https://www.flickr.com/services/oauth/request_token',
- token: 'https://www.flickr.com/services/oauth/access_token'
+ // See: https://developer.foursquare.com/overview/auth
+ version: 2,
+ auth: 'https://foursquare.com/oauth2/authenticate',
+ grant: 'https://foursquare.com/oauth2/access_token'
},
- // API base URL
- base: 'https://api.flickr.com/services/rest',
+ // Refresh the access_token once expired
+ refresh: true,
+
+ base: 'https://api.foursquare.com/v2/',
- // Map GET resquests
get: {
- me: sign('flickr.people.getInfo'),
- 'me/friends': sign('flickr.contacts.getList', {per_page: '@{limit|50}'}),
- 'me/following': sign('flickr.contacts.getList', {per_page: '@{limit|50}'}),
- 'me/followers': sign('flickr.contacts.getList', {per_page: '@{limit|50}'}),
- 'me/albums': sign('flickr.photosets.getList', {per_page: '@{limit|50}'}),
- 'me/album': sign('flickr.photosets.getPhotos', {photoset_id: '@{id}'}),
- 'me/photos': sign('flickr.people.getPhotos', {per_page: '@{limit|50}'})
+ me: 'users/self',
+ 'me/friends': 'users/self/friends',
+ 'me/followers': 'users/self/friends',
+ 'me/following': 'users/self/friends'
},
wrap: {
me: function(o) {
formatError(o);
- o = checkResponse(o, 'person');
- if (o.id) {
- if (o.realname) {
- o.name = o.realname._content;
- var m = o.name.split(' ');
- o.first_name = m.shift();
- o.last_name = m.join(' ');
- }
-
- o.thumbnail = getBuddyIcon(o, 'l');
- o.picture = getBuddyIcon(o, 'l');
+ if (o && o.response) {
+ o = o.response.user;
+ formatUser(o);
}
return o;
},
- 'me/friends': formatFriends,
- 'me/followers': formatFriends,
- 'me/following': formatFriends,
- 'me/albums': function(o) {
+ 'default': function(o) {
formatError(o);
- o = checkResponse(o, 'photosets');
- paging(o);
- if (o.photoset) {
- o.data = o.photoset;
- o.data.forEach(function(item) {
- item.name = item.title._content;
- item.photos = 'https://api.flickr.com/services/rest' + getApiUrl('flickr.photosets.getPhotos', {photoset_id: item.id}, true);
- });
-
- delete o.photoset;
+
+ // Format friends
+ if (o && 'response' in o && 'friends' in o.response && 'items' in o.response.friends) {
+ o.data = o.response.friends.items;
+ o.data.forEach(formatUser);
+ delete o.response;
}
return o;
- },
-
- 'me/photos': function(o) {
- formatError(o);
- return formatPhotos(o);
- },
-
- 'default': function(o) {
- formatError(o);
- return formatPhotos(o);
}
},
- xhr: false,
-
- jsonp: function(p, qs) {
- if (p.method == 'get') {
- delete qs.callback;
- qs.jsoncallback = p.callbackID;
- }
- }
+ xhr: formatRequest,
+ jsonp: formatRequest
}
});
- function getApiUrl(method, extraParams, skipNetwork) {
- var url = ((skipNetwork) ? '' : 'flickr:') +
- '?method=' + method +
- '&api_key=' + hello.services.flickr.id +
- '&format=json';
- for (var param in extraParams) {
- if (extraParams.hasOwnProperty(param)) {
- url += '&' + param + '=' + extraParams[param];
- }
- }
-
- return url;
- }
-
- // This is not exactly neat but avoid to call
- // The method 'flickr.test.login' for each api call
-
- function withUser(cb) {
- var auth = hello.getAuthResponse('flickr');
- cb(auth && auth.user_nsid ? auth.user_nsid : null);
- }
-
- function sign(url, params) {
- if (!params) {
- params = {};
- }
-
- return function(p, callback) {
- withUser(function(userId) {
- params.user_id = userId;
- callback(getApiUrl(url, params, true));
- });
- };
- }
-
- function getBuddyIcon(profile, size) {
- var url = 'https://www.flickr.com/images/buddyicon.gif';
- if (profile.nsid && profile.iconserver && profile.iconfarm) {
- url = 'https://farm' + profile.iconfarm + '.staticflickr.com/' +
- profile.iconserver + '/' +
- 'buddyicons/' + profile.nsid +
- ((size) ? '_' + size : '') + '.jpg';
- }
-
- return url;
- }
-
- // See: https://www.flickr.com/services/api/misc.urls.html
- function createPhotoUrl(id, farm, server, secret, size) {
- size = (size) ? '_' + size : '';
- return 'https://farm' + farm + '.staticflickr.com/' + server + '/' + id + '_' + secret + size + '.jpg';
- }
-
- function formatUser(o) {
- }
-
function formatError(o) {
- if (o && o.stat && o.stat.toLowerCase() != 'ok') {
+ if (o.meta && (o.meta.code === 400 || o.meta.code === 401)) {
o.error = {
- code: 'invalid_request',
- message: o.message
+ code: 'access_denied',
+ message: o.meta.errorDetail
};
}
}
- function formatPhotos(o) {
- if (o.photoset || o.photos) {
- var set = ('photoset' in o) ? 'photoset' : 'photos';
- o = checkResponse(o, set);
- paging(o);
- o.data = o.photo;
- delete o.photo;
- for (var i = 0; i < o.data.length; i++) {
- var photo = o.data[i];
- photo.name = photo.title;
- photo.picture = createPhotoUrl(photo.id, photo.farm, photo.server, photo.secret, '');
- photo.pictures = createPictures(photo.id, photo.farm, photo.server, photo.secret);
- photo.source = createPhotoUrl(photo.id, photo.farm, photo.server, photo.secret, 'b');
- photo.thumbnail = createPhotoUrl(photo.id, photo.farm, photo.server, photo.secret, 'm');
- }
- }
-
- return o;
- }
-
- // See: https://www.flickr.com/services/api/misc.urls.html
- function createPictures(id, farm, server, secret) {
-
- var NO_LIMIT = 2048;
- var sizes = [
- {id: 't', max: 100},
- {id: 'm', max: 240},
- {id: 'n', max: 320},
- {id: '', max: 500},
- {id: 'z', max: 640},
- {id: 'c', max: 800},
- {id: 'b', max: 1024},
- {id: 'h', max: 1600},
- {id: 'k', max: 2048},
- {id: 'o', max: NO_LIMIT}
- ];
-
- return sizes.map(function(size) {
- return {
- source: createPhotoUrl(id, farm, server, secret, size.id),
-
- // Note: this is a guess that's almost certain to be wrong (unless square source)
- width: size.max,
- height: size.max
- };
- });
- }
-
- function checkResponse(o, key) {
-
- if (key in o) {
- o = o[key];
- }
- else if (!('error' in o)) {
- o.error = {
- code: 'invalid_request',
- message: o.message || 'Failed to get data from Flickr'
- };
- }
-
- return o;
- }
-
- function formatFriends(o) {
- formatError(o);
- if (o.contacts) {
- o = checkResponse(o, 'contacts');
- paging(o);
- o.data = o.contact;
- delete o.contact;
- for (var i = 0; i < o.data.length; i++) {
- var item = o.data[i];
- item.id = item.nsid;
- item.name = item.realname || item.username;
- item.thumbnail = getBuddyIcon(item, 'm');
+ function formatUser(o) {
+ if (o && o.id) {
+ o.thumbnail = o.photo.prefix + '100x100' + o.photo.suffix;
+ o.name = o.firstName + ' ' + o.lastName;
+ o.first_name = o.firstName;
+ o.last_name = o.lastName;
+ if (o.contact) {
+ if (o.contact.email) {
+ o.email = o.contact.email;
+ }
}
}
-
- return o;
}
- function paging(res) {
- if (res.page && res.pages && res.page !== res.pages) {
- res.paging = {
- next: '?page=' + (++res.page)
- };
- }
+ function formatRequest(p, qs) {
+ var token = qs.access_token;
+ delete qs.access_token;
+ qs.oauth_token = token;
+ qs.v = 20121125;
+ return true;
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/github.js b/src/modules/github.js
index 1100d7b..ec7216f 100644
--- a/src/modules/github.js
+++ b/src/modules/github.js
@@ -1,3 +1,4 @@
+
(function(hello) {
hello.init({
@@ -13,7 +14,7 @@
response_type: 'code'
},
- scope: {
+ scope_map: {
email: 'user:email'
},
diff --git a/src/modules/google.js b/src/modules/google.js
index 411133e..865a0eb 100644
--- a/src/modules/google.js
+++ b/src/modules/google.js
@@ -16,7 +16,7 @@
},
// Authorization scopes
- scope: {
+ scope_map: {
basic: 'openid profile',
email: 'email',
birthday: '',
@@ -35,19 +35,19 @@
login: function(p) {
- if (p.qs.response_type === 'code') {
+ if (p.query.response_type === 'code') {
// Let's set this to an offline access to return a refresh_token
- p.qs.access_type = 'offline';
+ p.query.access_type = 'offline';
}
- else if (p.qs.response_type.indexOf('id_token') > -1) {
- p.qs.nonce = parseInt(Math.random() * 1e12, 10).toString(36);
+ else if (p.query.response_type.indexOf('id_token') > -1) {
+ p.query.nonce = parseInt(Math.random() * 1e12, 10).toString(36);
}
// Reauthenticate
// https://developers.google.com/identity/protocols/
if (p.options.force) {
- p.qs.prompt = 'consent';
+ p.query.prompt = 'consent';
}
},
@@ -583,4 +583,4 @@
}
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/instagram.js b/src/modules/instagram.js
index 5079fbc..e78c421 100644
--- a/src/modules/instagram.js
+++ b/src/modules/instagram.js
@@ -16,7 +16,7 @@
// Refresh the access_token once expired
refresh: true,
- scope: {
+ scope_map: {
basic: 'basic',
photos: '',
friends: 'relationships',
@@ -188,4 +188,4 @@
}
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/joinme.js b/src/modules/joinme.js
index 54d44bb..724a188 100644
--- a/src/modules/joinme.js
+++ b/src/modules/joinme.js
@@ -14,7 +14,7 @@
refresh: false,
- scope: {
+ scope_map: {
basic: 'user_info',
user: 'user_info',
scheduler: 'scheduler',
@@ -162,4 +162,4 @@
}
}
-}(hello));
+}(hello));
\ No newline at end of file
diff --git a/src/modules/linkedin.js b/src/modules/linkedin.js
index 12672e4..1d1f180 100644
--- a/src/modules/linkedin.js
+++ b/src/modules/linkedin.js
@@ -14,7 +14,7 @@
// Refresh the access_token once expired
refresh: true,
- scope: {
+ scope_map: {
basic: 'r_basicprofile',
email: 'r_emailaddress',
files: '',
@@ -198,4 +198,4 @@
callback('people/~/network/updates/key=' + id + '/is-liked');
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/soundcloud.js b/src/modules/soundcloud.js
index 78d825c..60ba176 100644
--- a/src/modules/soundcloud.js
+++ b/src/modules/soundcloud.js
@@ -82,4 +82,4 @@
}
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/spotify.js b/src/modules/spotify.js
index e8d3235..84c9985 100644
--- a/src/modules/spotify.js
+++ b/src/modules/spotify.js
@@ -14,7 +14,7 @@
// See: https://developer.spotify.com/web-api/using-scopes/
scope_delim: ' ',
- scope: {
+ scope_map: {
basic: '',
photos: '',
friends: 'user-follow-read',
@@ -96,4 +96,4 @@
}
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/tumblr.js b/src/modules/tumblr.js
index 5479cf3..9a2d471 100644
--- a/src/modules/tumblr.js
+++ b/src/modules/tumblr.js
@@ -107,4 +107,4 @@
}
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/twitter.js b/src/modules/twitter.js
index 829fbb1..035624f 100644
--- a/src/modules/twitter.js
+++ b/src/modules/twitter.js
@@ -219,4 +219,4 @@
}
*/
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/twitter.js.bak b/src/modules/twitter.js.bak
new file mode 100644
index 0000000..d640100
--- /dev/null
+++ b/src/modules/twitter.js.bak
@@ -0,0 +1,224 @@
+(function(hello) {
+
+var base = 'https://api.twitter.com/';
+
+hello.init({
+
+ twitter: {
+
+ // Ensure that you define an oauth_proxy
+ oauth: {
+ version: '1.0a',
+ auth: base + 'oauth/authenticate',
+ request: base + 'oauth/request_token',
+ token: base + 'oauth/access_token'
+ },
+
+ login: function(p) {
+ // Reauthenticate
+ // https://dev.twitter.com/oauth/reference/get/oauth/authenticate
+ var prefix = '?force_login=true';
+ this.oauth.auth = this.oauth.auth.replace(prefix, '') + (p.options.force ? prefix : '');
+ },
+
+ base: base + '1.1/',
+
+ get: {
+ me: 'account/verify_credentials.json',
+ 'me/friends': 'friends/list.json?count=@{limit|200}',
+ 'me/following': 'friends/list.json?count=@{limit|200}',
+ 'me/followers': 'followers/list.json?count=@{limit|200}',
+
+ // Https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline
+ 'me/share': 'statuses/user_timeline.json?count=@{limit|200}',
+
+ // Https://dev.twitter.com/rest/reference/get/favorites/list
+ 'me/like': 'favorites/list.json?count=@{limit|200}'
+ },
+
+ post: {
+ 'me/share': function(p, callback) {
+
+ var data = p.data;
+ p.data = null;
+
+ var status = [];
+
+ // Change message to status
+ if (data.message) {
+ status.push(data.message);
+ delete data.message;
+ }
+
+ // If link is given
+ if (data.link) {
+ status.push(data.link);
+ delete data.link;
+ }
+
+ if (data.picture) {
+ status.push(data.picture);
+ delete data.picture;
+ }
+
+ // Compound all the components
+ if (status.length) {
+ data.status = status.join(' ');
+ }
+
+ // Tweet media
+ if (data.file) {
+ data['media[]'] = data.file;
+ delete data.file;
+ p.data = data;
+ callback('statuses/update_with_media.json');
+ }
+
+ // Retweet?
+ else if ('id' in data) {
+ callback('statuses/retweet/' + data.id + '.json');
+ }
+
+ // Tweet
+ else {
+ // Assign the post body to the query parameters
+ hello.utils.extend(p.query, data);
+ callback('statuses/update.json?include_entities=1');
+ }
+ },
+
+ // See: https://dev.twitter.com/rest/reference/post/favorites/create
+ 'me/like': function(p, callback) {
+ var id = p.data.id;
+ p.data = null;
+ callback('favorites/create.json?id=' + id);
+ }
+ },
+
+ del: {
+
+ // See: https://dev.twitter.com/rest/reference/post/favorites/destroy
+ 'me/like': function(p, callback) {
+ p.method = 'post';
+ var id = p.data.id;
+ p.data = null;
+ callback('favorites/destroy.json?id=' + id);
+ }
+ },
+
+ wrap: {
+ me: function(res) {
+ formatError(res);
+ formatUser(res);
+ return res;
+ },
+
+ 'me/friends': formatFriends,
+ 'me/followers': formatFriends,
+ 'me/following': formatFriends,
+
+ 'me/share': function(res) {
+ formatError(res);
+ paging(res);
+ if (!res.error && 'length' in res) {
+ return {data: res};
+ }
+
+ return res;
+ },
+
+ 'default': function(res) {
+ res = arrayToDataResponse(res);
+ paging(res);
+ return res;
+ }
+ },
+ xhr: function(p) {
+
+ // Rely on the proxy for non-GET requests.
+ // Twitter OAuth1 requires ALL requests to be proxied for signing
+ return true;
+ }
+ }
+});
+
+function formatUser(o) {
+ if (o.id) {
+ if (o.name) {
+ var m = o.name.split(' ');
+ o.first_name = m.shift();
+ o.last_name = m.join(' ');
+ }
+
+ // See: https://dev.twitter.com/overview/general/user-profile-images-and-banners
+ o.thumbnail = o.profile_image_url_https || o.profile_image_url;
+ }
+
+ return o;
+}
+
+function formatFriends(o) {
+ formatError(o);
+ paging(o);
+ if (o.users) {
+ o.data = o.users.map(formatUser);
+ delete o.users;
+ }
+
+ return o;
+}
+
+function formatError(o) {
+ if (o.errors) {
+ var e = o.errors[0];
+ o.error = {
+ code: 'request_failed',
+ message: e.message
+ };
+ }
+}
+
+// Take a cursor and add it to the path
+function paging(res) {
+ // Does the response include a 'next_cursor_string'
+ if ('next_cursor_str' in res) {
+ // See: https://dev.twitter.com/docs/misc/cursoring
+ res.paging = {
+ next: '?cursor=' + res.next_cursor_str
+ };
+ }
+}
+
+function arrayToDataResponse(res) {
+ return Array.isArray(res) ? {data: res} : res;
+}
+
+/**
+// The documentation says to define user in the request
+// Although its not actually required.
+
+var user_id;
+
+function withUserId(callback){
+ if(user_id){
+ callback(user_id);
+ }
+ else{
+ hello.api('twitter:/me', function(o){
+ user_id = o.id;
+ callback(o.id);
+ });
+ }
+}
+
+function sign(url){
+ return function(p, callback){
+ withUserId(function(user_id){
+ callback(url+'?user_id='+user_id);
+ });
+ };
+}
+*/
+
+
+})(hello);
\ No newline at end of file
diff --git a/src/modules/vimeo.js b/src/modules/vimeo.js
index d65499b..c2c7a22 100644
--- a/src/modules/vimeo.js
+++ b/src/modules/vimeo.js
@@ -16,7 +16,7 @@
// Instruct node-oauth-shim to pass an extra Authorization header when granting
// Authorization: basic base64(client_id:cient_secret)
// https://developer.vimeo.com/api/authentication#generate-redirect
- p.qs.state.authorisation = 'header';
+ p.query.state.authorisation = 'header';
},
xhr: function(p) {
@@ -34,7 +34,7 @@
},
// See https://developer.vimeo.com/api/authentication#scopes
- scope: {
+ scope_map: {
basic: 'public',
videos: 'public private',
publish: 'create edit delete interact',
@@ -44,4 +44,4 @@
base: baseUrl
}
});
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/vk.js b/src/modules/vk.js
index c435643..71ebb66 100644
--- a/src/modules/vk.js
+++ b/src/modules/vk.js
@@ -15,7 +15,7 @@
// Authorization scopes
// See https://vk.com/dev/permissions
- scope: {
+ scope_map: {
email: 'email',
friends: 'friends',
photos: 'photos',
@@ -28,7 +28,7 @@
refresh: true,
login: function(p) {
- p.qs.display = window.navigator &&
+ p.query.display = window.navigator &&
window.navigator.userAgent &&
/ipad|phone|phone|android/.test(window.navigator.userAgent.toLowerCase()) ? 'mobile' : 'popup';
},
@@ -88,4 +88,4 @@
}
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/windows.js b/src/modules/windows.js
index 2dcb45e..8074aec 100644
--- a/src/modules/windows.js
+++ b/src/modules/windows.js
@@ -19,7 +19,7 @@
},
// Authorization scopes
- scope: {
+ scope_map: {
basic: 'wl.signin,wl.basic',
email: 'wl.emails',
birthday: 'wl.birthday',
@@ -183,4 +183,4 @@
return o;
}
-})(hello);
+})(hello);
\ No newline at end of file
diff --git a/src/modules/yahoo.js b/src/modules/yahoo.js
index a70b180..6c8b7ae 100644
--- a/src/modules/yahoo.js
+++ b/src/modules/yahoo.js
@@ -22,7 +22,7 @@
p.options.popup.width = 560;
// Yahoo throws an parameter error if for whatever reason the state.scope contains a comma, so lets remove scope
- try {delete p.qs.state.scope;}
+ try {delete p.query.state.scope;}
catch (e) {}
},
@@ -157,4 +157,4 @@
return 'https://query.yahooapis.com/v1/yql?q=' + (q + ' limit @{limit|100} offset @{start|0}').replace(/\s/g, '%20') + '&format=json';
}
-})(hello);
+})(hello);
\ No newline at end of file