Scrapboxの更新をタイトルだけ通知するbot
https://gyazo.com/90233d5009df842f31eacf49d4641552
チャンネルごとに通知を振り分ける機能とかはない
(勢いで消してしまったyosider.icon)
需要があったので…yosider.icon
組み込まれたらそっち使うかも?
既知の問題
無かったので加えた
コード
code: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 {
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)};
code:createDefaultSettings.gs(js)
function createDefaultSettings() {
return {
}
}
code:appsscript.json
{
"timeZone": "Asia/Tokyo",
"dependencies": {
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8"
}