imgur
Version:
Unofficial JavaScript library for Imgur
405 lines (404 loc) • 13.1 kB
JavaScript
import { EventEmitter } from "events";
import FormData from "form-data";
import { URL } from "whatwg-url";
import axios from "axios";
function isAccessToken(arg) {
return arg.accessToken !== void 0;
}
function isRefreshToken(arg) {
return arg.refreshToken !== void 0;
}
function isClientId(arg) {
return arg.clientId !== void 0;
}
const IMGUR_API_PREFIX = "https://api.imgur.com";
const API_VERSION = "3";
const TOKEN_ENDPOINT = "oauth2/token";
const ACCOUNT_ENDPOINT = `${API_VERSION}/account`;
const ALBUM_ENDPOINT = `${API_VERSION}/album`;
const IMAGE_ENDPOINT = `${API_VERSION}/image`;
const UPLOAD_ENDPOINT = `${API_VERSION}/upload`;
const GALLERY_ENDPOINT = `${API_VERSION}/gallery`;
const SUBREDDIT_GALLERY_ENDPOINT = `${API_VERSION}/gallery/r`;
const SEARCH_GALLERY_ENDPOINT = `${API_VERSION}/gallery/search`;
async function getAuthorizationHeader(client) {
if (isAccessToken(client.credentials)) {
return `Bearer ${client.credentials.accessToken}`;
}
const { clientId, clientSecret, refreshToken } = client.credentials;
if (isRefreshToken(client.credentials)) {
const options = {
url: TOKEN_ENDPOINT,
baseURL: IMGUR_API_PREFIX,
method: "POST",
data: {
client_id: clientId,
client_secret: clientSecret,
refresh_token: refreshToken,
grant_type: "refresh_token"
}
};
const response = await client.plainRequest(options);
if (response.status === 200 && response.data) {
const { access_token: accessToken, refresh_token: refreshToken2 } = response.data;
client.credentials.accessToken = accessToken;
client.credentials.refreshToken = refreshToken2;
return `Bearer ${accessToken}`;
}
}
if (isClientId(client.credentials)) {
return `Client-ID ${clientId}`;
}
return null;
}
function createForm(payload) {
const form = new FormData();
if (typeof payload === "string") {
form.append("image", payload);
return form;
}
for (const [key, value] of Object.entries(payload)) {
const supportedUploadObjectTypes = ["base64", "stream"];
if (supportedUploadObjectTypes.indexOf(key) !== -1) {
if (supportedUploadObjectTypes.indexOf(payload.type) !== -1) {
form.append(key, payload);
}
} else if (value) {
form.append(key, value);
}
}
form.getHeaders = form.getHeaders ? form.getHeaders : () => {
return {
"Content-Type": "multipart/form-data"
};
};
return form;
}
function getImgurApiResponseFromResponse(response) {
var _a, _b, _c, _d;
let success = true;
let headers;
let data;
let status = 200;
const responseIsValid = response && (typeof response.status !== "undefined" || typeof ((_a = response.data) == null ? void 0 : _a.status) !== "undefined") && typeof response.data !== "undefined";
const responseIsSuccess = responseIsValid && !!response.data.success;
const responseIsError = responseIsValid && !responseIsSuccess && (typeof ((_b = response.data.data) == null ? void 0 : _b.error) !== "undefined" || typeof response.data.errors !== "undefined");
const getResponseData = (d) => Array.isArray(d) ? d.map((t) => responseIsError ? t.detail : t.data) : d;
if (typeof response === "undefined") {
data = "response was empty";
status = 500;
success = false;
} else if (typeof response === "string") {
data = response;
status = 500;
success = false;
} else if (responseIsSuccess) {
status = response.data.status;
headers = response.headers;
data = response.data.data.error ? response.data.data.error : response.data.data;
} else {
success = false;
status = ((_d = (_c = response.data.data) == null ? void 0 : _c.error) == null ? void 0 : _d.code) ?? response.status ?? response.data.status;
headers = response.headers;
data = getResponseData(
responseIsError ? response.data.errors ?? response.data.data.error.message ?? response.data.data.error : response.data.data ?? response.data.message ?? response.data
);
}
return {
headers,
data,
status,
success
};
}
async function deleteImage(client, imageHash) {
const url = `${IMAGE_ENDPOINT}/${imageHash}`;
return getImgurApiResponseFromResponse(
await client.request({ url, method: "DELETE" }).catch((e) => e.response)
);
}
async function favoriteImage(client, imageHash) {
const url = `${IMAGE_ENDPOINT}/${imageHash}/favorite`;
return getImgurApiResponseFromResponse(
await client.request({ url, method: "POST" }).catch((e) => e.response)
);
}
async function getImage(client, imageHash) {
const url = `${IMAGE_ENDPOINT}/${imageHash}`;
return getImgurApiResponseFromResponse(
await client.request({ url }).catch((e) => e.response)
);
}
function isValidUpdatePayload(p) {
return typeof p.title === "string" || typeof p.description === "string";
}
async function updateImage(client, payload) {
if (!isValidUpdatePayload(payload)) {
throw new Error("Update requires a title and/or description");
}
const url = `${IMAGE_ENDPOINT}/${payload.imageHash}`;
const form = createForm(payload);
return new Promise(async (resolve) => {
return resolve(
getImgurApiResponseFromResponse(
await client.request({
url,
method: "POST",
data: form,
headers: form.getHeaders()
}).catch((e) => e.response)
)
);
});
}
async function upload(client, payload) {
const form = createForm(payload);
const image = payload.image;
const filename = typeof image === "string" ? image : image.path ?? image.name;
const isVideo = payload.type === "stream" && filename && (filename.indexOf(".mp4") !== -1 || filename.indexOf(".avi") !== -1);
const url = isVideo ? UPLOAD_ENDPOINT : IMAGE_ENDPOINT;
return new Promise(async (resolve) => {
return resolve(
getImgurApiResponseFromResponse(
await client.request({
url,
method: "POST",
data: form,
headers: form.getHeaders(),
onUploadProgress: (progressEvent) => {
client.emit("uploadProgress", { ...progressEvent });
}
}).catch((e) => e.response)
)
);
});
}
const defaultOptions = {
section: "hot",
sort: "viral"
};
function constructGalleryUrl(options) {
const mergedOptions = Object.assign({}, defaultOptions, options);
let uri = `${mergedOptions.section}`;
if (mergedOptions.sort) {
uri += `/${mergedOptions.sort}`;
}
if (mergedOptions.section === "top" && mergedOptions.window) {
uri += `/${mergedOptions.window}`;
}
if (mergedOptions.page) {
uri += `/${mergedOptions.page}`;
}
const url = new URL(`${IMGUR_API_PREFIX}/${GALLERY_ENDPOINT}/${uri}`);
if (mergedOptions.showViral !== void 0) {
url.searchParams.append("showViral", mergedOptions.showViral.toString());
}
if (mergedOptions.mature !== void 0) {
url.searchParams.append("mature", mergedOptions.mature.toString());
}
if (mergedOptions.album_previews !== void 0) {
url.searchParams.append(
"album_previews",
mergedOptions.album_previews.toString()
);
}
return url;
}
async function getGallery(client, options = defaultOptions) {
const { pathname } = constructGalleryUrl(options);
const finalPathname = pathname.slice(1);
return getImgurApiResponseFromResponse(
await client.request({ url: finalPathname }).catch((e) => e.response)
);
}
function constructSubredditGalleryUrl(options) {
let uri = `${options.subreddit}`;
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}/${SUBREDDIT_GALLERY_ENDPOINT}/${uri}`
);
return url;
}
async function getSubredditGallery(client, options) {
const { pathname } = constructSubredditGalleryUrl(options);
const finalPathname = pathname.slice(1);
return getImgurApiResponseFromResponse(
await client.request({ url: finalPathname }).catch((e) => e.response)
);
}
const advancedParameters = [
"q_all",
"q_any",
"q_exactly",
"q_not",
"q_type",
"q_size_px"
];
function constructSearchGalleryUrl(options) {
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) => {
var _a;
if ((_a = options[param]) == null ? void 0 : _a.length) {
url.searchParams.append(param, options[param]);
}
});
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;
}
async function searchGallery(client, options) {
const { pathname, search } = constructSearchGalleryUrl(options);
const finalPathname = pathname.slice(1);
return getImgurApiResponseFromResponse(
await client.request({ url: finalPathname + search }).catch((e) => e.response)
);
}
async function createAlbum(client, title, description) {
var _a, _b;
const form = createForm({ title, description });
const response = await client.request({
url: ALBUM_ENDPOINT,
headers: form.getHeaders(),
method: "POST",
data: form
}).catch((e) => e.response);
if (((_a = response.data) == null ? void 0 : _a.success) && ((_b = response.data) == null ? void 0 : _b.data)) {
response.data.data.title = title;
response.data.data.description = description;
}
return getImgurApiResponseFromResponse(
response
);
}
async function getAlbum(client, albumHash) {
const url = `${ALBUM_ENDPOINT}/${albumHash}`;
return getImgurApiResponseFromResponse(
await client.request({ url }).catch((e) => e.response)
);
}
async function getAccount(client, account) {
const url = `${ACCOUNT_ENDPOINT}/${account}`;
return getImgurApiResponseFromResponse(
await client.plainRequest({ url }).catch((e) => e.response)
);
}
async function getAlbums(client, account, page) {
const url = `${ACCOUNT_ENDPOINT}/${account}/albums/${page ?? ""}`;
return getImgurApiResponseFromResponse(
await client.request({ url }).catch((e) => e.response)
);
}
async function getAlbumsIds(client, account, page) {
const url = `${ACCOUNT_ENDPOINT}/${account}/albums/ids/${page ?? ""}`;
return getImgurApiResponseFromResponse(
await client.request({ url }).catch((e) => e.response)
);
}
const USERAGENT = "imgur (https://github.com/keneucker/imgur)";
class ImgurClient extends EventEmitter {
constructor(credentials) {
var _a, _b;
super();
this.credentials = credentials;
this.credentials.rapidApiHost = ((_a = credentials.rapidApiKey) == null ? void 0 : _a.length) ? credentials.rapidApiHost ?? "imgur-apiv3.p.rapidapi.com" : credentials.rapidApiHost;
const headers = typeof window !== "undefined" ? {} : {
"user-agent": USERAGENT
};
this.plainFetcher = axios.create({
baseURL: IMGUR_API_PREFIX,
headers,
responseType: "json"
});
this.fetcher = axios.create({
baseURL: ((_b = credentials.rapidApiKey) == null ? void 0 : _b.length) ? `https://${this.credentials.rapidApiHost}` : IMGUR_API_PREFIX,
headers,
responseType: "json"
});
this.fetcher.interceptors.request.use(
async (config) => {
var _a2;
config.headers = config.headers ? config.headers : {};
config.headers.authorization = await getAuthorizationHeader(this);
if ((_a2 = credentials.rapidApiKey) == null ? void 0 : _a2.length) {
config.headers["x-rapidapi-host"] = credentials.rapidApiHost;
config.headers["x-rapidapi-key"] = credentials.rapidApiKey;
}
return config;
},
(e) => Promise.reject(e)
);
}
plainRequest(options) {
return this.plainFetcher(options);
}
request(options = {}) {
return this.fetcher(options);
}
deleteImage(imageHash) {
return deleteImage(this, imageHash);
}
favoriteImage(imageHash) {
return favoriteImage(this, imageHash);
}
getAlbum(albumHash) {
return getAlbum(this, albumHash);
}
getAccount(account) {
return getAccount(this, account);
}
getAlbums(account, page) {
return getAlbums(this, account, page);
}
createAlbum(title, description) {
return createAlbum(this, title, description);
}
getAlbumsIds(account, page) {
return getAlbumsIds(this, account, page);
}
getGallery(options) {
return getGallery(this, options);
}
getSubredditGallery(options) {
return getSubredditGallery(this, options);
}
searchGallery(options) {
return searchGallery(this, options);
}
getImage(imageHash) {
return getImage(this, imageHash);
}
updateImage(payload) {
return updateImage(this, payload);
}
upload(payload) {
return upload(this, payload);
}
}
export {
ImgurClient,
ImgurClient as default,
getAuthorizationHeader
};