Node.js土台構築の記事

前回の準備の記事

Tomoya前回の記事で、テーマの選定と必要な準備を済ませました。
ここからが本題、実際の開発フェーズです!!
今回の仕組み全体図

価格を取得するコードを書く
Tomoyaまずは、CoinGeckoのAPIキーがちゃんと機能するのかを確かめるところから始めました。
cd ~/crypto-watcher
nano fetch-price.js
↓
※コード記入・保存後、実行
node fetch-price.js
require('dotenv').config(); //※.envファイルの中身を読み込む一文
const API_KEY = process.env.COINGECKO_API_KEY;
async function getBitcoinPrice() {
const url = 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=jpy';
const response = await fetch(url, {
headers: {
'accept': 'application/json',
'x-cg-demo-api-key': API_KEY
}
});
const data = await response.json();
return data.bitcoin.jpy;
}
getBitcoinPrice().then((price) => {
console.log(`現在のビットコイン価格:${price}円`);
});
TomoyaAIにサポートしてもらいながらコードを組み立てましたが、コピペで済ませず、学習のためにあえて自分の手で1文字ずつ入力していきました。
Node.js導入編で書いたごく短いコードと比べると、量が一気に増えて少し圧倒されましたが、何とか書き切ることができました。
Tomoya特に気をつけたのはインデント(字下がり)の量です。
ツールによってはインデントが1つズレただけでもエラーになることがあると聞いていたので、慎重に記述していきました。
実際に動かしてみると、価格を表示する部分の${price}のところを、うっかり%{price}と打ち間違えてしまい、計算されるべき数字ではなく文字列がそのまま出力されてしまう、というタイプミスがありました。
Tomoyaすぐに気づいて修正し、無事にビットコインの現在価格を取得できることを確認しました。
今回はひとまずビットコインのみを対象にしています。

Discordに通知が届くかの実験
次に、通知が実際に届くかどうかの実験です。同じようにnanoエディタで記述していきました。
nano notify-test.js
↓
※コード記入・保存後、実行
node notify-test.js
require('dotenv').config();
const WEBHOOK_URL = process.env.DISCORD_WEBHOOK_URL;
async function sendDiscordNotification(message) {
await fetch(WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content: message })
});
}
sendDiscordNotification('テスト通知:この文章が届けば成功です!');

Tomoya今回はタイプミスもなく、無事にDiscordへメッセージが送られました。

この過程で、Discordには「contentという項目にメッセージを入れて送る」という決まったルールがあることを知りました。
サービスやツールごとに細かなルールがあり、それを一つひとつ調べながら進めるのはなかなか大変だなと感じつつ、ここでもAIのサポートのおかげでスムーズに理解できたことに、あらためて感動しました。
条件を加えたロジックの設計
Tomoya次に、条件を組み込んだロジックを設計します。
仕組みとしては単純でも、同じ条件のまま何度も連続で通知が来てしまうのはうっとうしいので、ここをどう防ぐかを考えました。
「ある条件を満たした時にだけ通知する」
「一度通知したら、条件が解除されるまでは連続で送らない」
というルールを設定していきました。
シンプルなルールですが、実際に運用する上ではとても重要な部分だと感じています。
本番用のコードを作成する
ここまでの要素を組み合わせて、本番用のコードを作成しました。
nano index.js
↓
※コード記入・保存後、実行
node index.js
require('dotenv').config();
const cron = require('node-cron');
const API_KEY = process.env.COINGECKO_API_KEY;
const WEBHOOK_URL = process.env.DISCORD_WEBHOOK_URL;
const ALERT_THRESHOLD = 15000000; // ← ここが今回つまずいたポイント(後述)
let alreadyNotified = false;
async function getBitcoinPrice() {
const url = 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=jpy';
const response = await fetch(url, {
headers: {
'accept': 'application/json',
'x-cg-demo-api-key': API_KEY
}
});
const data = await response.json();
return data.bitcoin.jpy;
}
async function sendDiscordNotification(message) {
await fetch(WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content: message })
});
}
async function checkPrice() {
const price = await getBitcoinPrice();
const now = new Date().toLocaleString('ja-JP');
console.log(`[${now}] 現在価格:${price}円`);
if (price < ALERT_THRESHOLD && !alreadyNotified) {
await sendDiscordNotification(
`⚠️ ビットコインが${ALERT_THRESHOLD}円を下回りました!\n現在価格:${price}円`
);
alreadyNotified = true;
} else if (price >= ALERT_THRESHOLD && alreadyNotified) {
alreadyNotified = false;
}
}
checkPrice();
cron.schedule('*/5 * * * *', checkPrice);
console.log('価格監視を開始しました。');

