Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework image api #425

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "lemmy-js-client",
"description": "A javascript / typescript client for Lemmy",
"version": "0.20.0-api-v4.17",
"version": "0.20.0-image-api-rework.6",
"author": "Dessalines <tyhou13@gmx.com>",
"license": "AGPL-3.0",
"main": "./dist/index.js",
Expand Down
2 changes: 1 addition & 1 deletion putTypesInIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const exportRegex = /export\s+(?:enum|interface|type)\s+([A-Za-z0-9_]+)/g;

const baseExports = [
'export * from "./http";',
'export {UploadImage,UploadImageResponse,ImageFile,DeleteImage} from "./other_types";',
'export {UploadImage} from "./other_types";',
];

async function putTypesInIndex() {
Expand Down
91 changes: 51 additions & 40 deletions src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,7 @@ import { SearchResponse } from "./types/SearchResponse";
import { SiteResponse } from "./types/SiteResponse";
import { TransferCommunity } from "./types/TransferCommunity";
import { VerifyEmail } from "./types/VerifyEmail";
import {
DeleteImage,
UploadImage,
UploadImageResponse,
VERSION,
} from "./other_types";
import { UploadImage, VERSION } from "./other_types";
import { HideCommunity } from "./types/HideCommunity";
import { GenerateTotpSecretResponse } from "./types/GenerateTotpSecretResponse";
import { UpdateTotp } from "./types/UpdateTotp";
Expand Down Expand Up @@ -163,11 +158,14 @@ import { MyUserInfo } from "./types/MyUserInfo";
import { UserBlockInstanceParams } from "./types/UserBlockInstanceParams";
import { AdminAllowInstanceParams } from "./types/AdminAllowInstanceParams";
import { AdminBlockInstanceParams } from "./types/AdminBlockInstanceParams";
import { DeleteImageParams } from "./types/DeleteImageParams";
import { UploadImageResponse } from "./types/UploadImageResponse";

enum HttpType {
Get = "GET",
Post = "POST",
Put = "PUT",
Delete = "DELETE",
}

type RequestOptions = Pick<RequestInit, "signal">;
Expand All @@ -178,7 +176,6 @@ type RequestOptions = Pick<RequestInit, "signal">;
export class LemmyHttp {
#apiUrl: string;
#headers: { [key: string]: string } = {};
#pictrsUrl: string;
#fetchFunction: typeof fetch = fetch.bind(globalThis);

/**
Expand All @@ -194,7 +191,6 @@ export class LemmyHttp {
},
) {
this.#apiUrl = `${baseUrl.replace(/\/+$/, "")}/api/${VERSION}`;
this.#pictrsUrl = `${baseUrl}/pictrs/image`;

if (options?.headers) {
this.#headers = options.headers;
Expand Down Expand Up @@ -1874,58 +1870,73 @@ export class LemmyHttp {

/**
* Upload an image to the server.
*
* `HTTP.Post /image`
*/
async uploadImage(
{ image }: UploadImage,
options?: RequestOptions,
): Promise<UploadImageResponse> {
const formData = createFormData(image);

let url: string | undefined = undefined;
let delete_url: string | undefined = undefined;

const response = await this.#fetchFunction(this.#pictrsUrl, {
const response = await this.#fetchFunction(this.#buildFullUrl("/image"), {
...options,
method: HttpType.Post,
body: formData as unknown as BodyInit,
headers: this.#headers,
});
return response.json();
}

if (response.status === 413) {
return { msg: "too_large" };
}

const responseJson = await response.json();

if (responseJson.msg === "ok") {
const { file: hash, delete_token: deleteToken } = responseJson.files[0];
delete_url = `${this.#pictrsUrl}/delete/${deleteToken}/${hash}`;
url = `${this.#pictrsUrl}/${hash}`;
}
/**
* Upload new user avatar.
*
* `HTTP.Post /account/avatar`
*/
async userUploadAvatar(
{ image }: UploadImage,
options?: RequestOptions,
): Promise<SuccessResponse> {
const formData = createFormData(image);

return {
...responseJson,
url,
delete_url,
};
const response = await this.#fetchFunction(
this.#buildFullUrl("/account/avatar"),
{
...options,
method: HttpType.Post,
body: formData as unknown as BodyInit,
headers: this.#headers,
},
);
return response.json();
}

/**
* Delete a pictrs image
*
* `HTTP.Delete /image`
*/
async deleteImage(
{ token, filename }: DeleteImage,
options?: RequestOptions,
): Promise<boolean> {
const deleteUrl = `${this.#pictrsUrl}/delete/${token}/${filename}`;

const response = await this.#fetchFunction(deleteUrl, {
...options,
method: HttpType.Get,
headers: this.#headers,
});
async deleteImage(form: DeleteImageParams, options?: RequestOptions) {
return this.#wrapper<DeleteImageParams, SuccessResponse>(
HttpType.Delete,
"/image",
form,
options,
);
}

return response.status == 204;
/**
* Health check for image functionality
*
* `HTTP.Get /image/health`
*/
async imageHealth(options?: RequestOptions) {
return this.#wrapper<object, SuccessResponse>(
HttpType.Get,
"/image/health",
{},
options,
);
}

