1. Panoramica
In questo codelab imparerai a utilizzare Presentazioni Google come strumento di presentazione personalizzato per un'analisi delle licenze software più comuni. Eseguirai query su tutto il codice open source su GitHub utilizzando l'API BigQuery e creerai una presentazione utilizzando l'API Google Presentazioni per presentare i risultati. L'applicazione di esempio è creata utilizzando Node.js, ma gli stessi principi di base sono applicabili a qualsiasi architettura.
Obiettivi didattici
- Creare presentazioni utilizzando l'API Slides
- Utilizzare BigQuery per ottenere informazioni su un set di dati di grandi dimensioni
- Copiare un file utilizzando l'API Google Drive
Che cosa ti serve
- Node.js installato
- Accesso a internet e a un browser web
- Un Account Google
- Un progetto Google Cloud
2. recupera il codice campione
Puoi scaricare tutto il codice di esempio sul computer…
...oppure clona il repository GitHub dalla riga di comando.
git clone https://github.com/googleworkspace/slides-api.git
Il repository contiene un insieme di directory che rappresentano ogni passaggio del processo, nel caso in cui tu debba fare riferimento a una versione funzionante.
Lavorerai sulla copia nella directory start
, ma puoi fare riferimento alle altre o copiare file da queste, se necessario.
3. Esegui l'app di esempio
Per prima cosa, avvia lo script Node. Dopo aver scaricato il codice, segui le istruzioni riportate di seguito per installare e avviare l'applicazione Node.js:
- Apri un terminale a riga di comando sul computer e vai alla directory
start
del codelab. - Inserisci il seguente comando per installare le dipendenze Node.js.
npm install
- Inserisci il seguente comando per eseguire lo script:
node .
- Leggi il messaggio di saluto che mostra i passaggi per questo progetto.
-- Start generating slides. --
TODO: Get Client Secrets
TODO: Authorize
TODO: Get Data from BigQuery
TODO: Create Slides
TODO: Open Slides
-- Finished generating slides. --
Puoi consultare il nostro elenco di elementi da fare in slides.js
, license.js
e auth.js
. Tieni presente che utilizziamo le Promise di JavaScript per collegare i passaggi necessari per completare l'app, poiché ogni passaggio dipende dal completamento del passaggio precedente.
Se non hai dimestichezza con le promesse, non preoccuparti: ti forniremo tutto il codice di cui hai bisogno. In breve, le promesse ci offrono un modo per gestire l'elaborazione asincrona in modo più sincrono.
4. Ottenere i client secret
Per utilizzare le API Presentazioni, BigQuery e Drive, creeremo un client OAuth e un account di servizio.
Configurare Google Developers Console
- Utilizza questa procedura guidata per creare o selezionare un progetto in Google Developers Console e attivare automaticamente l'API. Fai clic su Continua, quindi su Vai alle credenziali.
- Nella pagina Aggiungi le credenziali al progetto, fai clic sul pulsante Annulla.
- Nella parte superiore della pagina, seleziona la scheda Schermata di consenso OAuth. Seleziona un indirizzo email, inserisci il nome del prodotto
Slides API Codelab
e fai clic sul pulsante Salva.
Abilita le API BigQuery, Drive e Presentazioni
- Seleziona la scheda Dashboard, fai clic sul pulsante Attiva API e abilita le tre API seguenti:
- API BigQuery
- API Google Drive
- API Google Slides
Scarica il client secret OAuth (per Presentazioni e Drive)
- Seleziona la scheda Credenziali, fai clic sul pulsante Crea credenziali e seleziona ID client OAuth.
- Seleziona il tipo di applicazione Altro, inserisci il nome
Google Slides API Codelab
e fai clic sul pulsante Crea.Fai clic su OK per chiudere la finestra di dialogo visualizzata. - Fai clic sul pulsante file_download (Scarica JSON) a destra dell'ID client.
- Rinomina il file segreto in
client_secret.json
e copialo nelle directory start/ e finish/.
Scarica il segreto dell'account di servizio (per BigQuery)
- Seleziona la scheda Credenziali, fai clic sul pulsante Crea credenziali e seleziona Chiave account di servizio.
- Nel menu a discesa, seleziona Nuovo account di servizio. Scegli il nome
Slides API Codelab Service
per il servizio. Poi fai clic su Ruolo, scorri fino a BigQuery e seleziona sia Visualizzatore dati BigQuery sia Utente job BigQuery. - In Tipo di chiave, seleziona JSON.
- Fai clic su Crea. Il file della chiave verrà scaricato automaticamente sul tuo computer. Fai clic su Chiudi per uscire dalla finestra di dialogo visualizzata.
- Rinomina il file segreto in
service_account_secret.json
e copialo nelle directory start/ e finish/.
Ottenere i client secret
In start/auth.js
, compiliamo il metodo getClientSecrets
.
auth.js
const fs = require('fs');
/**
* Loads client secrets from a local file.
* @return {Promise} A promise to return the secrets.
*/
module.exports.getClientSecrets = () => {
return new Promise((resolve, reject) => {
fs.readFile('client_secret.json', (err, content) => {
if (err) return reject('Error loading client secret file: ' + err);
console.log('loaded secrets...');
resolve(JSON.parse(content));
});
});
}
Ora abbiamo caricato i client secret. Le credenziali verranno passate alla promessa successiva. Esegui il progetto con node .
per assicurarti che non siano presenti errori.
5. Creare un client OAuth2
Per creare le diapositive, aggiungiamo l'autenticazione alle API Google aggiungendo il seguente codice al file auth.js. Questa autenticazione richiede l'accesso al tuo Account Google per leggere e scrivere file in Google Drive, creare presentazioni in Presentazioni Google ed eseguire query di sola lettura da Google BigQuery. (Nota: non abbiamo modificato getClientSecrets
)
auth.js
const fs = require('fs');
const readline = require('readline');
const openurl = require('openurl');
const googleAuth = require('google-auth-library');
const TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH ||
process.env.USERPROFILE) + '/.credentials/';
const TOKEN_PATH = TOKEN_DIR + 'slides.googleapis.com-nodejs-quickstart.json';
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/slides.googleapis.com-nodejs-quickstart.json
const SCOPES = [
'https://www.googleapis.com/auth/presentations', // needed to create slides
'https://www.googleapis.com/auth/drive', // read and write files
'https://www.googleapis.com/auth/bigquery.readonly' // needed for bigquery
];
/**
* Loads client secrets from a local file.
* @return {Promise} A promise to return the secrets.
*/
module.exports.getClientSecrets = () => {
return new Promise((resolve, reject) => {
fs.readFile('client_secret.json', (err, content) => {
if (err) return reject('Error loading client secret file: ' + err);
console.log('loaded secrets...');
resolve(JSON.parse(content));
});
});
}
/**
* Create an OAuth2 client promise with the given credentials.
* @param {Object} credentials The authorization client credentials.
* @param {function} callback The callback for the authorized client.
* @return {Promise} A promise to return the OAuth client.
*/
module.exports.authorize = (credentials) => {
return new Promise((resolve, reject) => {
console.log('authorizing...');
const clientSecret = credentials.installed.client_secret;
const clientId = credentials.installed.client_id;
const redirectUrl = credentials.installed.redirect_uris[0];
const auth = new googleAuth();
const oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) {
getNewToken(oauth2Client).then(() => {
resolve(oauth2Client);
});
} else {
oauth2Client.credentials = JSON.parse(token);
resolve(oauth2Client);
}
});
});
}
/**
* Get and store new token after prompting for user authorization, and then
* fulfills the promise. Modifies the `oauth2Client` object.
* @param {google.auth.OAuth2} oauth2Client The OAuth2 client to get token for.
* @return {Promise} A promise to modify the oauth2Client credentials.
*/
function getNewToken(oauth2Client) {
console.log('getting new auth token...');
openurl.open(oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES
}));
console.log(''); // \n
return new Promise((resolve, reject) => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oauth2Client.getToken(code, (err, token) => {
if (err) return reject(err);
oauth2Client.credentials = token;
let storeTokenErr = storeToken(token);
if (storeTokenErr) return reject(storeTokenErr);
resolve();
});
});
});
}
/**
* Store token to disk be used in later program executions.
* @param {Object} token The token to store to disk.
* @return {Error?} Returns an error or undefined if there is no error.
*/
function storeToken(token) {
try {
fs.mkdirSync(TOKEN_DIR);
fs.writeFileSync(TOKEN_PATH, JSON.stringify(token));
} catch (err) {
if (err.code != 'EEXIST') return err;
}
console.log('Token stored to ' + TOKEN_PATH);
}
6. Configurare BigQuery
Esplora BigQuery (facoltativo)
BigQuery ci consente di eseguire query su set di dati di grandi dimensioni in pochi secondi. Utilizziamo l'interfaccia web prima di eseguire query in modo programmatico. Se non hai mai configurato BigQuery, segui i passaggi descritti in questa guida introduttiva.
Apri la console Cloud per sfogliare i dati di GitHub disponibili in BigQuery ed eseguire le tue query. Scopri le licenze software più utilizzate su GitHub scrivendo questa query e premendo il pulsante Esegui.
bigquery.sql
WITH AllLicenses AS (
SELECT * FROM `bigquery-public-data.github_repos.licenses`
)
SELECT
license,
COUNT(*) AS count,
ROUND((COUNT(*) / (SELECT COUNT(*) FROM AllLicenses)) * 100, 2) AS percent
FROM `bigquery-public-data.github_repos.licenses`
GROUP BY license
ORDER BY count DESC
LIMIT 10
Abbiamo appena analizzato milioni di repository pubblici su GitHub e abbiamo scoperto le licenze più utilizzate. Interessante! Ora impostiamo l'esecuzione della stessa query, ma questa volta in modo programmatico.
Configurare BigQuery
Sostituisci il codice nel file license.js
. La funzione bigquery.query
restituisce una promessa.
license**.js**
const google = require('googleapis');
const read = require('read-file');
const BigQuery = require('@google-cloud/bigquery');
const bigquery = BigQuery({
credentials: require('./service_account_secret.json')
});
// See codelab for other queries.
const query = `
WITH AllLicenses AS (
SELECT * FROM \`bigquery-public-data.github_repos.licenses\`
)
SELECT
license,
COUNT(*) AS count,
ROUND((COUNT(*) / (SELECT COUNT(*) FROM AllLicenses)) * 100, 2) AS percent
FROM \`bigquery-public-data.github_repos.licenses\`
GROUP BY license
ORDER BY count DESC
LIMIT 10
`;
/**
* Get the license data from BigQuery and our license data.
* @return {Promise} A promise to return an object of licenses keyed by name.
*/
module.exports.getLicenseData = (auth) => {
console.log('querying BigQuery...');
return bigquery.query({
query,
useLegacySql: false,
useQueryCache: true,
}).then(bqData => Promise.all(bqData[0].map(getLicenseText)))
.then(licenseData => new Promise((resolve, reject) => {
resolve([auth, licenseData]);
}))
.catch((err) => console.error('BigQuery error:', err));
}
/**
* Gets a promise to get the license text about a license
* @param {object} licenseDatum An object with the license's
* `license`, `count`, and `percent`
* @return {Promise} A promise to return license data with license text.
*/
function getLicenseText(licenseDatum) {
const licenseName = licenseDatum.license;
return new Promise((resolve, reject) => {
read(`licenses/${licenseName}.txt`, 'utf8', (err, buffer) => {
if (err) return reject(err);
resolve({
licenseName,
count: licenseDatum.count,
percent: licenseDatum.percent,
license: buffer.substring(0, 1200) // first 1200 characters
});
});
});
}
Prova a console.log
alcuni dei dati all'interno del callback della nostra promessa per comprendere la struttura dei nostri oggetti e vedere il codice in azione.
7. Creazione slide
E ora la parte divertente. Creiamo delle diapositive chiamando i metodi create
e batchUpdate
dell'API Slides. Il nostro file deve essere sostituito con quanto segue:
slides.js
const google = require('googleapis');
const slides = google.slides('v1');
const drive = google.drive('v3');
const openurl = require('openurl');
const commaNumber = require('comma-number');
const SLIDE_TITLE_TEXT = 'Open Source Licenses Analysis';
/**
* Get a single slide json request
* @param {object} licenseData data about the license
* @param {object} index the slide index
* @return {object} The json for the Slides API
* @example licenseData: {
* "licenseName": "mit",
* "percent": "12.5",
* "count": "1667029"
* license:"<body>"
* }
* @example index: 3
*/
function createSlideJSON(licenseData, index) {
// Then update the slides.
const ID_TITLE_SLIDE = 'id_title_slide';
const ID_TITLE_SLIDE_TITLE = 'id_title_slide_title';
const ID_TITLE_SLIDE_BODY = 'id_title_slide_body';
return [{
// Creates a "TITLE_AND_BODY" slide with objectId references
createSlide: {
objectId: `${ID_TITLE_SLIDE}_${index}`,
slideLayoutReference: {
predefinedLayout: 'TITLE_AND_BODY'
},
placeholderIdMappings: [{
layoutPlaceholder: {
type: 'TITLE'
},
objectId: `${ID_TITLE_SLIDE_TITLE}_${index}`
}, {
layoutPlaceholder: {
type: 'BODY'
},
objectId: `${ID_TITLE_SLIDE_BODY}_${index}`
}]
}
}, {
// Inserts the license name, percent, and count in the title
insertText: {
objectId: `${ID_TITLE_SLIDE_TITLE}_${index}`,
text: `#${index + 1} ${licenseData.licenseName} — ~${licenseData.percent}% (${commaNumber(licenseData.count)} repos)`
}
}, {
// Inserts the license in the text body paragraph
insertText: {
objectId: `${ID_TITLE_SLIDE_BODY}_${index}`,
text: licenseData.license
}
}, {
// Formats the slide paragraph's font
updateParagraphStyle: {
objectId: `${ID_TITLE_SLIDE_BODY}_${index}`,
fields: '*',
style: {
lineSpacing: 10,
spaceAbove: {magnitude: 0, unit: 'PT'},
spaceBelow: {magnitude: 0, unit: 'PT'},
}
}
}, {
// Formats the slide text style
updateTextStyle: {
objectId: `${ID_TITLE_SLIDE_BODY}_${index}`,
style: {
bold: true,
italic: true,
fontSize: {
magnitude: 10,
unit: 'PT'
}
},
fields: '*',
}
}];
}
/**
* Creates slides for our presentation.
* @param {authAndGHData} An array with our Auth object and the GitHub data.
* @return {Promise} A promise to return a new presentation.
* @see https://developers.google.com/apis-explorer/#p/slides/v1/
*/
module.exports.createSlides = (authAndGHData) => new Promise((resolve, reject) => {
console.log('creating slides...');
const [auth, ghData] = authAndGHData;
// First copy the template slide from drive.
drive.files.copy({
auth: auth,
fileId: '1toV2zL0PrXJOfFJU-NYDKbPx9W0C4I-I8iT85TS0fik',
fields: 'id,name,webViewLink',
resource: {
name: SLIDE_TITLE_TEXT
}
}, (err, presentation) => {
if (err) return reject(err);
const allSlides = ghData.map((data, index) => createSlideJSON(data, index));
slideRequests = [].concat.apply([], allSlides); // flatten the slide requests
slideRequests.push({
replaceAllText: {
replaceText: SLIDE_TITLE_TEXT,
containsText: { text: '{{TITLE}}' }
}
})
// Execute the requests
slides.presentations.batchUpdate({
auth: auth,
presentationId: presentation.id,
resource: {
requests: slideRequests
}
}, (err, res) => {
if (err) {
reject(err);
} else {
resolve(presentation);
}
});
});
});
8. Apri Presentazioni
Infine, apri la presentazione nel browser. Aggiorna il seguente metodo in slides.js
.
slides.js
/**
* Opens a presentation in a browser.
* @param {String} presentation The presentation object.
*/
module.exports.openSlidesInBrowser = (presentation) => {
console.log('Presentation URL:', presentation.webViewLink);
openurl.open(presentation.webViewLink);
}
Esegui il progetto un'ultima volta per visualizzare il risultato finale.
9. Complimenti!
Hai generato correttamente Presentazioni Google dai dati analizzati utilizzando BigQuery. Lo script crea una presentazione utilizzando l'API Google Presentazioni e BigQuery per generare un report sull'analisi delle licenze software più comuni.
Possibili miglioramenti
Ecco alcune idee aggiuntive per creare un'integrazione ancora più efficace:
- Aggiungere immagini a ogni diapositiva
- Condividere le diapositive via email utilizzando l'API Gmail
- Personalizzare la diapositiva del modello come argomento della riga di comando
Scopri di più
- Leggi la documentazione per sviluppatori dell'API Google Slides.
- Pubblica domande e trova risposte su Stack Overflow utilizzando il tag google-slides-api.