2025-05-01 16:27:34 +02:00
import {
Attachment as AttachmentSchema ,
RolePermission ,
} from "@versia/client/schemas" ;
2025-06-15 04:38:20 +02:00
import { ApiError } from "@versia/kit" ;
2025-06-15 23:43:27 +02:00
import { apiRoute , auth , handleZodError } from "@versia/kit/api" ;
2025-01-23 16:08:42 +01:00
import { Media } from "@versia/kit/db" ;
2025-06-15 04:38:20 +02:00
import { config } from "@versia-server/config" ;
2025-03-29 03:30:06 +01:00
import { describeRoute } from "hono-openapi" ;
import { resolver , validator } from "hono-openapi/zod" ;
import { z } from "zod" ;
2023-11-29 00:54:39 +01:00
2025-03-29 03:30:06 +01:00
export default apiRoute ( ( app ) = >
app . post (
"/api/v1/media" ,
describeRoute ( {
summary : "Upload media as an attachment (v1)" ,
description :
"Creates an attachment to be used with a new status. This method will return after the full sized media is done processing." ,
deprecated : true ,
externalDocs : {
url : "https://docs.joinmastodon.org/methods/media/#v1" ,
} ,
tags : [ "Media" ] ,
responses : {
200 : {
description :
"Attachment created successfully. Note that the MediaAttachment will be created even if the file is not understood correctly due to failed processing." ,
content : {
"application/json" : {
schema : resolver ( AttachmentSchema ) ,
} ,
} ,
} ,
413 : {
description : "File too large" ,
content : {
"application/json" : {
schema : resolver ( ApiError . zodSchema ) ,
} ,
} ,
} ,
415 : {
description : "Disallowed file type" ,
content : {
"application/json" : {
schema : resolver ( ApiError . zodSchema ) ,
} ,
} ,
} ,
401 : ApiError.missingAuthentication ( ) . schema ,
422 : ApiError.validationFailed ( ) . schema ,
} ,
} ) ,
2024-12-30 19:18:31 +01:00
auth ( {
auth : true ,
scopes : [ "write:media" ] ,
2025-03-22 18:04:47 +01:00
permissions : [ RolePermission . ManageOwnMedia ] ,
2024-12-30 19:18:31 +01:00
} ) ,
2025-03-29 03:30:06 +01:00
validator (
"form" ,
z . object ( {
file : z.instanceof ( File ) . openapi ( {
description :
"The file to be attached, encoded using multipart form data. The file must have a MIME type." ,
} ) ,
thumbnail : z.instanceof ( File ) . optional ( ) . openapi ( {
description :
"The custom thumbnail of the media to be attached, encoded using multipart form data." ,
} ) ,
2025-05-13 11:51:59 +02:00
description : AttachmentSchema.shape.description
. unwrap ( )
. max ( config . validation . media . max_description_characters )
. optional ( ) ,
2025-03-29 03:30:06 +01:00
focus : z
. string ( )
. optional ( )
. openapi ( {
2025-02-14 16:44:32 +01:00
description :
2025-03-29 03:30:06 +01:00
"Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0. Used for media cropping on clients." ,
externalDocs : {
url : "https://docs.joinmastodon.org/api/guidelines/#focal-points" ,
} ,
2025-02-14 16:44:32 +01:00
} ) ,
2025-03-29 03:30:06 +01:00
} ) ,
handleZodError ,
) ,
async ( context ) = > {
const { file , thumbnail , description } = context . req . valid ( "form" ) ;
2024-09-15 14:28:47 +02:00
2025-03-29 03:30:06 +01:00
const attachment = await Media . fromFile ( file , {
thumbnail ,
description : description ? ? undefined ,
} ) ;
2024-09-15 14:28:47 +02:00
2025-03-29 03:30:06 +01:00
return context . json ( attachment . toApi ( ) , 200 ) ;
} ,
) ,
2024-08-19 20:06:38 +02:00
) ;