138 lines
3.8 KiB
JavaScript
138 lines
3.8 KiB
JavaScript
import request from 'request';
|
|
|
|
if (!Meteor.isServer) throw 'Server only, do not import this code in the client';
|
|
|
|
const config = ServiceConfiguration.configurations.findOne({service: 'patreon'});
|
|
const getIdentity = function(accessToken, callback){
|
|
request({
|
|
uri: 'https://www.patreon.com/api/oauth2/v2/identity',
|
|
headers:{
|
|
Authorization: 'Bearer ' + accessToken,
|
|
},
|
|
qs: {
|
|
'include': 'memberships',
|
|
'fields[member]': 'currently_entitled_amount_cents',
|
|
}
|
|
}, callback);
|
|
};
|
|
|
|
// Should return a new access token for the user
|
|
// callback is called with (error, response, body)
|
|
const refreshAccessToken = Meteor.wrapAsync(function(refreshToken, userId, callback){
|
|
request({
|
|
method: 'POST',
|
|
uri: 'https://www.patreon.com/api/oauth2/token',
|
|
qs: {
|
|
grant_type: 'refresh_token',
|
|
refresh_token: refreshToken,
|
|
client_id: config.clientId,
|
|
client_secret: config.secret,
|
|
}
|
|
}, Meteor.bindEnvironment((error, response, body) => {
|
|
// Should return an access token, valid for 1 month, which needs to be
|
|
// stored and used to make requests on behalf of the user
|
|
if (error){
|
|
if (callback){
|
|
callback(error);
|
|
return;
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
let token;
|
|
try {
|
|
token = JSON.parse(body);
|
|
writePatreonToken(userId, token);
|
|
callback(undefined, token.access_token);
|
|
} catch(error) {
|
|
if (callback){
|
|
callback(error);
|
|
return;
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
}));
|
|
});
|
|
|
|
const updateIdentity = Meteor.wrapAsync(function(accessToken, userId, callback){
|
|
getIdentity(accessToken, Meteor.bindEnvironment((error, response, body) => {
|
|
if (error){
|
|
throw error;
|
|
}
|
|
try {
|
|
let identity = JSON.parse(body);
|
|
let membership = identity.included[0];
|
|
let entitledAmount = membership && membership.attributes
|
|
.currently_entitled_amount_cents || 0;
|
|
writeEntitledCents(userId, entitledAmount);
|
|
if (callback) callback();
|
|
} catch(error) {
|
|
if(callback) {
|
|
callback(error);
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
}));
|
|
});
|
|
|
|
const updatePatreonDetails = function(user){
|
|
if (!user) {
|
|
throw new Meteor.Error('no-user', 'User must be provided to update patreon details');
|
|
}
|
|
if (!user.services.patreon || !user.services.patreon.accessToken){
|
|
throw new Meteor.Error('no-patreon-access', 'Patreon access token not found for this user');
|
|
}
|
|
let accessToken = user.services.patreon.accessToken;
|
|
if (user.services.patreon.tokenExpiryDate < new Date()){
|
|
// Token expired, refresh it before continuing
|
|
accessToken = refreshAccessToken(user.services.patreon.refreshToken, user._id);
|
|
}
|
|
updateIdentity(accessToken, user._id);
|
|
}
|
|
|
|
Meteor.methods({
|
|
updateMyPatreonDetails(){
|
|
const userId = this.userId;
|
|
if (!userId) throw new Meteor.Error('not-logged-in', 'You must be logged in to update Patreon details');
|
|
const user = Meteor.users.findOne(userId, {fields: {patreon: 1}});
|
|
updatePatreonDetails(user);
|
|
},
|
|
});
|
|
|
|
const writePatreonToken = function(userId, {
|
|
access_token, refresh_token, expires_in
|
|
}){
|
|
// The expiry date is now plus `expires_in` seconds
|
|
let expiryDate = new Date();
|
|
expiryDate.setSeconds(expiryDate.getSeconds() + expires_in);
|
|
// Expire a day early so we don't accidentally miss it
|
|
expiryDate.setDate(expiryDate.getDate() - 1);
|
|
|
|
// Write
|
|
Meteor.users.update(userId, {
|
|
$set: {
|
|
'patreon.accessToken': access_token,
|
|
'patreon.refreshToken': refresh_token,
|
|
'patreon.tokenExpiryDate': expiryDate,
|
|
},
|
|
$unset: {
|
|
'patreon.error': 1,
|
|
},
|
|
});
|
|
};
|
|
|
|
const writeEntitledCents = function(userId, amount){
|
|
Meteor.users.update(userId, {
|
|
$set: {
|
|
'services.patreon.entitledCents': amount,
|
|
},
|
|
$unset: {
|
|
'patreon.error': 1,
|
|
},
|
|
});
|
|
};
|
|
|
|
export { updatePatreonDetails };
|