This Post Has 2,451 Views, 168 Reactions And 26 Comments
Tags: showdev, javascript, opensource, tutorial
Published: 2020-06-03 13:05:17

In this post, I'll be teaching you how to update a [DEV](https://dev.to/) post title, The [Tom Scott](https://www.youtube.com/channel/UCBa659QWEk1AI4Tg--mrJ2A) way.

YouTuber Tom Scott's latest video titled, "This Video Has X Views", continually updates itself to reflect its own view count.

{% youtube BxV14h0kFs0 %}

Basically what he does is run a background job that hits the YouTube API to update the title with the latest view count every few minutes.

Here's another one from Mr. Beast but instead of updating the title of the video, the thumbnail gets updated every few minutes with the amount of money given away.

{% youtube YSoJPA8-oHc %}

## Getting Started

We will use [Firebase Cloud Functions](https://firebase.google.com/docs/functions) to make a script that will update our DEV post title every x minutes. Also, Node.js and [axios](https://github.com/axios/axios) to get and update a DEV article.

## 1. Configure Firebase

Create a Firebase Project using the [Firebase Developer Console](https://console.firebase.google.com).

Then install the [Firebase CLI](https://github.com/firebase/firebase-tools) globally.

```bash
$ npm install -g firebase-tools
```

Having installed the Firebase CLI in the last step, we’re now able to login to Firebase by using the following command:

```
$ firebase login
```

Now you’re ready to create a new Firebase Cloud Functions project. First create a new empty project folder:

```bash
$ mkdir this-post-has-n-views
$ cd this-post-has-n-views
```

and execute the following command:

```bash
$ firebase init functions
```

![firebase init](https://i.imgur.com/4Aj1Ds8.png)

- **Select a default Firebase project for this directory**: your-project-name

- **What language would you like to use**? JavaScript

- **Do you want to use ESLint to catch probable bugs**? No

- **Do you want to install dependencies with npm now**? Yes

Here's what we've got:

- `firebase.json`: Contains settings for our project
- `.firebaserc`: For configuring multiple projects
- `functions/index.js`: Boilerplate provided by Firebase

Let's also install axios to communicate with the DEV API later.

```bash
$ cd functions
$ npm install axios
```

## 2. DEV API Key

Next, we need a DEV API Key which you can obtain [here](https://dev.to/settings/account). We need it to authorize our requests to the [DEV API](https://dev.to/settings/account). Keep the API key for now.

## 3. Scripting Time

Assuming that all went well, we now have a starting point for what we want to do. It's time for the fun stuff.

First, we need to set the `dev.api_key` and `dev.post_id` environment variables for our project. For this use:

```bash
$ firebase functions:config:set dev.api_key="YOUR_DEV_API_KEY" dev.post_id="DEV_POST_ID_TO_UPDATE"
```

Tip: To get a post ID, right-click and inspect your dev post page and look for the `data-article-id` attribute.

Next, open file `firebase/index.js` and insert the following implementation:

```javascript
const functions = require("firebase-functions");
const axios = require("axios");

const articlesEndpoint = "https://dev.to/api/articles";

// A recursive function that checks if a post
// is present in the current response and returns it.
async function getPost(postId, pageNo = 1) {
  const { data } = await axios.get(
    `${articlesEndpoint}/me/all?per_page=10&page=${pageNo}`,
    {
      headers: {
        "api-key": functions.config().dev.api_key,
      },
    }
  );

  const post = data.find((i) => i.id == postId);

  if (!post) {
    return getPost(postId, pageNo + 1);
  }

  return post;
}

// A snippet taken from SO that adds commas to a number.
// https://stackoverflow.com/a/2901298/4698790
function addCommas(x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

// A function that updates a post title
// to the current views, reactions and comments
// count by its id.
async function updatePost(postId) {
  const {
    page_views_count,
    public_reactions_count,
    comments_count,
  } = await getPost(postId);
  const data = {
    title: `This Post Has ${addCommas(page_views_count)} Views, ${addCommas(
      public_reactions_count
    )} Reactions And ${addCommas(comments_count)} Comments`,
  };
  const res = await axios.put(`${articlesEndpoint}/${postId}`, data, {
    headers: {
      "api-key": functions.config().dev.api_key,
    },
  });
  return res.data;
}

// A function that uses the scheduler and
// pubsub APIs to run a given code every
// 3 minutes.
exports.updatePostTitle = functions.pubsub
  .schedule("every 3 minutes")
  .onRun(() => {
    const postId = functions.config().dev.post_id;
    return updatePost(postId);
  });
```

The area of focus in the code above is the `getPost`, `updatePost`, and the `updatePostTitle` functions.

The `getPost` function is a recursive function that gets the user's articles and runs until the given post id is found. We do this because currently, the DEV API endpoint `https://dev.to/api/articles/YOUR_POST_ID_HERE` doesn't return the `page_views_count` property that we need to add to the title of the post.

The `updatePost` function updates a post's title by including the current views, reactions and comments count of the post. The format looks like this.

```
This Post Has 1,001 Views, 532 Reactions And 69 Comments
```

Lastly, the `updatePostTitle`, is a cloud function that uses the [Pub/Sub](https://cloud.google.com/pubsub/docs/reference/rest) and the [Cloud Scheduler](https://cloud.google.com/scheduler/docs/reference/rest) APIs to update the post title every 3 minutes.

## 4. Deployment

To deploy our Cloud Function, simply run:

```bash
$ firebase deploy --only functions
```

![Deployment](https://i.imgur.com/PPyqb8m.png)

Now that your deployment is complete, you can go to your [Firebase console](https://console.firebase.google.com/u/0/) and find your function.

![Function](https://i.imgur.com/gpCPjWF.png)

You can find the complete soure code here:

{% github https://github.com/sorxrob/this-post-has-n-views %}

## Final Thoughts

I hope you enjoyed this tutorial on automatically updating a DEV post title in the background using Cloud Functions.

Note: The background job is on a 3 minute interval, so it won't be very accurate. 

Happy coding! 🚀

*Cover photo by [NESA by Makers](https://unsplash.com/@nesabymakers) on [Unsplash](https://unsplash.com/)*