UNPKG

derpibooru-api

Version:

Modern TypeScript implementation of Derpibooru API with Zod validation

204 lines (203 loc) 6.37 kB
import * as z from "zod"; // Base schemas const ImageMetadataSchema = z.looseInterface({ width: z.number(), height: z.number(), mime_type: z.string(), size: z.number(), duration: z.number().optional(), }); const ArtistLinkSchema = z.looseInterface({ user_id: z.number(), tag_id: z.number(), url: z.url(), }); // Tag schema with self-referential structure const TagSchema = z.looseInterface({ id: z.number(), name: z.string(), slug: z.string(), description: z.string(), short_description: z.string(), spoiler_image_uri: z.string().nullable(), aliased_tag: z.string().nullable(), aliases: z.array(z.string()), category: z.enum([ "character", "content-fanmade", "content-official", "error", "oc", "origin", "rating", "species", "spoiler", ]), dnp_entries: z.array(z.any()), images: z.number(), implied_by_tags: z.array(z.string()), implied_tags: z.array(z.string()), name_in_namespace: z.string(), namespace: z.string().nullable(), }); // Image response schema const ImageResponseSchema = z.looseInterface({ id: z.number(), created_at: z.iso.datetime(), updated_at: z.iso.datetime(), first_seen_at: z.iso.datetime(), score: z.number(), comment_count: z.number(), width: z.number(), height: z.number(), description: z.string(), uploader: z.string().nullable(), uploader_id: z.number().nullable(), thumbnails_generated: z.boolean(), spoilered: z.boolean(), tag_ids: z.array(z.number()), tags: z.array(z.string()), tag_count: z.number(), source_url: z.string().optional(), source_urls: z.array(z.string()).optional(), representations: z.record(z.enum([ "full", "small", "thumb_tiny", "thumb_small", "thumb", "medium", "large", "tall", "mp4", "webm", ]), z.url().optional()), intensities: z.record(z.string(), z.number()).optional(), aspect_ratio: z.number().optional(), size: z.number().optional(), format: z.enum(["gif", "jpg", "jpeg", "png", "svg", "webm"]), mime_type: z.enum([ "image/gif", "image/jpeg", "image/png", "image/svg+xml", "video/webm", ]), name: z.string().optional(), orig_sha512_hash: z.string().nullable(), sha512_hash: z.string().optional(), orig_size: z.number().optional(), processed: z.boolean().optional(), deletion_reason: z.string().nullable(), duplicate_of: z.number().nullable(), hidden_from_users: z.boolean().optional(), view_url: z.string().optional(), wilson_score: z.number().optional(), faves: z.number().optional(), upvotes: z.number().optional(), downvotes: z.number().optional(), animated: z.boolean().optional(), duration: z.number().optional(), }); // Filter response schema const FilterResponseSchema = z.looseInterface({ id: z.number(), name: z.string(), description: z.string(), user_id: z.number().nullable(), user_count: z.number(), system: z.boolean(), public: z.boolean(), spoilered_tag_ids: z.array(z.number()), spoilered_complex: z.string().nullable(), hidden_tag_ids: z.array(z.number()), hidden_complex: z.string().nullable(), }); // User response schema const UserResponseSchema = z.looseInterface({ id: z.number(), name: z.string(), slug: z.string(), role: z.string(), description: z.string(), avatar_url: z.url().optional(), created_at: z.iso.datetime(), comment_count: z.number(), uploads_count: z.number(), posts_count: z.number(), topics_count: z.number(), links: z.array(z.url()), awards: z.array(z.string()), }); // Oembed response schema const OembedResponseSchema = z.looseInterface({ author_name: z.string(), author_url: z.url(), cache_age: z.literal(7200), derpibooru_comments: z.number(), derpibooru_id: z.number(), derpibooru_score: z.number(), derpibooru_tags: z.array(z.string()), provider_name: z.literal("Derpibooru"), provider_url: z.literal("https://derpibooru.org"), title: z.string(), type: z.literal("photo"), version: z.literal("1.0"), }); // API Response wrappers const SearchImagesResponseSchema = z.looseInterface({ total: z.number(), images: z.array(ImageResponseSchema), interactions: z.array(z.unknown()).optional(), }); const SearchTagsResponseSchema = z.looseInterface({ tags: z.array(TagSchema), total: z.number(), }); // Comment response schema const CommentResponseSchema = z.looseInterface({ id: z.number(), author: z.string(), avatar: z.string().nullable(), body: z.string(), created_at: z.iso.datetime(), edited_at: z.iso.datetime().nullable(), image_id: z.number().nullable(), user_id: z.number().nullable(), }); // Post response schema const PostResponseSchema = z.looseInterface({ author: z.string(), avatar: z.string().nullable(), body: z.string(), created_at: z.iso.datetime(), edit_reason: z.string().nullable(), edited_at: z.iso.datetime().nullable(), id: z.number(), updated_at: z.iso.datetime(), user_id: z.number().nullable(), }); // Gallery response schema const GalleryResponseSchema = z.looseInterface({ description: z.string(), id: z.number(), spoiler_warning: z.string().nullable(), thumbnail_id: z.number().nullable(), title: z.string(), user: z.string(), user_id: z.number(), }); // Search response wrappers for new types const SearchCommentsResponseSchema = z.looseInterface({ total: z.number(), comments: z.array(CommentResponseSchema), }); const SearchGalleriesResponseSchema = z.looseInterface({ total: z.number(), galleries: z.array(GalleryResponseSchema), }); const SearchPostsResponseSchema = z.looseInterface({ total: z.number(), posts: z.array(PostResponseSchema), }); export { ImageMetadataSchema, ArtistLinkSchema, TagSchema, ImageResponseSchema, FilterResponseSchema, UserResponseSchema, OembedResponseSchema, SearchImagesResponseSchema, SearchTagsResponseSchema, CommentResponseSchema, PostResponseSchema, GalleryResponseSchema, SearchCommentsResponseSchema, SearchGalleriesResponseSchema, SearchPostsResponseSchema, };