-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.js
executable file
·109 lines (97 loc) · 4.29 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"use strict";
const axios = require('axios').default;
const FormData = require('form-data');
// This is hard-coded in https://www.life360.com/circles/scripts/ccf35026.scripts.js
// const LIFE360_CLIENT_SECRET = "cFJFcXVnYWJSZXRyZTRFc3RldGhlcnVmcmVQdW3hbUV4dWNyRUh1YzptM2ZydXBSZXRSZXN3ZXJFQ2hBUHJFOTZxYWtFZHI0Vg==";
const LIFE360_CLIENT_SECRET = "Y2F0aGFwYWNyQVBoZUtVc3RlOGV2ZXZldnVjSGFmZVRydVl1ZnJhYzpkOEM5ZVlVdkE2dUZ1YnJ1SmVnZXRyZVZ1dFJlQ1JVWQ==";
const LIFE360_API = "https://api-cloudfront.life360.com:443/v3"
const USER_AGENT = "node-red-contrib-life360"
const authHeaders = (session) => ({
headers: {'Authorization': `${session.token_type} ${session.access_token}`}
});
const handleError = (errorPrefix) => (error) => {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
throw new Error(`${errorPrefix}: ${error.response.status} ${error.toString()} ${error.response.data.errorMessage}`)
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
throw new Error(`${errorPrefix}: ${error.message}`)
} else {
// Something happened in setting up the request that triggered an Error
throw new Error(`${errorPrefix}: ${error.toString()}`)
}
}
/**
* Login to life360.com and get an oauth token.
* Specify a username OR both a phone number and country code.
* username: Life360 username, or undefined if phone specified.
* password: Life360 password.
* phone: Life360 phone, or undefined if username specified.
* countryCode: Optional phone country code, defaults to 1 if not specified.
* returns: Life360 session.
*/
module.exports.authenticate = function (username, password) {
username = typeof username !== 'undefined' ? username : '';
if (!password) return Promise.reject(new Error("No password specified."))
const form = {
username,
password,
grant_type: 'password'
};
const bodyFormData = Object.keys(form).reduce((formData, key) => {
formData.append(key, form[key]);
return formData;
}, new FormData())
return axios.post(`${LIFE360_API}/oauth2/token.json`, bodyFormData, {
headers: bodyFormData.getHeaders({'User-Agent': `${USER_AGENT}`, 'Authorization': `Authorization: Basic ${LIFE360_CLIENT_SECRET}`})
}).then(response => {
if (!response.data.access_token) {
throw new Error("Unauthorized");
} else {
return {
access_token: response.data.access_token,
token_type: response.data.token_type
};
}
}).catch(handleError('Life360 server error logging in'))
}
/**
* Fetch the user's circles
*/
module.exports.circles = function (session) {
if (!session) return Promise.reject(new Error("session not specified"))
return axios.get(`${LIFE360_API}/circles`, authHeaders(session))
.then(({data}) => data.circles)
.catch(handleError('Life360 server error getting circles'))
}
/**
* Fetch a specific circle by circle ID
*/
module.exports.circle = function (session, circleId) {
if (!session) return Promise.reject(new Error("session not specified"))
if (!circleId) return Promise.reject(new Error("circleId not specified"))
return axios.get(`${LIFE360_API}/circles/${circleId}`, authHeaders(session))
.then(({data}) => data)
.catch(handleError('Life360 server error getting circle'))
}
/**
* Fetch the user's places
*/
module.exports.places = function (session, circleId) {
if (!session) return Promise.reject(new Error("session not specified"))
return axios.get(`${LIFE360_API}/circles/${circleId}/allplaces`, authHeaders(session))
.then(({data}) => data.places)
.catch(handleError('Life360 server error getting places'))
}
/**
* Fetch the user's members
*/
module.exports.members = function (session, circleId) {
if (!session) return Promise.reject(new Error("session not specified"))
return axios.get(`${LIFE360_API}/circles/${circleId}/members`, authHeaders(session))
.then(({data}) => data.members)
.catch(handleError('Life360 server error getting members'))
}