import { extname } from "node:path"; import type { DocumentBody } from "../model/doc"; import { readZip } from "../util/zipwrap"; import { type ContentConstructOption, createDefaultClass, registerContentReferrer } from "./file"; import { TextWriter } from "@zip.js/zip.js"; type ComicType = "doujinshi" | "artist cg" | "manga" | "western"; interface ComicDesc { title: string; artist?: string[]; group?: string[]; series?: string[]; type: ComicType | [ComicType]; character?: string[]; tags?: string[]; } const ImageExt = [".gif", ".png", ".jpeg", ".bmp", ".webp", ".jpg"]; export class ComicReferrer extends createDefaultClass("comic") { desc: ComicDesc | undefined; pagenum: number; additional: ContentConstructOption | undefined; constructor(path: string, option?: ContentConstructOption) { super(path); this.additional = option; this.pagenum = 0; } async initDesc(): Promise { if (this.desc !== undefined) return; const zip = await readZip(this.path); const entries = await zip.reader.getEntries(); this.pagenum = entries.filter((x) => ImageExt.includes(extname(x.filename))).length; const entry = entries.find(x=> x.filename === "desc.json"); if (entry === undefined) { return; } if (entry.getData === undefined) { throw new Error("entry.getData is undefined"); } const textWriter = new TextWriter(); const data = (await entry.getData(textWriter)); this.desc = JSON.parse(data); if (this.desc === undefined) { throw new Error(`JSON.parse is returning undefined. ${this.path} desc.json format error`); } } async createDocumentBody(): Promise { await this.initDesc(); const basebody = await super.createDocumentBody(); this.desc?.title; if (this.desc === undefined) { return basebody; } let tags: string[] = this.desc.tags ?? []; tags = tags.concat(this.desc.artist?.map((x) => `artist:${x}`) ?? []); tags = tags.concat(this.desc.character?.map((x) => `character:${x}`) ?? []); tags = tags.concat(this.desc.group?.map((x) => `group:${x}`) ?? []); tags = tags.concat(this.desc.series?.map((x) => `series:${x}`) ?? []); const type = Array.isArray(this.desc.type) ? this.desc.type[0] : this.desc.type; tags.push(`type:${type}`); return { ...basebody, title: this.desc.title, additional: { page: this.pagenum, }, tags: tags, }; } } registerContentReferrer(ComicReferrer);