generated at
Scrapboxの更新をタイトルだけ通知するbot
1日ごとにScrapboxの更新を通知するbotの、更新されたページのタイトル・URLだけを通知するバージョン
チャンネルごとに通知を振り分ける機能とかはない
(勢いで消してしまったyosider
1日ごとにScrapboxの更新を通知するbotに組み込もうと思ってたけどまあいいやtakker
需要があったので…yosider
組み込まれたらそっち使うかも?

既知の問題
無かったので加えた

コード
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)}`;

Incoming Webhooksを設定し、そのwebhook URLを↓に書く
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" }