Skip to content

Commit 81d8474

Browse files
committed
Step 17.17: Create facebook Meteor service
1 parent bcb567c commit 81d8474

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

api/server/services/facebook.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import {Users} from "../collections/users";
2+
import {FB} from "fb";
3+
4+
export interface FbProfile {
5+
name?: string;
6+
pictureUrl?: string;
7+
};
8+
9+
export class FacebookService {
10+
private APP_ID: string = Meteor.settings.private.oAuth.facebook.appId;
11+
private APP_SECRET: string = Meteor.settings.private.oAuth.facebook.secret;
12+
13+
constructor() {
14+
}
15+
16+
async getAppToken(): Promise<string> {
17+
try {
18+
return (await FB.api(`/oauth/access_token?client_id=${this.APP_ID}&client_secret=${this.APP_SECRET}&grant_type=client_credentials`)).access_token;
19+
} catch (e) {
20+
throw new Meteor.Error('cannot-receive', 'Cannot get an app token');
21+
}
22+
}
23+
24+
//TODO: create a before.insert in the users collection to check if the token is valid
25+
async tokenIsValid(token: string): Promise<boolean> {
26+
try {
27+
return (await FB.api(`debug_token?input_token=${token}&access_token=${await this.getAppToken()}`)).data.is_valid;
28+
} catch (e) {
29+
console.error(e);
30+
return false;
31+
}
32+
}
33+
34+
// Useless because we already got a long lived token
35+
async getLongLivedToken(token: string): Promise<string> {
36+
try {
37+
return (await FB.api(`/oauth/access_token?grant_type=fb_exchange_token&client_id=${this.APP_ID}&client_secret=${this.APP_SECRET}&fb_exchange_token=${token}`)).access_token;
38+
} catch (e) {
39+
throw new Meteor.Error('cannot-receive', 'Cannot get a long lived token');
40+
}
41+
}
42+
43+
async getAccessToken(user: string): Promise<string> {
44+
//TODO: check if token has expired, if so the user must login again
45+
try {
46+
const facebook = await Users.findOne(user).services.facebook;
47+
if (facebook.accessToken) {
48+
return facebook.accessToken;
49+
} else {
50+
throw new Error();
51+
}
52+
} catch (e) {
53+
throw new Meteor.Error('unauthorized', 'User must be logged-in with Facebook to call this method');
54+
}
55+
}
56+
57+
async getFriends(accessToken: string, user?: string): Promise<any> {
58+
//TODO: check if more permissions are needed, if so user must login again
59+
try {
60+
const params: any = {
61+
//fields: 'id,name',
62+
limit: 5000
63+
};
64+
let friends: string[] = [];
65+
let result: any;
66+
const fb = FB.withAccessToken(accessToken);
67+
68+
do {
69+
result = await fb.api(`/${user || 'me'}/friends`, params);
70+
friends = friends.concat(result.data);
71+
params.after = result.paging && result.paging.cursors && result.paging.cursors.after;
72+
} while (result.paging && result.paging.next);
73+
74+
return friends;
75+
} catch (e) {
76+
console.error(e);
77+
throw new Meteor.Error('cannot-receive', 'Cannot get friends')
78+
}
79+
}
80+
81+
async getProfile(accessToken: string, user?: string): Promise<FbProfile> {
82+
//TODO: check if more permissions are needed, if so user must login again
83+
try {
84+
const params: any = {
85+
fields: 'id,name,picture.width(800).height(800)'
86+
};
87+
88+
let profile: FbProfile = {};
89+
90+
const fb = FB.withAccessToken(accessToken);
91+
const result = await fb.api(`/${user || 'me'}`, params);
92+
93+
profile.name = result.name;
94+
profile.pictureUrl = result.picture.data.url;
95+
96+
return profile;
97+
} catch (e) {
98+
console.error(e);
99+
throw new Meteor.Error('cannot-receive', 'Cannot get profile')
100+
}
101+
}
102+
}
103+
104+
export const facebookService = new FacebookService();

0 commit comments

Comments
 (0)