add zod schemas for amq json data

This commit is contained in:
2026-02-04 22:57:33 -08:00
parent 021b4acf96
commit 5f6bf410c0
6 changed files with 507 additions and 0 deletions

View File

@@ -0,0 +1,385 @@
import { z } from "zod";
export const AmqAnimeCategory = z.enum([
"TV",
"OVA",
"Movie",
"Season",
"movie",
"TV Special",
"ONA",
"special",
"Music Video",
"Game Cutscene Compilation",
"Doujin",
]);
export const AmqAnimeGenre = z.enum([
"Action",
"Adventure",
"Comedy",
"Drama",
"Ecchi",
"Fantasy",
"Horror",
"Mahou Shoujo",
"Mecha",
"Music",
"Mystery",
"Psychological",
"Romance",
"Sci-Fi",
"Slice of Life",
"Sports",
"Supernatural",
"Thriller",
]);
export const AmqAnimeTag = z.enum([
"Achromatic",
"Achronological Order",
"Acrobatics",
"Acting",
"Adoption",
"Advertisement",
"Afterlife",
"Age Gap",
"Age Regression",
"Agender",
"Agriculture",
"Airsoft",
"Alchemy",
"Aliens",
"Alternate Universe",
"American Football",
"Amnesia",
"Anachronism",
"Ancient China",
"Angels",
"Animals",
"Anthology",
"Anthropomorphism",
"Anti-Hero",
"Archery",
"Aromantic",
"Arranged Marriage",
"Artificial Intelligence",
"Asexual",
"Assassins",
"Astronomy",
"Athletics",
"Augmented Reality",
"Autobiographical",
"Aviation",
"Badminton",
"Ballet",
"Band",
"Bar",
"Baseball",
"Basketball",
"Battle Royale",
"Biographical",
"Bisexual",
"Blackmail",
"Board Game",
"Boarding School",
"Body Horror",
"Body Image",
"Body Swapping",
"Bowling",
"Boxing",
"Boys' Love",
"Bullying",
"Butler",
"CGI",
"Calligraphy",
"Camping",
"Cannibalism",
"Card Battle",
"Cars",
"Centaur",
"Cheerleading",
"Chibi",
"Chimera",
"Chuunibyou",
"Circus",
"Class Struggle",
"Classic Literature",
"Classical Music",
"Clone",
"Coastal",
"Cohabitation",
"College",
"Coming of Age",
"Conspiracy",
"Cosmic Horror",
"Cosplay",
"Cowboys",
"Creature Taming",
"Crime",
"Criminal Organization",
"Crossdressing",
"Crossover",
"Cult",
"Cultivation",
"Curses",
"Cute Boys Doing Cute Things",
"Cute Girls Doing Cute Things",
"Cyberpunk",
"Cyborg",
"Cycling",
"Dancing",
"Death Game",
"Delinquents",
"Demons",
"Denpa",
"Desert",
"Detective",
"Dinosaurs",
"Disability",
"Dissociative Identities",
"Dragons",
"Drawing",
"Drugs",
"Dullahan",
"Dungeon",
"Dystopian",
"E-Sports",
"Eco-Horror",
"Economics",
"Educational",
"Elderly Protagonist",
"Elf",
"Ensemble Cast",
"Environmental",
"Episodic",
"Ero Guro",
"Espionage",
"Estranged Family",
"Exorcism",
"Fairy",
"Fairy Tale",
"Fake Relationship",
"Family Life",
"Fashion",
"Female Harem",
"Female Protagonist",
"Femboy",
"Fencing",
"Filmmaking",
"Firefighters",
"Fishing",
"Fitness",
"Flash",
"Food",
"Football",
"Foreign",
"Found Family",
"Fugitive",
"Full CGI",
"Gambling",
"Gangs",
"Gender Bending",
"Ghost",
"Go",
"Goblin",
"Gods",
"Golf",
"Gore",
"Guns",
"Gyaru",
"Handball",
"Henshin",
"Heterosexual",
"Hikikomori",
"Hip-hop Music",
"Historical",
"Homeless",
"Horticulture",
"Ice Skating",
"Idol",
"Indigenous Cultures",
"Inn",
"Isekai",
"Iyashikei",
"Jazz Music",
"Josei",
"Judo",
"Kabuki",
"Kaiju",
"Karuta",
"Kemonomimi",
"Kids",
"Kingdom Management",
"Konbini",
"Kuudere",
"LGBTQ+ Themes",
"Lacrosse",
"Language Barrier",
"Lost Civilization",
"Love Triangle",
"Mafia",
"Magic",
"Mahjong",
"Maids",
"Makeup",
"Male Harem",
"Male Protagonist",
"Manzai",
"Marriage",
"Martial Arts",
"Matchmaking",
"Matriarchy",
"Medicine",
"Medieval",
"Memory Manipulation",
"Mermaid",
"Meta",
"Metal Music",
"Military",
"Mixed Gender Harem",
"Mixed Media",
"Modeling",
"Monster Boy",
"Monster Girl",
"Mopeds",
"Motorcycles",
"Mountaineering",
"Musical Theater",
"Mythology",
"Natural Disaster",
"Necromancy",
"Nekomimi",
"Ninja",
"No Dialogue",
"Noir",
"Non-fiction",
"Nudity",
"Nun",
"Office",
"Office Lady",
"Oiran",
"Ojou-sama",
"Orphan",
"Otaku Culture",
"Outdoor Activities",
"POV",
"Pandemic",
"Parenthood",
"Parkour",
"Parody",
"Philosophy",
"Photography",
"Pirates",
"Poker",
"Police",
"Politics",
"Polyamorous",
"Post-Apocalyptic",
"Pregnancy",
"Primarily Adult Cast",
"Primarily Animal Cast",
"Primarily Child Cast",
"Primarily Female Cast",
"Primarily Male Cast",
"Primarily Teen Cast",
"Prison",
"Proxy Battle",
"Psychosexual",
"Puppetry",
"Rakugo",
"Real Robot",
"Rehabilitation",
"Reincarnation",
"Religion",
"Rescue",
"Restaurant",
"Revenge",
"Reverse Isekai",
"Robots",
"Rock Music",
"Rotoscoping",
"Royal Affairs",
"Rugby",
"Rural",
"Samurai",
"Satire",
"School",
"School Club",
"Scuba Diving",
"Seinen",
"Shapeshifting",
"Ships",
"Shogi",
"Shoujo",
"Shounen",
"Shrine Maiden",
"Skateboarding",
"Skeleton",
"Slapstick",
"Slavery",
"Snowscape",
"Software Development",
"Space",
"Space Opera",
"Spearplay",
"Steampunk",
"Stop Motion",
"Succubus",
"Suicide",
"Sumo",
"Super Power",
"Super Robot",
"Superhero",
"Surfing",
"Surreal Comedy",
"Survival",
"Swimming",
"Swordplay",
"Table Tennis",
"Tanks",
"Tanned Skin",
"Teacher",
"Teens' Love",
"Tennis",
"Terrorism",
"Time Loop",
"Time Manipulation",
"Time Skip",
"Tokusatsu",
"Tomboy",
"Torture",
"Tragedy",
"Trains",
"Transgender",
"Travel",
"Triads",
"Tsundere",
"Twins",
"Unrequited Love",
"Urban",
"Urban Fantasy",
"VTuber",
"Vampire",
"Vertical Video",
"Veterinarian",
"Video Games",
"Vikings",
"Villainess",
"Virtual World",
"Vocal Synth",
"Volleyball",
"War",
"Werewolf",
"Wilderness",
"Witch",
"Work",
"Wrestling",
"Writing",
"Wuxia",
"Yakuza",
"Yandere",
"Youkai",
"Yuri",
"Zombie",
]);

