-
Notifications
You must be signed in to change notification settings - Fork 0
/
authorize.mjs
151 lines (127 loc) · 4.03 KB
/
authorize.mjs
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* Magic Mirror
* Module: MMM-GoogleDocs-Notes
*
* By No3x
* MIT Licensed.
*/
import fs from 'node:fs/promises'
import axios from 'axios';
import ora from 'ora';
const SCOPES = [
'https://www.googleapis.com/auth/drive.file'
];
const MAX_POLLING_ATTEMPTS = 100;
const TOKEN_DIR = `${process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE}/.credentials`;
const TOKEN_PATH = `${TOKEN_DIR}/MMM-GoogleDocs-Notes.json`;
async function main() {
let credentials;
try {
const content = await fs.readFile('client_secret.json', 'utf-8');
credentials = JSON.parse(content);
} catch (err) {
console.error(`Error loading client secret file: ${err}`);
return true;
}
return await authorize(credentials);
}
async function pollSuccess(clientId, clientSecret, responseData) {
const data = {
client_id: clientId,
client_secret: clientSecret,
device_code: responseData.device_code,
grant_type: 'urn:ietf:params:oauth:grant-type:device_code'
};
const headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
const spinner = ora('Polling website...')
.start();
let response = null;
let attempts = 0;
while (attempts < MAX_POLLING_ATTEMPTS) {
try {
response = await axios.post(
'https://oauth2.googleapis.com/token',
new URLSearchParams(data).toString(),
{ headers }
);
if (response.data.access_token) {
// Stop the spinner and display the final result
spinner.succeed(`Authorization succeeded. Token: ${response.data.access_token}`);
return response.data;
}
} catch (error) {
if (error.response) {
spinner.text = `Authorization status: ${error.response.data.error}`;
} else if (error.request) {
spinner.text = `Something is wrong: ${error.message}`;
} else {
// Anything else
console.error('Error', error.message);
spinner.text = `Something is wrong: ${error.message}`;
}
}
// Wait for the specified interval before making the next request
await new Promise(resolve => setTimeout(resolve, responseData.interval * 1000));
// Update the spinner text with the number of attempts
spinner.text = `Polling authorization status ... (Attempt ${attempts + 1}/${MAX_POLLING_ATTEMPTS})`;
// Wait some time so the text is readable
await new Promise(resolve => setTimeout(resolve, 1000));
attempts++;
}
spinner.fail(`No attempts left. Please try again`);
}
/**
* Create an OAuth2 client with the given credentials, and then execute the
* given callback function.
*
* @param {Object} credentials The authorization client credentials.
*/
async function authorize(credentials) {
const { device_authorization_endpoint } = (await axios.get(`https://accounts.google.com/.well-known/openid-configuration`)).data;
const clientSecret = credentials.installed.client_secret;
const clientId = credentials.installed.client_id;
const data = {
client_id: clientId,
scope: `email profile ${SCOPES}`
};
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
try {
const response = await axios.post(device_authorization_endpoint, new URLSearchParams(data).toString(), config);
console.log(`Authorize MMM-GoogleDocs-Notes by visiting this url: ${response.data.verification_url} on any device and enter the code: ${response.data.user_code}`);
return await pollSuccess(clientId, clientSecret, response.data);
} catch (error) {
console.error('Error:', error.response.data.error || 'An unexpected error occurred.');
}
}
/**
* Store token to disk be used in later program executions.
*
* @param {Object} token The token to store to disk.
*/
async function storeToken(token) {
try {
await fs.mkdir(TOKEN_DIR);
} catch (err) {
if (err.code !== 'EEXIST') {
throw err;
}
}
try {
await fs.writeFile(TOKEN_PATH, JSON.stringify(token));
console.log(`Token stored to ${TOKEN_PATH}`);
} catch (err) {
console.error(`Error storing token: ${err}`);
}
}
function finishAuthorization() {
console.log('MMM-GoogleDocs-Notes is authorized.');
}
main()
.then(storeToken)
.then(finishAuthorization)
.catch(err => console.log(err));