slackで自分のアカウントからメッセージを送るapiをhonoで作った話
こんにちは、あやにゃんです!
友達の研究室が毎日平日の朝におはようございますとスラックに送らなければならないと聞いて、それ、自動化しちゃおうよ!!となったので作りました!
ぜひ同じ境遇の人は参考にしてください!
最近、「Slackに自分のアカウントから、毎朝9時台にランダムな時間でメッセージを投稿するAPI」を作りました。
しかも、
-
Hono
-
Cloudflare Workers
-
TypeScript
を組み合わせて、めちゃくちゃ軽くてスマートに動いてます(3150)
この記事ではその構成・コード・ちょっとハマったところなどをまとめました。
🛠️ 作ったもの
- 平日のみ
- 朝9:00〜9:59の間にランダムな分にSlackへ「おはようございます ☀️」を
- Botではなく、自分のSlackアカウントで投稿する!
🧱 技術スタック
技術 | 用途 |
---|---|
Hono | 軽量なWebフレームワーク |
Cloudflare Workers | サーバレスでAPIホスティング |
Slack API (chat.postMessage ) |
自分のユーザーとして投稿 |
Workers KV | 投稿予定時間の一時保存 |
🌅 構成の概要
1日2回 API が呼ばれます:
- 深夜0時:ランダムな分数(0〜59)を生成して保存
- 朝9時台(毎分):現在の分が一致したら投稿!
Cloudflare Workersの Cron Triggers
機能を使って、スケジュール実行しています。
なぜCron Triggersを使用したかと申しますと、
Cloudflare Workers の無料プランでは、1リクエストあたりの最大実行時間が 30秒 までです 😢
なので、ランダムな数を生成して待つよりも、深夜にランダムな数を生成して予約する方がいいのです!!
🧑💻 コード:Hono + Workers
Hono CLI でプロジェクトを作成
bun create hono@latest slack-hono-bot
-
プロンプトで選ぶ項目
- Target directory:
slack-hono-bot
- Template:
cloudflare-workers
- Package manager:
bun
(またはお好みでnpm
/yarn
/pnpm
)
- Target directory:
デフォルトのディレクトリ構成を確認
生成された直後の構成はこんな感じです:
slack-hono-bot/
├── package.json
├── public/
│ ├── favicon.ico
│ └── static/…
├── src/
│ └── index.ts ← ここに API ロジックを書く
└── wrangler.toml ← Cloudflare Workers の設定!なければ自分で作る
/// <reference types="@cloudflare/workers-types" />
import { Hono } from 'hono'
type Env = {
SLACK_USER_TOKEN: string
SLACK_CHANNEL_ID: string
POST_TIME: KVNamespace
}
const app = new Hono<{ Bindings: Env }>()
// 深夜0時:投稿分数をランダムに設定
app.get('/set-time', async (c) => {
const randomMinute = Math.floor(Math.random() * 60)
await c.env.POST_TIME.put('next_post_minute', String(randomMinute))
return c.text(`明日の投稿時間は 9:${String(randomMinute).padStart(2, '0')} に設定しました`)
})
// 朝9時台:もし一致したらSlackに投稿
app.get('/post-if-match', async (c) => {
const now = new Date()
const weekday = now.getDay() // 月〜金:1〜5
const currentMinute = now.getMinutes()
if (weekday < 1 || weekday > 5) {
return c.text('今日は平日ではありません。')
}
const savedMinuteStr = await c.env.POST_TIME.get('next_post_minute')
const savedMinute = savedMinuteStr ? parseInt(savedMinuteStr, 10) : -1
if (currentMinute === savedMinute) {
const token = c.env.SLACK_USER_TOKEN
const channelId = c.env.SLACK_CHANNEL_ID
const payload = {
channel: channelId,
text: 'おはようございます ☀️(ランダム投稿)',
}
const res = await fetch('https://slack.com/api/chat.postMessage', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
const data: { ok: boolean; error?: string } = await res.json()
if (!data.ok) {
return c.text(`Slack投稿失敗: ${data.error}`, 500)
}
return c.text(`✅ 投稿しました!(9:${currentMinute})`)
}
return c.text(`今は ${currentMinute}分、投稿予定は ${savedMinute}分`)
})
export default app
🔐 環境変数の設定(Wrangler)
環境変数の取得はこちら💁🏻♀️ https://api.slack.com/apps
SLACK_USER_TOKEN
SLACK_CHANNEL_ID
npx wrangler secret put SLACK_USER_TOKEN # xoxp-... 自分のSlackアカウントのOAuthトークン
npx wrangler secret put SLACK_CHANNEL_ID # 投稿先のチャンネルID
wrangler.toml
🗂 次に、
Cloudflare Workers の KVストア(永続的なキー・バリュー保存) を使用します
npx wrangler kv namespace create "POST_TIME"
で
{
"kv_namespaces": [
{
"binding": "POST_TIME",
"id": "xxxxx..." # 自動で生成される
}
]
}
が出てくるのでこれらをwrangler.toml以下のような形で入れます。
wrangler.tomlがなければ自分で作ってください。
コピーする編集する
name = "slack-hono-bot"
compatibility_date = "2025-04-17"
[[kv_namespaces]]
binding = "POST_TIME"
id = "xxxxx..." # 自動で生成される
[build]
command = "bun run build"
[build.upload]
main = "dist/index.js"
format = "modules"
[triggers]
crons = [
"0 15 * * *", # JST 0:00 → UTC 15:00(set-time)
"0-59 0 * * 1-5" # JST 9:00〜9:59 → UTC 0:00〜0:59(post-if-match)
]
さらに、wrangler.jsoncに
"kv_namespaces": [
{
"binding": "POST_TIME",
"id": "xxxxx..." # 自動で生成される
}
]
を追加し、
bun run build
でビルドします
🧠 ハマったポイント
-
KVNamespace
の型定義がない →@cloudflare/workers-types
を入れる -
String.padStart()
が使えない →tsconfig.json
のlib
に"ES2020"
を追加 -
fetch().json()
の型がunknown
→ 明示的に型定義する
🎁 補足:なぜ「自分のアカウント」で投稿?
SlackのIncoming Webhookだと「Bot名」でしか投稿できませんが、自分のアカウントから送ると自然で教授もニッコリ‼️
🙏 最後に
ここまで読んでくれてありがとうございます!
Cloudflare Workers と Hono の組み合わせは、無料枠が充実していてさらにデプロイが簡単なので開発体験がめちゃ良い〜‼️
「Slack自動投稿してみたい」という方の参考になれば嬉しいです ☀️
Discussion