2024-08-25 16:32:04 +08:00

133 lines
4.5 KiB
JavaScript

const scripts = ['https://apis.google.com/js/api.js', 'https://accounts.google.com/gsi/client'];
const DISCOVERY_DOC = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';
const CLIENT_ID = '53206975661-ih3r0ubph3rqejdq97b029difbrk2bqj.apps.googleusercontent.com';
// Authorization scopes required by the API; multiple scopes can be included, separated by spaces.
const SCOPES = 'openid email profile';
const SCOPES_DRIVE = 'https://www.googleapis.com/auth/drive.appdata';
export class GoogleClient {
async initGApi() {
return new Promise((resolve, reject) => {
gapi.load('client', async () => {
await gapi.client.init({ discoveryDocs: [DISCOVERY_DOC] });
resolve();
});
});
}
initTokenClient(scopes, cb) {
this.tokenClient = google.accounts.oauth2.initTokenClient({
client_id: CLIENT_ID,
scope: scopes,
callback: cb // defined later
});
console.log('google client init success');
}
async initGoolgeClient() {
await Promise.all([loadSingleScript([scripts[0]]), loadSingleScript([scripts[1]])]);
await this.initGApi();
this.initTokenClient(SCOPES);
}
login(funid) {
this.tokenClient.callback = async (resp) => {
if (resp.error !== undefined) {
throw resp;
}
console.log('token: ', gapi.client.getToken());
this.access_token = gapi.client.getToken().access_token;
let result = {
data: gapi.client.getToken().access_token,
errcode: 0,
};
jc.wallet.nativeSvr.handleNativeCallback(funid, JSON.stringify(result));
};
if (gapi.client.getToken() === null) {
// Prompt the user to select a Google Account and ask for consent to share their data
// when establishing a new session.
this.tokenClient.requestAccessToken({ prompt: 'consent' });
} else {
// Skip display of account chooser and consent dialog for an existing session.
this.tokenClient.requestAccessToken({ prompt: '' });
}
}
generateCfgName(key) {
return `wallet_${key}.json`;
}
hasDriveScope() {
return google.accounts.oauth2.hasGrantedAnyScope(gapi.client.getToken(), SCOPES_DRIVE);
}
async requestDriveScope() {
return new Promise((resolve, reject) => {
this.initTokenClient(SCOPES + " " + SCOPES_DRIVE, (resp) => {
if (resp.error !== undefined) {
throw resp;
}
resolve();
});
this.tokenClient.requestAccessToken({ prompt: 'consent' });
});
}
async listFiles() {
return gapi.client.drive.files.list({
spaces: 'appDataFolder',
fields: 'files(id, name)',
});
}
async downloadCfg(key) {
if (!this.hasDriveScope()) {
await this.requestDriveScope();
}
let fileName = this.generateCfgName(key)
let files = await this.listFiles();
let file = files.result.files.find((file) => file.name.toLowerCase() === fileName.toLowerCase());
if (file) {
let fileId = file.id;
let info = await gapi.client.drive.files.get({
fileId: fileId,
alt: 'media',
});
return info.result;
}
}
async uploadOneFile(content, fileName) {
return new Promise((resolve, reject) => {
var file = new Blob([JSON.stringify(content)], {type: 'application/json'});
var metadata = {
'name': fileName, // Filename at Google Drive
'mimeType': 'application/json', // mimeType at Google Drive
'parents': ['appDataFolder'], // Folder ID at Google Drive
};
var accessToken = gapi.auth.getToken().access_token; // Here gapi is used for retrieving the access token.
var form = new FormData();
form.append('metadata', new Blob([JSON.stringify(metadata)], {type: 'application/json'}));
form.append('file', file);
var xhr = new XMLHttpRequest();
xhr.open('post', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id');
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xhr.responseType = 'json';
xhr.onload = () => {
console.log(xhr.response.id); // Retrieve uploaded file ID.
resolve && resolve(xhr.response);
};
xhr.send(form);
});
}
async uploadCfg(key, pass) {
if (!this.hasDriveScope()) {
await this.requestDriveScope();
}
let fileName = this.generateCfgName(key);
let files = await this.listFiles();
let file = files.result.files.find((file) => file.name.toLowerCase() === fileName.toLowerCase());
if (!file) {
let res = await this.uploadOneFile({pass}, fileName);
return res;
} else {
return file;
}
}
}