ارائه های Google Slides را از Big Data در Node.js ایجاد کنید

۱. مرور کلی

در این آزمایشگاه کد، یاد خواهید گرفت که چگونه می‌توانید از گوگل اسلایدز به عنوان یک ابزار ارائه سفارشی برای تجزیه و تحلیل رایج‌ترین مجوزهای نرم‌افزاری استفاده کنید. شما با استفاده از BigQuery API، تمام کدهای متن‌باز موجود در GitHub را جستجو خواهید کرد و با استفاده از Google Slides API، یک مجموعه اسلاید ایجاد خواهید کرد تا نتایج خود را ارائه دهید. برنامه نمونه با استفاده از Node.js ساخته شده است، اما اصول اولیه مشابه برای هر معماری قابل اجرا است.

آنچه یاد خواهید گرفت

  • ایجاد ارائه‌ها با استفاده از API اسلایدها
  • استفاده از BigQuery برای کسب بینش در مورد یک مجموعه داده بزرگ
  • کپی کردن فایل با استفاده از API گوگل درایو

آنچه نیاز دارید

  • Node.js نصب شده است
  • دسترسی به اینترنت و مرورگر وب
  • یک حساب گوگل
  • یک پروژه پلتفرم ابری گوگل

۲. کد نمونه را دریافت کنید

شما می‌توانید تمام کدهای نمونه را روی کامپیوتر خود دانلود کنید...

... یا مخزن GitHub را از خط فرمان کلون کنید.

git clone https://github.com/googleworkspace/slides-api.git

این مخزن شامل مجموعه‌ای از دایرکتوری‌ها است که هر مرحله از فرآیند را نشان می‌دهند، در صورتی که نیاز به ارجاع به یک نسخهٔ در حال کار داشته باشید.

شما از روی کپی موجود در دایرکتوری start کار خواهید کرد، اما می‌توانید در صورت نیاز به سایر فایل‌ها مراجعه کنید یا از آنها کپی بگیرید.

۳. برنامه نمونه را اجرا کنید

ابتدا، بیایید اسکریپت Node را راه‌اندازی و اجرا کنیم. پس از دانلود کد، دستورالعمل‌های زیر را برای نصب و شروع برنامه Node.js دنبال کنید:

  1. یک ترمینال خط فرمان روی رایانه خود باز کنید و به دایرکتوری start codelab بروید.
  2. برای نصب وابستگی‌های Node.js، دستور زیر را وارد کنید.
npm install
  1. برای اجرای اسکریپت، دستور زیر را وارد کنید:
node .
  1. به پیام خوشامدگویی که مراحل این پروژه را نشان می‌دهد، توجه کنید.
-- Start generating slides. --
TODO: Get Client Secrets
TODO: Authorize
TODO: Get Data from BigQuery
TODO: Create Slides
TODO: Open Slides
-- Finished generating slides. --

می‌توانید لیست TODO های ما را در slides.js ، license.js و auth.js مشاهده کنید. توجه داشته باشید که ما از Promises جاوا اسکریپت برای زنجیره‌سازی مراحل مورد نیاز برای تکمیل برنامه استفاده می‌کنیم، زیرا هر مرحله به تکمیل مرحله قبلی وابسته است.

اگر با promiseها آشنا نیستید، نگران نباشید، ما تمام کد مورد نیاز شما را ارائه خواهیم داد. به طور خلاصه، promiseها راهی برای مدیریت پردازش ناهمزمان به روشی همگام‌تر به ما می‌دهند.

۴. اسرار مشتری را دریافت کنید

برای استفاده از APIهای Slides، Bigquery و Drive، یک کلاینت OAuth و یک حساب کاربری سرویس ایجاد خواهیم کرد.

راه اندازی کنسول توسعه دهندگان گوگل

  1. از این ویزارد برای ایجاد یا انتخاب یک پروژه در کنسول توسعه‌دهندگان گوگل و فعال کردن خودکار API استفاده کنید. روی ادامه کلیک کنید، سپس به اعتبارنامه‌ها بروید .
  2. در صفحه افزودن اعتبارنامه به پروژه خود ، روی دکمه لغو کلیک کنید.
  3. در بالای صفحه، برگه‌ی «رضایت OAuth» را انتخاب کنید. یک آدرس ایمیل انتخاب کنید، نام محصول را Slides API Codelab » وارد کنید و روی دکمه‌ی «ذخیره» کلیک کنید.

فعال کردن APIهای BigQuery، Drive و Slides

  1. برگه داشبورد را انتخاب کنید، روی دکمه فعال کردن API کلیک کنید و 3 API زیر را فعال کنید:
  2. رابط برنامه‌نویسی کاربردی بیگ‌کوئری
  3. رابط برنامه‌نویسی کاربردی گوگل درایو
  4. رابط برنامه‌نویسی کاربردی گوگل اسلایدز

دانلود OAuth Client Secret (برای اسلایدها و درایو)

  1. برگه اعتبارنامه‌ها را انتخاب کنید، روی دکمه ایجاد اعتبارنامه‌ها کلیک کنید و شناسه کلاینت OAuth را انتخاب کنید.
  2. نوع برنامه را Other انتخاب کنید، نام Google Slides API Codelab وارد کنید و روی دکمه Create کلیک کنید. برای بستن پنجره‌ی باز شده، روی OK کلیک کنید.
  3. روی دکمه file_download (دانلود JSON) در سمت راست شناسه کلاینت کلیک کنید.
  4. فایل مخفی خود را به client_secret.json تغییر نام دهید و آن را در هر دو دایرکتوری start/ و finish/ کپی کنید.

