node-catbox
Version:
A library for interacting with Catbox.moe written in TypeScript.
1 lines • 8.63 kB
JavaScript
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`node:fs`),l=require(`node:events`);l=s(l);let u=require(`node:path`),d=require(`node:os`),f=require(`node:fs/promises`),p=require(`node:crypto`);const m=`depthbomb/node-catbox`,h=`https://catbox.moe/user/api.php`,g=`https://litterbox.catbox.moe/resources/internals/api.php`,_=200*1024*1024,v=1024*1024*1024,y=3e4,b=new TextEncoder;async function x(e){try{return(await(0,f.stat)(e)).isFile()}catch{return!1}}function S(e){let t=Object.freeze(Object.fromEntries(e.headers.entries()));return Object.freeze({url:e.url,ok:e.ok,status:e.status,statusText:e.statusText,redirected:e.redirected,type:e.type,headers:t})}function C(e){return e?e instanceof Headers?Object.fromEntries(e.entries()):Array.isArray(e)?Object.fromEntries(e):Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0)):{}}function w(e,t){return Object.freeze({url:e,method:t.method??`GET`,headers:Object.freeze(C(t.headers)),hasBody:t.body!==void 0&&t.body!==null})}function T(e){try{let t=new URL(e);if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error()}catch{throw Error(`Invalid URL "${e}", expected an absolute http(s) URL`)}}async function E(e,t){if(!Number.isInteger(t)||t<=0)throw Error(`Invalid max file size "${t}", expected a positive integer`);if((await(0,f.stat)(e)).size>t)throw Error(`File exceeds maximum size of ${t} bytes`)}function D(e){return typeof e==`string`?b.encode(e):e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer,e.byteOffset,e.byteLength)}async function O(e,t){if(!Number.isInteger(t)||t<=0)throw Error(`Invalid max stream size "${t}", expected a positive integer`);let n=await(0,f.mkdtemp)((0,u.join)((0,d.tmpdir)(),`node-catbox-`)),r=(0,u.join)(n,`${(0,p.randomUUID)()}.upload`),i=(0,c.createWriteStream)(r,{flags:`wx`}),a=async()=>{await(0,f.rm)(n,{recursive:!0,force:!0})},o=0;try{for await(let n of e){if(typeof n!=`string`&&!(n instanceof ArrayBuffer)&&!ArrayBuffer.isView(n))throw Error(`Invalid stream chunk type, expected string, ArrayBuffer, or ArrayBufferView`);let e=D(n);if(o+=e.byteLength,o>t)throw Error(`Stream exceeds maximum size of ${t} bytes`);i.write(e)||await(0,l.once)(i,`drain`)}return i.end(),await(0,l.once)(i,`close`),{blob:await(0,c.openAsBlob)(r),cleanup:a}}catch(e){throw i.destroy(),await a(),e}}var k=class extends l.default{#e;constructor(e){super(),e&&this.setUserHash(e)}get userHash(){return this.#e}setUserHash(e){this.#e=e}async uploadURL({url:e}){T(e);let t=new FormData;t.set(`reqtype`,`urlupload`),t.set(`url`,e),this.#e&&t.set(`userhash`,this.#e),this.emit(`uploadingURL`,e);let n=await this.#t(t);if(n.startsWith(`https://files.catbox.moe/`))return n;throw Error(n)}async uploadFile({path:e,maxFileBytes:t=_}){if(e=(0,u.resolve)(e),!await x(e))throw Error(`Invalid file path "${e}"`);await E(e,t);let n=await(0,c.openAsBlob)(e),r=new FormData;r.set(`reqtype`,`fileupload`),r.set(`fileToUpload`,n,(0,u.basename)(e)),this.#e&&r.set(`userhash`,this.#e),this.emit(`uploadingFile`,e);let i=await this.#t(r);if(i.startsWith(`https://files.catbox.moe/`))return i;throw Error(i)}async uploadFileStream({stream:e,filename:t,maxStreamBytes:n=_}){let{blob:r,cleanup:i}=await O(e,n);try{let e=new FormData;e.set(`reqtype`,`fileupload`),e.set(`fileToUpload`,r,t),this.#e&&e.set(`userhash`,this.#e),this.emit(`uploadingStream`,t);let n=await this.#t(e);if(n.startsWith(`https://files.catbox.moe/`))return n;throw Error(n)}finally{await i()}}async deleteFiles({files:e}){let t=new FormData;t.set(`reqtype`,`deletefiles`),t.set(`userhash`,this.#a()),t.set(`files`,e.join(` `)),this.emit(`deletingFiles`,e);let n=await this.#t(t);if(n.includes(`successfully`))return!0;throw Error(n)}async createAlbum({title:e,description:t,files:n}){let r=new FormData;r.set(`reqtype`,`createalbum`),r.set(`title`,e),r.set(`desc`,t),n&&n.length&&r.set(`files`,n.join(` `)),this.#e&&r.set(`userhash`,this.#e),this.emit(`creatingAlbum`,e,t,n);let i=await this.#t(r);if(i.startsWith(`https://catbox.moe/c/`))return i;throw Error(i)}async editAlbum({id:e,title:t,description:n,files:r}){let i=new FormData;i.set(`reqtype`,`editalbum`),i.set(`short`,e),i.set(`title`,t),i.set(`desc`,n),r&&r.length&&i.set(`files`,r.join(` `)),i.set(`userhash`,this.#a()),this.emit(`editingAlbum`,e,t,n,r);let a=await this.#t(i);if(a===`https://catbox.moe/c/${e}`)return a;throw Error(a)}async addFilesToAlbum({id:e,files:t}){let n=new FormData;n.set(`reqtype`,`addtoalbum`),n.set(`short`,e),n.set(`files`,t.join(` `)),n.set(`userhash`,this.#a()),this.emit(`addingFilesToAlbum`,e,t);let r=await this.#t(n);if(r===`https://catbox.moe/c/${e}`)return r;throw Error(r)}async removeFilesFromAlbum({id:e,files:t}){let n=new FormData;n.set(`reqtype`,`removefromalbum`),n.set(`short`,e),n.set(`files`,t.join(` `)),n.set(`userhash`,this.#a()),this.emit(`removingFilesFromAlbum`,e,t);let r=await this.#t(n);if(r===`https://catbox.moe/c/${e}`)return r;throw Error(r)}async removeAlbum({id:e}){let t=new FormData;t.set(`reqtype`,`deletealbum`),t.set(`short`,e),t.set(`userhash`,this.#a()),this.emit(`removingAlbum`,e);let n=await this.#t(t);if(n.length===0)return!0;throw Error(n)}async#t(e){for(let t=0;t<=2;t++){let n=new AbortController,r=setTimeout(()=>n.abort(),y);try{let r={method:`POST`,headers:{"user-agent":m},body:e,signal:n.signal};this.emit(`request`,w(h,r));let i=await fetch(h,r);if(this.emit(`response`,S(i)),this.#n(i.status)&&t<2){await this.#i(t);continue}return i.text()}catch(e){if(this.#r(e)){if(t<2){await this.#i(t);continue}throw Error(`Request timed out after ${y} ms`)}if(t<2){await this.#i(t);continue}throw e}finally{clearTimeout(r)}}throw Error(`Request failed after retries`)}#n(e){return e===408||e===425||e===429||e>=500}#r(e){return e instanceof DOMException&&e.name===`AbortError`}async#i(e){let t=500*2**e;await new Promise(e=>setTimeout(e,t))}#a(){if(!this.#e)throw Error(`A user hash is required for this operation.`);return this.#e}};const A=[`1h`,`12h`,`24h`,`72h`];let j=function(e){return e.OneHour=`1h`,e.TwelveHours=`12h`,e.OneDay=`24h`,e.ThreeDays=`72h`,e}({}),M=function(e){return e[e.Six=6]=`Six`,e[e.Sixteen=16]=`Sixteen`,e}({});const N=[M.Six,M.Sixteen];var P=class extends l.default{async uploadFile({path:e,duration:t=j.OneHour,fileNameLength:n=M.Six,maxFileBytes:r=v}){if(e=(0,u.resolve)(e),!await x(e))throw Error(`Invalid file path "${e}"`);this.#e(t),this.#t(n),await E(e,r);let i=await(0,c.openAsBlob)(e),a=new FormData;a.set(`reqtype`,`fileupload`),a.set(`fileToUpload`,i,(0,u.basename)(e)),a.set(`time`,t),a.set(`fileNameLength`,n),this.emit(`uploadingFile`,e,t);let o=await this.#n(a);if(o.startsWith(`https://litter.catbox.moe/`))return o;throw Error(o)}async uploadFileStream({stream:e,filename:t,duration:n=j.OneHour,fileNameLength:r=M.Six,maxStreamBytes:i=v}){this.#e(n),this.#t(r);let{blob:a,cleanup:o}=await O(e,i);try{let e=new FormData;e.set(`reqtype`,`fileupload`),e.set(`fileToUpload`,a,t),e.set(`time`,n),e.set(`fileNameLength`,r),this.emit(`uploadingStream`,t,n);let i=await this.#n(e);if(i.startsWith(`https://litter.catbox.moe/`))return i;throw Error(i)}finally{await o()}}#e(e){if(!A.includes(e))throw Error(`Invalid duration "${e}", accepted values are ${A.join(`, `)}`)}#t(e){if(!N.includes(e))throw Error(`Invalid file name length "${e}", accepted values are ${N.join(`, `)}`)}async#n(e){for(let t=0;t<=2;t++){let n=new AbortController,r=setTimeout(()=>n.abort(),y);try{let r={method:`POST`,headers:{"user-agent":m},body:e,signal:n.signal};this.emit(`request`,w(g,r));let i=await fetch(g,r);if(this.emit(`response`,S(i)),this.#r(i.status)&&t<2){await this.#a(t);continue}return i.text()}catch(e){if(this.#i(e)){if(t<2){await this.#a(t);continue}throw Error(`Request timed out after ${y} ms`)}if(t<2){await this.#a(t);continue}throw e}finally{clearTimeout(r)}}throw Error(`Request failed after retries`)}#r(e){return e===408||e===425||e===429||e>=500}#i(e){return e instanceof DOMException&&e.name===`AbortError`}async#a(e){let t=500*2**e;await new Promise(e=>setTimeout(e,t))}};exports.Catbox=k,exports.FileLifetime=j,exports.FileNameLength=M,exports.Litterbox=P,exports.acceptedDurations=A;