💨

MiHoMo APIをNode.jsで叩いてみる 前編

2024/01/18に公開

前置き

はじめまして、詩哭と申します。
私事ではございますが、先日 崩壊: スターレイル (移行: 崩スタ)というゲームを始めました。
簡単に言えば原神の戦闘をターン制にしたようなゲーム。
原神はあまりハマらなかったのですが、こちらは中々面白くハマってしまいました。

そこで、原神には ビルドカード というものがあります。
キャラクターのレベル、ステータスの他、聖遺物のレベルなどを表示し、スコアを計算したカードのことです。
友人とステータスを見せ合ったり、フレンド募集の際にプロフィール代わりに見せたり...など使い方は色々あると思います。


Genshin Impact (JPN)にて生成したもの

調べてみると崩スタにもビルドカードがあるらしく、更に調べてみるとAPIも提供されているようで.........
ちょうどプログラミングのネタを考えていたところですので、これを気にビルドカードの自作をやってみよう!ということで挑戦してみます。

MiHoMo APIについて

MiHoMo API はuidをわたすことで崩スタでのプレイヤーのデータを取得するAPIです。
リクエストはGETで、APIホストは https://api.mihomo.me/ です。

動作環境

node.jsが動く環境であれば開発できるかと思います。
なお、APIリクエストができるならnode.js以外でも可。Pythonとか。

  • OS: Windows 11 pro
  • Node.js v18.16.1
  • Windows ターミナル
  • VScode

Node.jsでAPIを叩く

では早速APIを叩いてみましょうか。

今回はnode.js環境なのでモジュールを選定します。
node.jsでは、標準の https とライブラリの request があります。他にもあるかも?
インストールがいらないという点でとりあえずhttpsを使ってみます。requestでも問題なく動くと思います。

基本的な情報

まずは基本的な情報を取得していきます。
httpsの詳しい使い方については各自で調べてください。
URLの部分に先程のAPIホストを用いて書きます。
ホストに続いて、パラメータを書いていきます。

MiHoMo APIでは、エンドポストが2つあります。
sr_infosr_info_parsed ですね。
前者は素の情報を取得し、後者は整理した情報を取得します。今回は後者を使用。
パラメータにはuidを指定します。
https://api.mihomo.me/sr_info_parsed/{uid}?lang=jp{uid} 部に自分のuidを入れましょう。例では私のuidである 830647229 を入れています。

最後の ?lang=jp については言語設定です。標準では中国語表示になってますので、これを日本語に帰るために、langをjpとして設定しています。
他にも英語、スペイン語、フランス語、韓国語、ポルトガル語など対応していますのでお好みで。

const https = require("https");

https.get("https://api.mihomo.me/sr_info_parsed/{uid}?lang=jp", (rep) => {
    let data = "";

    rep.on("data", (c) => {
      data += c;
    });

    rep.on("end", () => {
      console.log(JSON.parse(data));
    });
  })
  .on("error", (e) => {
    console.error(e.message);
  });

  // Result
  // 例: {
  //   player: {
  //     uid: '830647229',
  //     nickname: 'Shicoku',
  //     level: 18,
  //     world_level: 0,
  //     friend_count: 2,
  //     avatar: { id: '201013', name: 'ヘルタ', icon: 'icon/avatar/1013.png' },
  //     signature: 'しこく 最近始めました。',
  //     is_display: true,
  //     中略
  //   },
  //   characters: [
  //     {
  //       id: '1013',
  //       name: 'ヘルタ',
  //       rarity: 4,
  //       rank: 0,
  //       level: 20,
  //       promotion: 1,
  //       icon: 'icon/character/1013.png',
  //       preview: 'image/character_preview/1013.png',
  //       portrait: 'image/character_portrait/1013.png', ... 略

取得できましたね。リクエストして帰ってきたデータはJSON形式に変換しています。
ただのJSONですので、例えばこのように書けば...

https.get("https://api.mihomo.me/sr_info_parsed/{uid}?lang=jp", (rep) => {
    let data = "";

    rep.on("data", (c) => {
      data += c;
    });

    rep.on("end", () => {
-     console.log(JSON.parse(data));
+     console.log(JSON.parse(data)["player"]["nickname"]);
    });
  })
  .on("error", (e) => {
    console.error(e.message);
  });

  // Result
  // 例: Shicoku

playerの情報からニックネーム、つまりゲーム内で設定している公開名を取得することができますね。
これで必要なデータを取得できるようになりました。

スコアを計算してみる

では、実際に遺物のスコアを計算していみましょう。
計算式には、 崩スタ - 遺物スコア計算機 からメインスコアの計算式を使用します。
スコア = (遺物のレベル + 1) ÷ 16 × 重要度 × 50 ですね。
重要度もサイトから引用します。

とりあえず、1番目(二人目に設定した)のキャラの0番目の遺物のスコアを計算します。
キャラは開拓者で遺物は頭なので、重要度には1を代入。

const https = require("https");

https.get("https://api.mihomo.me/sr_info_parsed/{uid}?lang=jp", (rep) => {
    let data = "";

    rep.on("data", (c) => {
      data += c;
    });

    rep.on("end", () => {
      let score = ((JSON.parse(data)["characters"][1]["relics"][0]["level"] + 1) / 16) * 1 * 50;
      console.log(score.toFixed(1));
    });
  })
  .on("error", (e) => {
    console.error(e.message);
  });
  
  // Result
  // 例: 3.1

まずはAPIで遺物のレベルを取得します。
先程も書いたように 1番目のキャラの0番目の遺物 ですから
JSON.parse(data)["characters"][1]["relics"][0]["level"]
このように書けばいいですね。
この計算結果をscoreに宣言します。
こちらの計算結果には少数が含まれ、長くなると見にくくなるので少数第2位以下は四捨五入します。ので toFixed を使ってコンソールに表示するといった形ですね。

ちなみに、3.1のランクはDですね。
if文でも使ってこの辺をカスタマイズすればランク付けもできそうです。

次回の予定

予想以上に長くなりそうなのと、実はこの執筆時点ではまだ完成していないため、ここで分けようと思います。すいません。
予定としては2月末あたりには出せたらなぁとは思っているんですが.....
できるだけ早く出せるように頑張ります。

後編を出しました!

https://zenn.dev/shicoku/articles/7a586a5615f3ee

参照

崩壊: スターレイル
Genshin Impact (JPN)
MiHoMo API
崩スタ - 遺物スコア計算機

Discussion