Programming

【GAS × Twitter】Automating Tweets (Twitter API v2)

Overview

Twitter API updated its pricing plans on February 2, 2023. Along with this change, they are encouraging migration from Twitter API v1.1 to v2. (For more details, see the article below.)

Twitter Monetization

Some of you might still want to automate tasks for Twitter. However, after some research, I couldn’t find any articles describing how to use Twitter API v2 with Google Apps Script (GAS) to post tweets.

To help those in need, I decided to share how to post tweets using Twitter API v2 with GAS!

Account Registration

First, register on the Twitter Developer Platform!
For details on how to create an account, the following article might be helpful:

Registering a Developer Account

Tweet Automation Code

Once you've created an account, I’ll share the GAS code to automate posting tweets!
If you’re wondering how to get started with GAS, the following article might help:
How to Begin with Google Apps Script

Additionally, the authentication process required for tweeting was implemented with reference to the following two Twitter documents:

Authentication Request

Creating an Authentication Signature

const CONSUMER_KEY = '<API Key(Consumer Keys)>'; // Enter your API Key
const CONSUMER_SECRET = '<API Secret(Consumer Keys)>'; // Enter your API Secret
const ACCESS_TOKEN = '<Access Token(Authentication Tokens)>'; // Enter your Access Key
const ACCESS_SECRET = '<Access Secret(Authentication Tokens)>'; // Enter your Access Secret
const END_POINT = 'https://api.twitter.com/2/tweets';

function tweet(text = 'Hello World!') {
  // Generate a unique token required for each unique request by your application
  const oauth_nonce = generateRandomStr(42);
  // Generate a timestamp
  const timestamp = getTimeStamp();

  // Generate a signature
  let parameters = [];
  parameters.push('POST');
  parameters.push(encodeRFC3986(END_POINT));
  parameters.push(encodeRFC3986(`oauth_consumer_key=${CONSUMER_KEY}&oauth_nonce=${oauth_nonce}&oauth_signature_method=HMAC-SHA1&oauth_timestamp=${timestamp}&oauth_token=${ACCESS_TOKEN}&oauth_version=1.0`));

  // Create a signature base string
  const signatureBaseString = parameters.join('&');
  // Generate a signature key
  const signingKey = `${CONSUMER_SECRET}&${ACCESS_SECRET}`;
  // Generate the signature
  let signeture = convertToHMmacSHA1(signatureBaseString, signingKey);
  signeture = encodeRFC3986(signeture);

  const options = {
    "method": "POST",
    "contentType": "application/json",
    "headers": {
      "Authorization": `OAuth oauth_consumer_key="${CONSUMER_KEY}", oauth_nonce="${oauth_nonce}", oauth_signature="${signeture}", oauth_signature_method="HMAC-SHA1", oauth_timestamp="${timestamp}", oauth_token="${ACCESS_TOKEN}", oauth_version="1.0"`
    },
    "payload": JSON.stringify({
      "text": text
    }),
    'muteHttpExceptions': true,
  };
  const response = JSON.parse(UrlFetchApp.fetch(END_POINT, options));
  console.log(response);
}

function getTimeStamp() {
  const now = new Date();
  const formatNow = Utilities.formatDate(now, 'GMT', 'dd MMM yyyy HH:mm:ss z');
  const unixTime = Date.parse(formatNow) / 1000;
  return unixTime.toFixed();
}

// Perform HMAC SHA1 hashing and Base64 encoding
function convertToHMmacSHA1(text, signingKey) {
  const rowHash = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_1, text, signingKey);
  return Utilities.base64Encode(rowHash);
};

// Percent-encode the result (RFC3986)
function encodeRFC3986(text) {
  let encodedText = encodeURIComponent(text);
  const encoders = {
    '!': '%21',
    "'": '%27',
    '(': '%28',
    ')': '%29',
    '*': '%2A'
  }
  for (let key in encoders) {
    encodedText = encodedText.replaceAll(key, encoders[key]);
  }
  return encodedText;
}

function generateRandomStr(l = 0) {
  // Include the necessary character set in the generated string
  var c = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

  var cl = c.length;
  var r = "";
  for (var i = 0; i < l; i++) {
    r += c[Math.floor(Math.random() * cl)];
  }
  return r;
}

Generate API keys and access keys

Below, I will explain the procedure to obtain the API Key and Access Key required in the code above!
First, navigate to the developer portal, select your application, and check the User Authentication Settings. Then click the Edit button! (Note: The actual screen might look slightly different.)

On the edit screen, set the following:

1.Set "App permissions" to Read and write.

2.Type of App: Select Web App, Automated App, or Bot.
3.Callback URI/Website URL under App Info: Enter https://sample.com.(This setting will not be used, but it’s a required field, so you need to enter some URL.)

Once you’ve entered the information, click the Save button to save your changes.

From the tabs on the screen, select Keys and Tokens and create the API Key and Secret and Access Token and Secret.
When creating these keys, a screen displaying the Key/Token and Secret information will appear. Copy this information and paste it into the appropriate sections of the code mentioned earlier.

Now you’re ready to execute the code!

Execute the Code

Now, let's give it a try!
In the GAS (Google Apps Script) interface, set the function to execute as tweet, then click the ▶︎ Run button!

You should see "Hello World!" appear as a tweet.
After that, you can modify the value of the text argument in the tweet function from the code above to any content you'd like to post!

Summary

In this article, I shared how to use Twitter API v2 with GAS to post tweets. This setup opens the door to automation!
I hope this article can be of help to someone, even just a little.

For those who want to learn more about the Tweet API, please refer to the following link:

Tweet API Details

Sponsored Link

  • Author

kaz

Full-stack Engineer specializing in Backend/Frontend/Cloud Infrastructure | Digital Nomad since June 2023, traveling the world | Sharing programming tips and insights | Posting travel updates on X

-Programming
-, ,