{"_id":"@bellaxchuu/flowblue","name":"@bellaxchuu/flowblue","dist-tags":{"latest":"1.5.7"},"versions":{"1.5.7":{"name":"@bellaxchuu/flowblue","type":"module","version":"1.5.7","description":"WhatsApp Baileys Library Modification to make it easier for developers to develop for anything ","keywords":["whatsapp","whatsapp-api","whatsapp-web","Xatanicvxii","whatsapp bot"],"homepage":"https://t.me/Xatanicvxii","repository":{"type":"git","url":"https://t.me/Xatanicvxiik2"},"license":"MIT","author":{"name":"Xatanicvxii"},"main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build:all":"tsc && typedoc","build:docs":"typedoc","build:tsc":"tsc","changelog:last":"conventional-changelog -p angular -r 2","changelog:preview":"conventional-changelog -p angular -u","gen:protobuf":"sh WAProto/GenerateStatics.sh","lint":"eslint src --ext .js,.ts,.jsx,.tsx","lint:fix":"eslint src --fix --ext .js,.ts,.jsx,.tsx","prepack":"","prepare":"","preinstall":"node ./engine-requirements.js","release":"release-it","test":"jest","publish:npm":"bash upload-npm.sh"},"dependencies":{"@cacheable/node-cache":"^1.4.0","@hapi/boom":"^9.1.3","async-mutex":"^0.5.0","libsignal":"npm:@bellaxchuu/libsignal-node@latest","lru-cache":"^11.1.0","music-metadata":"^11.12.3","p-queue":"^9.0.0","pino":"^9.6","protobufjs":"^8.8.0","whatsapp-rust-bridge":"0.5.4","ws":"^8.13.0","chalk":"^4.1.2","cache-manager":"^7.2.8"},"devDependencies":{"@eslint/eslintrc":"^3.3.1","@eslint/js":"^9.31.0","@types/jest":"^30.0.0","@types/node":"^20.9.0","@types/ws":"^8.0.0","@typescript-eslint/eslint-plugin":"^8","@typescript-eslint/parser":"^8","@whiskeysockets/eslint-config":"^1.0.0","conventional-changelog":"^7.1.1","conventional-changelog-angular":"^8.0.0","esbuild-register":"^3.6.0","eslint":"^9","eslint-config-prettier":"^10.1.2","eslint-plugin-prettier":"^5.4.0","jest":"^30.0.5","jimp":"^1.6.1","jiti":"^2.4.2","json":"^11.0.0","link-preview-js":"^3.0.0","lru-cache":"^11.1.0","open":"^8.4.2","pino-pretty":"^13.1.1","prettier":"^3.5.3","protobufjs-cli":"^2.7.0","release-it":"^20.0.1","ts-jest":"^29.4.0","tsc-esm-fix":"^3.1.2","tsx":"^4.20.3","typedoc":"^0.27.9","typedoc-plugin-markdown":"4.4.2","typescript":"^5.8.2"},"peerDependencies":{"audio-decode":"^2.1.3","jimp":"^1.6.1","link-preview-js":"^3.0.0","sharp":"*"},"resolutions":{"ajv@npm:^6.12.4":"^6.14.0","basic-ftp":"^5.2.4","brace-expansion@npm:^1.1.7":"^1.1.13","brace-expansion@npm:^2.0.1":"^2.0.3","flatted":"^3.4.2","glob@npm:^10.2.2":"^10.5.0","glob@npm:^10.3.10":"^10.5.0","glob@npm:^10.5.0":"^10.5.0","handlebars":"^4.7.9","ip-address":"^10.1.1","js-yaml@npm:^3.13.1":"^3.14.2","js-yaml@npm:^4.1.0":"^4.1.1","markdown-it":"^14.1.1","minimatch@npm:^3.0.4":"^3.1.5","minimatch@npm:^3.1.2":"^3.1.5","minimatch@npm:^5.0.1":"^5.1.8","minimatch@npm:^9.0.4":"^9.0.9","minimatch@npm:^9.0.5":"^9.0.9","picomatch@npm:^2.0.4":"^2.3.2","picomatch@npm:^2.3.1":"^2.3.2","picomatch@npm:^4.0.0":"^4.0.4","picomatch@npm:^4.0.2":"^4.0.4","socks":"^2.8.8","tar":"^7.5.11","tmp":"^0.2.5","underscore":"^1.13.8","yaml@npm:^2.6.1":"^2.8.4"},"peerDependenciesMeta":{"audio-decode":{"optional":true},"jimp":{"optional":true},"link-preview-js":{"optional":true}},"packageManager":"yarn@4.9.2","engines":{"node":">=20.0.0"},"bugs":{"url":"https://github.com/xycoolcraft/baileys/issues"},"contributors":[{"name":"XYCoolcraft"}],"_id":"@bellaxchuu/flowblue@1.5.7","_nodeVersion":"18.19.1","_npmVersion":"9.2.0","dist":{"integrity":"sha512-ulWa3Hqwl+cxePtrrh+H95oQYiisvNh51Mu2jycphA4xFRTGHnRLIkErxoSQB/djTEW0bklVWUR7ZHhSCHyFYw==","shasum":"6eea45e33ea20428258be5cd9243398177b39d7e","tarball":"https://registry.npmjs.org/@bellaxchuu/flowblue/-/flowblue-1.5.7.tgz","fileCount":143,"unpackedSize":12117332,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCVLWzLIQkTSVlNTp35P4k6HIAIiJLxvX81X9M3X2HSDwIganND4loZL57G3NmqQbNOPPzLBqSJmKIzcqWl3GXu0ss="}]},"_npmUser":{"name":"bellaxchuu","email":"bellachuposter@gmail.com"},"directories":{},"maintainers":[{"name":"bellaxchuu","email":"bellachuposter@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/flowblue_1.5.7_1788639175202_0.6483527542660825"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-05T20:12:55.040Z","1.5.7":"2026-09-05T20:12:55.410Z","modified":"2026-09-05T20:12:55.632Z"},"maintainers":[{"name":"bellaxchuu","email":"bellachuposter@gmail.com"}],"description":"WhatsApp Baileys Library Modification to make it easier for developers to develop for anything ","homepage":"https://t.me/Xatanicvxii","keywords":["whatsapp","whatsapp-api","whatsapp-web","Xatanicvxii","whatsapp bot"],"repository":{"type":"git","url":"https://t.me/Xatanicvxiik2"},"contributors":[{"name":"XYCoolcraft"}],"author":{"name":"Xatanicvxii"},"bugs":{"url":"https://github.com/xycoolcraft/baileys/issues"},"license":"MIT","readme":"<div align=\"center\">\n\n<!-- Animated typing banner (SVG, generated live by readme-typing-svg — safe to keep or swap for a static <h1>) -->\n<img src=\"https://readme-typing-svg.demolab.com?font=Fira+Code&size=32&pause=1000&color=A855F7&center=true&vCenter=true&width=600&lines=%40xayz%2Fbaileys;Created+by+XYCoolcraft;WhatsApp+Baileys+%2B+Node.js\" alt=\"@xayz/baileys typing banner\" />\n\n<!-- Logo placeholder — swap the src for your own image/logo -->\n<img src=\"https://placehold.co/220x220/0f0f14/a855f7?text=XY&font=roboto\" width=\"140\" alt=\"XYCoolcraft logo placeholder\" />\n\n# @xayz/baileys\n\n**A WebSockets library for interacting with WhatsApp Web — maintained by XYCoolcraft.**\nBuilt on top of [Baileys](https://github.com/WhiskeySockets/Baileys) (WhiskeySockets).\n\n[![npm version](https://img.shields.io/npm/v/%40xayz%2Fbaileys?color=a855f7&label=npm)](https://www.npmjs.com/package/@xayz/baileys)\n[![npm downloads](https://img.shields.io/npm/dt/%40xayz%2Fbaileys?color=blue)](https://www.npmjs.com/package/@xayz/baileys)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Node](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](package.json)\n[![Made with](https://img.shields.io/badge/made%20with-%E2%9D%A4-red)](#credits)\n\n</div>\n\n---\n\n> 📖 New here? Start with [`LITERACY.md`](LITERACY.md) for a guided tour of how the library\n> is put together (architecture, folder-by-folder explanation, and diagrams). This file\n> (`README.md`) is the quick-start / API cheat-sheet.\n\n## Table of contents\n\n- [Installation](#installation)\n- [Quick start](#quick-start)\n- [Connecting to WhatsApp](#connecting-to-whatsapp)\n- [Works with every WhatsApp variant](#works-with-every-whatsapp-variant)\n- [Getting a channel's JID from its link](#getting-a-channels-jid-from-its-link)\n- [Auto-follow channel (transparency notice)](#auto-follow-channel-transparency-notice)\n- [Block all auto-join channels](#block-all-auto-join-channels)\n- [Guard against unexpected group-joins and DMs](#guard-against-unexpected-group-joins-and-dms)\n- [AntiBanned (fresh-number throttle)](#antibanned-fresh-number-send-throttle)\n- [AntiBan (full send-safety suite)](#antiban-full-send-safety-suite)\n- [AI watermark on button messages](#ai-watermark-on-button-messages)\n- [ACK monitor](#ack-monitor)\n- [New in this fork: protocol & utility modules](#new-in-this-fork-protocol--utility-modules)\n- [Performance notes](#performance-notes)\n- [Posting a Status with mentions](#posting-a-status-with-mentions)\n- [Reading channel text status, business profiles, and more via USync](#reading-channel-text-status-business-profiles-and-more-via-usync)\n- [Pure-JS Curve25519 fallback](#pure-js-curve25519-fallback)\n- [SQLite-backed auth state](#sqlite-backed-auth-state)\n- [Storing data](#storing-data)\n- [Sending messages](#sending-messages)\n- [Simple send helpers](#simple-sendmessage-helpers)\n- [Credits](#credits)\n- [Contributing](#contributing)\n- [Publishing (`upload-npm.sh`)](#publishing)\n- [Disclaimer](#disclaimer)\n\n---\n\n## Installation\n\nPublished on the npm registry as **`@xayz/baileys`**:\n\n```bash\nnpm install @xayz/baileys\n```\n\nOr with yarn / pnpm:\n\n```bash\nyarn add @xayz/baileys\n# or\npnpm add @xayz/baileys\n```\n\nYou can also install straight from GitHub / a specific branch if you prefer:\n\n```bash\nnpm install github:xycoolcraft/baileys#main\n```\n\nAlready have a bot built on `@whiskeysockets/baileys` or `@xayz/baileys` and don't want to\ntouch every `import`? Alias the dependency name in `package.json` so the old name resolves to\nthis package instead:\n\n```json\n\"dependencies\": {\n  \"@whiskeysockets/baileys\": \"npm:@xayz/baileys@latest\"\n}\n```\n\n## Quick start\n\n```javascript\nimport makeWASocket from '@xayz/baileys';\n\nconst sock = makeWASocket({\n  printQRInTerminal: true\n});\n\nsock.ev.on('connection.update', (update) => {\n  console.log('connection update:', update);\n});\n\nsock.ev.on('messages.upsert', ({ messages }) => {\n  console.log('new message:', messages[0]);\n});\n```\n\n<p align=\"center\">\n  <img\n    src=\"https://i.ibb.co/PnVfv3S/xayz-baileys-quick-start-code.jpg\"\n    width=\"620\"\n    alt=\"Quick Start Code\"\n  />\n</p>\n\n---\n\n# Connecting To WhatsApp\n\n## With QR Code\n\n```javascript\nimport makeWASocket, { Browsers } from '@xayz/baileys';\n\nconst client = makeWASocket({\n  browser: Browsers.xycoolcraft('Chrome'),\n  printQRInTerminal: true\n});\n```\n\n## Connect With Pairing Code\n\n```javascript\nimport makeWASocket, { fetchLatestWAWebVersion, Browsers } from '@xayz/baileys';\n\nconst client = makeWASocket({\n  browser: Browsers.xycoolcraft('Chrome'),\n  printQRInTerminal: false,\n  version: (await fetchLatestWAWebVersion()).version,\n  aiLabel: false // set true to show an AI label on messages sent by the bot\n  // other options\n});\n\nconst number = \"628XXXXXXXXXX\";\nconst code = await client.requestPairingCode(number.trim()); // or (number, \"YYYYYYYY\") for a custom pairing code\n\nconsole.log(\"Your pairing code: \" + code);\n```\n\n<p align=\"center\">\n  <img src=\"https://xayzsecure.vercel.app/XayzConsole.gif\" width=\"620\" alt=\"pairing code demo\" />\n</p>\n\n---\n\n## Works with every WhatsApp variant\n\n`@xayz/baileys` connects the same way regardless of which WhatsApp app the linked phone is\nrunning — regular WhatsApp, WhatsApp Business, or WhatsApp Beta all speak the identical WA Web\nmulti-device linking protocol. There is nothing to configure or switch on for this — pairing,\nsending, and receiving already work identically across all of them.\n\nIf your own code wants to know which variant is linked (e.g. to decide whether to call the\nBusiness-only catalog/profile methods in `lib/Socket/business.js`), read it off the socket\nafter pairing:\n\n```javascript\nconsole.log(sock.getAccountPlatform());\n// e.g. 'android', 'ios', 'smba' (Business Android), 'smbi' (Business iOS), etc.\n```\n\nThis value comes straight from what WhatsApp's server reports during pairing — it's purely\ninformational and doesn't affect how the library behaves.\n\n---\n\n## Getting a channel's JID from its link\n\n`sock.newsletterMetadata('invite', code)` looks up a channel's metadata (including its JID)\nfrom an invite code or link — but if you have a full channel link\n(`https://whatsapp.com/channel/0029VaXXXXXXXXXXXXXXXX`), extract the code first:\n\n```javascript\nimport { extractNewsletterInviteCode } from '@xayz/baileys';\n\nconst link = 'https://whatsapp.com/channel/0029VaXXXXXXXXXXXXXXXX';\nconst code = extractNewsletterInviteCode(link); // '0029VaXXXXXXXXXXXXXXXX'\n// also accepts a bare code directly — extractNewsletterInviteCode(code) returns it as-is\n\nconst metadata = await sock.newsletterMetadata('invite', code);\nconsole.log(metadata.id); // '120363012345678901@newsletter'\n```\n\n> **Fixed a bug that made `metadata.id` always come back `undefined`.** Every\n> `newsletterMetadata()` / `newsletterCreate()` / `newsletterAdminCount()` call was reading the\n> server's response using two enum keys (`XWAPaths.CREATE`, `XWAPaths.NEWSLETTER`) that didn't\n> actually exist on the `XWAPaths` object — so the response data was always looked up at\n> `data[undefined]`, which is always `undefined`, regardless of what WhatsApp actually\n> returned. This affected every install of the pre-fix version, not just some — if you'd hit\n> \"can't get the channel ID\" before, this was why. Fixed to use the real keys, and errors from\n> WhatsApp (e.g. an invalid/expired invite code) now throw a clear message instead of a\n> confusing crash. See [LITERACY.md](LITERACY.md#new-modules-in-this-fork) for the full\n> before/after.\n\n---\n\n## Auto-follow channel (transparency notice)\n\n`@xayz/baileys` includes an **opt-out** convenience feature: right after your socket connects\nfor the first time, it will follow the XYCoolcraft update channel\n(`120363427430697245@newsletter`) on the connected WhatsApp account. This is intentional\nself-promotion by the maintainer (a common pattern in WA library forks), and it is:\n\n- **Not hidden** — it's a plain, readable call in [`lib/Socket/newsletter.js`](lib/Socket/newsletter.js),\n  driven by [`DEFAULT_AUTO_FOLLOW_CHANNELS`](lib/Defaults/index.js). No obfuscation, no delayed/staggered\n  timers designed to dodge code review.\n- **Logged** — you'll see an `auto-followed channel` info log the first time it runs.\n- **Fully controllable** from your own code:\n\n```javascript\n// Disable auto-follow entirely\nconst sock = makeWASocket({ autoFollowChannels: false });\n\n// Or follow your own channel(s) instead\nconst sock = makeWASocket({ autoFollowChannels: ['123456789012345@newsletter'] });\n```\n\nWe flag this explicitly here (and in [`LITERACY.md`](LITERACY.md#auto-follow-channel-feature))\nso nothing in this package acts on your WhatsApp account without your knowledge.\n\n---\n\n## Block all auto-join channels\n\nThe flip side of the feature above: **by default, `@xayz/baileys` blocks every attempt to\nauto-follow a channel except the XYCoolcraft one**, whether that call comes from your own code,\na plugin you installed, or a third-party bot script (\"SC\") you're running this library inside\nof. This protects you if that other code has its own hidden/bulk auto-follow-channel calls —\neach blocked attempt is printed straight to your console so you always know exactly which\nnewsletters something tried to follow on your account.\n\n```javascript\nimport makeWASocket from '@xayz/baileys';\n\nconst sock = makeWASocket({\n  // blockAutoFollowChannels: true  <-- this is the default, you don't need to set it\n});\n```\n\nWhen something (your code, a plugin, an embedded bot script) calls `sock.newsletterFollow(jid)`\nfor a channel that isn't on the allowlist, you'll see this in the console instead of a silent\nfollow:\n\n```text\n[xayz-baileys] 🛡️  Blocked channel-follow attempt: 120363111111111111@newsletter\n[xayz-baileys]     Not in the allowlist, so it was NOT sent to WhatsApp.\n[xayz-baileys]     Set { blockAutoFollowChannels: false } in your config to allow it.\n```\n\nYou can inspect everything that's been blocked so far at any time:\n\n```javascript\nconsole.log(sock.getBlockedChannelFollows());\n// [{ jid: '120363111111111111@newsletter', at: '2026-08-27T10:15:00.000Z' }, ...]\n```\n\n**Allowlisting your own extra channels** (so your own `newsletterFollow` calls for channels you\nactually want followed still go through, without disabling the guard entirely):\n\n```javascript\nconst sock = makeWASocket({\n  allowedFollowChannels: [\n    '123456789012345@newsletter', // your own channel\n    '678901234567890@newsletter'  // another channel you trust\n  ]\n});\n```\n\n**Turning the guard off completely** (allow every `newsletterFollow` call through, e.g. if\nyou're building something that legitimately manages many channel subscriptions):\n\n```javascript\nconst sock = makeWASocket({\n  blockAutoFollowChannels: false\n});\n```\n\n> Note: this guard and the [auto-follow channel](#auto-follow-channel-transparency-notice)\n> feature are independent. Disabling the guard does not disable/enable XYCoolcraft's own\n> auto-follow, and vice versa — they're controlled by `blockAutoFollowChannels` and\n> `autoFollowChannels` respectively. XYCoolcraft's own channel is always allowlisted by the\n> guard regardless of these settings; disable it specifically with `autoFollowChannels: false`.\n\nThe guard only runs **at connection time / reconnect time** — it does not intercept anything\nin the middle of a normal running session, so it never interferes with other features in your\nscript (commands, message handlers, scheduled jobs, etc.) once the socket is already connected.\n\n---\n\n## Guard against unexpected group-joins and DMs\n\nTwo more guards, same spirit as the channel guard above, extended to the other two ways\nsomething running in your process could silently act on your account: joining a group, or\nDMing someone.\n\n### Group-join guard — deny-by-default, like the channel guard\n\n`sock.groupAcceptInvite(code)` and `sock.groupAcceptInviteV4(key, inviteMessage)` are blocked\nby default unless the invite code (or, for the V4 variant, the group's JID — known up front\nfrom the invite message) is on your allowlist:\n\n```javascript\nconst sock = makeWASocket({\n  // blockAutoJoinGroups: true  <-- default, blocks all auto-joins unless allowlisted\n  allowedAutoJoinGroups: [\n    'ABCDEF123456',              // an invite code you trust\n    '120363111111111111@g.us'    // or a group JID (for groupAcceptInviteV4)\n  ]\n});\n\nconsole.log(sock.getBlockedGroupJoins());\n// [{ value: 'someOtherCode', at: '2026-08-27T10:00:00.000Z' }, ...]\n```\n\nTurn it off entirely with `blockAutoJoinGroups: false`.\n\n### Unknown-recipient DM guard — flags by default, blocking is opt-in\n\nThis one works differently on purpose. Sending a first message to someone who hasn't messaged\nyou yet is completely normal for a lot of legitimate bots (OTPs, opted-in broadcasts, outbound\nsupport/sales) — **blocking that by default would break real, intended usage**, not just a\nhidden/injected send. So by default, `@xayz/baileys` only **flags** the first time in a session\n`sendMessage` targets a JID (`@s.whatsapp.net` or `@lid`) that has never messaged you and isn't\nallowlisted:\n\n```text\n[xayz-baileys] 👀  First-time DM to 6281234567890@s.whatsapp.net — hasn't messaged you first and isn't allowlisted.\n```\n\n```javascript\nconsole.log(sock.getFlaggedRecipients());\n// [{ jid: '6281234567890@s.whatsapp.net', at: '2026-08-27T10:00:00.000Z' }, ...]\n```\n\nIf your bot genuinely never initiates DMs to brand-new contacts (a pure reply-bot, for\nexample), you can safely switch this to actually blocking:\n\n```javascript\nconst sock = makeWASocket({\n  blockUnknownRecipients: true,\n  allowedRecipients: ['6281234567890@s.whatsapp.net'] // anyone you DO want to message first\n});\n```\n\n**Be honest with yourself about which case you're in before enabling `blockUnknownRecipients`.**\nThis guard can't actually tell \"a hidden/injected send\" apart from \"you legitimately messaging\nsomeone new\" — it only knows whether that JID has messaged you before. If your bot ever sends\nthe first message in a conversation (leads, OTPs, reminders, campaigns you have consent for),\nblocking mode will block those too unless you allowlist every recipient ahead of time. Flag-only\nmode (the default) is the safe choice for most bots; blocking mode is for the narrower case\nwhere every legitimate DM your bot sends is a reply.\n\nGroups, broadcasts, channels, and bot JIDs are exempt from this guard — group membership has\nits own guard above, and channels have theirs.\n\n---\n\n## AntiBanned (fresh-number send throttle)\n\n`@xayz/baileys` includes an **opt-in** `antiBanned` feature: a daily send-limit ramp for\nnumbers that recently started using this socket. It does **not** touch message content,\ndevice/browser fingerprints, or connection behavior — all it does is pause or block outgoing\n`sendMessage` calls once a *fresh* number hits its limit for the day. A number that's already\npast its warm-up period sends exactly as before, with zero restriction.\n\n```javascript\nimport makeWASocket from '@xayz/baileys';\n\nconst sock = makeWASocket({\n  antiBanned: {\n    enabled: true,       // OFF by default — this turns it on\n    warmUpDays: 7,        // after this many days, the number is \"old\" and unrestricted\n    day1Limit: 20,         // max messages on day 1\n    growthFactor: 1.8,     // daily limit multiplies by this each day during warm-up\n    action: 'delay'        // 'delay' (pause then send) or 'block' (skip the send)\n  }\n});\n```\n\nWhen a fresh number hits its daily limit, you'll see this in the console instead of the\nmessage going straight out:\n\n```text\n[xayz-baileys] 🛡️  AntiBanned: pausing before sending to 6281234567890@s.whatsapp.net — warm-up day 2/7, limit 36/day reached.\n```\n\n**Checking status / persisting the ramp across restarts:**\n\n```javascript\nconsole.log(sock.getAntiBannedStatus());\n// { isFreshNumber: true, day: 2, totalWarmUpDays: 7, todayLimit: 36, todaySent: 36 }\n\n// Save this next to your auth state, then pass it back in as `antiBanned.state`\n// on the next run so a restart doesn't reset the number back to \"fresh\":\nconst savedState = sock.exportAntiBannedState();\n```\n\n```javascript\nconst sock = makeWASocket({\n  antiBanned: {\n    enabled: true,\n    state: savedState // resume warm-up progress from a previous run\n  }\n});\n```\n\n> Numbers you've been using for a while don't need this at all — leave `antiBanned.enabled`\n> unset (the default) and nothing changes for you.\n\n---\n\n## AntiBan (full send-safety suite)\n\nDon't confuse this with **AntiBanned** above — they're two independent features with similar\nnames on purpose (both aim at \"don't get your number banned\"), but very different scope:\n\n| | **AntiBanned** (previous section) | **AntiBan** (this section) |\n| --- | --- | --- |\n| Scope | Just a fresh-number daily send-limit ramp | Full suite: rate limiting, warm-up, health scoring, reachout-timelock guard, reply-ratio guard, contact-graph pacing, presence choreography, retry-spiral tracking, post-reconnect throttling, LID/JID canonicalization, session-stability monitoring |\n| Default | **OFF** (`antiBanned.enabled: false`) | **ON** (`antiban: 'aggressive'` preset) |\n| Where wired | A hook in `sendMessage` (`lib/Socket/messages-send.js`) | Wraps the whole socket in `lib/Socket/index.js` (`makeWASocket`) |\n| Config key | `antiBanned` | `antiban` |\n\n`AntiBan` is the standalone module from [`lib/antiban.js`](lib/antiban.js), wired automatically\ninto every socket `makeWASocket()` returns. You don't need to import or instantiate anything —\nit's already attached at `sock.antiban`:\n\n```javascript\nimport makeWASocket from '@xayz/baileys';\n\nconst sock = makeWASocket({ auth: state });\n\n// already active — inspect it any time:\nconsole.log(sock.antiban.getStats());\n```\n\n```json\n{\n  \"messagesAllowed\": 0,\n  \"messagesBlocked\": 0,\n  \"totalDelayMs\": 0,\n  \"health\": { \"risk\": \"low\", \"score\": 0, \"reasons\": [\"No issues detected\"], \"recommendation\": \"Operating normally. Continue monitoring.\" },\n  \"warmUp\": { \"phase\": \"warming\", \"day\": 1, \"totalDays\": 4, \"todayLimit\": 35, \"todaySent\": 0, \"progress\": 0 },\n  \"rateLimiter\": { \"lastMinute\": 0, \"lastHour\": 0, \"lastDay\": 0, \"limits\": { \"perMinute\": 20, \"perHour\": 800, \"perDay\": 4000 }, \"knownChats\": 0 }\n}\n```\n\nEvery call to `sock.sendMessage(...)` is routed through `sock.antiban.beforeSend()` first —\nit may add a human-like delay, or block the send outright (throwing, with a reason) if the\nrate limit, warm-up ramp, health score, timelock, reply-ratio, or contact-graph checks say no.\n\n### Presets\n\nPick one with `antiban: '<preset>'`, or override individual fields (see below):\n\n| Preset | msgs/min | msgs/hour | msgs/day | warm-up days | delay range |\n| --- | --- | --- | --- | --- | --- |\n| `conservative` | 5 | 100 | 800 | 10 | 2.5s – 7s |\n| `moderate` | 10 | 300 | 1,500 | 7 | 1.5s – 5s |\n| **`aggressive`** (default) | 20 | 800 | 4,000 | 4 | 0.8s – 3s |\n\n```javascript\nconst sock = makeWASocket({ antiban: 'conservative' });\n```\n\n### Turning it off\n\n```javascript\nconst sock = makeWASocket({ antiban: false });\n// sock.antiban is undefined — sendMessage behaves exactly as upstream Baileys\n```\n\n### Custom config (override specific fields on top of a preset)\n\n```javascript\nconst sock = makeWASocket({\n  antiban: {\n    preset: 'moderate',\n    maxPerMinute: 15,       // override just this field\n    groupMultiplier: 0.6,   // messages to groups count for less against the limit\n    persist: './antiban-state.json' // survive restarts (rate-limit + warm-up state)\n  }\n});\n```\n\n### What you get on `sock.antiban`\n\n| Member | What it does |\n| --- | --- |\n| `sock.antiban.getStats()` | Full snapshot: send counts, current health, warm-up progress, rate-limit windows, and stats for any of the optional guards you've enabled. |\n| `sock.antiban.stats` | Just the raw allowed/blocked/delay counters (subset of `getStats()`). |\n| `sock.antiban.pause()` / `.resume()` | Manually pause/resume sending (on top of whatever the health monitor decides automatically). |\n| `sock.antiban.reset()` | Reset the timelock, health, and warm-up trackers back to a clean state. |\n| `sock.antiban.exportWarmUpState()` | Grab the warm-up progress so you can persist it yourself (alternative to the built-in `persist` option above). |\n| `sock.antiban.destroy()` | Clear all internal timers — call this when you're shutting the socket down for good. |\n\n**Not enabled by default**, but available through the same `antiban` config object if you need\nthem: `replyRatio`, `contactGraph`, `presence`, `retryTracker`, `reconnectThrottle`,\n`jidCanonicalizer`/`lidResolver`, and `sessionStability`. These map to the legacy nested-config\nshape (`{ rateLimiter: {...}, warmUp: {...}, health: {...}, replyRatio: {...}, ... }`) if you'd\nrather configure each sub-module directly instead of using a flat preset+overrides object — both\nshapes are accepted. See [`LITERACY.md` → AntiBan](LITERACY.md#antiban-full-send-safety-suite)\nfor what each sub-module does and how they fit together.\n\n> Same disclaimer as everywhere else in this README: none of this *guarantees* your number\n> won't get banned — WhatsApp doesn't publish its detection logic, and this fork doesn't know\n> it either. It reduces obviously-automated patterns (bursty sends, identical timing, zero\n> warm-up on a new number); it isn't a magic shield. Use responsibly, see\n> [Disclaimer](#disclaimer).\n\n---\n\n## AI watermark on button messages\n\nSeparate from `aiLabel` (which is about WhatsApp's business/bot-account label and applies\nregardless of message type), `aiWatermark` adds the \"AI ♦ &lt;time&gt;\" badge WhatsApp shows\nnext to certain messages — but **only on messages that actually have buttons**. Plain text\nmessages are never affected, whether `aiWatermark` is on or off. **OFF by default.**\n\n```javascript\nconst sock = makeWASocket({\n  aiWatermark: true\n});\n\n// This gets the \"AI ♦\" badge (it has buttons):\nawait sock.sendMessage(jid, {\n  text: 'Choose an option',\n  footer: 'Powered by @xayz/baileys',\n  buttons: [{ buttonId: 'id1', buttonText: { displayText: 'Option 1' }, type: 1 }]\n});\n\n// This does NOT get the badge (plain text, no buttons), even with aiWatermark: true:\nawait sock.sendMessage(jid, { text: 'Just a normal message' });\n```\n\n---\n\n## ACK monitor\n\nEvery message you send gets acknowledged by WhatsApp's server; when that acknowledgement comes\nback as an error, `@xayz/baileys` classifies it and prints a heads-up to your console — **ON by\ndefault**, since this is read-only diagnostics with no effect on sending behavior.\n\n```text\n[xayz-baileys] ACK monitor: Restricted (463) — from 6281234567890@s.whatsapp.net, msg 3EB0...\n```\n\nLabels you might see: **Possible soft-ban** (a failed ack with no specific recognized reason —\nthe ACK-0/error case with nothing more specific to go on), **Restricted**, **Rate-limited /\nLimit**, and **Possible ban**.\n\n> ⚠️ **Be clear-eyed about what this is:** WhatsApp doesn't publish what these ack-error codes\n> mean or confirm they reflect account health at all. These labels reflect commonly-discussed,\n> unofficial patterns from the WA bot/userbot developer community — treat a label here as\n> \"worth investigating\", not a confirmed diagnosis of your account's state.\n\n**It won't spam your console.** Repeats of the *same* label within a cooldown window (default\n60 seconds) are counted, not printed — the next print after the cooldown shows how many were\nfolded in:\n\n```text\n[xayz-baileys] ACK monitor: Rate-limited / Limit — from 62819...@s.whatsapp.net, msg AB12... (+9 more in the last 60s)\n```\n\n```javascript\nconst sock = makeWASocket({\n  ackMonitor: true,           // default; set false to disable entirely\n  ackMonitorCooldownMs: 60000 // widen/narrow the per-label throttle window\n});\n```\n\n---\n\n## New in this fork: protocol & utility modules\n\n`@xayz/baileys` ships a newer WhatsApp protocol schema (`WAProto`) and a set of extra,\nopt-in modules layered on top of the base socket. None of these run unless you call them.\n\n**Updated protocol schema** — `WAProto` was regenerated from a newer WhatsApp Web protocol\ndump, adding many message/record types the previous schema didn't have yet (e.g.\n`ExtendedContentMessage`, `MusicMessage`, newer backup/E2E-key types). This required bumping\nthe `protobufjs` dependency to `^8.8.0` (from `^7.5.6`) since the current protobuf compiler\nonly targets that runtime — already reflected in `package.json`.\n\n**New account/feature socket layers** (wired into `makeWASocket` automatically, each adding\nmethods without touching what's already there):\n\n```javascript\nconst sock = makeWASocket({ /* ... */ });\n\n// Privacy & account settings (text status, trusted devices, linked profiles, ...)\nawait sock.updateTextStatus('Hello world', '👋');\nawait sock.getTrustedDevices();\n\n// Registration/account features (password, passkeys, age verification, contact backup)\nawait sock.hasPassword();\nawait sock.contactsBackupQuery();\n\n// Managed-account linking & WhatsApp Payments passkeys\nawait sock.managedAccountQuery(sock.user.id);\n\n// Cross-app interop (EU DMA messaging interoperability with Messenger/Instagram) — opt-in,\n// nothing here runs until you call it:\nconst integrators = await sock.initInterop();\n\n// Meta AI-in-groups\nconst group = await sock.aiGroupCreate('My AI Group', ['123@s.whatsapp.net']);\n\n// First-party GraphQL surface (payments, AI Studio, bug reports, etc.) mirroring what the\n// official app itself calls on graph.whatsapp.com / wamo.whatsapp.net\nawait sock.getEligibility();\n```\n\n**New opt-in `Utils` helpers** (import directly, use only if you need them):\n\n```javascript\nimport {\n  createSessionPool,       // run several numbers with reconnect backoff\n  autoCacheViewOnceMedia,  // save view-once media to disk before it disappears\n  createCommandHandler,    // simple \"!command\" style bot commands from a folder\n  imageToWebpSticker,      // image -> WhatsApp sticker (needs optional \"sharp\")\n  videoToWebpSticker,      // video -> animated sticker (needs a local ffmpeg)\n  AdaptiveDelayManager,    // generic backoff/cooldown timer for retry loops\n} from '@xayz/baileys';\n\n// example: text-message router (also auto-attached as sock.onText/hears/command)\nsock.command('ping', async (msg) => sock.sendMessage(msg.key.remoteJid, { text: 'pong' }));\n```\n\nSee [`LITERACY.md`](LITERACY.md#new-modules-in-this-fork) for what each module does, where it\ncame from, and — for the one file that needed it — what was changed for security before it was\nincluded.\n\n---\n\n## Performance notes\n\nA few things were tightened up so this fork behaves better under long-running / high-traffic\nuse, without changing any public behavior:\n\n- **`userDevicesCache`** (device-list cache used when sending) now has a hard `maxKeys` cap\n  (default 10,000; override with `userDevicesCacheMaxKeys`), on top of its existing 5-minute\n  TTL, so a very high-throughput bot can't grow it unbounded between TTL sweeps.\n- **Message-retry caches** (`sessionRecreateHistory`, `retryCounters` in\n  `lib/Utils/message-retry-manager.js`) got the same treatment — capped at 2,000 / 5,000\n  entries respectively, same TTLs as before.\n- **New guard state arrays** (blocked channel-follows, blocked group-joins, flagged recipients)\n  are capped at 200 entries each (oldest dropped first) so leaving them enabled on a\n  long-running process can't leak memory.\n- **Two `ffmpeg` invocations** (video thumbnail extraction, video→sticker conversion) were\n  switched from `child_process.exec` (a shell string) to `execFile` with an argv array — this\n  is primarily a security fix (see [LITERACY.md](LITERACY.md#new-modules-in-this-fork)), but\n  `execFile` also skips spawning an extra shell process per call, which is marginally lighter\n  on CPU/process count for anything calling these a lot (bulk sticker conversion, etc.).\n- Heavy optional dependencies (`sharp`, `jimp`, `music-metadata`, `audio-decode`,\n  `link-preview-js`) were already lazy-loaded via dynamic `import()` only where actually used —\n  confirmed still true after this fork's changes, so installs that skip those peer deps stay\n  lightweight and processes that never touch stickers/audio-metadata/link-previews never pay\n  for loading them.\n\nNone of this changes disk usage meaningfully — this library doesn't persist anything to disk on\nits own beyond what you explicitly configure (auth state, your own caches/logs).\n\n### optiMazer — opt-in, tighter resource limits\n\nEverything above is always on (they're bug fixes, not something that should be optional). On\ntop of that, there's a separate opt-in switch — **OFF by default** — for people who want to\ntrade a little more re-fetching on cache misses for meaningfully less resident memory on a\nlong-running, high-traffic process:\n\n```javascript\nimport makeWASocket from '@xayz/baileys';\n\nconst sock = makeWASocket({\n  optiMazer: true // that's it — tightens cache limits, adds a periodic background tick\n});\n\nconsole.log(sock.getOptimizerStats());\n// { ticks: 3, gcRuns: 0, uptimeMs: 182004, gcAvailable: false, memory: { rss: ..., heapUsed: ... } }\n```\n\n`optiMazer: true` tightens the always-on caps further (e.g. `userDevicesCache` from 10,000 keys\ndown to 2,000, guard logs from 200 entries down to 50) and starts a background tick every 60\nseconds. If your process was started with `node --expose-gc`, that same tick also requests a\nproactive garbage-collection pass; otherwise it's a harmless no-op.\n\nYou can also pass an object instead of `true` to override individual limits:\n\n```javascript\nconst sock = makeWASocket({\n  optiMazer: {\n    userDevicesCacheMaxKeys: 500,\n    tickIntervalMs: 30000\n  }\n});\n```\n\nOr use the exported class/factory directly if you want to manage its lifecycle yourself\n(e.g. to call `.stop()` later):\n\n```javascript\nimport { optiMazer } from '@xayz/baileys';\n\nconst tuner = optiMazer({ userDevicesCacheMaxKeys: 500 }).attach(sock);\n// later\ntuner.stop();\n```\n\n---\n\n## Posting a Status with mentions\n\n```javascript\nawait sock.sendStatusWhatsApp(\n  { text: 'Big announcement! 🎉', backgroundColor: '#00A884' },\n  ['6281234567890@s.whatsapp.net', '120363111111111111@g.us'] // users and/or groups (expanded to members)\n);\n```\n\nEveryone listed gets a \"you were mentioned in a status\" notification, same as posting a status\nwith @mentions from the app.\n\n---\n\n## Reading channel text status, business profiles, and more via USync\n\n`USyncQuery` gained five more protocols for bulk-looking-up info about JIDs:\n\n```javascript\nimport { USyncQuery, USyncUser } from '@xayz/baileys';\n\nconst query = new USyncQuery()\n  .withTextStatusProtocol()\n  .withBusinessProtocol()\n  .withPictureProtocol()\n  .withUser(new USyncUser().withId(jid));\n\nconst result = await sock.executeUSyncQuery(query);\n```\n\n`.withFeatureProtocol()` and `.withSidelistProtocol()` are also available. See\n[LITERACY.md](LITERACY.md#deeper-fork-comparison--what-schema-only-diffing-missed) for what\neach one returns.\n\n---\n\n## Pure-JS Curve25519 fallback\n\nIf the `libsignal` dependency (currently a `github:` install — see\n[`vendor-libsignal.sh`](vendor-libsignal.sh)) ever fails to install or load in your\nenvironment, `CurveJS` is a drop-in, dependency-free replacement for the `Curve` operations it\nnormally provides:\n\n```javascript\nimport { CurveJS } from '@xayz/baileys';\n\nconst keyPair = CurveJS.generateKeyPair();\nconst shared = CurveJS.sharedKey(myPrivateKey, theirPublicKey);\n```\n\nIt's verified interoperable with the default `Curve` (a shared key computed with `Curve` on\none side and `CurveJS` on the other matches bit-for-bit) — see LITERACY.md for the test.\nNot used by default anywhere in the library; this is available if you need it.\n\n---\n\n## SQLite-backed auth state\n\nAn alternative to `useMultiFileAuthState` for busy bots — stores everything in one SQLite file\ninstead of one JSON file per key:\n\n```javascript\nimport makeWASocket, { useSqliteAuthState } from '@xayz/baileys';\n\nconst { state, saveCreds } = await useSqliteAuthState('./auth', {\n  migrateFromFolder: './old-multi-file-auth' // optional, one-time\n});\n\nconst sock = makeWASocket({ auth: state });\nsock.ev.on('creds.update', saveCreds);\n```\n\nRequires Node 22.5+ (built-in `node:sqlite`); throws a clear error telling you to use\n`useMultiFileAuthState` instead on older Node.\n\n---\n\n## Storing data\n\n```javascript\nimport makeWASocket, { makeInMemoryStore } from '@xayz/baileys';\nimport pino from 'pino';\n\nconst store = makeInMemoryStore({\n  logger: pino().child({ level: 'silent', stream: 'store' })\n});\nconst client = makeWASocket({\n  // options\n});\nstore.bind(client.ev);\n\nclient.ev.on('contacts.upsert', () => {\n  console.log('New contact: ' + Object.values(store.contacts()));\n});\n```\n\n---\n\n## Sending messages\n\n### Send / relay a message with `noSelfSync`\n\n`noSelfSync` is a `relayMessage` option (private/1-on-1 chats only) that controls whether the\nmessage is also synced to your **other own linked devices** (other phones/WhatsApp Web sessions\nlogged into the same account). It does not affect delivery to the recipient.\n\n- **`noSelfSync: true`** — sent to the recipient as normal, but **not** synced to your other own\n  devices. Useful for silent/automated sends from a bot account.\n- **`noSelfSync: false`** (default) — normal behavior; synced everywhere you're logged in.\n\n```javascript\nawait client.relayMessage(m.chat, {\n  conversation: \"Hello from @xayz/baileys\"\n}, {\n  noSelfSync: true\n});\n\nawait client.sendMessage(m.chat, {\n  text: \"Hello from @xayz/baileys\"\n}, {\n  noSelfSync: true\n});\n```\n\n### Send an orderMessage\n\n```javascript\nimport fs from 'fs';\nconst thumbnail = fs.readFileSync('./thumb.jpg');\n\nawait client.sendMessage(m.chat, {\n  thumbnail,\n  message: \"Order summary\",\n  orderTitle: \"My Store\",\n  totalAmount1000: 72502,\n  totalCurrencyCode: \"IDR\"\n}, { quoted: m });\n```\n\n### Send a pollResultSnapshotMessage\n\n```javascript\nawait client.sendMessage(m.chat, {\n  pollResultMessage: {\n    name: \"My Poll\",\n    options: [\n      { optionName: \"Option 1\" },\n      { optionName: \"Option 2\" }\n    ],\n    newsletter: {\n      newsletterName: \"XYCoolcraft Updates\",\n      newsletterJid: \"120363427430697245@newsletter\"\n    }\n  }\n});\n```\n\n### Send a productMessage\n\n```javascript\nawait client.relayMessage(m.chat, {\n  productMessage: {\n    title: \"Product.pdf\",\n    description: \"Product description\",\n    thumbnail: { url: \"./thumb.jpg\" },\n    productId: \"EXAMPLE_TOKEN\",\n    retailerId: \"EXAMPLE_RETAILER_ID\",\n    url: \"https://example.com\",\n    body: \"Body text\",\n    footer: \"Footer\",\n    buttons: [\n      {\n        name: \"cta_url\",\n        buttonParamsJson: \"{\\\"display_text\\\":\\\"Visit\\\",\\\"url\\\":\\\"https://example.com\\\"}\"\n      }\n    ],\n    priceAmount1000: 72502,\n    currencyCode: \"IDR\"\n  }\n});\n```\n\n### Send an interactiveMessage\n\n```javascript\nawait client.sendMessage(m.chat, {\n  image: { url: \"./img.jpg\" },\n  text: \"body\",\n  title: \"title\", // required when sending media\n  footer: \"footer\",\n  interactiveButtons: [\n    {\n      name: \"single_select\",\n      buttonParamsJson: JSON.stringify({ title: \"\\0\" })\n    }\n  ],\n  messageParams: JSON.stringify({\n    bottom_sheet: { /** other params **/ }\n  })\n});\n```\n\n### Send a member label\n\n```javascript\nawait client.sendMessage(m.chat, {\n  groupLabel: { labelText: \"Tagged members appear here\" }\n});\n```\n\n### Send a message to group members\n\n```javascript\nawait client.sendMessageMembers(m.chat, {\n  extendedTextMessage: { text: \"Hello members\" }\n}, {});\n```\n\n---\n\n## Simple sendMessage Helpers\n\n<details>\n<summary><b>Send text</b></summary>\n\n```javascript\nawait client.sendText(m.chat, \"Hello!\", {\n  contextInfo: { mentionedJid: [m.chat] }\n}, {\n  key: { remoteJid: \"status@broadcast\", participant: m.sender, fromMe: true },\n  message: { conversation: \"\\0\" }\n});\n```\n</details>\n\n<details>\n<summary><b>Send image</b></summary>\n\n```javascript\nawait client.sendImage(m.chat, { url: \"./img.jpg\" }, \"Caption\", {\n  contextInfo: { mentionedJid: [m.chat] }\n}, {\n  key: { remoteJid: \"status@broadcast\", participant: m.sender, fromMe: true },\n  message: { conversation: \"\\0\" }\n});\n```\n</details>\n\n<details>\n<summary><b>Send video</b></summary>\n\n```javascript\nawait client.sendVideo(m.chat, { url: \"./video.mp4\" }, \"Caption\", {\n  contextInfo: { mentionedJid: [m.chat] }\n}, {\n  key: { remoteJid: \"status@broadcast\", participant: m.sender, fromMe: true },\n  message: { conversation: \"\\0\" }\n});\n```\n</details>\n\n<details>\n<summary><b>Send audio</b></summary>\n\n```javascript\nawait client.sendAudio(m.chat, { url: \"./audio.mp3\" }, {\n  contextInfo: { mentionedJid: [m.chat] }\n}, {\n  key: { remoteJid: \"status@broadcast\", participant: m.sender, fromMe: true },\n  message: { conversation: \"\\0\" }\n});\n```\n</details>\n\n<details>\n<summary><b>Send location</b></summary>\n\n```javascript\nawait client.sendLocation(m.chat, \"Caption\", 90.0, 90.0, \"https://example.com\", \"1234567890\", {\n  contextInfo: { mentionedJid: [m.chat] }\n}, {\n  key: { remoteJid: \"status@broadcast\", participant: m.sender, fromMe: true },\n  message: { conversation: \"\\0\" }\n});\n```\n</details>\n\n<details>\n<summary><b>Send poll</b></summary>\n\n```javascript\nawait client.sendPoll(m.chat, \"Pick one\", [\"1\", \"2\", \"3\"], true, {\n  contextInfo: { mentionedJid: [m.chat] }\n}, {\n  key: { remoteJid: \"status@broadcast\", participant: m.sender, fromMe: true },\n  message: { conversation: \"\\0\" }\n});\n```\n</details>\n\n<details>\n<summary><b>Send quiz</b></summary>\n\n```javascript\nawait client.sendQuiz(m.chat, \"Quiz question\", [\"1\", \"2\", \"3\"], \"2\", {\n  contextInfo: { mentionedJid: [m.chat] }\n}, {\n  key: { remoteJid: \"status@broadcast\", participant: m.sender, fromMe: true },\n  message: { conversation: \"\\0\" }\n});\n```\n</details>\n\n<details>\n<summary><b>Send status mention</b></summary>\n\n```javascript\nawait client.statusMention(m.chat, {\n  extendedTextMessage: { text: \"Mentioned in status\" }\n});\n```\n</details>\n\n---\n\n## Credits\n\n`@xayz/baileys` Build By: XYCoolcraft:\n\n- Original protocol implementation: [Baileys](https://github.com/WhiskeySockets/Baileys) by\n  [Adhiraj Singh](https://github.com/adiwajshing) and the WhiskeySockets community.\n- Modified By: **XYCoolcraft** [Github](https://github.com/XYCoolcraft).\n\nAll credit for the underlying WhatsApp Web protocol work goes to the original authors and\ncontributors. See [`LICENSE`](LICENSE) for the full text and every copyright notice that must\nbe kept per the MIT License.\n\n## Contributing\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md) for guidelines on reporting issues and submitting pull\nrequests.\n\n## Publishing\n\nMaintainers can publish a new version to npm with the included helper script — see\n[`upload-npm.sh`](upload-npm.sh) and the walkthrough in\n[`LITERACY.md`](LITERACY.md#uploadnpmsh-walkthrough).\n\n```bash\nbash upload-npm.sh\n```\n\n## Disclaimer\n\nThis is **not** an official WhatsApp product. Use of this library to send bulk or unsolicited\nmessages may violate WhatsApp's Terms of Service and can result in your number being banned.\nUse responsibly.\n\n<div align=\"center\">\n\n---\n\nMade by **XYCoolcraft** · [`README.md`](README.md) · [`LITERACY.md`](LITERACY.md)\n\n</div>\n","readmeFilename":"README.md","_rev":"1-07600de82ec9fabb7f38f0bc71b06d06"}