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 un file di Presentazioni utilizzando l'API Google Slides 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
- Creazione di presentazioni mediante l'API Slides
- Utilizzare BigQuery per ottenere approfondimenti 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 tuo computer...
...o 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 della procedura, nel caso in cui tu debba fare riferimento a una versione di lavoro.
Lavorerai sulla copia che si trova nella directory start, ma potrai fare riferimento agli altri file o copiarli, se necessario.
3. Esegui l'app di esempio
Per prima cosa, eseguiamo lo script Node. Una volta scaricato il codice, segui le istruzioni riportate di seguito per installare e avviare l'applicazione Node.js:
- Apri un terminale della riga di comando sul computer e vai alla directory
startdel codelab. - Inserisci il seguente comando per installare le dipendenze Node.js.
npm install
- Inserisci il seguente comando per eseguire lo script:
node .
- Osserva 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 visualizzare il nostro elenco di cose da fare in slides.js, license.js e auth.js. Tieni presente che utilizziamo le promesse JavaScript per concatenare i passaggi necessari per completare l'app, poiché ogni passaggio dipende dal completamento del precedente.
Se non hai familiarità con le promesse, non preoccuparti, ti forniremo tutto il codice necessario. In breve, le promesse ci consentono di gestire l'elaborazione asincrona in modo più sincrono.
4. Recupera i client secret
Per utilizzare le API Slides, 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, poi su Vai alle credenziali.
- Nella pagina Aggiungi 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 Codelabe fai clic sul pulsante Salva.
Abilita le API BigQuery, Drive e Slides
- Seleziona la scheda Dashboard, fai clic sul pulsante Abilita API e abilita le seguenti tre API:
- 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 Codelabe fai clic sul pulsante Crea.Fai clic su Ok per chiudere la finestra di dialogo risultante. - Fai clic sul pulsante file_download (Scarica JSON) a destra dell'ID client.
- Rinomina il file segreto in
client_secret.jsone copialo nelle directory start/ e finish/.
Scarica il segreto del service account (per BigQuery)
- Seleziona la scheda Credenziali, fai clic sul pulsante Crea credenziali e seleziona Chiave service account.
- Nel menu a discesa, seleziona Nuovo service account. Scegli il nome
Slides API Codelab Serviceper il tuo servizio. Poi fai clic su Ruolo, scorri fino a BigQuery e seleziona Visualizzatore dati BigQuery e Utente job BigQuery. - In Tipo di chiave, seleziona JSON.
- Fai clic su Crea. Il file della chiave verrà scaricato automaticamente sul computer. Fai clic su Chiudi per uscire dalla finestra di dialogo visualizzata.
- Rinomina il file segreto in
service_account_secret.jsone copialo nelle directory start/ e finish/.
Recupera 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 trasmesse alla promessa successiva. Esegui il progetto con node . per assicurarti che non ci siano errori.
5. Crea un client OAuth2
Per creare le slide, aggiungiamo l'autenticazione alle API di Google aggiungendo il seguente codice al file auth.js. Questa autenticazione richiederà 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 a livello di programmazione. Se non hai mai configurato BigQuery, segui i passaggi descritti in questa guida rapida.
Apri la console Cloud per sfogliare i dati di GitHub disponibili in BigQuery ed eseguire le tue query. Scopriamo le licenze software più popolari 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 analizzato milioni di repository pubblici su GitHub e abbiamo scoperto le licenze più popolari. Interessante! Ora configuriamo l'esecuzione della stessa query, ma questa volta in modo programmatico.
Configurare BigQuery
Sostituisci il codice nel file license.js. La funzione bigquery.query restituirà 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 slide chiamando i metodi create e batchUpdate dell'API Slides. Il nostro file deve essere sostituito con il seguente:
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 mostrare il risultato finale.
9. Complimenti!
Hai generato correttamente file Google Slides dai dati analizzati utilizzando BigQuery. Lo script crea un file di Presentazioni utilizzando l'API Google Slides e BigQuery per generare un report di analisi delle licenze software più comuni.
Possibili miglioramenti
Ecco alcune idee aggiuntive per creare un'integrazione ancora più avvincente:
- Aggiungere immagini a ogni slide
- Condividere le slide via email utilizzando l'API Gmail
- Personalizzare la slide 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.