Skip to content

Commit 815369b

Browse files
authored
Merge pull request #35 from takker99/add-search
✨ Implement wrappers of cross searches
2 parents c16e103 + f0fbb59 commit 815369b

File tree

3 files changed

+185
-2
lines changed

3 files changed

+185
-2
lines changed

deps/scrapbox.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,21 @@ export type {
77
InvalidURLError,
88
MemberProject,
99
MemberUser,
10+
NoQueryError,
1011
NotFoundError,
1112
NotLoggedInError,
1213
NotMemberError,
1314
NotMemberProject,
1415
NotPrivilegeError,
1516
Page,
1617
PageList,
18+
ProjectSearchResult,
1719
Scrapbox,
1820
SearchedTitle,
21+
SearchResult,
1922
SessionError,
2023
TweetInfo,
21-
} from "https://raw.githubusercontent.com/scrapbox-jp/types/0.1.2/mod.ts";
22-
import type { Page } from "https://raw.githubusercontent.com/scrapbox-jp/types/0.1.2/mod.ts";
24+
} from "https://raw.githubusercontent.com/scrapbox-jp/types/0.1.4/mod.ts";
25+
import type { Page } from "https://raw.githubusercontent.com/scrapbox-jp/types/0.1.4/mod.ts";
2326
export * from "https://esm.sh/@progfay/[email protected]";
2427
export type Line = Page["lines"][0];

rest/mod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from "./profile.ts";
44
export * from "./replaceLinks.ts";
55
export * from "./page-data.ts";
66
export * from "./link.ts";
7+
export * from "./search.ts";
78
export * from "./getWebPageTitle.ts";
89
export * from "./getTweetInfo.ts";
910
export * from "./auth.ts";

rest/search.ts

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import type {
2+
NoQueryError,
3+
NotFoundError,
4+
NotLoggedInError,
5+
NotMemberError,
6+
ProjectSearchResult,
7+
SearchResult,
8+
} from "../deps/scrapbox.ts";
9+
import { cookie } from "./auth.ts";
10+
import { UnexpectedResponseError } from "./error.ts";
11+
import { tryToErrorLike } from "../is.ts";
12+
import { BaseOptions, Result, setDefaults } from "./util.ts";
13+
14+
/** search a project for pages
15+
*
16+
* @param query 検索語句
17+
* @param project 検索範囲とするprojectの名前
18+
* @param init connect.sid etc.
19+
*/
20+
export const searchForPages = async (
21+
query: string,
22+
project: string,
23+
init?: BaseOptions,
24+
): Promise<
25+
Result<
26+
SearchResult,
27+
NotFoundError | NotMemberError | NotLoggedInError | NoQueryError
28+
>
29+
> => {
30+
const { sid, hostName, fetch } = setDefaults(init ?? {});
31+
32+
const path = `https://${hostName}/api/pages/${project}/search/query?q=${
33+
encodeURIComponent(query)
34+
}`;
35+
const res = await fetch(
36+
path,
37+
sid ? { headers: { Cookie: cookie(sid) } } : undefined,
38+
);
39+
40+
if (!res.ok) {
41+
if (res.status === 422) {
42+
return {
43+
ok: false,
44+
value: {
45+
name: "NoQueryError",
46+
message: (await res.json()).message,
47+
},
48+
};
49+
}
50+
const text = await res.json();
51+
const value = tryToErrorLike(text);
52+
if (!value) {
53+
throw new UnexpectedResponseError({
54+
path: new URL(path),
55+
...res,
56+
body: await res.text(),
57+
});
58+
}
59+
return {
60+
ok: false,
61+
value: value as NotFoundError | NotMemberError | NotLoggedInError,
62+
};
63+
}
64+
65+
const value = (await res.json()) as SearchResult;
66+
return { ok: true, value };
67+
};
68+
69+
/** search for joined projects
70+
*
71+
* @param query 検索語句
72+
* @param init connect.sid etc.
73+
*/
74+
export const searchForJoinedProjects = async (
75+
query: string,
76+
init?: BaseOptions,
77+
): Promise<
78+
Result<
79+
ProjectSearchResult,
80+
NotLoggedInError | NoQueryError
81+
>
82+
> => {
83+
const { sid, hostName, fetch } = setDefaults(init ?? {});
84+
85+
const path = `https://${hostName}/api/projects/search/query?q=${
86+
encodeURIComponent(query)
87+
}`;
88+
const res = await fetch(
89+
path,
90+
sid ? { headers: { Cookie: cookie(sid) } } : undefined,
91+
);
92+
93+
if (!res.ok) {
94+
if (res.status === 422) {
95+
return {
96+
ok: false,
97+
value: {
98+
name: "NoQueryError",
99+
message: (await res.json()).message,
100+
},
101+
};
102+
}
103+
const text = await res.json();
104+
const value = tryToErrorLike(text);
105+
if (!value) {
106+
throw new UnexpectedResponseError({
107+
path: new URL(path),
108+
...res,
109+
body: await res.text(),
110+
});
111+
}
112+
return { ok: false, value: value as NotLoggedInError };
113+
}
114+
115+
const value = (await res.json()) as ProjectSearchResult;
116+
return { ok: true, value };
117+
};
118+
119+
/** search for watch list
120+
*
121+
* watch listと銘打っているが、実際には参加していないpublic projectならどれでも検索できる
122+
*
123+
* 参加しているprojectのidは指定しても無視されるだけ
124+
*
125+
* @param query 検索語句
126+
* @param projectIds 検索候補のprojectのidのリスト
127+
* @param init connect.sid etc.
128+
*/
129+
export const searchForWatchList = async (
130+
query: string,
131+
projectIds: string[],
132+
init?: BaseOptions,
133+
): Promise<
134+
Result<
135+
ProjectSearchResult,
136+
NotLoggedInError | NoQueryError
137+
>
138+
> => {
139+
const { sid, hostName, fetch } = setDefaults(init ?? {});
140+
141+
const params = new URLSearchParams();
142+
params.append("q", encodeURIComponent(query));
143+
for (const projectId of projectIds) {
144+
params.append("ids", projectId);
145+
}
146+
147+
const path =
148+
`https://${hostName}/api/projects/search/watch-list?${params.toString()}`;
149+
const res = await fetch(
150+
path,
151+
sid ? { headers: { Cookie: cookie(sid) } } : undefined,
152+
);
153+
154+
if (!res.ok) {
155+
if (res.status === 422) {
156+
return {
157+
ok: false,
158+
value: {
159+
// 本当はproject idが不正なときも422 errorになる
160+
name: "NoQueryError",
161+
message: (await res.json()).message,
162+
},
163+
};
164+
}
165+
const text = await res.json();
166+
const value = tryToErrorLike(text);
167+
if (!value) {
168+
throw new UnexpectedResponseError({
169+
path: new URL(path),
170+
...res,
171+
body: await res.text(),
172+
});
173+
}
174+
return { ok: false, value: value as NotLoggedInError };
175+
}
176+
177+
const value = (await res.json()) as ProjectSearchResult;
178+
return { ok: true, value };
179+
};

0 commit comments

Comments
 (0)