ken_nogi/pleasanter/develop2/LINEWORKStoPLEASANTER/sample/newSample.js
Kenichiro NOGI 88a402ce0f up
2026-07-10 18:13:30 +09:00

163 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
// --- 1. 設定情報 ---
const ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN';
const BOT_ID = 'YOUR_BOT_ID';
const API_BASE_URL = `https://www.worksapis.com/v1.0/bots/${BOT_ID}/users`;
// --- 2. アンケート項目の定義 ---
const SURVEY_QUESTIONS = [
{
id: 'category',
type: 'select',
text: 'Q1. お問い合わせの種類を選択してください。',
options: ['製品について', '採用について', 'その他']
},
{
id: 'age',
type: 'number',
text: 'Q2. 年齢を数字のみで入力してください(例: 25。'
},
{
id: 'comment',
type: 'text',
text: 'Q3. 自由にご意見をご記入ください。'
}
];
// ユーザーの状態管理(メモリ保存用)
// 実運用では Redis や DB を推奨
const userStates = {};
// --- 3. メッセージ送信ヘルパー関数 ---
async function sendBotRequest(userId, payload) {
try {
await axios.post(`${API_BASE_URL}/${userId}/messages`, payload, {
headers: { 'Authorization': `Bearer ${ACCESS_TOKEN}`, 'Content-Type': 'application/json' }
});
} catch (err) {
console.error('API Error:', err.response?.data || err.message);
}
}
// 質問を送信するメイン関数
async function sendQuestion(userId, stepIndex) {
const question = SURVEY_QUESTIONS[stepIndex];
let content = {};
// 中断ボタン(共通)
const cancelAction = { type: 'postback', label: 'アンケートを中断', data: 'action=cancel' };
if (question.type === 'select') {
// ボタン形式
content = {
type: 'button_template',
contentText: `${stepIndex + 1}/${SURVEY_QUESTIONS.length}\n${question.text}`,
actions: [
...question.options.map(opt => ({
type: 'postback',
label: opt,
data: `step=${stepIndex}&ans=${opt}`
})),
cancelAction
]
};
} else {
// テキスト・数字入力形式
content = {
type: 'text',
text: `${stepIndex + 1}/${SURVEY_QUESTIONS.length}\n${question.text}`
};
}
const payload = { content };
// テキスト入力時にはクイックリプライで「中断」を表示
if (question.type !== 'select') {
payload.quickReply = { items: [{ action: cancelAction }] };
}
await sendBotRequest(userId, payload);
}
// --- 4. アンケート開始トリガー(プッシュ送信用) ---
async function initiateSurvey(userId) {
userStates[userId] = { currentStep: 0, answers: {} };
await sendQuestion(userId, 0);
}
// --- 5. Webhook 受信処理 ---
app.post('/callback', async (req, res) => {
const event = req.body;
const userId = event.source?.userId;
if (!userId) return res.sendStatus(200);
// A. 中断処理
if (event.type === 'postback' && event.postback?.data === 'action=cancel') {
delete userStates[userId];
await sendBotRequest(userId, { content: { type: 'text', text: 'アンケートを中断しました。' } });
return res.sendStatus(200);
}
// B. アンケート中のユーザーか確認
const state = userStates[userId];
if (!state) {
// アンケート中ではない場合、特定のワードで開始させる
if (event.type === 'message' && event.content.text === 'アンケート開始') {
await initiateSurvey(userId);
}
return res.sendStatus(200);
}
const currentQuestion = SURVEY_QUESTIONS[state.currentStep];
let answer = null;
// C. 回答の受け取りとバリデーション
if (currentQuestion.type === 'select' && event.type === 'postback') {
const params = new URLSearchParams(event.postback.data);
answer = params.get('ans');
} else if (event.type === 'message' && event.content.type === 'text') {
const inputText = event.content.text;
if (currentQuestion.type === 'number') {
if (!/^\d+$/.test(inputText)) {
await sendBotRequest(userId, { content: { type: 'text', text: '⚠️ 半角数字のみで入力してください。' } });
return res.sendStatus(200);
}
}
answer = inputText;
}
// D. 次のステップへ進む処理
if (answer !== null) {
state.answers[currentQuestion.id] = answer;
state.currentStep++;
if (state.currentStep < SURVEY_QUESTIONS.length) {
await sendQuestion(userId, state.currentStep);
} else {
// 全回答完了
const summary = Object.entries(state.answers)
.map(([id, val]) => `${id}: ${val}`).join('\n');
await sendBotRequest(userId, {
content: { type: 'text', text: `ご協力ありがとうございました!\n回答内容:\n${summary}` }
});
console.log(`【集計完了】User: ${userId}`, state.answers);
delete userStates[userId];
}
}
res.sendStatus(200);
});
// サーバー起動
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});