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

Commit 33e522b

Browse files
authored
Merge pull request #150 from kaimallea/next-dev
Ship latest changes to next channel
2 parents dc24c4f + aa863ad commit 33e522b

19 files changed

+360
-107
lines changed

README.md

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ If you don't have any credentials, you'll need to:
5656
1. [Create an Imgur account](https://imgur.com/register)
5757
1. [Register an application](https://api.imgur.com/#registerapp)
5858

59+
### **⚠️ For brevity, the rest of the examples will leave out the import and/or instantiation step.**
60+
5961
### Upload one or more images and videos
6062

6163
You can upload one or more files by simply passing a path to a file or array of paths to multiple files.
@@ -118,8 +120,6 @@ Acceptable key/values match what [the Imgur API expects](https://apidocs.imgur.c
118120
Instances of `ImgurClient` emit `uploadProgress` events so that you can track progress with event listeners.
119121

120122
```ts
121-
import { ImgurClient } from 'imgur';
122-
123123
const client = new ImgurClient({ accessToken: process.env.ACCESS_TOKEN });
124124

125125
client.on('uploadProgress', (progress) => console.log(progress));
@@ -143,3 +143,46 @@ The progress object looks like the following:
143143
| `transferred` | total number of bytes transferred thus far |
144144
| `total` | total number of bytes to be transferred |
145145
| `id` | unique id for the media being transferred; useful when uploading multiple things concurrently |
146+
147+
### Delete an image
148+
149+
Requires an image hash or delete hash, which are obtained in an image upload response
150+
151+
```ts
152+
client.delete('someImageHash');
153+
```
154+
155+
### Update image information
156+
157+
Update the title and/or description of an image
158+
159+
```ts
160+
client.updateImage({
161+
imageHash: 'someImageHash',
162+
title: 'A new title',
163+
description: 'A new description',
164+
});
165+
```
166+
167+
Update multiple images at once:
168+
169+
```ts
170+
client.updateImage([
171+
{
172+
imageHash: 'someImageHash',
173+
title: 'A new title',
174+
description: 'A new description',
175+
},
176+
{
177+
imageHash: 'anotherImageHash',
178+
title: 'A better title',
179+
description: 'A better description',
180+
},
181+
]);
182+
```
183+
184+
Favorite an image:
185+
186+
```ts
187+
client.favoriteImage('someImageHash');
188+
```

src/client.ts

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { EventEmitter } from 'events';
22
import got, { ExtendOptions, Got } from 'got';
3-
import { getAuthorizationHeader, Credentials } from './helpers';
4-
import { getImage, upload, Payload } from './image';
5-
import { IMGUR_API_PREFIX } from './helpers';
6-
7-
type ImgurApiResponse = {
8-
data: Record<string, unknown>;
9-
status: number;
10-
success: boolean;
11-
};
3+
import { getAuthorizationHeader } from './getAuthorizationHeader';
4+
import {
5+
deleteImage,
6+
favoriteImage,
7+
getImage,
8+
upload,
9+
updateImage,
10+
UpdateImagePayload,
11+
} from './image';
12+
import { IMGUR_API_PREFIX } from './common/endpoints';
13+
import { Credentials, Payload } from './common/types';
1214

1315
const USERAGENT = 'imgur/next (https://github.com/kaimallea/node-imgur)';
1416

@@ -44,11 +46,23 @@ export class ImgurClient extends EventEmitter {
4446
return this.gotExtended.extend(options)(url);
4547
}
4648

47-
async getImage(imageHash: string) {
49+
deleteImage(imageHash: string) {
50+
return deleteImage(this, imageHash);
51+
}
52+
53+
favoriteImage(imageHash: string) {
54+
return favoriteImage(this, imageHash);
55+
}
56+
57+
getImage(imageHash: string) {
4858
return getImage(this, imageHash);
4959
}
5060

51-
async upload(payload: string | string[] | Payload | Payload[]) {
61+
updateImage(payload: UpdateImagePayload | UpdateImagePayload[]) {
62+
return updateImage(this, payload);
63+
}
64+
65+
upload(payload: string | string[] | Payload | Payload[]) {
5266
return upload(this, payload);
5367
}
5468
}
File renamed without changes.

src/common/types.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
export interface AccessToken {
2+
accessToken: string;
3+
}
4+
5+
export interface ClientId {
6+
clientId: string;
7+
}
8+
9+
export interface Login extends ClientId {
10+
username: string;
11+
password: string;
12+
}
13+
14+
export type Credentials = AccessToken | ClientId | Login;
15+
16+
export function isAccessToken(arg: any): arg is AccessToken {
17+
return arg.accessToken !== undefined;
18+
}
19+
20+
export function isClientId(arg: any): arg is ClientId {
21+
return arg.clientId !== undefined;
22+
}
23+
24+
export function isLogin(arg: any): arg is Login {
25+
return (
26+
arg.clientId !== undefined &&
27+
arg.username !== undefined &&
28+
arg.password !== undefined
29+
);
30+
}
31+
32+
export interface ImgurApiResponse {
33+
data: Record<string, unknown> | string | boolean;
34+
status: number;
35+
success: boolean;
36+
}
37+
38+
export interface Payload {
39+
image?: string;
40+
video?: string;
41+
type?: 'file' | 'url' | 'base64';
42+
name?: string;
43+
title?: string;
44+
description?: string;
45+
album?: string;
46+
disable_audio?: '1' | '0';
47+
}

src/common/utils.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { createReadStream } from 'fs';
2+
import FormData from 'form-data';
3+
import { Payload } from './types';
4+
5+
export function isVideo(payload: string | Payload) {
6+
if (typeof payload === 'string') {
7+
return false;
8+
}
9+
10+
return typeof payload.video !== 'undefined' && payload.video;
11+
}
12+
13+
export function getSource(payload: string | Payload) {
14+
if (typeof payload === 'string') {
15+
return payload;
16+
}
17+
18+
if (isVideo(payload)) {
19+
return payload.video;
20+
} else {
21+
return payload.image;
22+
}
23+
}
24+
25+
export function createForm(payload: string | Payload) {
26+
const form = new FormData();
27+
28+
if (typeof payload === 'string') {
29+
form.append('image', createReadStream(payload));
30+
return form;
31+
}
32+
33+
for (const [key, value] of Object.entries(payload)) {
34+
if (key === 'image' || key === 'video') {
35+
if (!payload.type || payload.type === 'file')
36+
form.append(key, createReadStream(value));
37+
} else {
38+
form.append(key, value);
39+
}
40+
}
41+
return form;
42+
}

src/helpers/getAuthorizationHeader.test.ts renamed to src/getAuthorizationHeader.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ImgurClient } from '../client';
1+
import { ImgurClient } from './client';
22
import { getAuthorizationHeader } from './getAuthorizationHeader';
33

44
test('returns provided access code in bearer header', async () => {

src/helpers/getAuthorizationHeader.ts renamed to src/getAuthorizationHeader.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { isAccessToken, isClientId, isLogin } from './credentials';
2-
import { ImgurClient } from '../client';
3-
import { IMGUR_API_PREFIX, AUTHORIZE_ENDPOINT } from '../helpers';
1+
import { isAccessToken, isClientId, isLogin } from './common/types';
2+
import { ImgurClient } from './client';
3+
import { IMGUR_API_PREFIX, AUTHORIZE_ENDPOINT } from './common/endpoints';
44

55
export async function getAuthorizationHeader(client: ImgurClient) {
66
if (isAccessToken(client.credentials)) {

src/helpers/credentials.ts

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/helpers/index.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/image/deleteImage.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { ImgurClient } from '../client';
2+
import { deleteImage } from './deleteImage';
3+
4+
test('delete works successfully', async () => {
5+
const accessToken = 'abc123';
6+
const client = new ImgurClient({ accessToken });
7+
const response = await deleteImage(client, 'CEddrgP');
8+
expect(response).toMatchInlineSnapshot(`
9+
Object {
10+
"data": true,
11+
"status": 200,
12+
"success": true,
13+
}
14+
`);
15+
});

src/image/deleteImage.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { ImgurClient } from '../client';
2+
import { IMAGE_ENDPOINT } from '../common/endpoints';
3+
4+
export interface DeleteResponse {
5+
data: true;
6+
success: true;
7+
status: 200;
8+
}
9+
10+
export async function deleteImage(client: ImgurClient, imageHash: string) {
11+
const url = `${IMAGE_ENDPOINT}/${imageHash}`;
12+
return (await client
13+
.request(url, { method: 'DELETE' })
14+
.json()) as DeleteResponse;
15+
}

src/image/favoriteImage.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { ImgurClient } from '../client';
2+
import { favoriteImage } from './favoriteImage';
3+
4+
test('favorite works successfully', async () => {
5+
const accessToken = 'abc123';
6+
const client = new ImgurClient({ accessToken });
7+
const response = await favoriteImage(client, 'CEddrgP');
8+
expect(response).toMatchInlineSnapshot(`
9+
Object {
10+
"data": "favorited",
11+
"status": 200,
12+
"success": true,
13+
}
14+
`);
15+
});

src/image/favoriteImage.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { ImgurClient } from '../client';
2+
import { IMAGE_ENDPOINT } from '../common/endpoints';
3+
4+
type FavoriteResponse = {
5+
data: 'favorited';
6+
success: true;
7+
status: 200;
8+
};
9+
10+
export async function favoriteImage(client: ImgurClient, imageHash: string) {
11+
const url = `${IMAGE_ENDPOINT}/${imageHash}/favorite`;
12+
return (await client
13+
.request(url, { method: 'POST' })
14+
.json()) as FavoriteResponse;
15+
}

src/image/getImage.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ImgurClient } from '../client';
2-
import { IMAGE_ENDPOINT } from '../helpers';
2+
import { IMAGE_ENDPOINT } from '../common/endpoints';
33

4-
type ImageResponse = {
4+
export interface ImageResponse {
55
data?: {
66
id?: string;
77
title?: string | null;
@@ -39,12 +39,9 @@ type ImageResponse = {
3939
};
4040
success?: boolean;
4141
status?: number;
42-
};
42+
}
4343

44-
export async function getImage(
45-
client: ImgurClient,
46-
imageHash: string
47-
): Promise<ImageResponse> {
44+
export async function getImage(client: ImgurClient, imageHash: string) {
4845
const url = `${IMAGE_ENDPOINT}/${imageHash}`;
4946
return (await client.request(url).json()) as ImageResponse;
5047
}

src/image/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
export * from './deleteImage';
2+
export * from './favoriteImage';
13
export * from './getImage';
4+
export * from './updateImage';
25
export * from './upload';

0 commit comments

Comments
 (0)