This article has 86 reactions and 11 comments
Tags: tutorial, meta, showdev, go
Published: 2020-05-13 11:57:35

---
title:This article has 86 reactions and 11 comments
published: true
description: Update the title of the article with the number of reactions and comments 
tags: tutorial,meta,showdev,golang
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/mmlnbyvlnf9x20a1zrqz.png
---
Tom Scott made a video recently where the title contains the number of views that the video has. The title is kept up to date with the number of views by a program which calls the youtube API. It's a great video if [you haven't seen it yet](https://www.youtube.com/watch?v=BxV14h0kFs0). 

Anyway, I really liked that idea and wanted to try it with this dev.to article. The article is different from Tom's video in two ways: the title of the article contains the number of reactions and comments instead of the views. The second thing is the topic. Tom talks about the invention of the APIs. What I want to talk about is how to _use APIs_ to call the dev.to service.

The title of the article won't exactly match the number of comments and reactions because the program that updates the title only runs every minute. Also, I suspect the dev.to api is eventual consistent, which means the number of reactions and comments will be updated at some point, but it does not happen in real time. If, when you are reading the article, the title matches or is close to the number of reactions or comments, it means that the code is still working; but it could stop working any time. The [dev.to api](https://docs.dev.to/api/) I am using is in beta and could change or being dismissed in the future.

In the remainder of the article I am going to talk about the steps I took to use the dev.to api.

### OpenAPI specification

The first step to build a program which interacts with a service is to discover its api.

OpenAPI specification defines a standard which allows both developers and machines to discover and understand the capabilities of a service. It serves as documentation and as a contract.

An API defined via an OpenApi document is _machine friendly_, which means we can build programs that interpret that document and do something useful with it. For example, the [oapi-codegen](https://github.com/deepmap/oapi-codegen) is able to read the document and generate a golang http client to interact with the api. It can also generate a stub service which can be used both as starter or as a mock for your tests.

The other benefit of OpenAPI is that is also _human friendly_. It can be used as documentation, hosted on a server and browsed via a browser. This is what dev.to uses and anybody can read and download its OpenApi spec [here](https://docs.dev.to/api/).

### AuthN and AuthZ

The second step to build the program is getting valid credentials.

Services need a way to know that you are who you say you are (authentication). Once they have established that, they might also need to verify that you can carry on the action you want to perform (authorization).
In the case of dev.to, the _api key_ is used for authN and authZ. An _api key_ is a pseudo random service generated string which is associated with your account. To obtain one for dev.to:

- visit https://dev.to/settings/account
- in the "DEV API Keys" section create a new key by adding a description and clicking on "Generate API Key" 

### Generate the client

Once we have the OpenAPI document and the _api key_, we are ready to make good use of them.  

I have used the [oapi-codegen](https://github.com/deepmap/oapi-codegen) tool to generate a golang client to interact with the api. The process was quick. I downloaded the OpenAPI document for dev.to and run the _oapi-codegen_, and that was it, no errors or warnings. Sometimes you need to tweak a bit the document or the code generator to make it work, but not in this case. The result was a golang struct with the following methods:

![client](https://dev-to-uploads.s3.amazonaws.com/i/890u073f0yldc055pbsy.png)

### Use the client

After generating the client, I just had to write some code which:
1. retrieves the number of reactions and comments for the article
2. updates the title if the number of reactions or comments changed

The second step require a little bit more work than the first one. 
Since, I use front matter when writing on dev.to, updating the title means updating the _title_ field in markdown:

```markdown
---
title:This article has x reactions and y comments
published: true
description: ...
tags: ...
---
```

The gist of the program is here:

```go
func run(ctx context.Context, env *programEnv, client *ClientWithResponses) {
    r, e := getArticleActivity(ctx, client, env.ArticleID)
    if e != nil {
        log.Fatal(e)
    }
    log.Debugf("Article reactions: %[1]d - Article comments: %[2]d",
        r.ReactionsCount,
        r.CommentsCount)

    newTitle := generateNewTitle(r.ReactionsCount, r.CommentsCount)
    fmEditor, e := newFrontMatterEditor(r.BodyMarkdown)
    if e != nil {
        log.Fatal(e)
    }
    if fmEditor.title == newTitle {
        log.Debug("Article title is already up to date with the number of reactions and comments")
        return
    }

    log.Debug("Updating the title of the article")
    fmEditor.updateTitle(newTitle)
    e = saveArticle(ctx, client, env.ArticleID, fmEditor.markdown)
    if e != nil {
        log.Fatal(e)
    }
    log.Info("Article with the new title has been saved")
}
```

You can find the rest of the source code is on [github](https://github.com/napicella/this-article-has-x-reactions-and-y-comments).

### Profit
Lastly, I create a cron job which runs the program every minute:

```
SHELL=/bin/bash
* * * * * /home/napicella/wrapper.sh
```

where _wrapper.sh_ is a bash script which calls the program:

```bash
#!/bin/bash

source .env
./update-article >> /home/napicella/ua.log 2>&1 
```

Dev.to documentation does not mention any service quota for the api. I did not get throttled so far, so I guess it's a reasonable rate for the service.

### Conclusion
I want to conclude by thanking Tom Scott for the idea. If you haven't seen it, this is the link to the [video](https://www.youtube.com/watch?v=BxV14h0kFs0).

--------------------

Follow me on [Twitter](https://twitter.com/napicellatwit) to get new posts in your feed.
Credit for the cover image to [GraphicMama-team](https://pixabay.com/users/graphicmama-team-2641041/)