Skip to content
This repository was archived by the owner on Dec 30, 2021. It is now read-only.

Commit ea895bb

Browse files
authored
Merge pull request #161 from kaimallea/search-gallery
feat: add searchGallery()
2 parents ba393e4 + 935da3c commit ea895bb

File tree

5 files changed

+183
-1
lines changed

5 files changed

+183
-1
lines changed

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,31 @@ client.getSubredditGallery({
226226
| `sort` | optional | `time` \| `top` - defaults to time |
227227
| `page` | optional | `number` - the data paging number |
228228
| `window` | optional | Change the date range of the request if the section is `top`. Accepted values are `day` \| `week` \| `month` \| `year` \| `all`. Defaults to `week` |
229+
230+
### Search the gallery
231+
232+
```ts
233+
client.searchGallery({
234+
query: 'title: memes',
235+
});
236+
```
237+
238+
`searchGallery()` accepts an object of type `SearchGalleryOptions`. The follow options are available:
239+
240+
| Key | Required | Description |
241+
| -------------- | -------- | --------------------------------------------------------------------- | ------ | ------- | ------ | ------------------------- |
242+
| `query` or `q` | required | Query string |
243+
| `sort` | optional | `time` \| `viral` \| `top` - defaults to time |
244+
| `page` | optional | `number` - the data paging number |
245+
| `window` | optional | Change the date range of the request if the sort is `top` -- to `day` | `week` | `month` | `year` | `all`, defaults to `all`. |
246+
247+
Additionally, the following advanced search query options can be set (NOTE: if any of the below are set in the options, the `query` option is ignored and these will take precedent):
248+
249+
| Key | Required | Description |
250+
| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
251+
| `q_all` | optional | Search for all of these words (and) |
252+
| `q_any` | optional | Search for any of these words (or) |
253+
| `q_exactly` | optional | Search for exactly this word or phrase |
254+
| `q_not` | optional | Exclude results matching this string |
255+
| `q_type` | optional | Show results for any file type, `jpg` \| `png` \| `gif` \| `anigif` (animated gif) \| `album` |
256+
| `q_size_px` | optional | Size ranges, `small` (500 pixels square or less) \| `med` (500 to 2,000 pixels square) \| `big` (2,000 to 5,000 pixels square) \| `lrg` (5,000 to 10,000 pixels square) \| `huge` (10,000 square pixels and above) |

src/common/endpoints.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ export const UPLOAD_ENDPOINT = `${API_VERSION}/upload`;
1111
export const GALLERY_ENDPOINT = `${API_VERSION}/gallery`;
1212

1313
export const SUBREDDIT_GALLERY_ENDPOINT = `${API_VERSION}/gallery/r`;
14+
15+
export const SEARCH_GALLERY_ENDPOINT = `${API_VERSION}/gallery/search`;

src/gallery/getSubredditGallery.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ test('constructGalleryUrl', () => {
3838
);
3939
});
4040

41-
test('returns an image response', async () => {
41+
test('returns a gallery response', async () => {
4242
const accessToken = 'abc123';
4343
const client = new ImgurClient({ accessToken });
4444
const response = await getSubredditGallery(client, {

src/gallery/searchGallery.test.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { ImgurClient } from '../client';
2+
import { searchGallery, constructSearchGalleryUrl } from './searchGallery';
3+
4+
test('constructGalleryUrl', () => {
5+
expect(
6+
constructSearchGalleryUrl({
7+
q: 'cats',
8+
}).href
9+
).toMatchInlineSnapshot(`"https://api.imgur.com/3/gallery/search?q=cats"`);
10+
11+
expect(
12+
constructSearchGalleryUrl({ query: 'dogs', sort: 'time' }).href
13+
).toMatchInlineSnapshot(
14+
`"https://api.imgur.com/3/gallery/search/time?q=dogs"`
15+
);
16+
17+
expect(
18+
constructSearchGalleryUrl({
19+
q: 'cats subreddit:awwa ext:gif',
20+
sort: 'top',
21+
window: 'month',
22+
}).href
23+
).toMatchInlineSnapshot(
24+
`"https://api.imgur.com/3/gallery/search/top/month?q=cats+subreddit%3Aawwa+ext%3Agif"`
25+
);
26+
27+
const { href } = constructSearchGalleryUrl({
28+
query: 'wallstreetbets',
29+
q_all: 'nintendo switch',
30+
q_not: 'mario',
31+
q_type: 'anigif',
32+
q_size_px: 'lrg',
33+
});
34+
expect(href).toMatchInlineSnapshot(
35+
`"https://api.imgur.com/3/gallery/search?q_all=nintendo+switch&q_not=mario&q_type=anigif&q_size_px=lrg"`
36+
);
37+
});
38+
39+
test('returns an gallery response', async () => {
40+
const accessToken = 'abc123';
41+
const client = new ImgurClient({ accessToken });
42+
const response = await searchGallery(client, {
43+
query: 'wallstreetbets',
44+
});
45+
expect(response).toMatchInlineSnapshot(`
46+
Object {
47+
"data": Array [
48+
Object {
49+
"description": "gallery-description",
50+
"id": "ans7sd",
51+
"images": Array [
52+
Object {
53+
"description": null,
54+
"id": "4yMKKLTz",
55+
"link": "https://i.imgur.com/4yMKKLTz.jpg",
56+
"title": null,
57+
},
58+
],
59+
"link": "https://imgur.com/a/abc123",
60+
"title": "gallery-title",
61+
},
62+
],
63+
"status": 200,
64+
"success": true,
65+
}
66+
`);
67+
});

src/gallery/searchGallery.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { ImgurClient } from '../client';
2+
import { SEARCH_GALLERY_ENDPOINT, IMGUR_API_PREFIX } from '../common/endpoints';
3+
import { ImgurApiResponse, GalleryData } from '../common/types';
4+
import { URL } from 'url';
5+
6+
export type SearchOptions = {
7+
q?: string;
8+
query?: string;
9+
sort?: 'time' | 'viral';
10+
page?: number;
11+
};
12+
13+
export type TopSearchOptions = Omit<SearchOptions, 'sort'> & {
14+
sort?: 'top';
15+
window?: 'day' | 'week' | 'month' | 'year' | 'all';
16+
};
17+
18+
export type AdvancedSearchQueryParameters = {
19+
q_all?: string;
20+
q_any?: string;
21+
q_exactly?: string;
22+
q_not?: string;
23+
q_type?: 'jpg' | 'png' | 'gif' | 'anigif' | 'album';
24+
q_size_px?: 'small' | 'med' | 'big' | 'lrg' | 'huge';
25+
};
26+
27+
const advancedParameters: Array<keyof AdvancedSearchQueryParameters> = [
28+
'q_all',
29+
'q_any',
30+
'q_exactly',
31+
'q_not',
32+
'q_type',
33+
'q_size_px',
34+
];
35+
36+
export type SearchGalleryOptions = (SearchOptions | TopSearchOptions) &
37+
AdvancedSearchQueryParameters;
38+
39+
export function constructSearchGalleryUrl(options: SearchGalleryOptions): URL {
40+
let uri = '';
41+
42+
if (options.sort) {
43+
uri += `/${options.sort}`;
44+
}
45+
46+
if (options.sort === 'top' && options.window) {
47+
uri += `/${options.window}`;
48+
}
49+
50+
if (options.page) {
51+
uri += `/${options.page}`;
52+
}
53+
54+
const url = new URL(`${IMGUR_API_PREFIX}/${SEARCH_GALLERY_ENDPOINT}${uri}`);
55+
56+
advancedParameters.forEach((param) => {
57+
if (options[param]?.length) {
58+
url.searchParams.append(param, options[param] as string);
59+
}
60+
});
61+
62+
if (!url.search) {
63+
const query = options.q || options.query;
64+
if (!query) {
65+
throw new Error('No query was provided');
66+
}
67+
68+
url.searchParams.append('q', query);
69+
}
70+
71+
return url;
72+
}
73+
74+
export async function searchGallery(
75+
client: ImgurClient,
76+
options: SearchGalleryOptions
77+
): Promise<ImgurApiResponse<GalleryData>> {
78+
const { pathname } = constructSearchGalleryUrl(options);
79+
// since we're using prefixUrl with got, we have to remove the starting slash or it'll throw
80+
const finalPathname = pathname.slice(1);
81+
82+
return (await client
83+
.request(finalPathname)
84+
.json()) as ImgurApiResponse<GalleryData>;
85+
}

0 commit comments

Comments
 (0)