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

Commit

Permalink
Merge pull request #161 from kaimallea/search-gallery
Browse files Browse the repository at this point in the history
feat: add searchGallery()
  • Loading branch information
kaimallea authored Apr 11, 2021
2 parents ba393e4 + 935da3c commit ea895bb
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 1 deletion.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,31 @@ client.getSubredditGallery({
| `sort` | optional | `time` \| `top` - defaults to time |
| `page` | optional | `number` - the data paging number |
| `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` |

### Search the gallery

```ts
client.searchGallery({
query: 'title: memes',
});
```

`searchGallery()` accepts an object of type `SearchGalleryOptions`. The follow options are available:

| Key | Required | Description |
| -------------- | -------- | --------------------------------------------------------------------- | ------ | ------- | ------ | ------------------------- |
| `query` or `q` | required | Query string |
| `sort` | optional | `time` \| `viral` \| `top` - defaults to time |
| `page` | optional | `number` - the data paging number |
| `window` | optional | Change the date range of the request if the sort is `top` -- to `day` | `week` | `month` | `year` | `all`, defaults to `all`. |

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):

| Key | Required | Description |
| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `q_all` | optional | Search for all of these words (and) |
| `q_any` | optional | Search for any of these words (or) |
| `q_exactly` | optional | Search for exactly this word or phrase |
| `q_not` | optional | Exclude results matching this string |
| `q_type` | optional | Show results for any file type, `jpg` \| `png` \| `gif` \| `anigif` (animated gif) \| `album` |
| `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) |
2 changes: 2 additions & 0 deletions src/common/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export const UPLOAD_ENDPOINT = `${API_VERSION}/upload`;
export const GALLERY_ENDPOINT = `${API_VERSION}/gallery`;

export const SUBREDDIT_GALLERY_ENDPOINT = `${API_VERSION}/gallery/r`;

export const SEARCH_GALLERY_ENDPOINT = `${API_VERSION}/gallery/search`;
2 changes: 1 addition & 1 deletion src/gallery/getSubredditGallery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ test('constructGalleryUrl', () => {
);
});

test('returns an image response', async () => {
test('returns a gallery response', async () => {
const accessToken = 'abc123';
const client = new ImgurClient({ accessToken });
const response = await getSubredditGallery(client, {
Expand Down
67 changes: 67 additions & 0 deletions src/gallery/searchGallery.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { ImgurClient } from '../client';
import { searchGallery, constructSearchGalleryUrl } from './searchGallery';

test('constructGalleryUrl', () => {
expect(
constructSearchGalleryUrl({
q: 'cats',
}).href
).toMatchInlineSnapshot(`"https://api.imgur.com/3/gallery/search?q=cats"`);

expect(
constructSearchGalleryUrl({ query: 'dogs', sort: 'time' }).href
).toMatchInlineSnapshot(
`"https://api.imgur.com/3/gallery/search/time?q=dogs"`
);

expect(
constructSearchGalleryUrl({
q: 'cats subreddit:awwa ext:gif',
sort: 'top',
window: 'month',
}).href
).toMatchInlineSnapshot(
`"https://api.imgur.com/3/gallery/search/top/month?q=cats+subreddit%3Aawwa+ext%3Agif"`
);

const { href } = constructSearchGalleryUrl({
query: 'wallstreetbets',
q_all: 'nintendo switch',
q_not: 'mario',
q_type: 'anigif',
q_size_px: 'lrg',
});
expect(href).toMatchInlineSnapshot(
`"https://api.imgur.com/3/gallery/search?q_all=nintendo+switch&q_not=mario&q_type=anigif&q_size_px=lrg"`
);
});

test('returns an gallery response', async () => {
const accessToken = 'abc123';
const client = new ImgurClient({ accessToken });
const response = await searchGallery(client, {
query: 'wallstreetbets',
});
expect(response).toMatchInlineSnapshot(`
Object {
"data": Array [
Object {
"description": "gallery-description",
"id": "ans7sd",
"images": Array [
Object {
"description": null,
"id": "4yMKKLTz",
"link": "https://i.imgur.com/4yMKKLTz.jpg",
"title": null,
},
],
"link": "https://imgur.com/a/abc123",
"title": "gallery-title",
},
],
"status": 200,
"success": true,
}
`);
});
85 changes: 85 additions & 0 deletions src/gallery/searchGallery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { ImgurClient } from '../client';
import { SEARCH_GALLERY_ENDPOINT, IMGUR_API_PREFIX } from '../common/endpoints';
import { ImgurApiResponse, GalleryData } from '../common/types';
import { URL } from 'url';

export type SearchOptions = {
q?: string;
query?: string;
sort?: 'time' | 'viral';
page?: number;
};

export type TopSearchOptions = Omit<SearchOptions, 'sort'> & {
sort?: 'top';
window?: 'day' | 'week' | 'month' | 'year' | 'all';
};

export type AdvancedSearchQueryParameters = {
q_all?: string;
q_any?: string;
q_exactly?: string;
q_not?: string;
q_type?: 'jpg' | 'png' | 'gif' | 'anigif' | 'album';
q_size_px?: 'small' | 'med' | 'big' | 'lrg' | 'huge';
};

const advancedParameters: Array<keyof AdvancedSearchQueryParameters> = [
'q_all',
'q_any',
'q_exactly',
'q_not',
'q_type',
'q_size_px',
];

export type SearchGalleryOptions = (SearchOptions | TopSearchOptions) &
AdvancedSearchQueryParameters;

export function constructSearchGalleryUrl(options: SearchGalleryOptions): URL {
let uri = '';

if (options.sort) {
uri += `/${options.sort}`;
}

if (options.sort === 'top' && options.window) {
uri += `/${options.window}`;
}

if (options.page) {
uri += `/${options.page}`;
}

const url = new URL(`${IMGUR_API_PREFIX}/${SEARCH_GALLERY_ENDPOINT}${uri}`);

advancedParameters.forEach((param) => {
if (options[param]?.length) {
url.searchParams.append(param, options[param] as string);
}
});

if (!url.search) {
const query = options.q || options.query;
if (!query) {
throw new Error('No query was provided');
}

url.searchParams.append('q', query);
}

return url;
}

export async function searchGallery(
client: ImgurClient,
options: SearchGalleryOptions
): Promise<ImgurApiResponse<GalleryData>> {
const { pathname } = constructSearchGalleryUrl(options);
// since we're using prefixUrl with got, we have to remove the starting slash or it'll throw
const finalPathname = pathname.slice(1);

return (await client
.request(finalPathname)
.json()) as ImgurApiResponse<GalleryData>;
}

0 comments on commit ea895bb

Please sign in to comment.