|
// axios を使わず Node.js 組み込みの http・https で送信する場合 |
|
// ==================================================================================================== |
|
|
|
const http = require('http'); |
|
const https = require('https'); |
|
|
|
/** |
|
* リクエストする |
|
* |
|
* @param {string} url URL |
|
* @param {object} options オプション |
|
* @return {Promise<*>} Promise |
|
*/ |
|
function request(url, options) { |
|
return new Promise((resolve, reject) => { |
|
options = options || {}; |
|
const body = options.body || null; |
|
|
|
if(options.body) { |
|
delete options.body; |
|
} |
|
|
|
const agent = url.startsWith('https:') ? https : http; |
|
|
|
const req = agent.request(url, options, (res) => { |
|
res.setEncoding('utf8'); |
|
let data = ''; |
|
res.on('data', (chunk) => { |
|
data += chunk; |
|
}) |
|
.on('end', () => { |
|
resolve(data); |
|
}); |
|
}) |
|
.on('error', (error) => { |
|
reject(error); |
|
}) |
|
.on('timeout', () => { |
|
req.abort(); |
|
reject('Request Timeout'); |
|
}); |
|
|
|
req.setTimeout(8000); |
|
|
|
if(body) { |
|
req.write(body); |
|
} |
|
req.end(); |
|
}); |
|
} |
|
|
|
/** |
|
* Do Well (オレオレマイクロブログ) に POST する |
|
* |
|
* @param text 投稿文字列 |
|
* @return {Promise} 通信結果 |
|
*/ |
|
function postDoWell(text) { |
|
return request('http://example.com/index.php', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' |
|
}, |
|
body: new URLSearchParams({ |
|
credential: 'CREDENTIAL', |
|
text : text |
|
}).toString() |
|
}); |
|
} |
|
|
|
/** |
|
* Misskey に POST する |
|
* |
|
* @param text 投稿文字列 |
|
* @return {Promise} 通信結果 |
|
*/ |
|
function postMisskey(text) { |
|
return request('https://misskey.io/api/notes/create', { |
|
method: 'POST', |
|
body: JSON.stringify({ |
|
i : 'MISSKEY_API_KEY', |
|
text: text |
|
}) |
|
}); |
|
} |
|
|
|
/** |
|
* Mastodon に POST する |
|
* |
|
* @param text 投稿文字列 |
|
* @return {Promise} 通信結果 |
|
*/ |
|
function postMastodon(text) { |
|
return request('https://mstdn.jp/api/v1/statuses', { |
|
method: 'POST', |
|
headers: { |
|
'Accept' : 'application/json, text/plain, */*', |
|
'Content-Type': 'application/json;charset=utf-8', |
|
'User-Agent' : 'my-post-api' // 必須 |
|
}, |
|
body: JSON.stringify({ |
|
access_token: 'MASTODON_ACCESS_TOKEN', |
|
status : text, |
|
visibility : 'public' |
|
}) |
|
}); |
|
} |
|
|
|
|
|
// axios を使う例 |
|
// ==================================================================================================== |
|
|
|
const axios = require('axios'); |
|
|
|
/** |
|
* Do Well (オレオレマイクロブログ) に POST する |
|
* |
|
* @param text 投稿文字列 |
|
* @return {Promise} 通信結果 |
|
*/ |
|
function postDoWell(text) { |
|
const params = new URLSearchParams(); |
|
params.append('credential', 'CREDENTIAL'); |
|
params.append('text' , text); |
|
return axios.post('http://example.com/index.php', params); |
|
} |
|
|
|
/** |
|
* Misskey に POST する |
|
* |
|
* @param text 投稿文字列 |
|
* @return {Promise} 通信結果 |
|
*/ |
|
function postMisskey(text) { |
|
return axios.post('https://misskey.io/api/notes/create', { |
|
timeout: 8000, |
|
i : 'MISSKEY_API_KEY', |
|
text : text |
|
}); |
|
} |
|
|
|
/** |
|
* Mastodon に POST する |
|
* |
|
* @param text 投稿文字列 |
|
* @return {Promise} 通信結果 |
|
*/ |
|
function postMastodon(text) { |
|
return axios.post('https://mstdn.jp/api/v1/statuses', { |
|
timeout : 8000, |
|
access_token: 'MASTODON_ACCESS_TOKEN', |
|
status : text, |
|
visibility : 'public' |
|
}); |
|
} |
|
|
|
|
|
// Netlify Functions を想定したエントリポイント |
|
// ==================================================================================================== |
|
|
|
/** |
|
* エントリポイント |
|
* |
|
* @param event イベント |
|
* @param _context 未使用 |
|
* @param callback レスポンスを行うコールバック |
|
* @return statusCode と body を含む連想配列 |
|
*/ |
|
exports.handler = (event, _context, callback) => { |
|
// レスポンスの雛形 (通常時は result・エラー時は error プロパティにメッセージを入れる) |
|
const response = { |
|
statusCode: 400, |
|
headers: { 'Content-Type': 'application/json' } |
|
}; |
|
|
|
// ブックマークレットから本エントリポイントを GET で呼び出した場合 |
|
const credential = event.queryStringParameters.credential; |
|
const text = event.queryStringParameters.text; |
|
|
|
// IFTTT の Webhook から本エントリポイントを POST で呼び出した場合 |
|
const params = JSON.parse(event.body); |
|
const credential = params.credential; // IFTTT Webhook から送られてきたモノと判別するためのパラメータを用意しておく |
|
const text = params.text; |
|
|
|
// Slack Incoming Webhook から本エントリポイントを POST で呼び出した場合 |
|
const params = [...new URLSearchParams(event.body)].reduce((acc, pair) => ({...acc, [pair[0]]: pair[1]}), {}); |
|
const token = params.token; // Slack Incoming Webhook が送ってくるトークン |
|
const text = params.text; |
|
|
|
// 適宜パラメータの正当性チェック、例外ハンドリングなどを行うこと |
|
|
|
return Promise.all([postDoWell(text), postMisskey(text), postMastodon(text)]) |
|
.then((results) => { |
|
response.statusCode = 200; |
|
response.body = JSON.stringify({ result: 'Success' }); |
|
return callback(null, response); |
|
}) |
|
.catch((error) => { |
|
response.body = JSON.stringify({ error: 'Failed' }); |
|
return callback(null, response); |
|
}); |
|
}; |