チュートリアル · Cloudflare · REST
Cloudflare Workerでピナクルオッズ
回答: wrangler secret put PINNFEED_KEY でキーを保存します。Workerの fetch は短いエッジキャッシュ付きでフロント向けに /v1/odds をプロキシし(キーはブラウザに渡りません)、scheduled はcronで /v1/drops を呼び、新しいドロップをDiscord webhookへ投稿します。すべてRESTなのでFree(30秒遅延)から使えます。
wrangler.toml#
name = "pinnfeed-worker"
main = "src/index.js"
compatibility_date = "2026-11-01"
[triggers]
crons = ["*/2 * * * *"]
npx wrangler secret put PINNFEED_KEY # ps_live_...
npx wrangler secret put DISCORD_WEBHOOK # https://discord.com/api/webhooks/...
npx wrangler deploy
src/index.js#
const API = 'https://pinnfeed.io/v1';
export default {
async fetch(req, env, ctx) {
const url = new URL(req.url);
if (url.pathname !== '/odds') return new Response('not found', { status: 404 });
const sport = url.searchParams.get('sport') || 'soccer';
const cache = caches.default;
const cacheKey = new Request(`${url.origin}/odds?sport=${sport}`);
let res = await cache.match(cacheKey);
if (!res) {
const r = await fetch(`${API}/odds?sport=${sport}&market=moneyline&main=true&limit=50`, {
headers: { 'x-api-key': env.PINNFEED_KEY },
});
res = new Response(r.body, { status: r.status, headers: { 'content-type': 'application/json', 'cache-control': 'max-age=5' } });
if (r.ok) ctx.waitUntil(cache.put(cacheKey, res.clone()));
}
return res;
},
async scheduled(_event, env) {
const r = await fetch(`${API}/drops?sport=soccer&minutes=2&min_pct=5&limit=10`, {
headers: { 'x-api-key': env.PINNFEED_KEY },
});
if (!r.ok) return;
const { drops } = await r.json();
if (!drops.length) return;
const lines = drops.map((d) => `${d.home} v ${d.away}: ${d.market} ${d.outcome} ${d.from} → ${d.to} (${d.dropPct}%)`);
await fetch(env.DISCORD_WEBHOOK, {
method: 'POST', headers: { 'content-type': 'application/json' },
body: JSON.stringify({ content: lines.join('\n').slice(0, 1900) }),
});
},
};
守るべき制限#
Freeは1 req/s・1,000/日、Hobby 2/s、Builder 10/s。エッジキャッシュでスパイクがAPI呼び出しにならないようにします。本物のプッシュには常時起動サーバー上のWebSocketとBuilder(99€/月)。3日間トライアル、カード必須。無料REST:signup。。関連:ブラウザJS / CORS、FastAPIプロキシ。
よくある質問#
WorkerでWebSocketは開けますか?#
短い実行時間では信頼できません。ここではREST、WSは常時サーバーで。
Discord必須ですか?#
いいえ。webhook URLをSlackやTelegramなどに差し替えられます。
成人向けの教育コンテンツですか?#
はい(18+)。
18歳以上の方を対象とした教育目的のコンテンツです。予想や利益の約束ではありません。日本では刑法により賭博は原則として禁止されています。