Rework image api

This commit is contained in:
Felix Ableitner 2024-12-13 12:47:46 +01:00
parent 5efb9f774f
commit c862bd816e
9 changed files with 76 additions and 62 deletions

View file

@ -123,12 +123,7 @@ import { SearchResponse } from "./types/SearchResponse";
import { SiteResponse } from "./types/SiteResponse"; import { SiteResponse } from "./types/SiteResponse";
import { TransferCommunity } from "./types/TransferCommunity"; import { TransferCommunity } from "./types/TransferCommunity";
import { VerifyEmail } from "./types/VerifyEmail"; import { VerifyEmail } from "./types/VerifyEmail";
import { import { UploadImage, VERSION } from "./other_types";
DeleteImage,
UploadImage,
UploadImageResponse,
VERSION,
} from "./other_types";
import { HideCommunity } from "./types/HideCommunity"; import { HideCommunity } from "./types/HideCommunity";
import { GenerateTotpSecretResponse } from "./types/GenerateTotpSecretResponse"; import { GenerateTotpSecretResponse } from "./types/GenerateTotpSecretResponse";
import { UpdateTotp } from "./types/UpdateTotp"; import { UpdateTotp } from "./types/UpdateTotp";
@ -163,11 +158,14 @@ import { MyUserInfo } from "./types/MyUserInfo";
import { UserBlockInstanceParams } from "./types/UserBlockInstanceParams"; import { UserBlockInstanceParams } from "./types/UserBlockInstanceParams";
import { AdminAllowInstanceParams } from "./types/AdminAllowInstanceParams"; import { AdminAllowInstanceParams } from "./types/AdminAllowInstanceParams";
import { AdminBlockInstanceParams } from "./types/AdminBlockInstanceParams"; import { AdminBlockInstanceParams } from "./types/AdminBlockInstanceParams";
import { DeleteImageParams } from "./types/DeleteImageParams";
import { UploadImageResponse } from "./types/UploadImageResponse";
enum HttpType { enum HttpType {
Get = "GET", Get = "GET",
Post = "POST", Post = "POST",
Put = "PUT", Put = "PUT",
Delete = "DELETE",
} }
type RequestOptions = Pick<RequestInit, "signal">; type RequestOptions = Pick<RequestInit, "signal">;
@ -1874,6 +1872,8 @@ export class LemmyHttp {
/** /**
* Upload an image to the server. * Upload an image to the server.
*
* `HTTP.Post /image`
*/ */
async uploadImage( async uploadImage(
{ image }: UploadImage, { image }: UploadImage,
@ -1881,8 +1881,25 @@ export class LemmyHttp {
): Promise<UploadImageResponse> { ): Promise<UploadImageResponse> {
const formData = createFormData(image); const formData = createFormData(image);
let url: string | undefined = undefined; const response = await this.#fetchFunction(this.#pictrsUrl, {
let delete_url: string | undefined = undefined; ...options,
method: HttpType.Post,
body: formData as unknown as BodyInit,
headers: this.#headers,
});
return response.json();
}
/**
* Upload new user avatar.
*
* `HTTP.Post /account/avatar`
*/
async userUploadAvatar(
{ image }: UploadImage,
options?: RequestOptions,
): Promise<SuccessResponse> {
const formData = createFormData(image);
const response = await this.#fetchFunction(this.#pictrsUrl, { const response = await this.#fetchFunction(this.#pictrsUrl, {
...options, ...options,
@ -1890,42 +1907,35 @@ export class LemmyHttp {
body: formData as unknown as BodyInit, body: formData as unknown as BodyInit,
headers: this.#headers, 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}`;
}
return {
...responseJson,
url,
delete_url,
};
} }
/** /**
* Delete a pictrs image * Delete a pictrs image
*
* `HTTP.Delete /image`
*/ */
async deleteImage( async deleteImage(form: DeleteImageParams, options?: RequestOptions) {
{ token, filename }: DeleteImage, return this.#wrapper<DeleteImageParams, SuccessResponse>(
options?: RequestOptions, HttpType.Delete,
): Promise<boolean> { "/image",
const deleteUrl = `${this.#pictrsUrl}/delete/${token}/${filename}`; form,
options,
);
}
const response = await this.#fetchFunction(deleteUrl, { /**
...options, * Health check for image functionality
method: HttpType.Get, *
headers: this.#headers, * `HTTP.Get /image/health`
}); */
async imageHealth(options?: RequestOptions) {
return response.status == 204; return this.#wrapper<object, SuccessResponse>(
HttpType.Get,
"/image/health",
{},
options,
);
} }
#buildFullUrl(endpoint: string) { #buildFullUrl(endpoint: string) {

