Summarizing Slides as Thumbnails

Gists

This is a sample script for summarizing Slides as thumbnails. For example, it supposes a Slides including 15 pages. When this script is run, it summarizes 6 pages to one page as images. I created this because there are no methods for directly achieving this. This is useful for myself. If this is also useful for you, I’m glad.

The flow of this workaround is as follows.

Flow:

  1. Copy the original Slides file as a temporary file.
  2. Retrieve images of all slides.
    • When the Slides file is exported to PNG file, the top page is exported as PNG file. I used this.
  3. Put and arrange the retrieved images to the temporary file.
    • When the image is inserted to a slide, retrieve the size and change the size, then put the image to the calculated position.

Sample script 1:

function myFunction() {
  // Please set these parameters
  var id = "### file ID ###"; // file ID of original Slides
  var col = 3; // Number of columns
  var row = 2; // Number of rows
  var wsize = 200; // Size of width of each image (pixels)
  var sep = 5; // Space of each image (pexels)


  // Create temporary file
  var originalFile = DriveApp.getFileById(id);
  var tempFile = originalFile.makeCopy();
  var idt = tempFile.getId();
  
  // Retrieve slides as images
  var s = SlidesApp.openById(idt);
  var slides = s.getSlides();
  var accessToken = ScriptApp.getOAuthToken();
  var baseUrl = "https://docs.google.com/presentation/d/" + idt + "/export/";
  var url = baseUrl + "png?access_token=" + accessToken;
  var blobs = slides.map(function(e) {
    var blob = UrlFetchApp.fetch(url).getBlob();
    slides[0].remove();
    s.saveAndClose();
    s = SlidesApp.openById(idt);
    slides = s.getSlides();
    return blob;
  });

  // Put images 
  var ph = s.getPageHeight();
  var pw = s.getPageWidth();
  var leftOffset = (pw - ((wsize * col) + (sep * (col - 1)))) / 2;
  if (leftOffset < 0) throw new Error("Images are sticking out from a slide.");
  var len = col * row;
  var loops = Math.ceil(blobs.length / (col * row));
  for (var loop = 0; loop < loops; loop++) {
    var ns = s.insertSlide(loop);
    var topOffset, top;
    var left = leftOffset;
    for (var i = len * loop; i < len + (len * loop); i++) {
      if (i === blobs.length) break;
      var image = ns.insertImage(blobs[i]);
      var w = image.getWidth();
      var h = image.getHeight();
      var hsize = h * wsize / w;
      if (i === 0 || i % len === 0) {
        topOffset = (ph - ((hsize * row) + sep)) / 2;
        if (topOffset < 0) throw new Error("Images are sticking out from a slide.");
        top = topOffset;
      }
      image.setWidth(wsize).setHeight(hsize).setTop(top).setLeft(left).getObjectId();
      if (i === col - 1 + (loop * len)) {
        top = topOffset + hsize + sep;
        left = leftOffset;
      } else {
        left += wsize + sep;
      }
    }
  }
  s.saveAndClose();
}

Sample script 2:

When you use this script, please enable Slides API at API console.

Updated goodls to v122

  • v1.2.2 (December 12, 2018)

    1. When files are downloaded from a specific folder, it got to be able to select mimeType. By this, files with the specific mimeType in the specific folder can be retrieved. For this, I updated the go library go-getfilelist.
      • $ goodls -u [URL] -key [APIkey] -m "application/pdf,image/png"

The detail information and how to get this are https://github.com/tanaikech/goodls.

Retrieving Access Token using Service Account by Google's OAuth2 package for Golang

Gists

This is a sample golang script for retrieving access token using Service Account of Google by Google’s OAuth2 package.

The script without using Google’s OAuth2 package is here.

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "os"

    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "golang.org/x/oauth2/jwt"
)

func serviceAccount(credentialFile string) (*oauth2.Token, error) {
    b, err := ioutil.ReadFile(credentialFile)
    if err != nil {
        return nil, err
    }
    var c = struct {
        Email      string `json:"client_email"`
        PrivateKey string `json:"private_key"`
    }{}
    json.Unmarshal(b, &c)
    config := &jwt.Config{
        Email:      c.Email,
        PrivateKey: []byte(c.PrivateKey),
        Scopes: []string{
            "https://www.googleapis.com/auth/drive.metadata.readonly",
        },
        TokenURL: google.JWTTokenURL,
    }
    token, err := config.TokenSource(oauth2.NoContext).Token()
    if err != nil {
        return nil, err
    }
    return token, nil
}

