January 27, 2023: Decrypting Salted Base64 of finance.yahoo.com using Google Apps Script

Gists

This sample script decrypts the salted base64 data of finance.yahoo.com using Google Apps Script.

Recently, it seems that the specification of the key for decrypting the data has been changed at the server side. So. from this script, I updated the script as follows.

Sample script

function myFunction() {
  // Load crypto-js.min.js.
  const cdnjs =
    "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js";
  eval(UrlFetchApp.fetch(cdnjs).getContentText());

  // Retrieve HTML and retrieve salted base64.
  const url = "https://finance.yahoo.com/quote/PGEN/press-releases"; // This is a sample URL.
  const html = UrlFetchApp.fetch(url)
    .getContentText()
    .match(/root.App.main = ([\s\S\w]+?);\n/);
  if (!html || html.length == 1) return;
  const tempObj = JSON.parse(html[1].trim());
  let obj;
  if (
    typeof tempObj.context.dispatcher.stores === "string" ||
    tempObj.context.dispatcher.stores instanceof String
  ) {
    // Decrypt the salted base64.
    const key = [
      ...new Map(
        Object.entries(tempObj)
          .filter(([k]) => !["context", "plugins"].includes(k))
          .splice(-4)
      ).values(),
    ].join("");
    if (!key) {
      throw new Error(
        "Specification at the server side might be changed. Please check it."
      );
    }
    obj = JSON.parse(
      CryptoJS.enc.Utf8.stringify(
        CryptoJS.AES.decrypt(tempObj.context.dispatcher.stores, key)
      )
    );
  } else {
    obj = tempObj.context.dispatcher.stores;
  }
  console.log(obj);
}
  • About the value of context.dispatcher.stores, this script can be used for both the salted base64 and the JSON object.

Note

  • In this sample, in order to load crypto-js, eval(UrlFetchApp.fetch(cdnjs).getContentText()) is used. But, if you don’t want to use it, you can also use this script by copying and pasting the script of https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js to the script editor of Google Apps Script. By this, the process cost can be reduced.

IMPORTANT

  • I can confirm that this method can be used for the current situation (January 27, 2023). But, when the specification in the data and HTML is changed in the future update on the server side, this script might not be able to be used. Please be careful about this.

References

Using OnEdit trigger on Google Spreadsheet Created by Service Account

Gists

In the current stage, by the current specification, Google Apps Script cannot be directly run on Google Spreadsheet created by Service Account. But, there is a case in that we want to use the OnEdit trigger on the Spreadsheet that the service account is the owner. In this post, I would like to introduce the method for achieving this.

Recently, I published “Using OnEdit Trigger to Google Spreadsheet by Hiding Google Apps Script from Other Users”. Here, this method is used.

Using OnEdit Trigger to Google Spreadsheet by Hiding Google Apps Script from Other Users

Gists

Using OnEdit Trigger to Google Spreadsheet  by Hiding Google Apps Script from Other Users

This is a method for using OnEdit Trigger to Google Spreadsheet by hiding Google Apps Script from other users.

A sample flow for achieving this is as follows.

Flow

1. Create a new Google Spreadsheet.

Please create a new Google Spreadsheet. In this flow, this Google Spreadsheet is used for testing the script. And, please copy the Spreadsheet ID. This spreadsheet ID is used.

Replacing U+00A0 with U+0020 as Unicode using Google Apps Script

Gists

Replacing U+00A0 with U+0020 as Unicode using Google Apps Script

This is a sample script for checking and replacing a character of U+00A0 (no-break space) with U+0020 (space) as Unicode using Google Apps Script.

When I’m seeing the questions on Stackoverflow, I sometimes saw the situation that the script doesn’t work while the script is correct. In this case, there is the case that the reason is due to U+00A0 being used as the spaces. When U+00A0 is used as the spaces, Google Apps Script and formulas cannot be correctly run. I thought that when this information is published, it might be useful for a lot of users.

Set Line Space of Paragraph on Google Document using Google Apps Script

Gists

This is a sample script for setting the line space of paragraphs on Google Documents using Google Apps Script.

When the line space of a paragraph on Google Documents is manually set, you can do it as follows.

Set Line Space of Paragraph on Google Document using Google Apps Script

When it is set with Google Apps Script, the following script can be used.

function sample1() {
  const doc = DocumentApp.getActiveDocument();
  const body = doc.getBody();
  const paragraph = body.appendParagraph(
    "sample paragraph 1\nsample paragraph 2\nsample paragraph 3"
  );
  paragraph.setLineSpacing(2); // Double
}

When this script is run, the appended paragraphs have a line space of 2 (Double).