View file

@ -85,6 +85,7 @@ export { DeleteAccount } from "./types/DeleteAccount";
export { DeleteComment } from "./types/DeleteComment"; export { DeleteComment } from "./types/DeleteComment";
export { DeleteCommunity } from "./types/DeleteCommunity"; export { DeleteCommunity } from "./types/DeleteCommunity";
export { DeleteCustomEmoji } from "./types/DeleteCustomEmoji"; export { DeleteCustomEmoji } from "./types/DeleteCustomEmoji";
export { DeleteImageParams } from "./types/DeleteImageParams";
export { DeleteOAuthProvider } from "./types/DeleteOAuthProvider"; export { DeleteOAuthProvider } from "./types/DeleteOAuthProvider";
export { DeletePost } from "./types/DeletePost"; export { DeletePost } from "./types/DeletePost";
export { DeletePrivateMessage } from "./types/DeletePrivateMessage"; export { DeletePrivateMessage } from "./types/DeletePrivateMessage";
@ -138,6 +139,8 @@ export { GetUnreadRegistrationApplicationCountResponse } from "./types/GetUnread
export { HideCommunity } from "./types/HideCommunity"; export { HideCommunity } from "./types/HideCommunity";
export { HidePost } from "./types/HidePost"; export { HidePost } from "./types/HidePost";
export { ImageDetails } from "./types/ImageDetails"; export { ImageDetails } from "./types/ImageDetails";
export { ImageGetParams } from "./types/ImageGetParams";
export { ImageProxyParams } from "./types/ImageProxyParams";
export { Instance } from "./types/Instance"; export { Instance } from "./types/Instance";
export { InstanceId } from "./types/InstanceId"; export { InstanceId } from "./types/InstanceId";
export { InstanceWithFederationState } from "./types/InstanceWithFederationState"; export { InstanceWithFederationState } from "./types/InstanceWithFederationState";
@ -291,6 +294,7 @@ export { TransferCommunity } from "./types/TransferCommunity";
export { UpdateTagline } from "./types/UpdateTagline"; export { UpdateTagline } from "./types/UpdateTagline";
export { UpdateTotp } from "./types/UpdateTotp"; export { UpdateTotp } from "./types/UpdateTotp";
export { UpdateTotpResponse } from "./types/UpdateTotpResponse"; export { UpdateTotpResponse } from "./types/UpdateTotpResponse";
export { UploadImageResponse } from "./types/UploadImageResponse";
export { UserBlockInstanceParams } from "./types/UserBlockInstanceParams"; export { UserBlockInstanceParams } from "./types/UserBlockInstanceParams";
export { VerifyEmail } from "./types/VerifyEmail"; export { VerifyEmail } from "./types/VerifyEmail";
export { VoteView } from "./types/VoteView"; export { VoteView } from "./types/VoteView";

View file

@ -3,23 +3,3 @@ export const VERSION = "v4";
export interface UploadImage { export interface UploadImage {
image: File | Buffer; 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;
}

View file

@ -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 = { file: string; token: string };

View file

@ -0,0 +1,6 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ImageGetParams = {
format: string | null;
thumbnail: number | null;
};

View file

@ -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;
format: string | null;
thumbnail: number | null;
};

View file

@ -22,6 +22,7 @@ export type LemmyErrorType =
| { error: "pictrs_api_key_not_provided" } | { error: "pictrs_api_key_not_provided" }
| { error: "no_content_type_header" } | { error: "no_content_type_header" }
| { error: "not_an_image_type" } | { error: "not_an_image_type" }
| { error: "invalid_image_upload" }
| { error: "not_a_mod_or_admin" } | { error: "not_a_mod_or_admin" }
| { error: "not_top_mod" } | { error: "not_top_mod" }
| { error: "not_logged_in" } | { error: "not_logged_in" }

View file

@ -42,10 +42,6 @@ export type SaveUserSettings = {
* The language of the lemmy interface * The language of the lemmy interface
*/ */
interface_language?: string; interface_language?: string;
/**
* A URL for your avatar.
*/
avatar?: string;
/** /**
* A URL for your banner. * A URL for your banner.
*/ */

View file

@ -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;
};