UNPKG

@lenml/char-card-reader

Version:

SillyTavern character card info reader

3 lines 11.4 kB
function D(r){if(typeof Buffer<"u"&&Buffer.isBuffer(r))return Promise.resolve(r.toString("base64"));if(typeof Blob<"u"&&r instanceof Blob)return new Promise((t,a)=>{let n=new FileReader;n.onload=()=>{let s=n.result.split(",")[1];t(s)},n.onerror=a,n.readAsDataURL(r)});let e;if(r instanceof ArrayBuffer)e=new Uint8Array(r);else if(r instanceof Uint8Array)e=r;else throw new TypeError("Unsupported input type");if(typeof Buffer<"u")return Promise.resolve(Buffer.from(e).toString("base64"));{let t="";for(let a=0;a<e.length;a++)t+=String.fromCharCode(e[a]);return Promise.resolve(btoa(t))}}function k(r){return typeof r!="string"?!1:!!(r.startsWith("http://")||r.startsWith("https://")||r.startsWith("data:"))}var u=globalThis.structuredClone?globalThis.structuredClone:r=>JSON.parse(JSON.stringify(r)),l=class{static encode(e){if(typeof window<"u"&&typeof window.btoa=="function")return window.btoa(unescape(encodeURIComponent(e)));if(typeof Buffer<"u")return Buffer.from(e,"utf-8").toString("base64");throw new Error("Base64.encode: Environment not supported.")}static decode(e){if(typeof window<"u"&&typeof window.atob=="function")return decodeURIComponent(escape(window.atob(e)));if(typeof Buffer<"u")return Buffer.from(e,"base64").toString("utf-8");throw new Error("Base64.decode: Environment not supported.")}};function A(r){return typeof r=="object"&&r!==null}function P(r){return r!=null}function v(...r){let e=new Set(r.flatMap(Object.keys));return Object.fromEntries(Array.from(e).map(t=>{let a=r.map(n=>n[t]);return a.some(Array.isArray)?[t,[...a].reverse().filter(P).filter(Boolean)[0]]:a.some(A)?[t,v(...a.filter(A))]:[t,[...a].reverse().filter(P)[0]]}))}function d(r){return Array.from(new Set(r))}var g=class r{static from_json(e){if(typeof e!="object"||e===null)throw new Error("data must be an object");let t=[];Array.isArray(e)?t=e:t=Array.isArray(e?.entries)?e.entries:Array.isArray(e?.data?.character_book?.entries)?e.data.character_book.entries:[];let a=new r(t),n=e?.character_book??e?.data?.character_book??e;return a.name=n?.name,a.description=n?.description,a.recursive_scanning=n?.recursive_scanning??!0,a.scan_depth=n?.scan_depth??10,a.extensions=n?.extensions??{},a}name="unknown";description="";token_budget;recursive_scanning=!0;extensions={};entries=[];scan_depth=10;constructor(e=[]){this.entries=u(e),this._keys_fix()}_keys_fix(){let e=/[,|;,;]/g;for(let t of this.entries){let{keys:a}=t,n=[];for(let o of a)e.test(o)?n.push(...o.split(e).map(s=>s.trim()).filter(Boolean)):n.push(o);t.keys=n}}_scan(e,t=[],a=1){if(a>=(this.scan_depth??10))return d(t);let n=[e,...d(t).map(s=>s.content)].join(` `),o=this.entries.filter(s=>s.content?.trim()).filter(s=>s.enabled&&!t.includes(s));if(o.length===0)return d(t);for(let s of o)s.keys.some(c=>n.includes(c))&&t.push(s);return this.recursive_scanning?this._scan(e,t,a+1):d(t)}scan(e){let t=this._scan(e),a=this.entries.filter(n=>n.constant&&n.enabled&&n.content?.trim());return d([...t,...a]).sort((n,o)=>n.insertion_order-o.insertion_order)}};function V(r){let e=r instanceof Uint8Array?r:new Uint8Array(r),t=e.slice(0,8).every((o,s)=>o===[137,80,78,71,13,10,26,10][s]),a=e[0]===255&&e[1]===216,n=String.fromCharCode(...e.slice(0,4))==="RIFF"&&String.fromCharCode(...e.slice(8,12))==="WEBP";if(t)return{format:"png",chunks:I(e)};if(a)return{format:"jpeg",segments:O(e)};if(n)return{format:"webp",chunks:R(e)};throw new Error("Unsupported image format")}function I(r){let e=[],t=8;for(;t<r.length&&!(t+8>r.length);){let a=(r[t]<<24|r[t+1]<<16|r[t+2]<<8|r[t+3])>>>0,n=String.fromCharCode(r[t+4],r[t+5],r[t+6],r[t+7]),o=t+8,s=o+a;if(s+4>r.length)break;let i=r.slice(o,s),c=(r[s]<<24|r[s+1]<<16|r[s+2]<<8|r[s+3])>>>0,_={type:n,length:a,crc:c};if(n==="IHDR")_.width=(i[0]<<24|i[1]<<16|i[2]<<8|i[3])>>>0,_.height=(i[4]<<24|i[5]<<16|i[6]<<8|i[7])>>>0,_.bitDepth=i[8],_.colorType=i[9];else if(n==="tEXt"){let h=new TextDecoder().decode(i),p=h.indexOf("\0");p>=0?(_.keyword=h.slice(0,p),_.text=h.slice(p+1)):_.rawText=h}e.push(_),t=s+4}return e}function O(r){let e=[],t=2;for(;t<r.length;){if(r[t]!==255)throw new Error(`Invalid marker at offset ${t}`);let a=r[t+1];for(;a===255;)t++,a=r[t+1];let n=t;if(t+=2,a===217||a===218)break;let o=r[t]<<8|r[t+1],s=t+2,i=s+o-2,c=r.slice(s,i),_={marker:`FF ${a.toString(16).toUpperCase().padStart(2,"0")}`,offset:n,length:o,type:"Other",preview:Array.from(c.slice(0,16)).map(h=>h.toString(16).padStart(2,"0")).join(" ")};a===224&&String.fromCharCode(...c.slice(0,5))==="JFIF\0"?_.type="JFIF":a===225?String.fromCharCode(...c.slice(0,6)).startsWith("Exif")?_.type="EXIF":String.fromCharCode(...c.slice(0,29)).includes("http://ns.adobe.com/xap/1.0/")?_.type="XMP":_.type="APP1":a===254&&(_.type="Comment",_.comment=new TextDecoder().decode(c)),e.push(_),t=i}return e}function R(r){let e=[],t=12,a=r.length;for(;t+8<=a;){let n=String.fromCharCode(r[t],r[t+1],r[t+2],r[t+3]),o=r[t+4]|r[t+5]<<8|r[t+6]<<16|r[t+7]<<24,s=t+8,i=s+o;if(i>a)break;e.push({type:n,offset:t,length:o,preview:Array.from(r.slice(s,s+16)).map(c=>c.toString(16).padStart(2,"0")).join(" ")}),t=i+o%2}return e}function E(r,e){let t=e.offset+8,n=String.fromCharCode(r[t],r[t+1])==="II",o=p=>n?r[p]|r[p+1]<<8:r[p]<<8|r[p+1],s=p=>n?r[p]|r[p+1]<<8|r[p+2]<<16|r[p+3]<<24:r[p]<<24|r[p+1]<<16|r[p+2]<<8|r[p+3],i=t,c=s(t+4),_=i+c,h=o(_);for(let p=0;p<h;p++){let m=_+2+p*12,U=o(m),W=o(m+2),x=s(m+4),C=m+8;if(U===37510){let f=s(C);x<=4?f=C:f=i+f;let w=r.slice(f,f+x),T="ASCII\0\0\0",j="UTF8\0\0\0",S=String.fromCharCode(...w.slice(0,8)),b="";return S.startsWith(T)||S.startsWith(j)?b=new TextDecoder("utf-8").decode(w.slice(8)):b=new TextDecoder("utf-8").decode(w),b}}}var y=class extends Error{};var B=class r{constructor(e,t=""){this.raw_data=e;this.fallback_avatar=t}static async from_file(e){let t=V(e),a=await D(e),n=`data:image/${t.format};base64,${a}`,o=this.parse_char_info(e,t);return new r({spec:"chara_card_v1",spec_version:"1.0",data:{},...o},n)}static from_json(e,t=""){return new r(e,t)}static parse_char_info(e,t){let a;if(t.format==="png"){let s=t.chunks.find(c=>c.keyword==="chara");a=t.chunks.find(c=>c.keyword==="ccv3")?.text??s?.text}else if(t.format==="jpeg"){let s=t.segments.find(c=>c.marker==="chara");a=t.segments.find(c=>c.marker==="ccv3")?.comment??s?.comment}else if(t.format==="webp"){let s=t.chunks.find(i=>i.type==="EXIF");s&&(a=E(e instanceof Uint8Array?e:new Uint8Array(e),s))}if(!a)throw new y("Failed to extract chara card data from image");let n=l.decode(a);return JSON.parse(n)}async get_avatar(e=!1){let t=e?"":this.fallback_avatar;return[this.raw_data.avatar,this.raw_data.data?.avatar,t].filter(k)[0]}get avatar(){return[this.raw_data.avatar,this.raw_data.data?.avatar,this.fallback_avatar].filter(k)[0]}get spec(){return this.raw_data.spec||"unknown"}get spec_version(){return this.raw_data.spec_version||"unknown"}get name(){switch(this.spec){case"chara_card_v2":return this.raw_data.data?.name??this.raw_data.name;case"chara_card_v3":return this.raw_data.data?.name??this.raw_data.name;default:return this.raw_data.char_name??this.raw_data.name??"unknown"}}get description(){switch(this.spec){case"chara_card_v2":return this.raw_data.data?.description??this.raw_data.description;case"chara_card_v3":return this.raw_data.data?.description??this.raw_data.description;default:return this.raw_data.description??"unknown"}}get first_message(){switch(this.spec){case"chara_card_v2":return this.raw_data.data?.first_mes??this.raw_data.first_mes;case"chara_card_v3":return this.raw_data.data?.first_mes??this.raw_data.first_mes;default:return this.raw_data.first_mes??"unknown"}}get message_example(){switch(this.spec){case"chara_card_v2":return this.raw_data.data?.mes_example??this.raw_data.mes_example;case"chara_card_v3":return this.raw_data.data?.mes_example??this.raw_data.mes_example;default:return this.raw_data.mes_example??"unknown"}}get create_date(){switch(this.spec){case"chara_card_v2":return this.raw_data.data?.create_date??this.raw_data.create_date;case"chara_card_v3":return this.raw_data.data?.create_date??this.raw_data.create_date;default:return this.raw_data.create_date??"unknown"}}get personality(){switch(this.spec){case"chara_card_v2":return this.raw_data.data?.personality??this.raw_data.personality;case"chara_card_v3":return this.raw_data.data?.personality??this.raw_data.personality;default:return this.raw_data.personality??"unknown"}}get scenario(){switch(this.spec){case"chara_card_v2":return this.raw_data.data?.scenario??this.raw_data.scenario;case"chara_card_v3":return this.raw_data.data?.scenario??this.raw_data.scenario;default:return this.raw_data.scenario??"unknown"}}get alternate_greetings(){switch(this.spec){case"chara_card_v2":return this.raw_data.data?.alternate_greetings;case"chara_card_v3":return this.raw_data.data?.alternate_greetings;default:return[]}}get character_book(){switch(this.spec){case"chara_card_v2":return this.raw_data.data?.character_book;case"chara_card_v3":return this.raw_data.data?.character_book;default:return{entries:[],name:this.name,extensions:{}}}}get tags(){switch(this.spec){case"chara_card_v2":return this.raw_data.data?.tags;case"chara_card_v3":return this.raw_data.data?.tags;default:return[]}}toSpecV1(){let e=t=>this[t]??this.raw_data[t]??this.raw_data.data?.[t];return{name:e("name")??e("char_name"),description:e("description"),personality:e("personality"),scenario:e("scenario"),first_mes:e("first_mes"),mes_example:e("mes_example")}}toSpecV2(){let e=t=>this[t]??this.raw_data[t]??this.raw_data.data?.[t];return u({spec:"chara_card_v2",spec_version:"2.0",data:{name:e("name")??e("char_name"),description:e("description"),mes_example:e("mes_example"),first_mes:e("first_mes"),personality:e("personality"),scenario:e("scenario"),creator_notes:e("creator_notes"),system_prompt:e("system_prompt"),post_history_instructions:e("post_history_instructions"),alternate_greetings:e("alternate_greetings"),character_book:e("character_book"),tags:e("tags"),creator:e("creator"),character_version:e("character_version"),extensions:e("extensions")}})}toSpecV3(){let e=t=>this[t]??this.raw_data[t]??this.raw_data.data?.[t];return u({spec:"chara_card_v3",spec_version:"3.0",data:{name:e("name")??e("char_name"),description:e("description"),tags:e("tags"),creator:e("creator"),character_version:e("character_version"),mes_example:e("mes_example"),extensions:e("extensions"),system_prompt:e("system_prompt"),post_history_instructions:e("post_history_instructions"),first_mes:e("first_mes"),alternate_greetings:e("alternate_greetings"),personality:e("personality"),scenario:e("scenario"),creator_notes:e("creator_notes"),character_book:e("character_book"),assets:e("assets"),nickname:e("nickname"),creator_notes_multilingual:e("creator_notes_multilingual"),source:e("source"),group_only_greetings:e("group_only_greetings"),creation_date:e("create_date")??e("creation_date"),modification_date:e("modify_date")??e("modification_date")}})}toMaxCompatibleSpec(){return v(this.toSpecV1(),this.toSpecV2(),this.toSpecV3())}clone(e="v3"){let t=null;switch(e){case"v1":{t=this.toSpecV1();break}case"v2":{t=this.toSpecV2();break}case"v3":{t=this.toSpecV3();break}default:throw new Error(`Unsupported version ${e}`)}return r.from_json({spec:"chara_card_v1",spec_version:"1.0",data:{},...t})}get_book(){return g.from_json(this.raw_data)}};export{g as CharacterBook,B as CharacterCard,E as extractUserCommentFromWebPChunk,V as parseImageMetadata}; //# sourceMappingURL=main.mjs.map