View File

@@ -0,0 +1,61 @@
import { z } from "zod";
import { AmqAnimeCategory, AmqAnimeGenre, AmqAnimeTag } from "./anime-extended";
export const Season = z.enum({
Winter: 0,
Spring: 1,
Summer: 2,
Fall: 3,
} as const);
export const SongLinkType = z.enum({
OP: 1,
ED: 2,
INS: 3,
} as const);
const BooleanInt = z.enum({
false: 0,
true: 1,
} as const);
export const AmqSongLink = z.object({
songId: z.int().positive(),
number: z.int().nonnegative(),
type: SongLinkType,
annSongId: z.int().positive(),
uploaded: BooleanInt,
rebroadcast: BooleanInt,
dub: BooleanInt,
});
export const AmqAnimeSchema = z.object({
annId: z.int().positive(),
aniListId: z.int().positive().nullable(),
malId: z.int().positive(),
kitsuId: z.int().positive().nullable(),
category: z.object({
name: AmqAnimeCategory,
number: z.union([z.number(), z.string()]).nullable(),
}),
genres: z.array(AmqAnimeGenre),
tags: z.array(AmqAnimeTag),
mainName: z.string(),
mainNames: z.object({
EN: z.string().nullable(),
JA: z.string().nullable(),
}),
names: z.array(
z.object({
language: z.enum(["EN", "JA"]),
name: z.string(),
}),
),
year: z.int().positive(),
seasonId: Season,
songLinks: z.array(AmqSongLink),
opCount: z.int().nonnegative(),
edCount: z.int().nonnegative(),
insertCount: z.int().nonnegative(),
});

View File

@@ -0,0 +1,13 @@
import { z } from "zod";
export const AmqArtistSchema = z.object({
songArtistId: z.int().positive(),
name: z.string(),
inGroups: z.array(z.int().positive()),
altNames: z.array(
z.object({
songArtistId: z.int().positive(),
name: z.string(),
}),
),
});

View File

@@ -0,0 +1,14 @@
import { z } from "zod";
export const AmqGroupSchema = z.object({
songGroupId: z.int().positive(),
name: z.string(),
artistMembers: z.array(z.int().positive()),
groupMembers: z.array(z.int().positive()),
altNames: z.array(
z.object({
songGroupId: z.int().positive(),
name: z.string(),
}),
),
});

View File

@@ -0,0 +1,5 @@
export * from "./anime";
export * from "./anime-extended";
export * from "./artist";
export * from "./group";
export * from "./song";

29
src/lib/types/amq/song.ts Normal file
View File

@@ -0,0 +1,29 @@
import { z } from "zod";
export const AmqSongCategory = z.enum({
none: 0,
instrumental: 1,
chanting: 2,
character: 3,
standard: 4,
});
export const AmqSongSchema = z.object({
annSongId: z.int().positive(),
songId: z.int().positive(),
name: z.string(),
category: AmqSongCategory,
songArtistId: z.int().positive().nullable(),
songGroupId: z.int().positive().nullable(),
composerArtistId: z.int().positive().nullable(),
composerGroupId: z.int().positive().nullable(),
arrangerArtistId: z.int().positive().nullable(),
arrangerGroupId: z.int().positive().nullable(),
globalPercent: z.number().int().min(0).max(100),
fileName: z.string().nullable(),
fileNameMap: z.object({
0: z.string().optional(),
480: z.string().optional(),
720: z.string().optional(),
}),
});