概要
事前に設定したタイトル/作者の漫画の発売日になったら、自動的にSlackに通知が来る
データ経路
RSS(新刊ネット)=>AWS Lambda=>Slack
作業手順
1.Lambda用RoleをIAMで作成
2.AWS LamdaにてFunction登録
3.新刊ネットにてRSS生成
4.コード実装
1.Lambda用RoleをIAMを作成
IAMよりLambdaで使用するロールを作成
("Lambda"という文字を辿ってポチポチして完了)
2.AWS LamdaにてFunction登録
①AWS LambdaよりFunction(node.js)作成
②blueprintは[Blank Function]を選択
③トリガーにCronを選択(キャプチャでは毎日9:00に設定)
※[Enable trigger]はチェックしない!
④環境変数にSlckのHookUrl/Channelを指定
※[Encryption key]は IAM > 暗号化キーより作成
⑤とりあえず保存
3.新刊ネットにてRSS生成
①新刊ネット( http://sinkan.net )にてアカウント作成
③設定の「まもなく発売の表示範囲」を 「0日前から、1日後まで」に設定
⇛「本日が発売日」である漫画をRSSに載せるため
4.コード実装
ソースコード:https://github.com/kon-shou/lambda_manga
①RSS取得を設定
pubTitleArr[]にタイトルを格納、pubLinkArr[]に商品リンクを格納
const fetchOptions = {
uri: '新刊ネットのRSSのURL',
transform: function (body) {
let $ = cheerio.load(body ,{xmlMode : true});
$("channel > item").each(function(i) {
pubTitleArr[i] = $(this).find("title").text();
pubLinkArr[i] = $(this).find("link").text();
console.log(pubTitleArr);
console.log(pubLinkArr);
});
}
};
②AWSよりRSS取得を実行
nodejsは非同期処理なので、request-promiseによって同期処理を実行
exports.handler = (event, context, callback) => {
rp(fetchOptions)
.then(function ($) {
processEventWithHookUrl (event, callback);
})
.catch(function (err) {
console.log("Error Fetch API");
});
};
③HookUrl/ChannelをAWS kmsより取得
function processEventWithHookUrl (event, callback) {
if (hookUrl) {
// Container reuse, simply process the event with the key in memory
processEvent(event, callback);
} else if (kmsEncryptedHookUrl && kmsEncryptedHookUrl !== '<kmsEncryptedHookUrl>') {
const encryptedBuf = new Buffer(kmsEncryptedHookUrl, 'base64');
const cipherText = { CiphertextBlob: encryptedBuf };
const kms = new AWS.KMS();
kms.decrypt(cipherText, (err, data) => {
if (err) {
console.log('Decrypt error:', err);
return callback(err);
}
hookUrl = data.Plaintext.toString('ascii');
processEvent(event, callback);
});
} else {
callback('Hook URL has not been set.');
}
}
④通知(1)
pubTitleArrの長さで「発売タイトルの有無」を判定
複数タイトルの場合はpostMessageを繰り返す
function processEvent(event, callback) {
if (pubTitleArr.length > 0) {
for (let i = 0; i < pubTitleArr.length; i++) {
slackMessage = {
text: `${pubTitleArr[i]}\n${pubLinkArr[i]}`,
};
console.log(slackMessage);
postMessage(slackMessage, (response) => {
if (response.statusCode < 400) {
console.info('Message posted successfully');
callback(null);
} else if (response.statusCode < 500) {
console.error(`Error posting message to Slack API: ${response.statusCode} - ${response.statusMessage}`);
callback(null); // Don't retry because the error is due to a problem with the request
} else {
// Let Lambda retry
callback(`Server error when processing message: ${response.statusCode} - ${response.statusMessage}`);
}
});
}
} else {
callback(`本日発売の漫画はありません`);
}
}
⑤通知(2)
messageをjsonにしてHTTPメソッドでPOSTする
function postMessage(message, callback) {
const body = JSON.stringify(message);
const Sendoptions = url.parse(hookUrl);
Sendoptions.method = 'POST';
Sendoptions.headers = {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(body),
};
const postReq = https.request(Sendoptions, (res) => {
const chunks = [];
res.setEncoding('utf8');
res.on('data', (chunk) => chunks.push(chunk));
res.on('end', () => {
if (callback) {
callback({
body: chunks.join(''),
statusCode: res.statusCode,
statusMessage: res.statusMessage,
});
}
});
return res;
});
postReq.write(body);
postReq.end();
}
通知完了
tips
testコード(上記レポジトリのtest.js)を作っておくと、
node test.js
でスクリプト起動できるので楽
最後に
Javascript/Lambda初心者が作ったので間違いがあるかもしれませんが、その時はご指摘をお願いします。