pin-diary-6
変更点
機能面は特になし
若干performanceが上がったかも
カスタマイズ性を上げた
日記の形式に関する処理をすべて外部に切り出した
井戸端での設定はこんな感じ
$ deno check --remote -r=https://scrapbox.io https://scrapbox.io/api/code/villagepump/pin-diary-6/script.ts
script.tsimport { launch } from "./mod.ts";
import {
makeDiary, isOldDiary,
} from "../pin-diary-6%2Ftemplate/mod.ts";
launch(
"villagepump",
{
makeDiary,
isOldDiary,
},
);
makeDiary
と isOldDiary
を交換すれば、どんな形式のページにも対応できる
井戸端で使用しているscriptの導入方法
2. 生成されたscriptを
自分のページのscript.jsから読み込めるようにする
ここは他のUserScriptの導入と同じ
2024-05-29
17:44:13 update dependencies
2024-05-02
13:36:38 update dependencies
icon,helpfeel,infoboxの情報が正確に反映されるようにした
2023-09-14
07:06:32 convert function
to arrow functions
2023-09-04
10:52:35 update dependencies
↑の条件を満たしたときにpin-diaryがエラーを吐く現象を修正しました
2023-08-17
13:08:09 update dependencies
2023-01-03
14:36:29 update dependencies
2022-11-29
12:35:05 scrapbox-userscript-stdのversionを更新
2022-09-01
13:42:55
scrapbox-userscript-stdのversionを更新
2022-07-26
08:22:46
scrapbox-userscript-stdのversionを更新
これにより、youtubeのサムネイルが反映されるようになった
型エラーがあったので修正
2022-05-23 17:47:48 破壊的変更:s/ filter
/ isOldDiary
普通に各自のuserscriptからpin-diary-6を外すだけで十分そう
script2.tsimport { launch } from "./mod.ts";
import {
makeDiary, isOldDiary,
} from "../pin-diary-6%2Ftemplate/mod.ts";
import isWithinInterval from "https://deno.land/x/date_fns@v2.22.1/isWithinInterval/index.ts";
if (isWithinInterval(new Date(), {
start: new Date(2022, 3, 29), end: new Date(2022, 5, 5)
})) {
launch(
"villagepump",
{
makeDiary,
isOldDiary,
},
);
}
$ deno check --remote -r=https://scrapbox.io https://scrapbox.io/api/code/villagepump/pin-diary-6/mod.ts
mod.ts/// <reference no-default-lib="true"/>
/// <reference lib="esnext"/>
/// <reference lib="dom"/>
import {
pin,
unpin,
patch,
useStatusBar,
sleep,
makeSocket,
disconnect,
format,
} from "./deps.ts";
import { listPinnedPages } from "./list.ts";
import type { Scrapbox, Socket } from "./deps.ts";
declare const scrapbox: Scrapbox;
export interface DiaryInit {
/** 与えられた日付の日記ページのテンプレートを作る */
makeDiary: (date: Date) => {
title: string;
header: string[];
footer: string[];
},
mod.ts /** 今日以外の日記ページかどうかを判断する函数
*
* @param title 判断対象のページタイトル
* @param today 今日の日付
* @param 今日以外の日記ページなら`true`, それ以外のページは `false`
*/
isOldDiary: (title: string, today: Date) => boolean;
}
// initialize
export const launch = (
project: string,
init: DiaryInit & { interval?: number },
) => {
const interval = init.interval ?? 24 * 3600 * 1000;
const handleChange = () =>
scrapbox.Project.name === project ?
startObserve(project, interval, init) :
endObserve();
handleChange();
scrapbox.addListener("project:changed", handleChange);
};
let updateTimer: number | undefined;
const startObserve = async (
project: string,
interval: number,
init: DiaryInit,
) => {
endObserve();
await pinDiary(project, new Date(), init);
updateTimer = setInterval(
() => pinDiary(project, new Date(), init),
interval,
);
};
const endObserve = () => clearInterval(updateTimer);
mod.tsexport const pinDiary = async (
project: string,
date: Date,
{ makeDiary, isOldDiary, }: DiaryInit,
): Promise<void> => {
const { render, dispose } = useStatusBar();
let socket: Socket | undefined;
try {
// 今日以外の日付ページを外す
render(
{ type: "spinner" },
{ type: "text", text: `unpin other diary pages...`},
);
socket = await makeSocket();
for await (const { title } of listPinnedPages(project)) {
if (!isOldDiary(title, date)) continue;
await unpin(project, title, { socket });
}
// 今日の日付ページをピン留めする
const { title, header, footer } = makeDiary(date);
render(
{ type: "spinner" },
{ type: "text", text: `pin "/${project}/${title}"...`},
);
await pin(project, title, { socket, create: true });
// 今日の日付ページにtemplateを挿入する
render(
{ type: "spinner" },
{ type: "text", text: `format "/${project}/${title}"...`},
);
await patch(project, title, (lines) => [
lines[0].text,
...format(
lines.slice(1).map(line => line.text),
header,
footer,
),
], { socket });
render(
{ type: "check-circle" },
{ type: "text", text: `Pinned "/${project}/${title}".`},
);
} catch(e: unknown) {
render(
{ type: "exclamation-triangle" },
{ type: "text", text: e instanceof Error ?
`${e.name} ${e.message}` :
`Unknown error! (see developper console)`,
},
);
console.error(e);
} finally {
if (socket) await disconnect(socket);
await sleep(1000);
dispose();
}
};
list.tsimport { listPages, BasePage } from "./deps.ts";
/** 全てのピン留めされたページを取得する */
export async function* listPinnedPages(project: string, skip = 0): AsyncGenerator<BasePage> {
const { count, pages } = await ensureList(project, skip);
for (const page of pages) {
if (page.pin === 0) continue;
yield page;
}
// pinしたページこれ以上ないときは終了
if ((pages.at(-1)?.pin ?? 0) === 0) return;
yield* listPinnedPages(project, skip + 1000);
}
const ensureList = async (project: string, skip: number) => {
const result = await listPages(project, {
limit: 1000,
skip,
});
// login errorなどは全部例外として扱う
if (!result.ok) {
const error = new Error();
error.name = result.value.name;
error.message = result.value.message;
throw error;
}
return result.value;
};
deps.tsexport { patchTemplate as format } from "../pin-diary-5/format.ts";
export {
pin,
unpin,
patch,
useStatusBar,
makeSocket,
disconnect,
listPages,
} from "https://raw.githubusercontent.com/takker99/scrapbox-userscript-std/0.26.1/mod.ts";
export type {
Socket,
} from "https://raw.githubusercontent.com/takker99/scrapbox-userscript-std/0.26.1/mod.ts";
export {
sleep,
} from "https://raw.githubusercontent.com/takker99/scrapbox-userscript-std/0.26.1/sleep.ts";
export type {
Scrapbox,
} from "https://raw.githubusercontent.com/scrapbox-jp/types/0.7.0/userscript.ts";
export type {
BasePage,
} from "https://raw.githubusercontent.com/scrapbox-jp/types/0.7.0/rest.ts";
Project開くと必ず動くの、気になるのでそのうちなんとかしたい
どういうふうにすればいいかな
ステータスを表示しない
多分そういうことじゃない
projectを開く && ある時間帯のみ更新する
必ずPin&Unpinしてるのが気になるなと
実装未だに読んでなくて申し訳ないけどチェックする方が面倒なら大丈夫です
pin()
と
unpin()
は、それぞれすでにpinされている、pinが外れているなら
何もしませんただし、pageIdやprojectId, userIdを毎回fetchするので、そのoverheadがあるのは否めません
ここはどう実装すべきか悩むところ
外部から pageId
などを指定できるようにすればいい?
あ、そうなのか、ならよかった