#buildFullUrl(endpoint: string) {
Expand Down
11 changes: 5 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
export * from "./http";
export {
UploadImage,
UploadImageResponse,
ImageFile,
DeleteImage,
} from "./other_types";
export { UploadImage } from "./other_types";
export { ActivityId } from "./types/ActivityId";
export { AddAdmin } from "./types/AddAdmin";
export { AddAdminResponse } from "./types/AddAdminResponse";
Expand Down Expand Up @@ -85,6 +80,7 @@ export { DeleteAccount } from "./types/DeleteAccount";
export { DeleteComment } from "./types/DeleteComment";
export { DeleteCommunity } from "./types/DeleteCommunity";
export { DeleteCustomEmoji } from "./types/DeleteCustomEmoji";
export { DeleteImageParams } from "./types/DeleteImageParams";
export { DeleteOAuthProvider } from "./types/DeleteOAuthProvider";
export { DeletePost } from "./types/DeletePost";
export { DeletePrivateMessage } from "./types/DeletePrivateMessage";
Expand Down Expand Up @@ -138,6 +134,8 @@ export { GetUnreadRegistrationApplicationCountResponse } from "./types/GetUnread
export { HideCommunity } from "./types/HideCommunity";
export { HidePost } from "./types/HidePost";
export { ImageDetails } from "./types/ImageDetails";
export { ImageGetParams } from "./types/ImageGetParams";
export { ImageProxyParams } from "./types/ImageProxyParams";
export { Instance } from "./types/Instance";
export { InstanceId } from "./types/InstanceId";
export { InstanceWithFederationState } from "./types/InstanceWithFederationState";
Expand Down Expand Up @@ -291,6 +289,7 @@ export { TransferCommunity } from "./types/TransferCommunity";
export { UpdateTagline } from "./types/UpdateTagline";
export { UpdateTotp } from "./types/UpdateTotp";
export { UpdateTotpResponse } from "./types/UpdateTotpResponse";
export { UploadImageResponse } from "./types/UploadImageResponse";
export { UserBlockInstanceParams } from "./types/UserBlockInstanceParams";
export { VerifyEmail } from "./types/VerifyEmail";
export { VoteView } from "./types/VoteView";
20 changes: 0 additions & 20 deletions src/other_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,3 @@ export const VERSION = "v4";
export interface UploadImage {
image: File | Buffer;
}

export interface UploadImageResponse {
/**
* Is "ok" if the upload was successful; is something else otherwise.
*/
msg: string;
files?: ImageFile[];
url?: string;
delete_url?: string;
}

export interface ImageFile {
file: string;
delete_token: string;
}

export interface DeleteImage {
token: string;
filename: string;
}
2 changes: 0 additions & 2 deletions src/types/CreateSite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ export type CreateSite = {
name: string;
sidebar?: string;
description?: string;
icon?: string;
banner?: string;
enable_nsfw?: boolean;
community_creation_admin_only?: boolean;
require_email_verification?: boolean;
Expand Down
3 changes: 3 additions & 0 deletions src/types/DeleteImageParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type DeleteImageParams = { filename: string; token: string };
8 changes: 0 additions & 8 deletions src/types/EditCommunity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@ export type EditCommunity = {
* A shorter, one line description of your community.
*/
description?: string;
/**
* An icon URL.
*/
icon?: string;
/**
* A banner URL.
*/
banner?: string;
/**
* Whether its an NSFW community.
*/
Expand Down
8 changes: 0 additions & 8 deletions src/types/EditSite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@ export type EditSite = {
* A shorter, one line description of your site.
*/
description?: string;
/**
* A url for your site's icon.
*/
icon?: string;
/**
* A url for your site's banner.
*/
banner?: string;
/**
* Whether to enable NSFW.
*/
Expand Down
1 change: 1 addition & 0 deletions src/types/GetSiteResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ export type GetSiteResponse = {
oauth_providers?: Array<PublicOAuthProvider>;
admin_oauth_providers?: Array<OAuthProvider>;
blocked_urls: Array<LocalSiteUrlBlocklist>;
image_upload_disabled: boolean;
};
3 changes: 3 additions & 0 deletions src/types/ImageGetParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type ImageGetParams = { file_type?: string; max_size?: number };
7 changes: 7 additions & 0 deletions src/types/ImageProxyParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type ImageProxyParams = {
url: string;
file_type?: string;
max_size?: number;
};
2 changes: 2 additions & 0 deletions src/types/LemmyErrorType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export type LemmyErrorType =
| { error: "pictrs_api_key_not_provided" }
| { error: "no_content_type_header" }
| { error: "not_an_image_type" }
| { error: "invalid_image_upload" }
| { error: "image_upload_disabled" }
| { error: "not_a_mod_or_admin" }
| { error: "not_top_mod" }
| { error: "not_logged_in" }
Expand Down
8 changes: 0 additions & 8 deletions src/types/SaveUserSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,6 @@ export type SaveUserSettings = {
* The language of the lemmy interface
*/
interface_language?: string;
/**
* A URL for your avatar.
*/
avatar?: string;
/**
* A URL for your banner.
*/
banner?: string;
/**
* Your display name, which can contain strange characters, and does not need to be unique.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/types/SiteResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { SiteView } from "./SiteView";
export type SiteResponse = {
site_view: SiteView;
/**
* deprecated, use field `tagline` or /api/v3/tagline/list
* deprecated, use field `tagline` or /api/v4/tagline/list
*/
taglines: Array<null>;
};
7 changes: 7 additions & 0 deletions src/types/UploadImageResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type UploadImageResponse = {
image_url: string;
filename: string;
delete_token: string;
};