├── .gitignore ├── README.md ├── build.js ├── doFrame.js ├── extractFrames.js ├── index.js ├── package-lock.json ├── package.json ├── res └── BadApple.mp4 └── utilities.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/node,vscode 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node,vscode 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Optional stylelint cache 62 | .stylelintcache 63 | 64 | # Microbundle cache 65 | .rpt2_cache/ 66 | .rts2_cache_cjs/ 67 | .rts2_cache_es/ 68 | .rts2_cache_umd/ 69 | 70 | # Optional REPL history 71 | .node_repl_history 72 | 73 | # Output of 'npm pack' 74 | *.tgz 75 | 76 | # Yarn Integrity file 77 | .yarn-integrity 78 | 79 | # dotenv environment variables file 80 | .env 81 | .env.test 82 | .env*.local 83 | 84 | # parcel-bundler cache (https://parceljs.org/) 85 | .cache 86 | .parcel-cache 87 | 88 | # Next.js build output 89 | .next 90 | 91 | # Nuxt.js build / generate output 92 | .nuxt 93 | dist 94 | 95 | # Gatsby files 96 | .cache/ 97 | # Comment in the public line in if your project uses Gatsby and not Next.js 98 | # https://nextjs.org/blog/next-9-1#public-directory-support 99 | # public 100 | 101 | # vuepress build output 102 | .vuepress/dist 103 | 104 | # Serverless directories 105 | .serverless/ 106 | 107 | # FuseBox cache 108 | .fusebox/ 109 | 110 | # DynamoDB Local files 111 | .dynamodb/ 112 | 113 | # TernJS port file 114 | .tern-port 115 | 116 | # Stores VSCode versions used for testing VSCode extensions 117 | .vscode-test 118 | 119 | ### vscode ### 120 | .vscode/* 121 | !.vscode/settings.json 122 | !.vscode/tasks.json 123 | !.vscode/launch.json 124 | !.vscode/extensions.json 125 | *.code-workspace 126 | 127 | # End of https://www.toptal.com/developers/gitignore/api/node,vscode 128 | 129 | data.txt 130 | frames/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bad Apple but it is played in the Terminal 2 | 3 | Here is a Demo [Youtube video](https://youtu.be/_JTHbbsSCZk). 4 | 5 | ## Requirements 6 | 7 | - Node.js 8 | - FFmpeg 9 | - A terminal that supports unicode characters 10 | 11 | ## Steps to run 12 | 13 | ### `npm install` 14 | 15 | Installs the required dependecies. 16 | 17 | ### `npm run prepare` 18 | Prepare the resources for the included Bad Apple video by default. 19 | - Extracts the video file into an image sequence. 20 | - Reads the image sequence and generates `data/` containing the frames converted into text. 21 | 22 | **OR** 23 | 24 | ### `npm run prepare ` 25 | Prepare the resources for a specific video. 26 | 27 | ### `npm start` 28 | 29 | Plays the video in the console. Enjoy! 30 | 31 | Note: If you want to play it again, run `npm start`. You dont have to run the other commands, unless you delete the `data.txt` file. 32 | 33 | Note^2: Make sure the console font size is small enough, otherwise it might not form the image properly, or start flickering. You know the font is small enough if the console doesnt start scrolling down. 34 | 35 | ## Contributors 36 | 37 | Special thanks to [@yeonfish6040](https://github.com/yeonfish6040) for adding support for custom videos and optimising the video to text extraction process. 38 | -------------------------------------------------------------------------------- /build.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const os = require("os"); 3 | const childprocess = require("child_process"); 4 | 5 | const build = (index) => { 6 | if (fs.existsSync("./data")) { 7 | fs.rmSync("./data", { recursive: true, force: true }); 8 | } 9 | fs.mkdirSync("./data"); 10 | 11 | fs.readdir("./frames", (err, files) => { 12 | files.sort((a, b) => { 13 | return parseInt(a.match(/\d+/)[0]) - parseInt(b.match(/\d+/)[0]); 14 | }); 15 | const unit = Math.ceil(files.length/os.cpus().length); 16 | let progress = 0; 17 | let processCount = Math.ceil(files.length/unit); 18 | for (let i = 0; i < processCount; i++) { 19 | const cprocess = childprocess.fork("./doFrame.js"); 20 | cprocess.send({ id: i, index: i*unit+1, end: (i*unit)+unit+1 }); 21 | cprocess.on("message", (msg) => { if (msg === "plus") progress++; process.stdout.write(`\rTo text frames... ${(progress/files.length*100).toFixed(2)}%`); }); 22 | cprocess.on("exit", () => { 23 | processCount--; 24 | console.log(` ${processCount} processes left...`); 25 | 26 | if (processCount === 0) { 27 | console.log("Frame extract done! Merging..."); 28 | mergeData(); 29 | process.exit(); 30 | } 31 | }) 32 | } 33 | }); 34 | }; 35 | 36 | function mergeData() { 37 | if (fs.existsSync("./data.txt")) { 38 | fs.writeFileSync("./data.txt", "", { flag: "w" }, (err) => {}); 39 | } 40 | 41 | const data = fs.readdirSync("./data"); 42 | data.sort((a, b) => { 43 | return parseInt(a.match(/\d+/)[0]) - parseInt(b.match(/\d+/)[0]); 44 | }); 45 | data.forEach((file) => { 46 | const content = fs.readFileSync(`./data/${file}`, "utf-8"); 47 | fs.writeFileSync("./data.txt", content, { flag: "a" }, (err) => {}); 48 | }); 49 | console.log("Done!"); 50 | } 51 | 52 | build(1); 53 | 54 | module.exports.build = build; 55 | -------------------------------------------------------------------------------- /doFrame.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const getPixels = require("get-pixels"); 3 | const { toFourDigits } = require("./utilities"); 4 | 5 | let id; 6 | let startIndex; 7 | let endIndex; 8 | 9 | function doFrame(id, index = 1, end = NaN) { 10 | let indexString = toFourDigits(index.toString()); 11 | let path = `frames/frame_${indexString}.png`; 12 | 13 | if (!isNaN(end) && index === end) 14 | return process.exit(); 15 | 16 | getPixels(path, (err, pixels) => { 17 | if (err) 18 | return process.exit(); 19 | 20 | let string = ""; 21 | 22 | const symbols = "⠀⠃⠇⠏⠟⠿"; 23 | 24 | let widthCounter = 0; 25 | for (let i = 0; i < pixels.data.length; i += 4) { 26 | let value = (pixels.data[i] + pixels.data[i + 1] + pixels.data[i + 2]) / 3; 27 | value = Math.max(pixels.data[i], pixels.data[i + 1], pixels.data[i + 2]); 28 | 29 | // string += getCharacterForGrayScale(value) + getCharacterForGrayScale(value); 30 | const index = Math.floor(value / (256 / 6)); 31 | string += symbols[index].repeat(2); 32 | 33 | widthCounter++; 34 | if (widthCounter === 120) { 35 | widthCounter = 0; 36 | string += "\n"; 37 | } 38 | } 39 | string += "\n"; 40 | 41 | // compress 42 | const regexes = [/(⠀+)/g, /(⠃+)/g, /(⠇+)/g, /(⠏+)/g, /(⠟+)/g, /(⠿+)/g]; 43 | for (let i = 0; i < regexes.length; i++) { 44 | const matches = string.match(regexes[i]) || []; 45 | for (let match of matches) { 46 | string = string.replace(match, symbols[i] + toFourDigits(match.length.toString())); 47 | } 48 | } 49 | 50 | fs.writeFileSync(`./data/data_${id}.txt`, string, { flag: "a" }, (err) => {}); 51 | 52 | process.send("plus"); 53 | 54 | doFrame(id, index + 1, end); 55 | }); 56 | } 57 | 58 | process.on('message', (msg) => { 59 | id = msg.id; 60 | startIndex = msg.index; 61 | endIndex = msg.end; 62 | doFrame(msg.id, msg.index, msg.end); 63 | }); -------------------------------------------------------------------------------- /extractFrames.js: -------------------------------------------------------------------------------- 1 | const ffmpeg = require("ffmpeg"); 2 | const fs = require("fs"); 3 | 4 | const { Jimp } = require("jimp"); 5 | 6 | if (fs.existsSync("./frames")) { 7 | fs.rmSync("./frames", { recursive: true, force: true }); 8 | } 9 | fs.mkdirSync("./frames"); 10 | 11 | function extract() { 12 | const file = process.argv.length === 2 ? "res/BadApple.mp4" : process.argv[2]; 13 | console.log(`Extracting frames from ${file}`); 14 | try { 15 | ffmpeg(file).then( 16 | (video) => { 17 | console.log("Processing Video..."); 18 | video.setVideoSize("120x90"); 19 | video.setVideoFrameRate(30); 20 | video.save("frames/frame_%04d.png", (error, file) => { 21 | if (error) console.log(error); 22 | else console.log("Video has been processed!"); 23 | toGrayScale(); 24 | }); 25 | }, 26 | (err) => { 27 | console.log(`Error: ${err}`); 28 | } 29 | ); 30 | } catch (e) { 31 | console.log(e.code); 32 | console.log(e.message); 33 | } 34 | } 35 | 36 | function toGrayScale() { 37 | fs.readdir("./frames", (err, files) => { 38 | let i = 0; 39 | files.forEach((file, index) => { 40 | Jimp.read(`./frames/${file}`).then((image) => { 41 | if (err) throw err; 42 | image.greyscale().write(`./frames/${file}`); 43 | i++; 44 | process.stdout.write(`\rTo grayscale... ${(i/files.length*100).toFixed(0) == 100 ? "100% complete" : (i/files.length*100).toFixed(2)+"%"}`); 45 | }); 46 | }); 47 | }); 48 | } 49 | 50 | extract(); -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const gameloop = require("node-gameloop"); 2 | const readline = require("readline"); 3 | const fs = require("fs"); 4 | 5 | run(); 6 | 7 | function decompressFrame(frame) { 8 | let string = ""; 9 | let lines = frame.split("\n"); 10 | for (let line of lines) { 11 | let tokens = line.match(/.{1,5}/g); 12 | for (let token of tokens) { 13 | let multiplier = parseInt(token.substring(1)); 14 | string += token[0].repeat(multiplier); 15 | } 16 | string += "\n"; 17 | } 18 | return string; 19 | } 20 | 21 | function run() { 22 | fs.readFile("data.txt", "utf8", (err, data) => { 23 | if (err) { 24 | console.error(err); 25 | return; 26 | } 27 | 28 | let frames = data.split("\n\n"); 29 | 30 | let index = 0; 31 | const startTime = Date.now(); 32 | gameloop.setGameLoop((delta) => { 33 | let string = decompressFrame(frames[index]); 34 | 35 | readline.clearLine(process.stdout, -1); 36 | readline.cursorTo(process.stdout, 0, 2); 37 | process.stdout.write(string); 38 | process.stdout.write( 39 | `Frame: ${index}(${(index/frames.length*100).toFixed(2)}%) | FPS: ${index / ((Date.now() - startTime) / 1000)} \n` 40 | ); 41 | 42 | index++; 43 | }, 1000 / 30); 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bad-apple-terminal", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "bad-apple-terminal", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "ffmpeg": "0.0.4", 13 | "get-pixels": "^3.3.2", 14 | "jimp": "^1.6.0", 15 | "node-gameloop": "^0.1.4" 16 | } 17 | }, 18 | "node_modules/@jimp/core": { 19 | "version": "1.6.0", 20 | "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz", 21 | "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==", 22 | "license": "MIT", 23 | "dependencies": { 24 | "@jimp/file-ops": "1.6.0", 25 | "@jimp/types": "1.6.0", 26 | "@jimp/utils": "1.6.0", 27 | "await-to-js": "^3.0.0", 28 | "exif-parser": "^0.1.12", 29 | "file-type": "^16.0.0", 30 | "mime": "3" 31 | }, 32 | "engines": { 33 | "node": ">=18" 34 | } 35 | }, 36 | "node_modules/@jimp/diff": { 37 | "version": "1.6.0", 38 | "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz", 39 | "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==", 40 | "license": "MIT", 41 | "dependencies": { 42 | "@jimp/plugin-resize": "1.6.0", 43 | "@jimp/types": "1.6.0", 44 | "@jimp/utils": "1.6.0", 45 | "pixelmatch": "^5.3.0" 46 | }, 47 | "engines": { 48 | "node": ">=18" 49 | } 50 | }, 51 | "node_modules/@jimp/file-ops": { 52 | "version": "1.6.0", 53 | "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz", 54 | "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==", 55 | "license": "MIT", 56 | "engines": { 57 | "node": ">=18" 58 | } 59 | }, 60 | "node_modules/@jimp/js-bmp": { 61 | "version": "1.6.0", 62 | "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz", 63 | "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==", 64 | "license": "MIT", 65 | "dependencies": { 66 | "@jimp/core": "1.6.0", 67 | "@jimp/types": "1.6.0", 68 | "@jimp/utils": "1.6.0", 69 | "bmp-ts": "^1.0.9" 70 | }, 71 | "engines": { 72 | "node": ">=18" 73 | } 74 | }, 75 | "node_modules/@jimp/js-gif": { 76 | "version": "1.6.0", 77 | "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz", 78 | "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==", 79 | "license": "MIT", 80 | "dependencies": { 81 | "@jimp/core": "1.6.0", 82 | "@jimp/types": "1.6.0", 83 | "gifwrap": "^0.10.1", 84 | "omggif": "^1.0.10" 85 | }, 86 | "engines": { 87 | "node": ">=18" 88 | } 89 | }, 90 | "node_modules/@jimp/js-jpeg": { 91 | "version": "1.6.0", 92 | "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz", 93 | "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==", 94 | "license": "MIT", 95 | "dependencies": { 96 | "@jimp/core": "1.6.0", 97 | "@jimp/types": "1.6.0", 98 | "jpeg-js": "^0.4.4" 99 | }, 100 | "engines": { 101 | "node": ">=18" 102 | } 103 | }, 104 | "node_modules/@jimp/js-jpeg/node_modules/jpeg-js": { 105 | "version": "0.4.4", 106 | "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", 107 | "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", 108 | "license": "BSD-3-Clause" 109 | }, 110 | "node_modules/@jimp/js-png": { 111 | "version": "1.6.0", 112 | "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz", 113 | "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==", 114 | "license": "MIT", 115 | "dependencies": { 116 | "@jimp/core": "1.6.0", 117 | "@jimp/types": "1.6.0", 118 | "pngjs": "^7.0.0" 119 | }, 120 | "engines": { 121 | "node": ">=18" 122 | } 123 | }, 124 | "node_modules/@jimp/js-png/node_modules/pngjs": { 125 | "version": "7.0.0", 126 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", 127 | "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", 128 | "license": "MIT", 129 | "engines": { 130 | "node": ">=14.19.0" 131 | } 132 | }, 133 | "node_modules/@jimp/js-tiff": { 134 | "version": "1.6.0", 135 | "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz", 136 | "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==", 137 | "license": "MIT", 138 | "dependencies": { 139 | "@jimp/core": "1.6.0", 140 | "@jimp/types": "1.6.0", 141 | "utif2": "^4.1.0" 142 | }, 143 | "engines": { 144 | "node": ">=18" 145 | } 146 | }, 147 | "node_modules/@jimp/plugin-blit": { 148 | "version": "1.6.0", 149 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz", 150 | "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==", 151 | "license": "MIT", 152 | "dependencies": { 153 | "@jimp/types": "1.6.0", 154 | "@jimp/utils": "1.6.0", 155 | "zod": "^3.23.8" 156 | }, 157 | "engines": { 158 | "node": ">=18" 159 | } 160 | }, 161 | "node_modules/@jimp/plugin-blur": { 162 | "version": "1.6.0", 163 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz", 164 | "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==", 165 | "license": "MIT", 166 | "dependencies": { 167 | "@jimp/core": "1.6.0", 168 | "@jimp/utils": "1.6.0" 169 | }, 170 | "engines": { 171 | "node": ">=18" 172 | } 173 | }, 174 | "node_modules/@jimp/plugin-circle": { 175 | "version": "1.6.0", 176 | "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz", 177 | "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==", 178 | "license": "MIT", 179 | "dependencies": { 180 | "@jimp/types": "1.6.0", 181 | "zod": "^3.23.8" 182 | }, 183 | "engines": { 184 | "node": ">=18" 185 | } 186 | }, 187 | "node_modules/@jimp/plugin-color": { 188 | "version": "1.6.0", 189 | "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz", 190 | "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==", 191 | "license": "MIT", 192 | "dependencies": { 193 | "@jimp/core": "1.6.0", 194 | "@jimp/types": "1.6.0", 195 | "@jimp/utils": "1.6.0", 196 | "tinycolor2": "^1.6.0", 197 | "zod": "^3.23.8" 198 | }, 199 | "engines": { 200 | "node": ">=18" 201 | } 202 | }, 203 | "node_modules/@jimp/plugin-contain": { 204 | "version": "1.6.0", 205 | "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz", 206 | "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==", 207 | "license": "MIT", 208 | "dependencies": { 209 | "@jimp/core": "1.6.0", 210 | "@jimp/plugin-blit": "1.6.0", 211 | "@jimp/plugin-resize": "1.6.0", 212 | "@jimp/types": "1.6.0", 213 | "@jimp/utils": "1.6.0", 214 | "zod": "^3.23.8" 215 | }, 216 | "engines": { 217 | "node": ">=18" 218 | } 219 | }, 220 | "node_modules/@jimp/plugin-cover": { 221 | "version": "1.6.0", 222 | "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz", 223 | "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==", 224 | "license": "MIT", 225 | "dependencies": { 226 | "@jimp/core": "1.6.0", 227 | "@jimp/plugin-crop": "1.6.0", 228 | "@jimp/plugin-resize": "1.6.0", 229 | "@jimp/types": "1.6.0", 230 | "zod": "^3.23.8" 231 | }, 232 | "engines": { 233 | "node": ">=18" 234 | } 235 | }, 236 | "node_modules/@jimp/plugin-crop": { 237 | "version": "1.6.0", 238 | "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz", 239 | "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==", 240 | "license": "MIT", 241 | "dependencies": { 242 | "@jimp/core": "1.6.0", 243 | "@jimp/types": "1.6.0", 244 | "@jimp/utils": "1.6.0", 245 | "zod": "^3.23.8" 246 | }, 247 | "engines": { 248 | "node": ">=18" 249 | } 250 | }, 251 | "node_modules/@jimp/plugin-displace": { 252 | "version": "1.6.0", 253 | "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz", 254 | "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==", 255 | "license": "MIT", 256 | "dependencies": { 257 | "@jimp/types": "1.6.0", 258 | "@jimp/utils": "1.6.0", 259 | "zod": "^3.23.8" 260 | }, 261 | "engines": { 262 | "node": ">=18" 263 | } 264 | }, 265 | "node_modules/@jimp/plugin-dither": { 266 | "version": "1.6.0", 267 | "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz", 268 | "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==", 269 | "license": "MIT", 270 | "dependencies": { 271 | "@jimp/types": "1.6.0" 272 | }, 273 | "engines": { 274 | "node": ">=18" 275 | } 276 | }, 277 | "node_modules/@jimp/plugin-fisheye": { 278 | "version": "1.6.0", 279 | "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz", 280 | "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==", 281 | "license": "MIT", 282 | "dependencies": { 283 | "@jimp/types": "1.6.0", 284 | "@jimp/utils": "1.6.0", 285 | "zod": "^3.23.8" 286 | }, 287 | "engines": { 288 | "node": ">=18" 289 | } 290 | }, 291 | "node_modules/@jimp/plugin-flip": { 292 | "version": "1.6.0", 293 | "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz", 294 | "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==", 295 | "license": "MIT", 296 | "dependencies": { 297 | "@jimp/types": "1.6.0", 298 | "zod": "^3.23.8" 299 | }, 300 | "engines": { 301 | "node": ">=18" 302 | } 303 | }, 304 | "node_modules/@jimp/plugin-hash": { 305 | "version": "1.6.0", 306 | "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz", 307 | "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==", 308 | "license": "MIT", 309 | "dependencies": { 310 | "@jimp/core": "1.6.0", 311 | "@jimp/js-bmp": "1.6.0", 312 | "@jimp/js-jpeg": "1.6.0", 313 | "@jimp/js-png": "1.6.0", 314 | "@jimp/js-tiff": "1.6.0", 315 | "@jimp/plugin-color": "1.6.0", 316 | "@jimp/plugin-resize": "1.6.0", 317 | "@jimp/types": "1.6.0", 318 | "@jimp/utils": "1.6.0", 319 | "any-base": "^1.1.0" 320 | }, 321 | "engines": { 322 | "node": ">=18" 323 | } 324 | }, 325 | "node_modules/@jimp/plugin-mask": { 326 | "version": "1.6.0", 327 | "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz", 328 | "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==", 329 | "license": "MIT", 330 | "dependencies": { 331 | "@jimp/types": "1.6.0", 332 | "zod": "^3.23.8" 333 | }, 334 | "engines": { 335 | "node": ">=18" 336 | } 337 | }, 338 | "node_modules/@jimp/plugin-print": { 339 | "version": "1.6.0", 340 | "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.0.tgz", 341 | "integrity": "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==", 342 | "license": "MIT", 343 | "dependencies": { 344 | "@jimp/core": "1.6.0", 345 | "@jimp/js-jpeg": "1.6.0", 346 | "@jimp/js-png": "1.6.0", 347 | "@jimp/plugin-blit": "1.6.0", 348 | "@jimp/types": "1.6.0", 349 | "parse-bmfont-ascii": "^1.0.6", 350 | "parse-bmfont-binary": "^1.0.6", 351 | "parse-bmfont-xml": "^1.1.6", 352 | "simple-xml-to-json": "^1.2.2", 353 | "zod": "^3.23.8" 354 | }, 355 | "engines": { 356 | "node": ">=18" 357 | } 358 | }, 359 | "node_modules/@jimp/plugin-quantize": { 360 | "version": "1.6.0", 361 | "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz", 362 | "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==", 363 | "license": "MIT", 364 | "dependencies": { 365 | "image-q": "^4.0.0", 366 | "zod": "^3.23.8" 367 | }, 368 | "engines": { 369 | "node": ">=18" 370 | } 371 | }, 372 | "node_modules/@jimp/plugin-resize": { 373 | "version": "1.6.0", 374 | "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz", 375 | "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==", 376 | "license": "MIT", 377 | "dependencies": { 378 | "@jimp/core": "1.6.0", 379 | "@jimp/types": "1.6.0", 380 | "zod": "^3.23.8" 381 | }, 382 | "engines": { 383 | "node": ">=18" 384 | } 385 | }, 386 | "node_modules/@jimp/plugin-rotate": { 387 | "version": "1.6.0", 388 | "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz", 389 | "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==", 390 | "license": "MIT", 391 | "dependencies": { 392 | "@jimp/core": "1.6.0", 393 | "@jimp/plugin-crop": "1.6.0", 394 | "@jimp/plugin-resize": "1.6.0", 395 | "@jimp/types": "1.6.0", 396 | "@jimp/utils": "1.6.0", 397 | "zod": "^3.23.8" 398 | }, 399 | "engines": { 400 | "node": ">=18" 401 | } 402 | }, 403 | "node_modules/@jimp/plugin-threshold": { 404 | "version": "1.6.0", 405 | "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz", 406 | "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==", 407 | "license": "MIT", 408 | "dependencies": { 409 | "@jimp/core": "1.6.0", 410 | "@jimp/plugin-color": "1.6.0", 411 | "@jimp/plugin-hash": "1.6.0", 412 | "@jimp/types": "1.6.0", 413 | "@jimp/utils": "1.6.0", 414 | "zod": "^3.23.8" 415 | }, 416 | "engines": { 417 | "node": ">=18" 418 | } 419 | }, 420 | "node_modules/@jimp/types": { 421 | "version": "1.6.0", 422 | "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz", 423 | "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==", 424 | "license": "MIT", 425 | "dependencies": { 426 | "zod": "^3.23.8" 427 | }, 428 | "engines": { 429 | "node": ">=18" 430 | } 431 | }, 432 | "node_modules/@jimp/utils": { 433 | "version": "1.6.0", 434 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz", 435 | "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==", 436 | "license": "MIT", 437 | "dependencies": { 438 | "@jimp/types": "1.6.0", 439 | "tinycolor2": "^1.6.0" 440 | }, 441 | "engines": { 442 | "node": ">=18" 443 | } 444 | }, 445 | "node_modules/@tokenizer/token": { 446 | "version": "0.3.0", 447 | "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", 448 | "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", 449 | "license": "MIT" 450 | }, 451 | "node_modules/@types/node": { 452 | "version": "16.9.1", 453 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", 454 | "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", 455 | "license": "MIT" 456 | }, 457 | "node_modules/ajv": { 458 | "version": "6.12.6", 459 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 460 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 461 | "dependencies": { 462 | "fast-deep-equal": "^3.1.1", 463 | "fast-json-stable-stringify": "^2.0.0", 464 | "json-schema-traverse": "^0.4.1", 465 | "uri-js": "^4.2.2" 466 | }, 467 | "funding": { 468 | "type": "github", 469 | "url": "https://github.com/sponsors/epoberezkin" 470 | } 471 | }, 472 | "node_modules/any-base": { 473 | "version": "1.1.0", 474 | "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", 475 | "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", 476 | "license": "MIT" 477 | }, 478 | "node_modules/asn1": { 479 | "version": "0.2.4", 480 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 481 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 482 | "dependencies": { 483 | "safer-buffer": "~2.1.0" 484 | } 485 | }, 486 | "node_modules/assert-plus": { 487 | "version": "1.0.0", 488 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 489 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 490 | "engines": { 491 | "node": ">=0.8" 492 | } 493 | }, 494 | "node_modules/asynckit": { 495 | "version": "0.4.0", 496 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 497 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 498 | }, 499 | "node_modules/await-to-js": { 500 | "version": "3.0.0", 501 | "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", 502 | "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==", 503 | "license": "MIT", 504 | "engines": { 505 | "node": ">=6.0.0" 506 | } 507 | }, 508 | "node_modules/aws-sign2": { 509 | "version": "0.7.0", 510 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 511 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 512 | "engines": { 513 | "node": "*" 514 | } 515 | }, 516 | "node_modules/aws4": { 517 | "version": "1.11.0", 518 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", 519 | "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" 520 | }, 521 | "node_modules/bcrypt-pbkdf": { 522 | "version": "1.0.2", 523 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 524 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 525 | "dependencies": { 526 | "tweetnacl": "^0.14.3" 527 | } 528 | }, 529 | "node_modules/bmp-ts": { 530 | "version": "1.0.9", 531 | "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", 532 | "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==", 533 | "license": "MIT" 534 | }, 535 | "node_modules/caseless": { 536 | "version": "0.12.0", 537 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 538 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 539 | }, 540 | "node_modules/combined-stream": { 541 | "version": "1.0.8", 542 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 543 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 544 | "dependencies": { 545 | "delayed-stream": "~1.0.0" 546 | }, 547 | "engines": { 548 | "node": ">= 0.8" 549 | } 550 | }, 551 | "node_modules/core-util-is": { 552 | "version": "1.0.2", 553 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 554 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 555 | }, 556 | "node_modules/cwise-compiler": { 557 | "version": "1.1.3", 558 | "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", 559 | "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", 560 | "dependencies": { 561 | "uniq": "^1.0.0" 562 | } 563 | }, 564 | "node_modules/dashdash": { 565 | "version": "1.14.1", 566 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 567 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 568 | "dependencies": { 569 | "assert-plus": "^1.0.0" 570 | }, 571 | "engines": { 572 | "node": ">=0.10" 573 | } 574 | }, 575 | "node_modules/data-uri-to-buffer": { 576 | "version": "0.0.3", 577 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-0.0.3.tgz", 578 | "integrity": "sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo=" 579 | }, 580 | "node_modules/delayed-stream": { 581 | "version": "1.0.0", 582 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 583 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 584 | "engines": { 585 | "node": ">=0.4.0" 586 | } 587 | }, 588 | "node_modules/ecc-jsbn": { 589 | "version": "0.1.2", 590 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 591 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 592 | "dependencies": { 593 | "jsbn": "~0.1.0", 594 | "safer-buffer": "^2.1.0" 595 | } 596 | }, 597 | "node_modules/exif-parser": { 598 | "version": "0.1.12", 599 | "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", 600 | "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==" 601 | }, 602 | "node_modules/extend": { 603 | "version": "3.0.2", 604 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 605 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 606 | }, 607 | "node_modules/extsprintf": { 608 | "version": "1.3.0", 609 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 610 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 611 | "engines": [ 612 | "node >=0.6.0" 613 | ] 614 | }, 615 | "node_modules/fast-deep-equal": { 616 | "version": "3.1.3", 617 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 618 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 619 | }, 620 | "node_modules/fast-json-stable-stringify": { 621 | "version": "2.1.0", 622 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 623 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" 624 | }, 625 | "node_modules/ffmpeg": { 626 | "version": "0.0.4", 627 | "resolved": "https://registry.npmjs.org/ffmpeg/-/ffmpeg-0.0.4.tgz", 628 | "integrity": "sha1-HEYN+OfaUSf2LO70v6BsWciWMMs=", 629 | "dependencies": { 630 | "when": ">= 0.0.1" 631 | } 632 | }, 633 | "node_modules/file-type": { 634 | "version": "16.5.4", 635 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", 636 | "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", 637 | "license": "MIT", 638 | "dependencies": { 639 | "readable-web-to-node-stream": "^3.0.0", 640 | "strtok3": "^6.2.4", 641 | "token-types": "^4.1.1" 642 | }, 643 | "engines": { 644 | "node": ">=10" 645 | }, 646 | "funding": { 647 | "url": "https://github.com/sindresorhus/file-type?sponsor=1" 648 | } 649 | }, 650 | "node_modules/forever-agent": { 651 | "version": "0.6.1", 652 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 653 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 654 | "engines": { 655 | "node": "*" 656 | } 657 | }, 658 | "node_modules/form-data": { 659 | "version": "2.3.3", 660 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 661 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 662 | "dependencies": { 663 | "asynckit": "^0.4.0", 664 | "combined-stream": "^1.0.6", 665 | "mime-types": "^2.1.12" 666 | }, 667 | "engines": { 668 | "node": ">= 0.12" 669 | } 670 | }, 671 | "node_modules/get-pixels": { 672 | "version": "3.3.2", 673 | "resolved": "https://registry.npmjs.org/get-pixels/-/get-pixels-3.3.2.tgz", 674 | "integrity": "sha512-6ar+8yPxRd1pskEcl2GSEu1La0+xYRjjnkby6AYiRDDwZ0tJbPQmHnSeH9fGLskT8kvR0OukVgtZLcsENF9YKQ==", 675 | "dependencies": { 676 | "data-uri-to-buffer": "0.0.3", 677 | "jpeg-js": "^0.3.2", 678 | "mime-types": "^2.0.1", 679 | "ndarray": "^1.0.13", 680 | "ndarray-pack": "^1.1.1", 681 | "node-bitmap": "0.0.1", 682 | "omggif": "^1.0.5", 683 | "parse-data-uri": "^0.2.0", 684 | "pngjs": "^3.3.3", 685 | "request": "^2.44.0", 686 | "through": "^2.3.4" 687 | } 688 | }, 689 | "node_modules/getpass": { 690 | "version": "0.1.7", 691 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 692 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 693 | "dependencies": { 694 | "assert-plus": "^1.0.0" 695 | } 696 | }, 697 | "node_modules/gifwrap": { 698 | "version": "0.10.1", 699 | "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", 700 | "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", 701 | "license": "MIT", 702 | "dependencies": { 703 | "image-q": "^4.0.0", 704 | "omggif": "^1.0.10" 705 | } 706 | }, 707 | "node_modules/har-schema": { 708 | "version": "2.0.0", 709 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 710 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 711 | "engines": { 712 | "node": ">=4" 713 | } 714 | }, 715 | "node_modules/har-validator": { 716 | "version": "5.1.5", 717 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 718 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 719 | "deprecated": "this library is no longer supported", 720 | "dependencies": { 721 | "ajv": "^6.12.3", 722 | "har-schema": "^2.0.0" 723 | }, 724 | "engines": { 725 | "node": ">=6" 726 | } 727 | }, 728 | "node_modules/http-signature": { 729 | "version": "1.2.0", 730 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 731 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 732 | "dependencies": { 733 | "assert-plus": "^1.0.0", 734 | "jsprim": "^1.2.2", 735 | "sshpk": "^1.7.0" 736 | }, 737 | "engines": { 738 | "node": ">=0.8", 739 | "npm": ">=1.3.7" 740 | } 741 | }, 742 | "node_modules/ieee754": { 743 | "version": "1.2.1", 744 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 745 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 746 | "funding": [ 747 | { 748 | "type": "github", 749 | "url": "https://github.com/sponsors/feross" 750 | }, 751 | { 752 | "type": "patreon", 753 | "url": "https://www.patreon.com/feross" 754 | }, 755 | { 756 | "type": "consulting", 757 | "url": "https://feross.org/support" 758 | } 759 | ], 760 | "license": "BSD-3-Clause" 761 | }, 762 | "node_modules/image-q": { 763 | "version": "4.0.0", 764 | "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", 765 | "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", 766 | "license": "MIT", 767 | "dependencies": { 768 | "@types/node": "16.9.1" 769 | } 770 | }, 771 | "node_modules/inherits": { 772 | "version": "2.0.4", 773 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 774 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 775 | "license": "ISC" 776 | }, 777 | "node_modules/iota-array": { 778 | "version": "1.0.0", 779 | "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", 780 | "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" 781 | }, 782 | "node_modules/is-buffer": { 783 | "version": "1.1.6", 784 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 785 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 786 | }, 787 | "node_modules/is-typedarray": { 788 | "version": "1.0.0", 789 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 790 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 791 | }, 792 | "node_modules/isstream": { 793 | "version": "0.1.2", 794 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 795 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 796 | }, 797 | "node_modules/jimp": { 798 | "version": "1.6.0", 799 | "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.0.tgz", 800 | "integrity": "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==", 801 | "license": "MIT", 802 | "dependencies": { 803 | "@jimp/core": "1.6.0", 804 | "@jimp/diff": "1.6.0", 805 | "@jimp/js-bmp": "1.6.0", 806 | "@jimp/js-gif": "1.6.0", 807 | "@jimp/js-jpeg": "1.6.0", 808 | "@jimp/js-png": "1.6.0", 809 | "@jimp/js-tiff": "1.6.0", 810 | "@jimp/plugin-blit": "1.6.0", 811 | "@jimp/plugin-blur": "1.6.0", 812 | "@jimp/plugin-circle": "1.6.0", 813 | "@jimp/plugin-color": "1.6.0", 814 | "@jimp/plugin-contain": "1.6.0", 815 | "@jimp/plugin-cover": "1.6.0", 816 | "@jimp/plugin-crop": "1.6.0", 817 | "@jimp/plugin-displace": "1.6.0", 818 | "@jimp/plugin-dither": "1.6.0", 819 | "@jimp/plugin-fisheye": "1.6.0", 820 | "@jimp/plugin-flip": "1.6.0", 821 | "@jimp/plugin-hash": "1.6.0", 822 | "@jimp/plugin-mask": "1.6.0", 823 | "@jimp/plugin-print": "1.6.0", 824 | "@jimp/plugin-quantize": "1.6.0", 825 | "@jimp/plugin-resize": "1.6.0", 826 | "@jimp/plugin-rotate": "1.6.0", 827 | "@jimp/plugin-threshold": "1.6.0", 828 | "@jimp/types": "1.6.0", 829 | "@jimp/utils": "1.6.0" 830 | }, 831 | "engines": { 832 | "node": ">=18" 833 | } 834 | }, 835 | "node_modules/jpeg-js": { 836 | "version": "0.3.7", 837 | "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", 838 | "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" 839 | }, 840 | "node_modules/jsbn": { 841 | "version": "0.1.1", 842 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 843 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 844 | }, 845 | "node_modules/json-schema": { 846 | "version": "0.2.3", 847 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 848 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 849 | }, 850 | "node_modules/json-schema-traverse": { 851 | "version": "0.4.1", 852 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 853 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 854 | }, 855 | "node_modules/json-stringify-safe": { 856 | "version": "5.0.1", 857 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 858 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 859 | }, 860 | "node_modules/jsprim": { 861 | "version": "1.4.1", 862 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 863 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 864 | "engines": [ 865 | "node >=0.6.0" 866 | ], 867 | "dependencies": { 868 | "assert-plus": "1.0.0", 869 | "extsprintf": "1.3.0", 870 | "json-schema": "0.2.3", 871 | "verror": "1.10.0" 872 | } 873 | }, 874 | "node_modules/mime": { 875 | "version": "3.0.0", 876 | "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", 877 | "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", 878 | "license": "MIT", 879 | "bin": { 880 | "mime": "cli.js" 881 | }, 882 | "engines": { 883 | "node": ">=10.0.0" 884 | } 885 | }, 886 | "node_modules/mime-db": { 887 | "version": "1.45.0", 888 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", 889 | "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", 890 | "engines": { 891 | "node": ">= 0.6" 892 | } 893 | }, 894 | "node_modules/mime-types": { 895 | "version": "2.1.28", 896 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", 897 | "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", 898 | "dependencies": { 899 | "mime-db": "1.45.0" 900 | }, 901 | "engines": { 902 | "node": ">= 0.6" 903 | } 904 | }, 905 | "node_modules/ndarray": { 906 | "version": "1.0.19", 907 | "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.19.tgz", 908 | "integrity": "sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==", 909 | "dependencies": { 910 | "iota-array": "^1.0.0", 911 | "is-buffer": "^1.0.2" 912 | } 913 | }, 914 | "node_modules/ndarray-pack": { 915 | "version": "1.2.1", 916 | "resolved": "https://registry.npmjs.org/ndarray-pack/-/ndarray-pack-1.2.1.tgz", 917 | "integrity": "sha1-jK6+qqJNXs9w/4YCBjeXfajuWFo=", 918 | "dependencies": { 919 | "cwise-compiler": "^1.1.2", 920 | "ndarray": "^1.0.13" 921 | } 922 | }, 923 | "node_modules/node-bitmap": { 924 | "version": "0.0.1", 925 | "resolved": "https://registry.npmjs.org/node-bitmap/-/node-bitmap-0.0.1.tgz", 926 | "integrity": "sha1-GA6scAPgxwdhjvMTaPYvhLKmkJE=", 927 | "engines": { 928 | "node": ">=v0.6.5" 929 | } 930 | }, 931 | "node_modules/node-gameloop": { 932 | "version": "0.1.4", 933 | "resolved": "https://registry.npmjs.org/node-gameloop/-/node-gameloop-0.1.4.tgz", 934 | "integrity": "sha1-nol9hzs7TaWcCwe7kZBZlhwb4og=" 935 | }, 936 | "node_modules/oauth-sign": { 937 | "version": "0.9.0", 938 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 939 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 940 | "engines": { 941 | "node": "*" 942 | } 943 | }, 944 | "node_modules/omggif": { 945 | "version": "1.0.10", 946 | "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", 947 | "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" 948 | }, 949 | "node_modules/pako": { 950 | "version": "1.0.11", 951 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", 952 | "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", 953 | "license": "(MIT AND Zlib)" 954 | }, 955 | "node_modules/parse-bmfont-ascii": { 956 | "version": "1.0.6", 957 | "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", 958 | "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==", 959 | "license": "MIT" 960 | }, 961 | "node_modules/parse-bmfont-binary": { 962 | "version": "1.0.6", 963 | "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", 964 | "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==", 965 | "license": "MIT" 966 | }, 967 | "node_modules/parse-bmfont-xml": { 968 | "version": "1.1.6", 969 | "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz", 970 | "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==", 971 | "license": "MIT", 972 | "dependencies": { 973 | "xml-parse-from-string": "^1.0.0", 974 | "xml2js": "^0.5.0" 975 | } 976 | }, 977 | "node_modules/parse-data-uri": { 978 | "version": "0.2.0", 979 | "resolved": "https://registry.npmjs.org/parse-data-uri/-/parse-data-uri-0.2.0.tgz", 980 | "integrity": "sha1-vwTYUd1ch7CrI45dAazklLYEtMk=", 981 | "dependencies": { 982 | "data-uri-to-buffer": "0.0.3" 983 | } 984 | }, 985 | "node_modules/peek-readable": { 986 | "version": "4.1.0", 987 | "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", 988 | "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", 989 | "license": "MIT", 990 | "engines": { 991 | "node": ">=8" 992 | }, 993 | "funding": { 994 | "type": "github", 995 | "url": "https://github.com/sponsors/Borewit" 996 | } 997 | }, 998 | "node_modules/performance-now": { 999 | "version": "2.1.0", 1000 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1001 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 1002 | }, 1003 | "node_modules/pixelmatch": { 1004 | "version": "5.3.0", 1005 | "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz", 1006 | "integrity": "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==", 1007 | "license": "ISC", 1008 | "dependencies": { 1009 | "pngjs": "^6.0.0" 1010 | }, 1011 | "bin": { 1012 | "pixelmatch": "bin/pixelmatch" 1013 | } 1014 | }, 1015 | "node_modules/pixelmatch/node_modules/pngjs": { 1016 | "version": "6.0.0", 1017 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", 1018 | "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", 1019 | "license": "MIT", 1020 | "engines": { 1021 | "node": ">=12.13.0" 1022 | } 1023 | }, 1024 | "node_modules/pngjs": { 1025 | "version": "3.4.0", 1026 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", 1027 | "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", 1028 | "engines": { 1029 | "node": ">=4.0.0" 1030 | } 1031 | }, 1032 | "node_modules/psl": { 1033 | "version": "1.8.0", 1034 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", 1035 | "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" 1036 | }, 1037 | "node_modules/punycode": { 1038 | "version": "2.1.1", 1039 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1040 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1041 | "engines": { 1042 | "node": ">=6" 1043 | } 1044 | }, 1045 | "node_modules/qs": { 1046 | "version": "6.5.2", 1047 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1048 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", 1049 | "engines": { 1050 | "node": ">=0.6" 1051 | } 1052 | }, 1053 | "node_modules/readable-stream": { 1054 | "version": "3.6.2", 1055 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 1056 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 1057 | "license": "MIT", 1058 | "dependencies": { 1059 | "inherits": "^2.0.3", 1060 | "string_decoder": "^1.1.1", 1061 | "util-deprecate": "^1.0.1" 1062 | }, 1063 | "engines": { 1064 | "node": ">= 6" 1065 | } 1066 | }, 1067 | "node_modules/readable-web-to-node-stream": { 1068 | "version": "3.0.2", 1069 | "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", 1070 | "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", 1071 | "license": "MIT", 1072 | "dependencies": { 1073 | "readable-stream": "^3.6.0" 1074 | }, 1075 | "engines": { 1076 | "node": ">=8" 1077 | }, 1078 | "funding": { 1079 | "type": "github", 1080 | "url": "https://github.com/sponsors/Borewit" 1081 | } 1082 | }, 1083 | "node_modules/request": { 1084 | "version": "2.88.2", 1085 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 1086 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 1087 | "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", 1088 | "dependencies": { 1089 | "aws-sign2": "~0.7.0", 1090 | "aws4": "^1.8.0", 1091 | "caseless": "~0.12.0", 1092 | "combined-stream": "~1.0.6", 1093 | "extend": "~3.0.2", 1094 | "forever-agent": "~0.6.1", 1095 | "form-data": "~2.3.2", 1096 | "har-validator": "~5.1.3", 1097 | "http-signature": "~1.2.0", 1098 | "is-typedarray": "~1.0.0", 1099 | "isstream": "~0.1.2", 1100 | "json-stringify-safe": "~5.0.1", 1101 | "mime-types": "~2.1.19", 1102 | "oauth-sign": "~0.9.0", 1103 | "performance-now": "^2.1.0", 1104 | "qs": "~6.5.2", 1105 | "safe-buffer": "^5.1.2", 1106 | "tough-cookie": "~2.5.0", 1107 | "tunnel-agent": "^0.6.0", 1108 | "uuid": "^3.3.2" 1109 | }, 1110 | "engines": { 1111 | "node": ">= 6" 1112 | } 1113 | }, 1114 | "node_modules/safe-buffer": { 1115 | "version": "5.2.1", 1116 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1117 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1118 | "funding": [ 1119 | { 1120 | "type": "github", 1121 | "url": "https://github.com/sponsors/feross" 1122 | }, 1123 | { 1124 | "type": "patreon", 1125 | "url": "https://www.patreon.com/feross" 1126 | }, 1127 | { 1128 | "type": "consulting", 1129 | "url": "https://feross.org/support" 1130 | } 1131 | ] 1132 | }, 1133 | "node_modules/safer-buffer": { 1134 | "version": "2.1.2", 1135 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1136 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1137 | }, 1138 | "node_modules/sax": { 1139 | "version": "1.4.1", 1140 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", 1141 | "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", 1142 | "license": "ISC" 1143 | }, 1144 | "node_modules/simple-xml-to-json": { 1145 | "version": "1.2.3", 1146 | "resolved": "https://registry.npmjs.org/simple-xml-to-json/-/simple-xml-to-json-1.2.3.tgz", 1147 | "integrity": "sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA==", 1148 | "license": "MIT", 1149 | "engines": { 1150 | "node": ">=20.12.2" 1151 | } 1152 | }, 1153 | "node_modules/sshpk": { 1154 | "version": "1.16.1", 1155 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 1156 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 1157 | "dependencies": { 1158 | "asn1": "~0.2.3", 1159 | "assert-plus": "^1.0.0", 1160 | "bcrypt-pbkdf": "^1.0.0", 1161 | "dashdash": "^1.12.0", 1162 | "ecc-jsbn": "~0.1.1", 1163 | "getpass": "^0.1.1", 1164 | "jsbn": "~0.1.0", 1165 | "safer-buffer": "^2.0.2", 1166 | "tweetnacl": "~0.14.0" 1167 | }, 1168 | "bin": { 1169 | "sshpk-conv": "bin/sshpk-conv", 1170 | "sshpk-sign": "bin/sshpk-sign", 1171 | "sshpk-verify": "bin/sshpk-verify" 1172 | }, 1173 | "engines": { 1174 | "node": ">=0.10.0" 1175 | } 1176 | }, 1177 | "node_modules/string_decoder": { 1178 | "version": "1.3.0", 1179 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1180 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1181 | "license": "MIT", 1182 | "dependencies": { 1183 | "safe-buffer": "~5.2.0" 1184 | } 1185 | }, 1186 | "node_modules/strtok3": { 1187 | "version": "6.3.0", 1188 | "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", 1189 | "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", 1190 | "license": "MIT", 1191 | "dependencies": { 1192 | "@tokenizer/token": "^0.3.0", 1193 | "peek-readable": "^4.1.0" 1194 | }, 1195 | "engines": { 1196 | "node": ">=10" 1197 | }, 1198 | "funding": { 1199 | "type": "github", 1200 | "url": "https://github.com/sponsors/Borewit" 1201 | } 1202 | }, 1203 | "node_modules/through": { 1204 | "version": "2.3.8", 1205 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1206 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 1207 | }, 1208 | "node_modules/tinycolor2": { 1209 | "version": "1.6.0", 1210 | "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", 1211 | "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", 1212 | "license": "MIT" 1213 | }, 1214 | "node_modules/token-types": { 1215 | "version": "4.2.1", 1216 | "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", 1217 | "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", 1218 | "license": "MIT", 1219 | "dependencies": { 1220 | "@tokenizer/token": "^0.3.0", 1221 | "ieee754": "^1.2.1" 1222 | }, 1223 | "engines": { 1224 | "node": ">=10" 1225 | }, 1226 | "funding": { 1227 | "type": "github", 1228 | "url": "https://github.com/sponsors/Borewit" 1229 | } 1230 | }, 1231 | "node_modules/tough-cookie": { 1232 | "version": "2.5.0", 1233 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 1234 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 1235 | "dependencies": { 1236 | "psl": "^1.1.28", 1237 | "punycode": "^2.1.1" 1238 | }, 1239 | "engines": { 1240 | "node": ">=0.8" 1241 | } 1242 | }, 1243 | "node_modules/tunnel-agent": { 1244 | "version": "0.6.0", 1245 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1246 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1247 | "dependencies": { 1248 | "safe-buffer": "^5.0.1" 1249 | }, 1250 | "engines": { 1251 | "node": "*" 1252 | } 1253 | }, 1254 | "node_modules/tweetnacl": { 1255 | "version": "0.14.5", 1256 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1257 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 1258 | }, 1259 | "node_modules/uniq": { 1260 | "version": "1.0.1", 1261 | "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", 1262 | "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" 1263 | }, 1264 | "node_modules/uri-js": { 1265 | "version": "4.4.1", 1266 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1267 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1268 | "dependencies": { 1269 | "punycode": "^2.1.0" 1270 | } 1271 | }, 1272 | "node_modules/utif2": { 1273 | "version": "4.1.0", 1274 | "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", 1275 | "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", 1276 | "license": "MIT", 1277 | "dependencies": { 1278 | "pako": "^1.0.11" 1279 | } 1280 | }, 1281 | "node_modules/util-deprecate": { 1282 | "version": "1.0.2", 1283 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1284 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 1285 | "license": "MIT" 1286 | }, 1287 | "node_modules/uuid": { 1288 | "version": "3.4.0", 1289 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 1290 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 1291 | "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", 1292 | "bin": { 1293 | "uuid": "bin/uuid" 1294 | } 1295 | }, 1296 | "node_modules/verror": { 1297 | "version": "1.10.0", 1298 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1299 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1300 | "engines": [ 1301 | "node >=0.6.0" 1302 | ], 1303 | "dependencies": { 1304 | "assert-plus": "^1.0.0", 1305 | "core-util-is": "1.0.2", 1306 | "extsprintf": "^1.2.0" 1307 | } 1308 | }, 1309 | "node_modules/when": { 1310 | "version": "3.7.8", 1311 | "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", 1312 | "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=" 1313 | }, 1314 | "node_modules/xml-parse-from-string": { 1315 | "version": "1.0.1", 1316 | "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", 1317 | "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==", 1318 | "license": "MIT" 1319 | }, 1320 | "node_modules/xml2js": { 1321 | "version": "0.5.0", 1322 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", 1323 | "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", 1324 | "license": "MIT", 1325 | "dependencies": { 1326 | "sax": ">=0.6.0", 1327 | "xmlbuilder": "~11.0.0" 1328 | }, 1329 | "engines": { 1330 | "node": ">=4.0.0" 1331 | } 1332 | }, 1333 | "node_modules/xmlbuilder": { 1334 | "version": "11.0.1", 1335 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 1336 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", 1337 | "license": "MIT", 1338 | "engines": { 1339 | "node": ">=4.0" 1340 | } 1341 | }, 1342 | "node_modules/zod": { 1343 | "version": "3.23.8", 1344 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", 1345 | "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", 1346 | "license": "MIT", 1347 | "funding": { 1348 | "url": "https://github.com/sponsors/colinhacks" 1349 | } 1350 | } 1351 | } 1352 | } 1353 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bad-apple-terminal", 3 | "version": "1.0.0", 4 | "description": "A nodejs script for playing BadApple in the terminal", 5 | "main": "index.js", 6 | "scripts": { 7 | "extract": "node extractFrames", 8 | "build": "node build", 9 | "prepare": "node extractFrames", 10 | "postprepare": "node build", 11 | "start": "node index" 12 | }, 13 | "author": "KineticTactic", 14 | "license": "MIT", 15 | "dependencies": { 16 | "ffmpeg": "0.0.4", 17 | "get-pixels": "^3.3.2", 18 | "jimp": "^1.6.0", 19 | "node-gameloop": "^0.1.4" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /res/BadApple.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KineticTactic/Bad-Apple-Terminal/8c037c1c2fca105820e1c353d96a997aba7991d9/res/BadApple.mp4 -------------------------------------------------------------------------------- /utilities.js: -------------------------------------------------------------------------------- 1 | const grayRamp = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,\"^`'. "; 2 | 3 | module.exports.getCharacterForGrayScale = (grayScale) => 4 | grayRamp[Math.ceil(((grayRamp.length - 1) * grayScale) / 255)]; 5 | 6 | module.exports.toFourDigits = (string) => { 7 | while (string.length <= 3) { 8 | string = "0" + string; 9 | } 10 | return string; 11 | }; 12 | --------------------------------------------------------------------------------