Skip to content
Go back
en

How to Build a GAS Tool That Automatically Likes Tweets on Your Twitter Timeline

Published:Updated:
This article was migrated from steins.gg.

Because the .gg domain was expensive to maintain and I could no longer keep operating the site, steins.gg was shut down.

Good morning/afternoon/evening! I made a GAS tool that automatically likes tweets on my Twitter timeline. Anyone can use it by copy-pasting, so please give it a try.

Table of Contents

Open Table of Contents

Implementation

GAS Library Used

  • TwitterWebService

main.gs

// Authorization instance
var twitter = TwitterWebService.getInstance(
  "{consumerKey}", // API key created in Twitter Apps
  "{consumerSecret}" // API Secret key created in Twitter Apps
);

var userList = [];

// Authorize
function authorize() {
  twitter.authorize();
}

// Reset authorization
function reset() {
  twitter.reset();
}

// Callback after authorization
function authCallback(request) {
  return twitter.authCallback(request);
}

function getTimeLine() {
  var service = twitter.getService();
  var response = service.fetch(
    "https://api.twitter.com/1.1/statuses/home_timeline.json?exclude_replies=true&count=200&include_rts=false"
  );

  // JSON.parse the fetch response body
  var array = JSON.parse(response.getContentText());

  array.forEach(function (tweet) {
    fav(tweet);
  });

  Logger.log(userList);
  userList = [];
}

function fav(tweet) {
  var service = twitter.getService();

  // Tweet body
  var twiStr = tweet && tweet.text ? tweet.text : "";

  // Keep only the text before the URL (Note 2)
  var urlIndex = twiStr.indexOf("https://");
  if (urlIndex >= 0) {
    twiStr = twiStr.slice(0, urlIndex);
  }

  // Keep only the text before the hashtag (Note 2)
  var hashIndex = twiStr.indexOf("#");
  if (hashIndex >= 0) {
    twiStr = twiStr.slice(0, hashIndex);
  }

  if (twiStr.length > 6) {
    // Whether the text is longer than 6 characters (Note 3)
    Logger.log(tweet.user.screen_name + " : " + twiStr);

    if (userList.indexOf(tweet.user.screen_name) === -1) {
      // Note 4
      if (tweet.user.screen_name !== "{your user ID}") {
        // Note 5
        try {
          service.fetch(
            "https://api.twitter.com/1.1/favorites/create.json?id=" +
              tweet.id_str,
            { method: "post" }
          );
          userList.push(tweet.user.screen_name);
        } catch (error) {
          Logger.log(error);
        }
      }
    }

    // Space out requests to avoid hitting rate limits when calling repeatedly
    Utilities.sleep(1500);
  }
}

appscript.json

{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
    "libraries": [
      {
        "userSymbol": "TwitterWebService",
        "libraryId": "1rgo8rXsxi1DxI_5Xgo_t3irTw1Y5cxl2mGSkbozKsSXf2E_KBBPC3xTF",
        "version": "2"
      }
    ]
  },
  "webapp": {
    "access": "MYSELF",
    "executeAs": "USER_DEPLOYING"
  },
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes": [
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/datastore"
  ]
}

Behavior

  • Likes tweets that appear in your own timeline.
    • Note 1: It does not like quote RTs with no comment, image-only tweets, or link-only tweets.
      • Because they may contain dangerous content or only a spam link
    • Note 2: URLs (https://...) and hashtags (#...) are not treated as “body text.”
    • Note 3: Tweets whose “body text” is 6 characters or shorter are not liked.
      • Because they are likely to be tweets with little intent or meaning from that user
      • As described in Notes 1 and 2, links and hashtags are not counted toward the character count
    • Note 4: In a single run, it does not like two or more tweets from the same user.
      • Because if the user was posting repeatedly, sending multiple like notifications could annoy them
    • Note 5: It does not like your own tweets.

How to Operate

For actual operation, either run getTimeLine() manually or set a time-driven trigger (around once every 6 hours) so it runs automatically.

Note: After trying various settings, I found that if the interval was not about 6 hours, it could hit rate limits and other restrictions. Note: Hitting limits too often could also lead to an account ban, so configure it with plenty of margin.

Advanced Usage (added 2021/4/20)

You can also search for tweets that contain specific strings and like them. For example, if you want to increase the number of friends you can play games with, search for and like tweets containing #LookingForFriends or #FollowBackIfLiked.

Implementation

First, add the following constants near the top of main.gs. Change the specified words as needed.

// Target hashtags
var TARGET_HASHTAGS = ["#PUBGFriendsWanted", "#VALORANTFriendsWanted"];

// Like-for-follow keywords
var LIKE_FOLLOW_KEYWORDS = ["#FollowBackIfLiked", "#FollowEveryoneWhoLikes"];

Next, add a function that searches and collects tweets, then passes the tweets that match the conditions to fav().

function searchAndFav() {
  var service = twitter.getService();

  var tagGroup = "(" + TARGET_HASHTAGS.join(" OR ") + ")";
  var kwGroup = "(" + LIKE_FOLLOW_KEYWORDS.join(" OR ") + ")";
  var q = tagGroup + " " + kwGroup;

  var url =
    "https://api.twitter.com/1.1/search/tweets.json" +
    "?q=" +
    encodeURIComponent(q) +
    "&result_type=recent" +
    "&count=100";

  var response = service.fetch(url);
  var data = JSON.parse(response.getContentText());
  var tweets = data.statuses || [];

  for (var i = 0; i < tweets.length; i++) {
    fav(tweets[i]);
  }

  Logger.log(userList);
  userList = [];
}

How to Operate

Run searchAndFav() with a time-driven trigger in the same way.

My Thoughts After Actually Running It

I often play games like PUBG and VALORANT, so for about a year I ran this setup to automatically like “like-for-follow” style tweets: tweets tagged with #PUBGFriendsWanted, #VALORANTFriendsWanted, and similar tags, plus hashtags like #FollowBackIfLiked.

As a result, my follower count increased by about 6,000 people.

However, I realized that followers gained this way ultimately almost never actually play with you. (Of course.)

The friends I actually play with can be counted on one hand, and having a large follower count causes more downsides than benefits. For example, people often become wary of you at first glance.

That said, if an account has a clear purpose, such as increasing its visible follower count as part of a concrete social media business strategy, I think copying this approach could be fine.

Final Notes

Also, this is a bit of a gray-area topic, so I’ll keep it vague, but accounts that have grown a certain number of followers can mumble mumble mumble. Oops, looks like someone’s at the door.

Personally, this advanced operation was a failure for me, but if used well I think it can help create a better social media life, so use it responsibly!


  • How to Build a GAS Tool That Sends Tweets from Specific Twitter Accounts to a Discord Channel
  • How My Solo-Developed Twitch Follower Analysis Web App Surpassed 100,000 Cumulative Active Users
  • [Twitch Follower Checker] How to Check New Followers and Unfollowers on a Twitch Channel
  • [PUBG] Lessons from Building and Operating Steins.GG, a Match Analysis Web App with 80,000 Cumulative Users
  • Recreating Twitter's old video clip feature as a Chrome extension

Previous Post
Follow This and You Can Pass: My AWS Certified Solutions Architect - Associate (SAA-C03) Exam Experience
Next Post
[VALORANT] A Seriously Top-Tier Aim Training Method