دانلود سرویس حساب مخفی (برای BigQuery)

  1. برگه اعتبارنامه‌ها را انتخاب کنید، روی دکمه ایجاد اعتبارنامه‌ها کلیک کنید و کلید حساب سرویس را انتخاب کنید.
  2. در منوی کشویی، حساب کاربری سرویس جدید (New Service Account) را انتخاب کنید. نام سرویس خود را Slides API Codelab Service انتخاب کنید. سپس روی نقش (Role) کلیک کنید و به BigQuery بروید و هر دو گزینه BigQuery Data Viewer و BigQuery Job User را انتخاب کنید.
  3. برای نوع کلید ، JSON را انتخاب کنید.
  4. روی ایجاد کلیک کنید. فایل کلید به طور خودکار در رایانه شما دانلود می‌شود. برای خروج از کادر محاوره‌ای ظاهر شده ، روی بستن کلیک کنید.
  5. فایل مخفی خود را به service_account_secret.json تغییر نام دهید و آن را در هر دو دایرکتوری start/ و finish/ کپی کنید.

دریافت اسرار مشتریان

در start/auth.js ، متد 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));
    });
  });
}

اکنون اطلاعات محرمانه کلاینت را بارگذاری کرده‌ایم. اعتبارنامه‌ها به promise بعدی منتقل می‌شوند. پروژه را با node . اجرا کنید تا مطمئن شوید خطایی وجود ندارد.

۵. یک کلاینت OAuth2 ایجاد کنید

برای ایجاد اسلایدها، بیایید با اضافه کردن کد زیر به فایل auth.js خود، احراز هویت را به APIهای گوگل اضافه کنیم. این احراز هویت، دسترسی به حساب گوگل شما را برای خواندن و نوشتن فایل‌ها در گوگل درایو، ایجاد ارائه‌ها در گوگل اسلایدز و اجرای کوئری‌های فقط خواندنی از گوگل بیگ‌کوئری درخواست می‌کند. (نکته: ما 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);
}

۶. راه‌اندازی بیگ‌کوئری

کاوش در BigQuery (اختیاری)

بیگ‌کوئری به ما امکان می‌دهد تا در عرض چند ثانیه از مجموعه داده‌های عظیم پرس‌وجو کنیم. بیایید قبل از پرس‌وجوی برنامه‌نویسی‌شده، از رابط وب استفاده کنیم. اگر قبلاً بیگ‌کوئری را راه‌اندازی نکرده‌اید، مراحل این راهنمای سریع را دنبال کنید .

کنسول ابری را باز کنید تا داده‌های گیت‌هاب موجود در BigQuery را مرور کنید و کوئری‌های خودتان را اجرا کنید. بیایید با نوشتن این کوئری و فشردن دکمه‌ی اجرا ، محبوب‌ترین مجوزهای نرم‌افزاری در گیت‌هاب را پیدا کنیم.

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

ما همین الان میلیون‌ها مخزن عمومی در گیت‌هاب را تجزیه و تحلیل کردیم و محبوب‌ترین مجوزها را پیدا کردیم. عالی! حالا بیایید همان کوئری را اجرا کنیم، اما این بار به صورت برنامه‌نویسی شده.

راه‌اندازی بیگ‌کوئری

کد موجود در فایل license.js را جایگزین کنید. تابع bigquery.query یک promise را برمی‌گرداند.

مجوز **.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
      });
    });
  });
}

سعی کنید برخی از داده‌های درون فراخوانی Promise خود را console.log تا ساختار اشیاء خود را درک کنید و عملکرد کد را در عمل مشاهده کنید.

۷. ایجاد اسلایدها

حالا به بخش جالب ماجرا می‌رسیم! بیایید با فراخوانی متدهای create و batchUpdate از API اسلایدها، اسلایدها را ایجاد کنیم. فایل ما باید با فایل زیر جایگزین شود:

اسلایدها.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);
      }
    });
  });
});

۸. باز کردن اسلایدها

در آخر، بیایید ارائه را در مرورگر باز کنیم. متد زیر را در slides.js به‌روزرسانی کنید.

اسلایدها.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);
}

پروژه خود را برای آخرین بار اجرا کنید تا نتیجه نهایی را مشاهده کنید.

۹. تبریک می‌گویم!

شما با موفقیت اسلایدهای گوگل را از داده‌های تحلیل‌شده با استفاده از BigQuery ایجاد کرده‌اید. اسکریپت شما با استفاده از API اسلایدهای گوگل و BigQuery یک ارائه ایجاد می‌کند تا تحلیلی از رایج‌ترین مجوزهای نرم‌افزاری را گزارش دهد.

بهبودهای احتمالی

در اینجا چند ایده اضافی برای ایجاد یک ادغام حتی جذاب‌تر ارائه شده است:

  • اضافه کردن تصاویر به هر اسلاید
  • اسلایدهای خود را از طریق ایمیل با استفاده از Gmail API به اشتراک بگذارید
  • اسلاید قالب را به عنوان آرگومان خط فرمان سفارشی کنید

اطلاعات بیشتر