Skip to content

Commit 1b32668

Browse files
committed
✨ Enable to replace links in a project
1 parent 03e0e9a commit 1b32668

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

rest/replaceLinks.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import type {
2+
NotFoundError,
3+
NotLoggedInError,
4+
NotMemberError,
5+
} from "../deps/scrapbox.ts";
6+
import {
7+
cookie,
8+
getCSRFToken,
9+
makeCustomError,
10+
tryToErrorLike,
11+
} from "./utils.ts";
12+
import type { Result } from "./utils.ts";
13+
14+
/** `replaceLinks`の認証情報 */
15+
export interface ReplaceLinksInit {
16+
/** connect.sid */ sid: string;
17+
/** CSRF token
18+
*
19+
* If it isn't set, automatically get CSRF token from scrapbox.io server.
20+
*/
21+
csrf?: string;
22+
}
23+
24+
/** 指定したproject内の全てのリンクを書き換える
25+
*
26+
* リンクと同一のタイトルは書き換わらないので注意
27+
* - タイトルも書き換えたいときは/browser/mod.tsの`patch()`などで書き換えること
28+
*
29+
* @param project これで指定したproject内の全てのリンクが置換対象となる
30+
* @param from 置換前のリンク
31+
* @param to 置換後のリンク
32+
* @param options connect.sidなど
33+
* @return 置換されたリンクがあったページの数
34+
*/
35+
export async function replaceLinks(
36+
project: string,
37+
from: string,
38+
to: string,
39+
init?: ReplaceLinksInit,
40+
): Promise<
41+
Result<
42+
number,
43+
NotFoundError | NotLoggedInError | NotMemberError
44+
>
45+
> {
46+
const path = `https://scrapbox.io/api/pages/${project}/replace/links`;
47+
const sid = init?.sid;
48+
const csrf = init?.csrf ?? await getCSRFToken(sid);
49+
50+
const res = await fetch(
51+
path,
52+
{
53+
method: "POST",
54+
headers: {
55+
"Content-Type": "application/json;charset=utf-8",
56+
"X-CSRF-TOKEN": csrf,
57+
...(sid
58+
? {
59+
Cookie: cookie(sid),
60+
}
61+
: {}),
62+
},
63+
body: JSON.stringify({ from, to }),
64+
},
65+
);
66+
67+
if (!res.ok) {
68+
const value = tryToErrorLike(await res.text()) as
69+
| false
70+
| NotFoundError
71+
| NotLoggedInError
72+
| NotMemberError;
73+
if (!value) {
74+
throw makeCustomError(
75+
"UnexpectedError",
76+
`Unexpected error has occuerd when fetching "${path}"`,
77+
);
78+
}
79+
return {
80+
ok: false,
81+
value,
82+
};
83+
}
84+
85+
// messageには"2 pages have been successfully updated!"というような文字列が入っているはず
86+
const { message } = (await res.json()) as { message: string };
87+
return { ok: true, value: parseInt(message.match(/\d+/)?.[0] ?? "0") };
88+
}

0 commit comments

Comments
 (0)