145 lines
5.1 KiB
JavaScript
145 lines
5.1 KiB
JavaScript
const fs = require('fs'); // ファイル操作用モジュール
|
|
const jwt = require('jsonwebtoken'); // JWT生成用モジュール
|
|
const { API_KEY } = require('../config.js'); // API_KEYをインポート
|
|
|
|
module.exports = (app) => {
|
|
app.post('/lwSendMessage', async (req, res) => {
|
|
let rawBody = '';
|
|
req.on('data', (chunk) => {
|
|
rawBody += chunk; // リクエストデータをそのまま取得
|
|
});
|
|
|
|
req.on('end', async () => {
|
|
// reqのすべてのパラメータを表示
|
|
// console.log('Request Headers:', req.headers);
|
|
// console.log('Request Body:', rawBody);
|
|
|
|
const apiKey = req.headers['x-api-key'];
|
|
if (!apiKey || apiKey !== API_KEY) {
|
|
console.log('APIキーが不正です');
|
|
return res.status(401).json({ error: 'APIキーが不正です' });
|
|
}
|
|
|
|
// botIdとuserIdをヘッダーから取得
|
|
const botId = req.headers['x-bot-id'];
|
|
const userId = req.headers['x-user-id'];
|
|
if (!botId || !userId) {
|
|
console.log('x-bot-id, x-user-idは必須です');
|
|
return res.status(400).json({ error: 'x-bot-id, x-user-idは必須です' });
|
|
}
|
|
|
|
const userIds = userId.split(';').map(id => id.trim()).filter(id => id);
|
|
|
|
// リクエストボディからメッセージテキストを取得
|
|
const messageText = rawBody;
|
|
if (!messageText) {
|
|
console.log('messageTextは必須です');
|
|
return res.status(400).json({ error: 'messageTextは必須です' });
|
|
}
|
|
|
|
try {
|
|
for (const uid of userIds) {
|
|
const result = await sendLineworksMessage(botId, uid, messageText);
|
|
if (result.success) {
|
|
console.log(`送信成功: ${uid}:`, result.message);
|
|
} else {
|
|
console.log(`送信失敗: ${uid}:`, result.message);
|
|
}
|
|
}
|
|
res.json({ result: 'ok', message: '全ユーザーに送信処理完了' });
|
|
return;
|
|
} catch (e) {
|
|
console.log('エラーが発生しました:', e.message);
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
// メッセージ送信
|
|
async function sendLineworksMessage(botId, userId, messageText) {
|
|
const accessToken = await getAccessToken();
|
|
if (!accessToken) {
|
|
console.log('アクセストークンの取得に失敗しました');
|
|
throw new Error('アクセストークンの取得に失敗しました');
|
|
}
|
|
|
|
// userIdに@が含まれない場合はchannelIdとして扱う
|
|
let apiUrl;
|
|
if (userId.includes('@')) {
|
|
apiUrl = `https://www.worksapis.com/v1.0/bots/${botId}/users/${userId}/messages`;
|
|
} else {
|
|
apiUrl = `https://www.worksapis.com/v1.0/bots/${botId}/channels/${userId}/messages`;
|
|
}
|
|
|
|
const body = {
|
|
'content': {
|
|
'type': 'text',
|
|
'text': messageText
|
|
}
|
|
};
|
|
|
|
const response = await fetch(apiUrl, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json;charset=UTF-8',
|
|
'Authorization': `Bearer ${accessToken}`
|
|
},
|
|
body: JSON.stringify(body)
|
|
});
|
|
|
|
if (response.ok) {
|
|
console.log('メッセージ送信成功');
|
|
return { success: true, message: '送信成功' };
|
|
} else {
|
|
const errorText = await response.text();
|
|
console.log('メッセージ送信失敗:', errorText);
|
|
return { success: false, message: `送信失敗: ${errorText}` };
|
|
}
|
|
}
|
|
|
|
// アクセストークン取得
|
|
async function getAccessToken() {
|
|
const clientId = 'V58hNobcAqRcQPerySMz';
|
|
const clientSecret = 'gJ84XQtigD';
|
|
const serviceAccount = 'x94xh.serviceaccount@works-nextgroup2';
|
|
const privateKey = fs.readFileSync('./modules/private_20250530180606.key', 'utf8');
|
|
const apiUrl = 'https://auth.worksmobile.com/oauth2/v2.0/token';
|
|
const now = Math.floor(Date.now() / 1000);
|
|
|
|
// JWT生成
|
|
const payload = {
|
|
'iss': clientId,
|
|
'sub': serviceAccount,
|
|
'iat': now,
|
|
'exp': now + 60 * 5,
|
|
'aud': apiUrl
|
|
};
|
|
const assertion = jwt.sign(payload, privateKey, { 'algorithm': 'RS256' });
|
|
|
|
const body = new URLSearchParams({
|
|
'assertion': assertion,
|
|
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
|
|
'client_id': clientId,
|
|
'client_secret': clientSecret,
|
|
'scope': 'bot'
|
|
});
|
|
|
|
const response = await fetch(apiUrl, {
|
|
'method': 'POST',
|
|
'headers': { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
'body': body.toString()
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
console.log('アクセストークン取得成功');
|
|
return data.access_token;
|
|
} else {
|
|
const errorText = await response.text();
|
|
console.log('アクセストークン取得失敗:', errorText);
|
|
return null;
|
|
}
|
|
}
|
|
|