vercel + Shields.ioでProtoPediaのバッジを作って実績アピールする


この記事は、ProtoPediaのユーザー情報をバッジ化し、見栄え良く表示できるようにする記事です。

↓↓ こんな感じです。
[![ProtoPedia posts](https://vercel-serverless-functions-henna.vercel.app/api/protopedia?username=yamaccu&post=true)](https://protopedia.net/prototyper/yamaccu)[![ProtoPedia views](https://vercel-serverless-functions-henna.vercel.app/api/protopedia?username=yamaccu&view=true)](https://protopedia.net/prototyper/yamaccu)[![ProtoPedia good](https://vercel-serverless-functions-henna.vercel.app/api/protopedia?username=yamaccu&good=true)](https://protopedia.net/prototyper/yamaccu)
最近、自分の個人活動をGitHubのプロフィールにまとめているのですが、ProtoPediaの情報も追記したいと思いまして、Web系ド素人なのですが意を決して作ってみました。

こちらからバッジ作成できます。
よろしければ使ってやってくださいm(_ _)m

https://yamaccu.github.io/app/20221206_protopedia-badge

### そもそもProtoPediaって何？

自分で作った作品を登録したり、他の人の作品を見たりすることができるサービスです。
Qiitaが技術情報を登録するサービスなのに対して、ProtoPediaは成果物を登録するイメージです。

https://protopedia.net/

以降、バッジを作った方法を書いていこうと思います。

# 使った技術

* Vercel Serverless Functions
* ProtoPedia API
* Shields.io

### Vercel serverless Functionsについて

Vercelというホスティングサービスの、サーバーレス機能です。（そのまま・・
サーバーの確保や、面倒な設定などなしに、サーバー用のプログラムをアップロードするだけで実行してくれる便利な機能です。
Node.js、GO、Python、Rubyに対応しています。
無料枠あります。
この業界あんまり詳しくないのですが、このようなサーバーレス機能が流行っているみたいです。


詳細はこちら

https://vercel.com/docs/concepts/functions/serverless-functions

### ProtoPedia APIについて

ProtoPediaの作品情報を入手できるREST APIです。
詳細はこちら

https://qiita.com/masaya3/items/44bce76da06ec1283ca3

少しクセがあるとのことです

* ユーザー自身の情報（投稿数とか）はとれない
* 作品情報に開発素材や登録イベントが複数登録されている場合、開発素材の数、登録イベントの数の分だけ同じ作品情報を取得してしまう仕様になっており、データが被る

### Shields.ioについて

Sields.ioとは、様々な技術情報をバッジ形状にして表示できるようにしてくれるサービスです。
GitHubのReadmeなどによく使われています。

https://shields.io/

固定値からバッジを出力する方法と、APIの戻り値を自動で反映しバッジを出力する方法があります。

例えば、QiitaのAPIではユーザーの投稿数を取得できるので、Shields.ioのみを使ってバッジを取得することができます。

以下のShields.ioのURLにデータを取りに行くと

```
https://img.shields.io/badge/dynamic/json?color=green&label=Qiita%20posts&query=items_count&url=https://qiita.com/api/v2/users/yamaccu
```

下のようなSVGが取得できます。
![ProtoPedia posts](https://img.shields.io/badge/dynamic/json?color=green&label=Qiita%20posts&query=items_count&url=https://qiita.com/api/v2/users/yamaccu)

一方で、ProtoPedia APIではユーザーの投稿数は直接とれない（2022/12/9時点）ので、Vercel Sereverless Functionsなどで一度APIからのデータを受けて、使いたいデータを抽出してからShields.ioへ渡す必要があります。

# ソースコード

全体は以下に保存してあります。
※Javascript歴二か月の人間のソースなので、ご注意ください。


https://github.com/yamaccu/vercel-serverless-functions/blob/main/api/protopedia.js

以降、ソースについて説明していきます。

## ProtoPedia APIにアクセスする

axiosライブラリを使ってAPIデータを取得しています。
ProtoPedia APIにアクセスするにはアクセストークンが必要で、[ProtoPediaの設定ページ](https://protopedia.net/settings/application)で取得できます。
アクセストークンは悪用されると危ないので、Vercel側の環境変数に登録してばれないようにして使います。

<details><summary>ソースコード</summary><div>

```javascript
async function requestAPI(username, limit) {
  const token = process.env[`PAT_2`];
  const res = await axios({
    url: `https://protopedia.net/api/prototypes.json?token=${token}&userNm=${username}${limit > 0 ? `&limit=${limit}` : ""}`,
    method: "get",
  });

  return res.data;
};
```

</div></details>

## データ処理

投稿数と、全作品のView合計と、全作品のGood合計を算出してみます。
まず、APIから取得したデータに対して、ID重複を排除し、クエリのうちのviewCountとgoodCountのみを抽出します。

<details><summary>ソースコード</summary><div>

```javascript
function fetchUserInfo(resAPI) {
  let removeDuplicates = [];
  removeDuplicates[0] = {
    id: resAPI[0].id,
    viewCount: resAPI[0].viewCount,
    goodCount: resAPI[0].goodCount,
  };

  for (let i = 0; i < (resAPI.length - 1); i++) {
    if (resAPI[i].id != resAPI[i + 1].id) {
      const temp = {
        id: resAPI[i + 1].id,
        viewCount: resAPI[i + 1].viewCount,
        goodCount: resAPI[i + 1].goodCount,
      }
      removeDuplicates = removeDuplicates.concat(temp);
    }
  }

  return removeDuplicates;
};
```

</div></details>

そのあと、重複排除後のjsonデータ数と、viewCountの合計と、goodCountの合計を計算します。

<details><summary>ソースコード</summary><div>

```javascript
const postNum = removeDuplicates.length;
const viewNum = removeDuplicates.reduce((sum, element) => sum + element.viewCount, 0);
const goodNum = removeDuplicates.reduce((sum, element) => sum + element.goodCount, 0);
```

</div></details>

## Shields.ioへデータを渡す

計算した値をShields.ioへ出力すれば、バッジのsvgデータを入手することができます。

<details><summary>ソースコード</summary><div>

```javascript
resPosts = await axios({
  url: `https://img.shields.io/badge/ProtoPedia%20posts-${postNum}-%2302ADBC`,
  method: "get",
});

resViews = await axios({
  url: `https://img.shields.io/badge/ProtoPedia%20views-${viewNum}-%2302ADBC`,
  method: "get",
});

resGood = await axios({
  url: `https://img.shields.io/badge/ProtoPedia%20good-${goodNum}-%2302ADBC`,
  method: "get",
});
```

</div></details>

## サーバーレスからsvgデータを返す

最後に、バッジのsvgデータをリターンすれば完了です。
下の例では、投稿数をリターンしています。

```javascript
return res.send(resPosts.data);
```

MarkDown上に表示すると以下のようになります。
[![ProtoPedia posts](https://vercel-serverless-functions-henna.vercel.app/api/protopedia?username=yamaccu&post=true)](https://protopedia.net/prototyper/yamaccu)

# 以上です。

ProtoPediaは、自分で作った作品を登録するとポートフォリオとして運用できる、便利で楽しいサービスだと思います。

作品を登録した後は、このShields.ioのバッジを使ってGitHubのプロフィールなどを賑やかにするのはいかがでしょうか。