func main() {
    token, err := serviceAccount("credentials.json") // Please set here
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    fmt.Println(res)
}

Retrieving Access Token for Service Account using Google Apps Script

Gists

Updated on June 22, 2024

This is a sample script for retrieving the access token for Service Account using Google Apps Script. The flow for using this script is as follows.

Usage

  1. Create the Service Account and retrieve JSON file.
  2. Put Scopes, private_key and client_email as an object.
  • If you want to use impersonate email, please set the value of impersonate_email.
  1. Run the script.
/**
 * ### Description
 * Get access token from service account.
 * ref: https://tanaikech.github.io/2018/12/07/retrieving-access-token-for-service-account-using-google-apps-script/
 *
 * @param {Object} object Object including private_key, client_email, impersonate_email.
 * @param {String} object.private_key
 * @param {String} object.client_email
 * @param {String} object.impersonate_email
 * @param {Array} object.scopes
 * @returns {String} Access token.
 */
function getAccessTokenFromServiceAccount_(object) {
  const { private_key, client_email, impersonate_email = "", scopes = [] } = object;
  const url = "https://www.googleapis.com/oauth2/v4/token";
  const header = { alg: "RS256", typ: "JWT" };
  const now = Math.floor(Date.now() / 1000);
  const claim = { iss: client_email, scope: scopes.join(" "), aud: url, exp: (now + 3600).toString(), iat: now.toString() };
  if (impersonate_email != "") {
    claim.sub = impersonate_email;
  }
  const signature = Utilities.base64Encode(JSON.stringify(header)) + "." + Utilities.base64Encode(JSON.stringify(claim));
  const jwt = signature + "." + Utilities.base64Encode(Utilities.computeRsaSha256Signature(signature, private_key));
  const params = { payload: { assertion: jwt, grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer" } };
  const res = UrlFetchApp.fetch(url, params);
  const { access_token } = JSON.parse(res.getContentText());
  return access_token;
}


// Please run this script.
function main() {
  const object = {
    private_key: "-----BEGIN PRIVATE KEY-----\n###-----END PRIVATE KEY-----\n",
    client_email: "###",
    // impersonate_email: "###", // If you want to use an impersonate email, please set this.
    scopes: ["###", "###",,,],
  };
  const accessToken = getAccessTokenFromServiceAccount_(object);
  console.log(accessToken);
}

Sample script

When you can obtain the access token by the above script, you can also use the following sample script. The following sample script retrieves the file list of the drive of the service account with Method: files.list of Drive API v3.

Google OAuth Verification & Application Privacy Policy

Registered Application Name: Workspace & Gemini AI Orchestration Engine

Application Purpose & Core Functionality:

This web page serves as the official homepage and privacy compliance interface for the application "Workspace & Gemini AI Orchestration Engine". This specialized developer utility is designed to research, benchmark, and optimize advanced integrations between Google Workspace services, the Google Apps Script API, and Gemini AI models (via Google Vertex AI / Gemini API endpoints).

The application facilitates automated multi-agent scaffolding, programmatic script deployment, project resource management, and structural analysis of Google Apps Script projects. It allows developers and autonomous AI agents (operating via Model Context Protocol / MCP) to securely evaluate execution performance, implement high-performance batch requests, and test agent-to-agent (A2A) workflows within a controlled and structured environment.

Google User Data Policy Compliance Statements:

1. Data Access & Specific Usage

Our application explicitly requests access to specific Google user accounts through OAuth scopes required strictly for interacting with the Google Apps Script API and Google Workspace endpoints. This access is utilized solely to execute user-initiated or agent-orchestrated programmatic operations—such as creating, modifying, deploying, or benchmarking script projects and executing automated workflows. No background automated extraction occurs without explicit session initiation.

2. Data Storage & Zero-Retention Policy

Adhering to a strict Zero-Retention Model, this application does not store, log, or persist any personal data, OAuth tokens, script source codes, or Google account configurations on any external server, database, or persistent storage medium. All data processing and API responses are handled entirely in-memory or securely on the client side within the active session context, ensuring complete cryptographic transient isolation.

3. Data Sharing & Third-Party Non-Disclosure

We maintain absolute data privacy. No data accessed via Google OAuth scopes is shared, sold, rented, or transferred to third-party entities, advertising networks, or data brokers. All data transmissions are strictly point-to-point, encrypted in transit using industry-standard protocols, and limited entirely to the direct channel between the execution environment and Google's official API gateways.

For inquiries regarding this developer application, technical benchmarks, or verification compliance, please refer to the official documentation and repositories linked on this homepage (tanaikech.github.io).