Opening and Closing Google Forms on Time using Google Apps Script

Gists

Opening and Closing Google Forms on Time using Google Apps Script

This is a sample script for opening and closing Google Forms on time using Google Apps Script.

In order to test this sample script, please do the following flow.

Usage

1. Create a new Google Form.

Please create a new Google Form and set your sample questions. And, please open the script editor of Google Form.

2. Prepare sample script.

Please copy and paste the following script to the script editor of Google Form. And, please set the values of start and end times you want.

Decrypting Salted Base64 of finance.yahoo.com using Google Apps Script

Gists

This sample script decrypts the salted base64 data of finance.yahoo.com using Google Apps Script.

Recently, it seems that the specification of the key for decrypting the data has been changed at the server side. So. in this post, this post is updated. About this specification, I checked this thread.

Sample script

function myFunction() {
  // Load crypto-js.min.js.
  const cdnjs =
    "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js";
  eval(UrlFetchApp.fetch(cdnjs).getContentText());

  // Retrieve HTML and retrieve salted base64.
  const url = "https://finance.yahoo.com/quote/PGEN/press-releases"; // This is a sample URL.
  const html = UrlFetchApp.fetch(url)
    .getContentText()
    .match(/root.App.main = ([\s\S\w]+?);\n/);
  if (!html || html.length == 1) return;
  const tempObj = JSON.parse(html[1].trim());
  let obj;
  if (
    typeof tempObj.context.dispatcher.stores === "string" ||
    tempObj.context.dispatcher.stores instanceof String
  ) {
    // Decrypt the salted base64.
    var key = Object.entries(tempObj).find(
      ([k]) => !["context", "plugins"].includes(k)
    )[1];
    if (!key) {
      throw new Error(
        "Specification at the server side might be changed. Please check it."
      );
    }
    obj = JSON.parse(
      CryptoJS.enc.Utf8.stringify(
        CryptoJS.AES.decrypt(tempObj.context.dispatcher.stores, key)
      )
    );
  } else {
    obj = tempObj.context.dispatcher.stores;
  }
  console.log(obj);
}
  • About the value of context.dispatcher.stores, this script can be used for both the salted base64 and the JSON object.

Note

  • In this sample, in order to load crypto-js, eval(UrlFetchApp.fetch(cdnjs).getContentText()) is used. But, if you don’t want to use it, you can also use this script by copying and pasting the script of https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js to the script editor of Google Apps Script. By this, the process cost can be reduced.

IMPORTANT

  • I can confirm that this method can be used for the current situation (January 14, 2023). But, when the specification in the data and HTML is changed in the future update on the server side, this script might not be able to be used. Please be careful about this.

References

Converting All Pages in PDF File to PNG Images using Google Apps Script

Gists

Converting All Pages in PDF File to PNG Images using Google Apps Script

This is a sample script for converting all pages in a PDF file to PNG images using Google Apps Script.

I have already published “Merging Multiple PDF Files as a Single PDF File using Google Apps Script”. In this post, it was found that pdf-lib can be used with Google Apps Script. From this, in this post, I would like to propose a sample script for converting all pages in a PDF file to PNG images using Google Apps Script. This cannot be directly achieved with Google Apps Script. So, I thought that this might be useful for users.

Merging Multiple PDF Files as a Single PDF File using Google Apps Script

Gists

Merging Multiple PDF Files as a Single PDF File using Google Apps Script

This is a sample script for merging multiple PDF files as a single PDF file using Google Apps Script.

In this sample script, pdf-lib is used. In the current stage, it seems that this Javascript can be directly used with Google Apps Script.

Sample script 1

As a sample situation, please put multiple PDF files in your Google Drive. This sample merges those PDF files as a single PDF file.

Transferring Owner of File to Other User using Google Apps Script

Gists

Transferring Owner of File to Other User using Google Apps Script

This is a sample script for transferring the ownership of a file to another user using Google Apps Script.

In the current stage, about the consumer account (gmail.com) the specification for transferring the ownership of a file has been changed as follows. Ref

  1. The current owner initiates an ownership transfer by creating or updating the prospective new owner’s file permission. The permission must include these settings: role=writer, type=user, and pendingOwner=true. If the new owner is creating a permission for the prospective owner, an email notification is sent to the prospective new owner indicating that they’re being asked to assume ownership of the file.
  1. The new owner accepts the ownership transfer request by creating or updating their file permission. The permission must include these settings: role=owner and transferOwnership=true. If the new owner is creating a new permission, an email notification is sent to the previous owner indicating that ownership has been transferred.

When this flow is reflected in the sample script, it becomes as follows.