A simple tool which lets you scrape twitter accounts and crosspost them to bluesky accounts! Comes with a CLI and a webapp for managing profiles! Works with images/videos/link embeds/threads.
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: high-quality screenshots for external Quote Tweets

jack 2be241c1 ce7ab265

+949 -4
+866 -1
package-lock.json
··· 21 21 "inquirer": "^13.1.0", 22 22 "iso-639-1": "^3.1.2", 23 23 "jsonwebtoken": "^9.0.3", 24 - "node-cron": "^4.2.1" 24 + "node-cron": "^4.2.1", 25 + "puppeteer-core": "^24.34.0" 25 26 }, 26 27 "devDependencies": { 27 28 "@biomejs/biome": "^1.9.4", ··· 1048 1049 } 1049 1050 } 1050 1051 }, 1052 + "node_modules/@puppeteer/browsers": { 1053 + "version": "2.11.0", 1054 + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.11.0.tgz", 1055 + "integrity": "sha512-n6oQX6mYkG8TRPuPXmbPidkUbsSRalhmaaVAQxvH1IkQy63cwsH+kOjB3e4cpCDHg0aSvsiX9bQ4s2VB6mGWUQ==", 1056 + "license": "Apache-2.0", 1057 + "dependencies": { 1058 + "debug": "^4.4.3", 1059 + "extract-zip": "^2.0.1", 1060 + "progress": "^2.0.3", 1061 + "proxy-agent": "^6.5.0", 1062 + "semver": "^7.7.3", 1063 + "tar-fs": "^3.1.1", 1064 + "yargs": "^17.7.2" 1065 + }, 1066 + "bin": { 1067 + "browsers": "lib/cjs/main-cli.js" 1068 + }, 1069 + "engines": { 1070 + "node": ">=18" 1071 + } 1072 + }, 1051 1073 "node_modules/@steipete/bird": { 1052 1074 "version": "0.4.0", 1053 1075 "resolved": "https://registry.npmjs.org/@steipete/bird/-/bird-0.4.0.tgz", ··· 1063 1085 "engines": { 1064 1086 "node": ">=20" 1065 1087 } 1088 + }, 1089 + "node_modules/@tootallnate/quickjs-emscripten": { 1090 + "version": "0.23.0", 1091 + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", 1092 + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", 1093 + "license": "MIT" 1066 1094 }, 1067 1095 "node_modules/@types/bcryptjs": { 1068 1096 "version": "2.4.6", ··· 1218 1246 "@types/node": "*" 1219 1247 } 1220 1248 }, 1249 + "node_modules/@types/yauzl": { 1250 + "version": "2.10.3", 1251 + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", 1252 + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", 1253 + "license": "MIT", 1254 + "optional": true, 1255 + "dependencies": { 1256 + "@types/node": "*" 1257 + } 1258 + }, 1221 1259 "node_modules/accepts": { 1222 1260 "version": "2.0.0", 1223 1261 "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", ··· 1256 1294 "url": "https://opencollective.com/express" 1257 1295 } 1258 1296 }, 1297 + "node_modules/agent-base": { 1298 + "version": "7.1.4", 1299 + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", 1300 + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", 1301 + "license": "MIT", 1302 + "engines": { 1303 + "node": ">= 14" 1304 + } 1305 + }, 1259 1306 "node_modules/ansi-regex": { 1260 1307 "version": "6.2.2", 1261 1308 "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", ··· 1280 1327 "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1281 1328 } 1282 1329 }, 1330 + "node_modules/ast-types": { 1331 + "version": "0.13.4", 1332 + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", 1333 + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", 1334 + "license": "MIT", 1335 + "dependencies": { 1336 + "tslib": "^2.0.1" 1337 + }, 1338 + "engines": { 1339 + "node": ">=4" 1340 + } 1341 + }, 1283 1342 "node_modules/asynckit": { 1284 1343 "version": "0.4.0", 1285 1344 "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", ··· 1303 1362 "proxy-from-env": "^1.1.0" 1304 1363 } 1305 1364 }, 1365 + "node_modules/b4a": { 1366 + "version": "1.7.3", 1367 + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", 1368 + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", 1369 + "license": "Apache-2.0", 1370 + "peerDependencies": { 1371 + "react-native-b4a": "*" 1372 + }, 1373 + "peerDependenciesMeta": { 1374 + "react-native-b4a": { 1375 + "optional": true 1376 + } 1377 + } 1378 + }, 1379 + "node_modules/bare-events": { 1380 + "version": "2.8.2", 1381 + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", 1382 + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", 1383 + "license": "Apache-2.0", 1384 + "peerDependencies": { 1385 + "bare-abort-controller": "*" 1386 + }, 1387 + "peerDependenciesMeta": { 1388 + "bare-abort-controller": { 1389 + "optional": true 1390 + } 1391 + } 1392 + }, 1393 + "node_modules/bare-fs": { 1394 + "version": "4.5.2", 1395 + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.2.tgz", 1396 + "integrity": "sha512-veTnRzkb6aPHOvSKIOy60KzURfBdUflr5VReI+NSaPL6xf+XLdONQgZgpYvUuZLVQ8dCqxpBAudaOM1+KpAUxw==", 1397 + "license": "Apache-2.0", 1398 + "optional": true, 1399 + "dependencies": { 1400 + "bare-events": "^2.5.4", 1401 + "bare-path": "^3.0.0", 1402 + "bare-stream": "^2.6.4", 1403 + "bare-url": "^2.2.2", 1404 + "fast-fifo": "^1.3.2" 1405 + }, 1406 + "engines": { 1407 + "bare": ">=1.16.0" 1408 + }, 1409 + "peerDependencies": { 1410 + "bare-buffer": "*" 1411 + }, 1412 + "peerDependenciesMeta": { 1413 + "bare-buffer": { 1414 + "optional": true 1415 + } 1416 + } 1417 + }, 1418 + "node_modules/bare-os": { 1419 + "version": "3.6.2", 1420 + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz", 1421 + "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==", 1422 + "license": "Apache-2.0", 1423 + "optional": true, 1424 + "engines": { 1425 + "bare": ">=1.14.0" 1426 + } 1427 + }, 1428 + "node_modules/bare-path": { 1429 + "version": "3.0.0", 1430 + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", 1431 + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", 1432 + "license": "Apache-2.0", 1433 + "optional": true, 1434 + "dependencies": { 1435 + "bare-os": "^3.0.1" 1436 + } 1437 + }, 1438 + "node_modules/bare-stream": { 1439 + "version": "2.7.0", 1440 + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz", 1441 + "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==", 1442 + "license": "Apache-2.0", 1443 + "optional": true, 1444 + "dependencies": { 1445 + "streamx": "^2.21.0" 1446 + }, 1447 + "peerDependencies": { 1448 + "bare-buffer": "*", 1449 + "bare-events": "*" 1450 + }, 1451 + "peerDependenciesMeta": { 1452 + "bare-buffer": { 1453 + "optional": true 1454 + }, 1455 + "bare-events": { 1456 + "optional": true 1457 + } 1458 + } 1459 + }, 1460 + "node_modules/bare-url": { 1461 + "version": "2.3.2", 1462 + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.3.2.tgz", 1463 + "integrity": "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==", 1464 + "license": "Apache-2.0", 1465 + "optional": true, 1466 + "dependencies": { 1467 + "bare-path": "^3.0.0" 1468 + } 1469 + }, 1470 + "node_modules/basic-ftp": { 1471 + "version": "5.1.0", 1472 + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.1.0.tgz", 1473 + "integrity": "sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==", 1474 + "license": "MIT", 1475 + "engines": { 1476 + "node": ">=10.0.0" 1477 + } 1478 + }, 1306 1479 "node_modules/bcryptjs": { 1307 1480 "version": "3.0.3", 1308 1481 "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz", ··· 1336 1509 "url": "https://opencollective.com/express" 1337 1510 } 1338 1511 }, 1512 + "node_modules/buffer-crc32": { 1513 + "version": "0.2.13", 1514 + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 1515 + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", 1516 + "license": "MIT", 1517 + "engines": { 1518 + "node": "*" 1519 + } 1520 + }, 1339 1521 "node_modules/buffer-equal-constant-time": { 1340 1522 "version": "1.0.1", 1341 1523 "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", ··· 1386 1568 "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", 1387 1569 "license": "MIT" 1388 1570 }, 1571 + "node_modules/chromium-bidi": { 1572 + "version": "12.0.1", 1573 + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-12.0.1.tgz", 1574 + "integrity": "sha512-fGg+6jr0xjQhzpy5N4ErZxQ4wF7KLEvhGZXD6EgvZKDhu7iOhZXnZhcDxPJDcwTcrD48NPzOCo84RP2lv3Z+Cg==", 1575 + "license": "Apache-2.0", 1576 + "dependencies": { 1577 + "mitt": "^3.0.1", 1578 + "zod": "^3.24.1" 1579 + }, 1580 + "peerDependencies": { 1581 + "devtools-protocol": "*" 1582 + } 1583 + }, 1389 1584 "node_modules/cli-width": { 1390 1585 "version": "4.1.0", 1391 1586 "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", ··· 1395 1590 "node": ">= 12" 1396 1591 } 1397 1592 }, 1593 + "node_modules/cliui": { 1594 + "version": "8.0.1", 1595 + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 1596 + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 1597 + "license": "ISC", 1598 + "dependencies": { 1599 + "string-width": "^4.2.0", 1600 + "strip-ansi": "^6.0.1", 1601 + "wrap-ansi": "^7.0.0" 1602 + }, 1603 + "engines": { 1604 + "node": ">=12" 1605 + } 1606 + }, 1607 + "node_modules/cliui/node_modules/ansi-regex": { 1608 + "version": "5.0.1", 1609 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1610 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1611 + "license": "MIT", 1612 + "engines": { 1613 + "node": ">=8" 1614 + } 1615 + }, 1616 + "node_modules/cliui/node_modules/ansi-styles": { 1617 + "version": "4.3.0", 1618 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1619 + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1620 + "license": "MIT", 1621 + "dependencies": { 1622 + "color-convert": "^2.0.1" 1623 + }, 1624 + "engines": { 1625 + "node": ">=8" 1626 + }, 1627 + "funding": { 1628 + "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1629 + } 1630 + }, 1631 + "node_modules/cliui/node_modules/emoji-regex": { 1632 + "version": "8.0.0", 1633 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1634 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1635 + "license": "MIT" 1636 + }, 1637 + "node_modules/cliui/node_modules/string-width": { 1638 + "version": "4.2.3", 1639 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1640 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1641 + "license": "MIT", 1642 + "dependencies": { 1643 + "emoji-regex": "^8.0.0", 1644 + "is-fullwidth-code-point": "^3.0.0", 1645 + "strip-ansi": "^6.0.1" 1646 + }, 1647 + "engines": { 1648 + "node": ">=8" 1649 + } 1650 + }, 1651 + "node_modules/cliui/node_modules/strip-ansi": { 1652 + "version": "6.0.1", 1653 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1654 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1655 + "license": "MIT", 1656 + "dependencies": { 1657 + "ansi-regex": "^5.0.1" 1658 + }, 1659 + "engines": { 1660 + "node": ">=8" 1661 + } 1662 + }, 1663 + "node_modules/cliui/node_modules/wrap-ansi": { 1664 + "version": "7.0.0", 1665 + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1666 + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1667 + "license": "MIT", 1668 + "dependencies": { 1669 + "ansi-styles": "^4.0.0", 1670 + "string-width": "^4.1.0", 1671 + "strip-ansi": "^6.0.0" 1672 + }, 1673 + "engines": { 1674 + "node": ">=10" 1675 + }, 1676 + "funding": { 1677 + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1678 + } 1679 + }, 1398 1680 "node_modules/collapse-white-space": { 1399 1681 "version": "2.1.0", 1400 1682 "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", ··· 1405 1687 "url": "https://github.com/sponsors/wooorm" 1406 1688 } 1407 1689 }, 1690 + "node_modules/color-convert": { 1691 + "version": "2.0.1", 1692 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1693 + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1694 + "license": "MIT", 1695 + "dependencies": { 1696 + "color-name": "~1.1.4" 1697 + }, 1698 + "engines": { 1699 + "node": ">=7.0.0" 1700 + } 1701 + }, 1702 + "node_modules/color-name": { 1703 + "version": "1.1.4", 1704 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1705 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1706 + "license": "MIT" 1707 + }, 1408 1708 "node_modules/combined-stream": { 1409 1709 "version": "1.0.8", 1410 1710 "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", ··· 1479 1779 "node": ">= 0.10" 1480 1780 } 1481 1781 }, 1782 + "node_modules/data-uri-to-buffer": { 1783 + "version": "6.0.2", 1784 + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", 1785 + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", 1786 + "license": "MIT", 1787 + "engines": { 1788 + "node": ">= 14" 1789 + } 1790 + }, 1482 1791 "node_modules/debug": { 1483 1792 "version": "4.4.3", 1484 1793 "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", ··· 1496 1805 } 1497 1806 } 1498 1807 }, 1808 + "node_modules/degenerator": { 1809 + "version": "5.0.1", 1810 + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", 1811 + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", 1812 + "license": "MIT", 1813 + "dependencies": { 1814 + "ast-types": "^0.13.4", 1815 + "escodegen": "^2.1.0", 1816 + "esprima": "^4.0.1" 1817 + }, 1818 + "engines": { 1819 + "node": ">= 14" 1820 + } 1821 + }, 1499 1822 "node_modules/delayed-stream": { 1500 1823 "version": "1.0.0", 1501 1824 "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", ··· 1514 1837 "node": ">= 0.8" 1515 1838 } 1516 1839 }, 1840 + "node_modules/devtools-protocol": { 1841 + "version": "0.0.1534754", 1842 + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1534754.tgz", 1843 + "integrity": "sha512-26T91cV5dbOYnXdJi5qQHoTtUoNEqwkHcAyu/IKtjIAxiEqPMrDiRkDOPWVsGfNZGmlQVHQbZRSjD8sxagWVsQ==", 1844 + "license": "BSD-3-Clause" 1845 + }, 1517 1846 "node_modules/dotenv": { 1518 1847 "version": "17.2.3", 1519 1848 "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", ··· 1568 1897 "license": "MIT", 1569 1898 "engines": { 1570 1899 "node": ">= 0.8" 1900 + } 1901 + }, 1902 + "node_modules/end-of-stream": { 1903 + "version": "1.4.5", 1904 + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", 1905 + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", 1906 + "license": "MIT", 1907 + "dependencies": { 1908 + "once": "^1.4.0" 1571 1909 } 1572 1910 }, 1573 1911 "node_modules/es-define-property": { ··· 1657 1995 "@esbuild/win32-x64": "0.27.2" 1658 1996 } 1659 1997 }, 1998 + "node_modules/escalade": { 1999 + "version": "3.2.0", 2000 + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", 2001 + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", 2002 + "license": "MIT", 2003 + "engines": { 2004 + "node": ">=6" 2005 + } 2006 + }, 1660 2007 "node_modules/escape-html": { 1661 2008 "version": "1.0.3", 1662 2009 "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1663 2010 "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 1664 2011 "license": "MIT" 1665 2012 }, 2013 + "node_modules/escodegen": { 2014 + "version": "2.1.0", 2015 + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", 2016 + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", 2017 + "license": "BSD-2-Clause", 2018 + "dependencies": { 2019 + "esprima": "^4.0.1", 2020 + "estraverse": "^5.2.0", 2021 + "esutils": "^2.0.2" 2022 + }, 2023 + "bin": { 2024 + "escodegen": "bin/escodegen.js", 2025 + "esgenerate": "bin/esgenerate.js" 2026 + }, 2027 + "engines": { 2028 + "node": ">=6.0" 2029 + }, 2030 + "optionalDependencies": { 2031 + "source-map": "~0.6.1" 2032 + } 2033 + }, 2034 + "node_modules/esprima": { 2035 + "version": "4.0.1", 2036 + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 2037 + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 2038 + "license": "BSD-2-Clause", 2039 + "bin": { 2040 + "esparse": "bin/esparse.js", 2041 + "esvalidate": "bin/esvalidate.js" 2042 + }, 2043 + "engines": { 2044 + "node": ">=4" 2045 + } 2046 + }, 2047 + "node_modules/estraverse": { 2048 + "version": "5.3.0", 2049 + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 2050 + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 2051 + "license": "BSD-2-Clause", 2052 + "engines": { 2053 + "node": ">=4.0" 2054 + } 2055 + }, 2056 + "node_modules/esutils": { 2057 + "version": "2.0.3", 2058 + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 2059 + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 2060 + "license": "BSD-2-Clause", 2061 + "engines": { 2062 + "node": ">=0.10.0" 2063 + } 2064 + }, 1666 2065 "node_modules/etag": { 1667 2066 "version": "1.8.1", 1668 2067 "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", ··· 1670 2069 "license": "MIT", 1671 2070 "engines": { 1672 2071 "node": ">= 0.6" 2072 + } 2073 + }, 2074 + "node_modules/events-universal": { 2075 + "version": "1.0.1", 2076 + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", 2077 + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", 2078 + "license": "Apache-2.0", 2079 + "dependencies": { 2080 + "bare-events": "^2.7.0" 1673 2081 } 1674 2082 }, 1675 2083 "node_modules/express": { ··· 1740 2148 "url": "https://opencollective.com/express" 1741 2149 } 1742 2150 }, 2151 + "node_modules/extract-zip": { 2152 + "version": "2.0.1", 2153 + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", 2154 + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", 2155 + "license": "BSD-2-Clause", 2156 + "dependencies": { 2157 + "debug": "^4.1.1", 2158 + "get-stream": "^5.1.0", 2159 + "yauzl": "^2.10.0" 2160 + }, 2161 + "bin": { 2162 + "extract-zip": "cli.js" 2163 + }, 2164 + "engines": { 2165 + "node": ">= 10.17.0" 2166 + }, 2167 + "optionalDependencies": { 2168 + "@types/yauzl": "^2.9.1" 2169 + } 2170 + }, 2171 + "node_modules/fast-fifo": { 2172 + "version": "1.3.2", 2173 + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", 2174 + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", 2175 + "license": "MIT" 2176 + }, 2177 + "node_modules/fd-slicer": { 2178 + "version": "1.1.0", 2179 + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 2180 + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", 2181 + "license": "MIT", 2182 + "dependencies": { 2183 + "pend": "~1.2.0" 2184 + } 2185 + }, 1743 2186 "node_modules/finalhandler": { 1744 2187 "version": "2.1.1", 1745 2188 "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", ··· 1852 2295 "url": "https://github.com/sponsors/ljharb" 1853 2296 } 1854 2297 }, 2298 + "node_modules/get-caller-file": { 2299 + "version": "2.0.5", 2300 + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 2301 + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 2302 + "license": "ISC", 2303 + "engines": { 2304 + "node": "6.* || 8.* || >= 10.*" 2305 + } 2306 + }, 1855 2307 "node_modules/get-east-asian-width": { 1856 2308 "version": "1.4.0", 1857 2309 "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", ··· 1901 2353 "node": ">= 0.4" 1902 2354 } 1903 2355 }, 2356 + "node_modules/get-stream": { 2357 + "version": "5.2.0", 2358 + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 2359 + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 2360 + "license": "MIT", 2361 + "dependencies": { 2362 + "pump": "^3.0.0" 2363 + }, 2364 + "engines": { 2365 + "node": ">=8" 2366 + }, 2367 + "funding": { 2368 + "url": "https://github.com/sponsors/sindresorhus" 2369 + } 2370 + }, 1904 2371 "node_modules/get-tsconfig": { 1905 2372 "version": "4.13.0", 1906 2373 "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", ··· 1912 2379 }, 1913 2380 "funding": { 1914 2381 "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" 2382 + } 2383 + }, 2384 + "node_modules/get-uri": { 2385 + "version": "6.0.5", 2386 + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", 2387 + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", 2388 + "license": "MIT", 2389 + "dependencies": { 2390 + "basic-ftp": "^5.0.2", 2391 + "data-uri-to-buffer": "^6.0.2", 2392 + "debug": "^4.3.4" 2393 + }, 2394 + "engines": { 2395 + "node": ">= 14" 1915 2396 } 1916 2397 }, 1917 2398 "node_modules/gopd": { ··· 1985 2466 "url": "https://opencollective.com/express" 1986 2467 } 1987 2468 }, 2469 + "node_modules/http-proxy-agent": { 2470 + "version": "7.0.2", 2471 + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", 2472 + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", 2473 + "license": "MIT", 2474 + "dependencies": { 2475 + "agent-base": "^7.1.0", 2476 + "debug": "^4.3.4" 2477 + }, 2478 + "engines": { 2479 + "node": ">= 14" 2480 + } 2481 + }, 2482 + "node_modules/https-proxy-agent": { 2483 + "version": "7.0.6", 2484 + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", 2485 + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", 2486 + "license": "MIT", 2487 + "dependencies": { 2488 + "agent-base": "^7.1.2", 2489 + "debug": "4" 2490 + }, 2491 + "engines": { 2492 + "node": ">= 14" 2493 + } 2494 + }, 1988 2495 "node_modules/iconv-lite": { 1989 2496 "version": "0.7.1", 1990 2497 "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", ··· 2033 2540 } 2034 2541 } 2035 2542 }, 2543 + "node_modules/ip-address": { 2544 + "version": "10.1.0", 2545 + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", 2546 + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", 2547 + "license": "MIT", 2548 + "engines": { 2549 + "node": ">= 12" 2550 + } 2551 + }, 2036 2552 "node_modules/ipaddr.js": { 2037 2553 "version": "1.9.1", 2038 2554 "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", ··· 2040 2556 "license": "MIT", 2041 2557 "engines": { 2042 2558 "node": ">= 0.10" 2559 + } 2560 + }, 2561 + "node_modules/is-fullwidth-code-point": { 2562 + "version": "3.0.0", 2563 + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2564 + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2565 + "license": "MIT", 2566 + "engines": { 2567 + "node": ">=8" 2043 2568 } 2044 2569 }, 2045 2570 "node_modules/is-promise": { ··· 2169 2694 "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", 2170 2695 "license": "MIT" 2171 2696 }, 2697 + "node_modules/lru-cache": { 2698 + "version": "7.18.3", 2699 + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", 2700 + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", 2701 + "license": "ISC", 2702 + "engines": { 2703 + "node": ">=12" 2704 + } 2705 + }, 2172 2706 "node_modules/math-intrinsics": { 2173 2707 "version": "1.1.0", 2174 2708 "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", ··· 2220 2754 "node": ">= 0.6" 2221 2755 } 2222 2756 }, 2757 + "node_modules/mitt": { 2758 + "version": "3.0.1", 2759 + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", 2760 + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", 2761 + "license": "MIT" 2762 + }, 2223 2763 "node_modules/ms": { 2224 2764 "version": "2.1.3", 2225 2765 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", ··· 2260 2800 "node": ">= 0.6" 2261 2801 } 2262 2802 }, 2803 + "node_modules/netmask": { 2804 + "version": "2.0.2", 2805 + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", 2806 + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", 2807 + "license": "MIT", 2808 + "engines": { 2809 + "node": ">= 0.4.0" 2810 + } 2811 + }, 2263 2812 "node_modules/node-cron": { 2264 2813 "version": "4.2.1", 2265 2814 "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-4.2.1.tgz", ··· 2311 2860 "wrappy": "1" 2312 2861 } 2313 2862 }, 2863 + "node_modules/pac-proxy-agent": { 2864 + "version": "7.2.0", 2865 + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", 2866 + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", 2867 + "license": "MIT", 2868 + "dependencies": { 2869 + "@tootallnate/quickjs-emscripten": "^0.23.0", 2870 + "agent-base": "^7.1.2", 2871 + "debug": "^4.3.4", 2872 + "get-uri": "^6.0.1", 2873 + "http-proxy-agent": "^7.0.0", 2874 + "https-proxy-agent": "^7.0.6", 2875 + "pac-resolver": "^7.0.1", 2876 + "socks-proxy-agent": "^8.0.5" 2877 + }, 2878 + "engines": { 2879 + "node": ">= 14" 2880 + } 2881 + }, 2882 + "node_modules/pac-resolver": { 2883 + "version": "7.0.1", 2884 + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", 2885 + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", 2886 + "license": "MIT", 2887 + "dependencies": { 2888 + "degenerator": "^5.0.0", 2889 + "netmask": "^2.0.2" 2890 + }, 2891 + "engines": { 2892 + "node": ">= 14" 2893 + } 2894 + }, 2314 2895 "node_modules/parseurl": { 2315 2896 "version": "1.3.3", 2316 2897 "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", ··· 2330 2911 "url": "https://opencollective.com/express" 2331 2912 } 2332 2913 }, 2914 + "node_modules/pend": { 2915 + "version": "1.2.0", 2916 + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 2917 + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", 2918 + "license": "MIT" 2919 + }, 2920 + "node_modules/progress": { 2921 + "version": "2.0.3", 2922 + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 2923 + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 2924 + "license": "MIT", 2925 + "engines": { 2926 + "node": ">=0.4.0" 2927 + } 2928 + }, 2333 2929 "node_modules/proxy-addr": { 2334 2930 "version": "2.0.7", 2335 2931 "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", ··· 2343 2939 "node": ">= 0.10" 2344 2940 } 2345 2941 }, 2942 + "node_modules/proxy-agent": { 2943 + "version": "6.5.0", 2944 + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", 2945 + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", 2946 + "license": "MIT", 2947 + "dependencies": { 2948 + "agent-base": "^7.1.2", 2949 + "debug": "^4.3.4", 2950 + "http-proxy-agent": "^7.0.1", 2951 + "https-proxy-agent": "^7.0.6", 2952 + "lru-cache": "^7.14.1", 2953 + "pac-proxy-agent": "^7.1.0", 2954 + "proxy-from-env": "^1.1.0", 2955 + "socks-proxy-agent": "^8.0.5" 2956 + }, 2957 + "engines": { 2958 + "node": ">= 14" 2959 + } 2960 + }, 2346 2961 "node_modules/proxy-from-env": { 2347 2962 "version": "1.1.0", 2348 2963 "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 2349 2964 "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", 2350 2965 "license": "MIT" 2351 2966 }, 2967 + "node_modules/pump": { 2968 + "version": "3.0.3", 2969 + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", 2970 + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", 2971 + "license": "MIT", 2972 + "dependencies": { 2973 + "end-of-stream": "^1.1.0", 2974 + "once": "^1.3.1" 2975 + } 2976 + }, 2977 + "node_modules/puppeteer-core": { 2978 + "version": "24.34.0", 2979 + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.34.0.tgz", 2980 + "integrity": "sha512-24evawO+mUGW4mvS2a2ivwLdX3gk8zRLZr9HP+7+VT2vBQnm0oh9jJEZmUE3ePJhRkYlZ93i7OMpdcoi2qNCLg==", 2981 + "license": "Apache-2.0", 2982 + "dependencies": { 2983 + "@puppeteer/browsers": "2.11.0", 2984 + "chromium-bidi": "12.0.1", 2985 + "debug": "^4.4.3", 2986 + "devtools-protocol": "0.0.1534754", 2987 + "typed-query-selector": "^2.12.0", 2988 + "webdriver-bidi-protocol": "0.3.10", 2989 + "ws": "^8.18.3" 2990 + }, 2991 + "engines": { 2992 + "node": ">=18" 2993 + } 2994 + }, 2352 2995 "node_modules/qs": { 2353 2996 "version": "6.14.1", 2354 2997 "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", ··· 2388 3031 "node": ">= 0.10" 2389 3032 } 2390 3033 }, 3034 + "node_modules/require-directory": { 3035 + "version": "2.1.1", 3036 + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 3037 + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 3038 + "license": "MIT", 3039 + "engines": { 3040 + "node": ">=0.10.0" 3041 + } 3042 + }, 2391 3043 "node_modules/resolve-pkg-maps": { 2392 3044 "version": "1.0.0", 2393 3045 "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", ··· 2630 3282 "url": "https://github.com/sponsors/isaacs" 2631 3283 } 2632 3284 }, 3285 + "node_modules/smart-buffer": { 3286 + "version": "4.2.0", 3287 + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", 3288 + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", 3289 + "license": "MIT", 3290 + "engines": { 3291 + "node": ">= 6.0.0", 3292 + "npm": ">= 3.0.0" 3293 + } 3294 + }, 3295 + "node_modules/socks": { 3296 + "version": "2.8.7", 3297 + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", 3298 + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", 3299 + "license": "MIT", 3300 + "dependencies": { 3301 + "ip-address": "^10.0.1", 3302 + "smart-buffer": "^4.2.0" 3303 + }, 3304 + "engines": { 3305 + "node": ">= 10.0.0", 3306 + "npm": ">= 3.0.0" 3307 + } 3308 + }, 3309 + "node_modules/socks-proxy-agent": { 3310 + "version": "8.0.5", 3311 + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", 3312 + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", 3313 + "license": "MIT", 3314 + "dependencies": { 3315 + "agent-base": "^7.1.2", 3316 + "debug": "^4.3.4", 3317 + "socks": "^2.8.3" 3318 + }, 3319 + "engines": { 3320 + "node": ">= 14" 3321 + } 3322 + }, 3323 + "node_modules/source-map": { 3324 + "version": "0.6.1", 3325 + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 3326 + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 3327 + "license": "BSD-3-Clause", 3328 + "optional": true, 3329 + "engines": { 3330 + "node": ">=0.10.0" 3331 + } 3332 + }, 2633 3333 "node_modules/statuses": { 2634 3334 "version": "2.0.2", 2635 3335 "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", ··· 2639 3339 "node": ">= 0.8" 2640 3340 } 2641 3341 }, 3342 + "node_modules/streamx": { 3343 + "version": "2.23.0", 3344 + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", 3345 + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", 3346 + "license": "MIT", 3347 + "dependencies": { 3348 + "events-universal": "^1.0.0", 3349 + "fast-fifo": "^1.3.2", 3350 + "text-decoder": "^1.1.0" 3351 + } 3352 + }, 2642 3353 "node_modules/string-width": { 2643 3354 "version": "7.2.0", 2644 3355 "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", ··· 2671 3382 "url": "https://github.com/chalk/strip-ansi?sponsor=1" 2672 3383 } 2673 3384 }, 3385 + "node_modules/tar-fs": { 3386 + "version": "3.1.1", 3387 + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", 3388 + "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", 3389 + "license": "MIT", 3390 + "dependencies": { 3391 + "pump": "^3.0.0", 3392 + "tar-stream": "^3.1.5" 3393 + }, 3394 + "optionalDependencies": { 3395 + "bare-fs": "^4.0.1", 3396 + "bare-path": "^3.0.0" 3397 + } 3398 + }, 3399 + "node_modules/tar-stream": { 3400 + "version": "3.1.7", 3401 + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", 3402 + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", 3403 + "license": "MIT", 3404 + "dependencies": { 3405 + "b4a": "^1.6.4", 3406 + "fast-fifo": "^1.2.0", 3407 + "streamx": "^2.15.0" 3408 + } 3409 + }, 3410 + "node_modules/text-decoder": { 3411 + "version": "1.2.3", 3412 + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", 3413 + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", 3414 + "license": "Apache-2.0", 3415 + "dependencies": { 3416 + "b4a": "^1.6.4" 3417 + } 3418 + }, 2674 3419 "node_modules/tlds": { 2675 3420 "version": "1.261.0", 2676 3421 "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.261.0.tgz", ··· 2768 3513 "url": "https://opencollective.com/express" 2769 3514 } 2770 3515 }, 3516 + "node_modules/typed-query-selector": { 3517 + "version": "2.12.0", 3518 + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", 3519 + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", 3520 + "license": "MIT" 3521 + }, 2771 3522 "node_modules/typescript": { 2772 3523 "version": "5.9.3", 2773 3524 "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", ··· 2821 3572 "engines": { 2822 3573 "node": ">= 0.8" 2823 3574 } 3575 + }, 3576 + "node_modules/webdriver-bidi-protocol": { 3577 + "version": "0.3.10", 3578 + "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.3.10.tgz", 3579 + "integrity": "sha512-5LAE43jAVLOhB/QqX4bwSiv0Hg1HBfMmOuwBSXHdvg4GMGu9Y0lIq7p4R/yySu6w74WmaR4GM4H9t2IwLW7hgw==", 3580 + "license": "Apache-2.0" 2824 3581 }, 2825 3582 "node_modules/wrap-ansi": { 2826 3583 "version": "9.0.2", ··· 2844 3601 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2845 3602 "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 2846 3603 "license": "ISC" 3604 + }, 3605 + "node_modules/ws": { 3606 + "version": "8.18.3", 3607 + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", 3608 + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", 3609 + "license": "MIT", 3610 + "engines": { 3611 + "node": ">=10.0.0" 3612 + }, 3613 + "peerDependencies": { 3614 + "bufferutil": "^4.0.1", 3615 + "utf-8-validate": ">=5.0.2" 3616 + }, 3617 + "peerDependenciesMeta": { 3618 + "bufferutil": { 3619 + "optional": true 3620 + }, 3621 + "utf-8-validate": { 3622 + "optional": true 3623 + } 3624 + } 3625 + }, 3626 + "node_modules/y18n": { 3627 + "version": "5.0.8", 3628 + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 3629 + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 3630 + "license": "ISC", 3631 + "engines": { 3632 + "node": ">=10" 3633 + } 3634 + }, 3635 + "node_modules/yargs": { 3636 + "version": "17.7.2", 3637 + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 3638 + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 3639 + "license": "MIT", 3640 + "dependencies": { 3641 + "cliui": "^8.0.1", 3642 + "escalade": "^3.1.1", 3643 + "get-caller-file": "^2.0.5", 3644 + "require-directory": "^2.1.1", 3645 + "string-width": "^4.2.3", 3646 + "y18n": "^5.0.5", 3647 + "yargs-parser": "^21.1.1" 3648 + }, 3649 + "engines": { 3650 + "node": ">=12" 3651 + } 3652 + }, 3653 + "node_modules/yargs-parser": { 3654 + "version": "21.1.1", 3655 + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 3656 + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 3657 + "license": "ISC", 3658 + "engines": { 3659 + "node": ">=12" 3660 + } 3661 + }, 3662 + "node_modules/yargs/node_modules/ansi-regex": { 3663 + "version": "5.0.1", 3664 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 3665 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 3666 + "license": "MIT", 3667 + "engines": { 3668 + "node": ">=8" 3669 + } 3670 + }, 3671 + "node_modules/yargs/node_modules/emoji-regex": { 3672 + "version": "8.0.0", 3673 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 3674 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 3675 + "license": "MIT" 3676 + }, 3677 + "node_modules/yargs/node_modules/string-width": { 3678 + "version": "4.2.3", 3679 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 3680 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 3681 + "license": "MIT", 3682 + "dependencies": { 3683 + "emoji-regex": "^8.0.0", 3684 + "is-fullwidth-code-point": "^3.0.0", 3685 + "strip-ansi": "^6.0.1" 3686 + }, 3687 + "engines": { 3688 + "node": ">=8" 3689 + } 3690 + }, 3691 + "node_modules/yargs/node_modules/strip-ansi": { 3692 + "version": "6.0.1", 3693 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 3694 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 3695 + "license": "MIT", 3696 + "dependencies": { 3697 + "ansi-regex": "^5.0.1" 3698 + }, 3699 + "engines": { 3700 + "node": ">=8" 3701 + } 3702 + }, 3703 + "node_modules/yauzl": { 3704 + "version": "2.10.0", 3705 + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 3706 + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", 3707 + "license": "MIT", 3708 + "dependencies": { 3709 + "buffer-crc32": "~0.2.3", 3710 + "fd-slicer": "~1.1.0" 3711 + } 2847 3712 }, 2848 3713 "node_modules/zod": { 2849 3714 "version": "3.25.76",
+2 -1
package.json
··· 37 37 "inquirer": "^13.1.0", 38 38 "iso-639-1": "^3.1.2", 39 39 "jsonwebtoken": "^9.0.3", 40 - "node-cron": "^4.2.1" 40 + "node-cron": "^4.2.1", 41 + "puppeteer-core": "^24.34.0" 41 42 }, 42 43 "devDependencies": { 43 44 "@biomejs/biome": "^1.9.4",
+81 -2
src/index.ts
··· 10 10 import { Command } from 'commander'; 11 11 import * as francModule from 'franc-min'; 12 12 import iso6391 from 'iso-639-1'; 13 + import os from 'node:os'; 14 + import puppeteer from 'puppeteer-core'; 13 15 import { getConfig } from './config-manager.js'; 14 16 15 17 // ESM __dirname equivalent ··· 259 261 async function uploadToBluesky(agent: BskyAgent, buffer: Buffer, mimeType: string): Promise<BlobRef> { 260 262 const { data } = await agent.uploadBlob(buffer, { encoding: mimeType }); 261 263 return data.blob; 264 + } 265 + 266 + async function captureTweetScreenshot(tweetUrl: string): Promise<Buffer | null> { 267 + console.log(`[SCREENSHOT] 📸 Capturing screenshot for: ${tweetUrl}`); 268 + let browser; 269 + try { 270 + browser = await puppeteer.launch({ 271 + executablePath: '/usr/bin/google-chrome', 272 + args: ['--no-sandbox', '--disable-setuid-sandbox'], 273 + }); 274 + const page = await browser.newPage(); 275 + await page.setViewport({ width: 800, height: 1200, deviceScaleFactor: 2 }); 276 + 277 + const html = ` 278 + <!DOCTYPE html> 279 + <html> 280 + <head> 281 + <style> 282 + body { 283 + margin: 0; 284 + padding: 20px; 285 + background: #ffffff; 286 + display: flex; 287 + justify-content: center; 288 + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; 289 + } 290 + #container { width: 550px; } 291 + </style> 292 + </head> 293 + <body> 294 + <div id="container"> 295 + <blockquote class="twitter-tweet" data-dnt="true"> 296 + <a href="${tweetUrl}"></a> 297 + </blockquote> 298 + <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 299 + </div> 300 + </body> 301 + </html> 302 + `; 303 + 304 + await page.setContent(html, { waitUntil: 'networkidle0' }); 305 + 306 + // Wait for the twitter iframe to load and render 307 + try { 308 + await page.waitForSelector('iframe', { timeout: 10000 }); 309 + // Small extra wait for images inside iframe 310 + await new Promise(r => setTimeout(r, 2000)); 311 + } catch (e) { 312 + console.warn(`[SCREENSHOT] ⚠️ Timeout waiting for tweet iframe, taking screenshot anyway.`); 313 + } 314 + 315 + const element = await page.$('#container'); 316 + if (element) { 317 + const buffer = await element.screenshot({ type: 'png', omitBackground: true }); 318 + console.log(`[SCREENSHOT] ✅ Captured successfully (${(buffer.length / 1024).toFixed(2)} KB)`); 319 + return buffer as Buffer; 320 + } 321 + } catch (err) { 322 + console.error(`[SCREENSHOT] ❌ Error capturing tweet:`, (err as Error).message); 323 + } finally { 324 + if (browser) await browser.close(); 325 + } 326 + return null; 262 327 } 263 328 264 329 async function uploadVideoToBluesky(agent: BskyAgent, buffer: Buffer, filename: string): Promise<BlobRef> { ··· 606 671 if (!isSelfQuote) { 607 672 externalQuoteUrl = qUrl; 608 673 console.log(`[${twitterUsername}] 🔗 Quoted tweet is external: ${externalQuoteUrl}`); 674 + 675 + // Try to capture screenshot for external QTs if we have space for images 676 + if (images.length < 4 && !videoBlob) { 677 + const ssBuffer = await captureTweetScreenshot(externalQuoteUrl); 678 + if (ssBuffer) { 679 + try { 680 + const blob = await uploadToBluesky(agent, ssBuffer, 'image/png'); 681 + images.push({ alt: `Quote Tweet: ${externalQuoteUrl}`, image: blob }); 682 + } catch (e) { 683 + console.warn(`[${twitterUsername}] ⚠️ Failed to upload screenshot blob.`); 684 + } 685 + } 686 + } 609 687 } else { 610 688 console.log(`[${twitterUsername}] 🔁 Quoted tweet is a self-quote, skipping link.`); 611 689 } 612 690 } 613 691 } 614 692 615 - // Only append link for external quotes IF we couldn't natively embed it 616 - if (externalQuoteUrl && !quoteEmbed && !text.includes(externalQuoteUrl)) { 693 + // Only append link for external quotes IF we couldn't natively embed it OR screenshot it 694 + const hasScreenshot = images.some(img => img.alt.startsWith('Quote Tweet:')); 695 + if (externalQuoteUrl && !quoteEmbed && !hasScreenshot && !text.includes(externalQuoteUrl)) { 617 696 text += `\n\nQT: ${externalQuoteUrl}`; 618 697 } 619 698