Tomoya定期実行の仕組み(node-cron)と、条件判定を組み合わせて、「指定した金額を下回ったら通知する」というシステムを組み上げていきました。
コード量が多く、書くこと自体はなかなか大変でしたが、流れに乗って何とか記述することができました。定期実行のcron.schedule('*/5 * * * *', ...)という書き方も独特で最初は戸惑いましたが、見本を参考にしながら書くことで、すんなりと進められました。
こうして実際に手を動かしてみると、日頃エンジニアの方々がどれだけのことを頭の中でこなしているのか、あらためて実感します。
ある程度の方針や要件が決まっているとはいえ、そこから何をどう書くかをフルで考えて組み立てていく作業は、本当にすごいことだと思います。AIの登場によって、この「書く」という作業のハードルが大きく下がり、初心者でも参入しやすくなったのは、間違いなく大きな転換点だと感じています。
「初心者でも参入できるようになった分、エンジニアの仕事がなくなるのでは」という意見も耳にしますが、僕はそうは思いません。エンジニアの方々は、すでに持っている知識を活かしてAIを使うことで、本当にやるべきことに集中できるようになるのだと思います。あくまで個人の推測に過ぎませんが、AIによってエンジニアという仕事自体が、より本質的で楽しいものになっていくのではないか、と感じています。
動作確認でのつまずき
いざ動作確認をしてみると、閾値の設定を現在価格より高くしてしまっていたため、一定間隔で通知が飛んでき続ける、という出来事が起きました。
「動作確認としては成功しているが、実運用としては失敗している」ということです。
たった1つの設定値の違いだけで、意図しない動きになってしまう——実際にやってみないとわからないことではありますが、事前にこの視点を持てていれば防げたはずだ、と思うと、こういう視点を持てること自体が、エンジニアへの第一歩なのかもしれないと感じました。
実際に使える設定値に調整する
その後、実際に運用したい、意味のある設定値に調整しました。
Tomoya現在のビットコイン価格が1,060万円程なので。
4%程下がったら通知が来るように1,020万円で設定しました。
ただ、この段階ではまだ、ターミナルの画面を閉じるとシステムそのものも消えてしまう状態です。そこで、前回のNode.js編で登場したpm2をここでも活用していきます。
pm2で常駐化する
前回と同様の手順で、ファイルを常駐化させました。
cd ~/crypto-watcher
pm2 start index.js --name crypto-watcher
今回は、--nameオプションで名前をつけて管理しやすくしています。今後も新しいシステムをどんどん追加していくことを考えると、ぐちゃぐちゃになる前に整理しておく土台を作れたのは良かったと感じています。
pm2 logs crypto-watcher
pm2 save
ログも確認し、再起動後も稼働し続けていることを確認できたので、これで完成です。

これで、ビットコインが1,020万円(記事執筆時点で現在価格は1,060万円ほど)を下回ったら通知が来る、24時間稼働の監視システムを作ることができました。
まとめ
こうしたちょっとした仕組みでも、自分の代わりに常に見張り、必要な時だけ報告してくれるシステムは、思っている以上に有効なのだと感じました。
アイデア次第では、自分にとって価値のある作業を代行してくれるシステムを開発し、常駐させておくことで、「ある条件のもとで24時間、実行・報告してくれる」という状態を作れます。
これは、まるで小さな会社を経営しているような感覚にも近く、想像するだけでワクワクしてきます。
アルゴリズムだけでは限界がある部分もあるかもしれませんが、そこにAIを組み合わせていくことで、できることの幅はさらに広がっていくのではないでしょうか。VPSを実際に触ってみて、こうした可能性が少しずつ見えてきたのは、間違いなく「体験してみたからこそ」だと思います。
TomoyaまだVPSを触ったことがない方は、ぜひ一度試してみてください!!
個人の方はもちろん、組織で活用したいという方にも、導入を検討してみる価値があると思います。






コメント