Scrapboxの更新をタイトルだけ通知するbot
チャンネルごとに通知を振り分ける機能とかはない
(勢いで消してしまった

)
需要があったので…

組み込まれたらそっち使うかも?
既知の問題
無かったので加えた
コード
main.gs(js)function main() {
const scriptProperties = PropertiesService.getScriptProperties();
// 最終更新日時(なければ昨日)
const lastUpdated = (() => {
const value = scriptProperties.getProperty('LAST_UPDATED');
return !isNaN(value) && yesterday() < value ? value : yesterday();
})();
const settings = getSettings();
const projects = Object.keys(settings);
console.log(
`Start searching ${projects.length} scrapbox projects for pages which are updated from ${toYYYYMMDD_HHMMSS(lastUpdated)}:
${projects}`
);
scriptProperties.setProperty(
'LAST_UPDATED',
now(),
);
// 各projectで(更新順に?)最大1000件まで取得する
const responses = UrlFetchApp.fetchAll(projects.map(
(project) => { return { url: `https://scrapbox.io/api/pages/${project}?limit=1000`, }; }
));
const jsons = responses.map(response => JSON.parse(response.getContentText()));
console.log(`Finish fetching.`);
let updatedTitleList = jsons.map(({ projectName, pages }) => {
pages = pages.filter(({ updated }) => updated > lastUpdated);
return {
project: projectName,
titles: pages.map(({ title }) => title),
}
});
updatedTitleList.map(({ project, titles }) => {
console.log(`Updated pages for ${project}: \n${titles}`);
});
// データを整形する
const params = updatedTitleList.map(({ project, titles }) => {
const linkList = titles.map((title) => `*<https://scrapbox.io/${project}/${title}|${title}>*`);
const msg = `${titles.length} pages updated at /${project}`;
return {
url: settings[project],
payload: {
text: msg,
blocks: [{
type: 'section',
text: {
type: 'mrkdwn',
text: `${linkList.join('\n')}\n${msg}`
}
}]
}
}
});
// slackにpostする
postToSlack(params);
}
function postToSlack(params) {
const responses = UrlFetchApp.fetchAll(params.map(({ url, payload }) => ({
url,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
payload: JSON.stringify(payload),
muteHttpExceptions: true,
})));
responses.map((r) => console.log(r.getContentText()));
};
function getSettings() {
return createDefaultSettings();
}
const now = () => {
const now = new Date();
return Math.floor(now.getTime() / 1000);
}
const yesterday = () => {
let now = new Date();
now.setDate(now.getDate() - 1);
return Math.floor(now.getTime() / 1000);
}
const zero = n => String(n).padStart(2, '0');
const toYYYYMMDD = seconds => {
const d = new Date(seconds * 1000);
return `${d.getFullYear()}-${zero(d.getMonth() + 1)}-${zero(d.getDate())}`;
};
const toHHMMSS = seconds => {
const d = new Date(seconds * 1000);
return `${zero(d.getHours())}:${zero(d.getMinutes())}:${zero(d.getSeconds())}`;
};
const toYYYYMMDD_HHMMSS = seconds => `${toYYYYMMDD(seconds)} ${toHHMMSS(seconds)}`;
createDefaultSettings.gs(js)function createDefaultSettings() {
return {
'villagepump': 'https://hooks.slack.com/services/zzzzzz',
'programming-notes': 'https://hooks.slack.com/services/zzzzzz',
}
}
appsscript.json{
"timeZone": "Asia/Tokyo",
"dependencies": {
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8"
}