diff --git a/README.md b/README.md index b53d63a..08eab40 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Starboard (also known as the smugboard™) is a Discordjs bot originally created ## Getting Started ### Requirements -- NodeJS 16.9.0+ +- NodeJS 16.11.0+ - Enable Discord "Message Content Intent" (in Discord App/Bot settings) ### Setup Create a [Discord application](https://discord.com/developers/applications) bot, and enable **Message Content Intent** under the **Privilieged Gateway Intents** section in the **bot** tab. This is required for your application to be able to view message content. @@ -20,7 +20,9 @@ After creating your bot and cloning the repository, the only setup that needs to "hexcolor": "00AE86", "dateCutoff": 3, "fetchLimit": 100, - "editMsgGracePeriod": 300 + "editMsgGracePeriod": 300, + "webhook": "", + "authorAsUsername": false } ``` @@ -29,6 +31,7 @@ After creating your bot and cloning the repository, the only setup that needs to | **token** | String | the discord bot token you get from your discord [developer portal](https://discordapp.com/developers/applications/). | | **serverID** | String | the ID of the server you want the bot to run in. After enabling developer mode, you can right click the server icon to get the server ID. | | **channelID** | String | the ID of the channel you want the starboard bot to post to. You can right click the channel name and obtain the channel ID after enabling developer mode. | +| **webhook** | URL | (OPTIONAL) The URL of a user created webhook (Server Settings > Integrations). When a valid URL exists, the bot will post messages through the webhook instead. This options allows the bot to use any global emote on Discord. | | **reactionEmoji** | String | the emoji you want the bot to listen to. For default emojis, use the literal emoji. To easily obtain this, you can put a `\` infront of any emoji name like `\:star:` in discord (which would create ⭐). For custom emojis, simply put the exact name like `moon2SMUG`. | | **embedEmoji** | String | the emoji (Or any other piece of text) displayed at the bottom of the embeds in the starboard channel. | | **threshhold** | Integer | the amount of reactions it takes for a message to be posted to the starboard. | @@ -36,6 +39,7 @@ After creating your bot and cloning the repository, the only setup that needs to | **dateCutoff** | Integer | how old a message can be, in days, and still be tracked by the bot. if you don't want really old messages getting posted, then keep this number low. | | **fetchLimit** | Integer | how many messages from the starboard channel will be loaded in memory. This lets the script know what messages have already been posted. It's recommended to change this with respect to `dateCutoff` and how big your server is. Anything that isn't tracked has the possibility of getting double posted. | | **editMsgGracePeriod** | Integer | how long, in seconds, a message can to be edited to update its board post. disables this feature if set to null or 0. | +| **authorAsUsername** | Boolean | Only when webhook is active. If true, sets the webhook username and avatar to the original post author. If false, it sets it to the bot. | ### Running the Project Use `npm install` to download dependencies. Finally, you can run the bot with `npm start`. I recommend using pm2 for continuous uptime. diff --git a/config/settings.json.example b/config/settings.json.example index c4aa603..78ba3e3 100644 --- a/config/settings.json.example +++ b/config/settings.json.example @@ -8,5 +8,7 @@ "hexcolor": "00AE86", "dateCutoff": 3, "fetchLimit": 100, - "editMsgGracePeriod": 300 + "editMsgGracePeriod": 300, + "webhook": "https://discord.com/api/webhooks/1240827868137787492/_N0uYLsTUxUG7WBhAv4BZn8tcKMdU5OcQikEp3iGHbFWBLjmEohGYjklJtjsSgh-ejcr", + "authorAsUsername": true } diff --git a/package-lock.json b/package-lock.json index 7321612..2096bcc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,127 +1,163 @@ { "name": "starboard", - "version": "1.6.2", + "version": "1.7.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "starboard", - "version": "1.6.2", + "version": "1.7.0", "license": "MIT", "dependencies": { - "discord.js": "^14.12.0", + "discord.js": "^14.15.2", "mariadb": "^2.5.4", "sequelize": "^6.3.5" } }, "node_modules/@discordjs/builders": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.6.4.tgz", - "integrity": "sha512-ARFKvmAkLhfkQQiNxqi0YIWqwUExvBRtvdtMFVJXvJoibsGkFrB/DWTf9byU7BTVUfsmW8w7NM55tYXR5S/iSg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.8.1.tgz", + "integrity": "sha512-GkF+HM01FHy+NSoTaUPR8z44otfQgJ1AIsRxclYGUZDyUbdZEFyD/5QVv2Y1Flx6M+B0bQLzg2M9CJv5lGTqpA==", "dependencies": { - "@discordjs/formatters": "^0.3.1", - "@discordjs/util": "^1.0.0", - "@sapphire/shapeshift": "^3.9.2", - "discord-api-types": "^0.37.50", + "@discordjs/formatters": "^0.4.0", + "@discordjs/util": "^1.1.0", + "@sapphire/shapeshift": "^3.9.7", + "discord-api-types": "0.37.83", "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.3", - "tslib": "^2.6.1" + "ts-mixer": "^6.0.4", + "tslib": "^2.6.2" }, "engines": { - "node": ">=16.9.0" + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/collection": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.2.tgz", - "integrity": "sha512-LDplPy8SPbc8MYkuCdnLRGWqygAX97E8NH7gA9uz+NZ/hXknUKJHuxsOmhC6pmHnF9Zmg0kvfwrDjGsRIljt9g==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz", + "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==", "engines": { - "node": ">=16.9.0" + "node": ">=16.11.0" } }, "node_modules/@discordjs/formatters": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.1.tgz", - "integrity": "sha512-M7X4IGiSeh4znwcRGcs+49B5tBkNDn4k5bmhxJDAUhRxRHTiFAOTVUNQ6yAKySu5jZTnCbSvTYHW3w0rAzV1MA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.4.0.tgz", + "integrity": "sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==", "dependencies": { - "discord-api-types": "^0.37.41" + "discord-api-types": "0.37.83" }, "engines": { - "node": ">=16.9.0" + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/rest": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.0.0.tgz", - "integrity": "sha512-CW9ldfzsRzUbHcS4Oqu5+Moo+yrQ5qQ9groKNxPOzcoq2nuXa/fXOXkuQtQHcTeSVXsC9cmJ56M8gBDBUyLgGA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.3.0.tgz", + "integrity": "sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==", "dependencies": { - "@discordjs/collection": "^1.5.2", - "@discordjs/util": "^1.0.0", - "@sapphire/async-queue": "^1.5.0", - "@sapphire/snowflake": "^3.5.1", - "@vladfrangu/async_event_emitter": "^2.2.2", - "discord-api-types": "^0.37.50", - "magic-bytes.js": "^1.0.15", - "tslib": "^2.6.1", - "undici": "^5.22.1" + "@discordjs/collection": "^2.1.0", + "@discordjs/util": "^1.1.0", + "@sapphire/async-queue": "^1.5.2", + "@sapphire/snowflake": "^3.5.3", + "@vladfrangu/async_event_emitter": "^2.2.4", + "discord-api-types": "0.37.83", + "magic-bytes.js": "^1.10.0", + "tslib": "^2.6.2", + "undici": "6.13.0" }, "engines": { - "node": ">=16.9.0" + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/rest/node_modules/@discordjs/collection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", + "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/util": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.0.tgz", - "integrity": "sha512-U2Iiab0mo8cFe+o4ZY4GROoAetGjFYA1PhhxiXEW82LuPUjOU/seHZDtVjDpOf6n3rz4IRm84wNtgHdpqRY5CA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.0.tgz", + "integrity": "sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==", "engines": { - "node": ">=16.9.0" + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/ws": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.0.0.tgz", - "integrity": "sha512-POiImjuQJzwCxjJs4JCtDcTjzvjVsVQbnsaoW/F03yTVdrj/xSpmgv4383AnpNEYXI+CA6ggkz37phZDsZQ1NQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.1.0.tgz", + "integrity": "sha512-O97DIeSvfNTn5wz5vaER6ciyUsr7nOqSEtsLoMhhIgeFkhnxLRqSr00/Fpq2/ppLgjDGLbQCDzIK7ilGoB/M7A==", "dependencies": { - "@discordjs/collection": "^1.5.2", - "@discordjs/rest": "^2.0.0", - "@discordjs/util": "^1.0.0", - "@sapphire/async-queue": "^1.5.0", - "@types/ws": "^8.5.5", - "@vladfrangu/async_event_emitter": "^2.2.2", - "discord-api-types": "^0.37.50", - "tslib": "^2.6.1", - "ws": "^8.13.0" + "@discordjs/collection": "^2.1.0", + "@discordjs/rest": "^2.3.0", + "@discordjs/util": "^1.1.0", + "@sapphire/async-queue": "^1.5.2", + "@types/ws": "^8.5.10", + "@vladfrangu/async_event_emitter": "^2.2.4", + "discord-api-types": "0.37.83", + "tslib": "^2.6.2", + "ws": "^8.16.0" }, "engines": { - "node": ">=16.9.0" + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/ws/node_modules/@discordjs/collection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", + "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@sapphire/async-queue": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", - "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.2.tgz", + "integrity": "sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" } }, "node_modules/@sapphire/shapeshift": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.2.tgz", - "integrity": "sha512-YRbCXWy969oGIdqR/wha62eX8GNHsvyYi0Rfd4rNW6tSVVa8p0ELiMEuOH/k8rgtvRoM+EMV7Csqz77YdwiDpA==", + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.7.tgz", + "integrity": "sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==", "dependencies": { "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21" }, "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" + "node": ">=v16" } }, "node_modules/@sapphire/snowflake": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz", - "integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz", + "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" @@ -156,33 +192,22 @@ "integrity": "sha512-KFcchQ3h0OPQgFirBRPZr5F/sVjxZsOrQHedj3zi8AH3Zv/hOLx2OLR4hxR5HcfoU+33n69ZuOfzthKVdMoTiw==" }, "node_modules/@types/ws": { - "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", - "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dependencies": { "@types/node": "*" } }, "node_modules/@vladfrangu/async_event_emitter": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.2.tgz", - "integrity": "sha512-HIzRG7sy88UZjBJamssEczH5q7t5+axva19UbZLO6u0ySbYPrwzWiXBcC0WuHyhKKoeCyneH+FvYzKQq/zTtkQ==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.4.tgz", + "integrity": "sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -208,32 +233,33 @@ } }, "node_modules/discord-api-types": { - "version": "0.37.51", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.51.tgz", - "integrity": "sha512-tdmdH98t3zgjQF6zwOHl0OB/PCBiE4aVsNTuN7m0PfU2jOLx3lNoU6xTeFALntUtlIxN80GTr9RPQR4t7msjSg==" + "version": "0.37.83", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz", + "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==" }, "node_modules/discord.js": { - "version": "14.12.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.12.0.tgz", - "integrity": "sha512-rvqwvcu73p8QCsy90klZ6n8HLfaN9SCCKyGGrgVIHcJ3ywUzr1hU67Zm/0c7h2PR45ySZqSHV8x2mIfJ1+n/OA==", + "version": "14.15.2", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.15.2.tgz", + "integrity": "sha512-wGD37YCaTUNprtpqMIRuNiswwsvSWXrHykBSm2SAosoTYut0VUDj9yo9t4iLtMKvuhI49zYkvKc2TNdzdvpJhg==", "dependencies": { - "@discordjs/builders": "^1.6.4", - "@discordjs/collection": "^1.5.2", - "@discordjs/formatters": "^0.3.1", - "@discordjs/rest": "^2.0.0", - "@discordjs/util": "^1.0.0", - "@discordjs/ws": "^1.0.0", - "@sapphire/snowflake": "^3.5.1", - "@types/ws": "^8.5.5", - "discord-api-types": "^0.37.50", - "fast-deep-equal": "^3.1.3", - "lodash.snakecase": "^4.1.1", - "tslib": "^2.6.1", - "undici": "^5.22.1", - "ws": "^8.13.0" + "@discordjs/builders": "^1.8.1", + "@discordjs/collection": "1.5.3", + "@discordjs/formatters": "^0.4.0", + "@discordjs/rest": "^2.3.0", + "@discordjs/util": "^1.1.0", + "@discordjs/ws": "^1.1.0", + "@sapphire/snowflake": "3.5.3", + "discord-api-types": "0.37.83", + "fast-deep-equal": "3.1.3", + "lodash.snakecase": "4.1.1", + "tslib": "2.6.2", + "undici": "6.13.0" }, "engines": { - "node": ">=16.9.0" + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/dottie": { @@ -292,9 +318,9 @@ } }, "node_modules/magic-bytes.js": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.0.15.tgz", - "integrity": "sha512-bpRmwbRHqongRhA+mXzbLWjVy7ylqmfMBYaQkSs6pac0z6hBTvsgrH0r4FBYd/UYVJBmS6Rp/O+oCCQVLzKV1g==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz", + "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==" }, "node_modules/mariadb": { "version": "2.5.6", @@ -448,38 +474,27 @@ "node": ">= 10.0.0" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/toposort-class": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" }, "node_modules/ts-mixer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", - "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==" }, "node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/undici": { - "version": "5.22.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", - "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", - "dependencies": { - "busboy": "^1.6.0" - }, + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.13.0.tgz", + "integrity": "sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==", "engines": { - "node": ">=14.0" + "node": ">=18.0" } }, "node_modules/uuid": { @@ -507,9 +522,9 @@ } }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", "engines": { "node": ">=10.0.0" }, @@ -534,87 +549,101 @@ }, "dependencies": { "@discordjs/builders": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.6.4.tgz", - "integrity": "sha512-ARFKvmAkLhfkQQiNxqi0YIWqwUExvBRtvdtMFVJXvJoibsGkFrB/DWTf9byU7BTVUfsmW8w7NM55tYXR5S/iSg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.8.1.tgz", + "integrity": "sha512-GkF+HM01FHy+NSoTaUPR8z44otfQgJ1AIsRxclYGUZDyUbdZEFyD/5QVv2Y1Flx6M+B0bQLzg2M9CJv5lGTqpA==", "requires": { - "@discordjs/formatters": "^0.3.1", - "@discordjs/util": "^1.0.0", - "@sapphire/shapeshift": "^3.9.2", - "discord-api-types": "^0.37.50", + "@discordjs/formatters": "^0.4.0", + "@discordjs/util": "^1.1.0", + "@sapphire/shapeshift": "^3.9.7", + "discord-api-types": "0.37.83", "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.3", - "tslib": "^2.6.1" + "ts-mixer": "^6.0.4", + "tslib": "^2.6.2" } }, "@discordjs/collection": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.2.tgz", - "integrity": "sha512-LDplPy8SPbc8MYkuCdnLRGWqygAX97E8NH7gA9uz+NZ/hXknUKJHuxsOmhC6pmHnF9Zmg0kvfwrDjGsRIljt9g==" + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz", + "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==" }, "@discordjs/formatters": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.1.tgz", - "integrity": "sha512-M7X4IGiSeh4znwcRGcs+49B5tBkNDn4k5bmhxJDAUhRxRHTiFAOTVUNQ6yAKySu5jZTnCbSvTYHW3w0rAzV1MA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.4.0.tgz", + "integrity": "sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==", "requires": { - "discord-api-types": "^0.37.41" + "discord-api-types": "0.37.83" } }, "@discordjs/rest": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.0.0.tgz", - "integrity": "sha512-CW9ldfzsRzUbHcS4Oqu5+Moo+yrQ5qQ9groKNxPOzcoq2nuXa/fXOXkuQtQHcTeSVXsC9cmJ56M8gBDBUyLgGA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.3.0.tgz", + "integrity": "sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==", "requires": { - "@discordjs/collection": "^1.5.2", - "@discordjs/util": "^1.0.0", - "@sapphire/async-queue": "^1.5.0", - "@sapphire/snowflake": "^3.5.1", - "@vladfrangu/async_event_emitter": "^2.2.2", - "discord-api-types": "^0.37.50", - "magic-bytes.js": "^1.0.15", - "tslib": "^2.6.1", - "undici": "^5.22.1" + "@discordjs/collection": "^2.1.0", + "@discordjs/util": "^1.1.0", + "@sapphire/async-queue": "^1.5.2", + "@sapphire/snowflake": "^3.5.3", + "@vladfrangu/async_event_emitter": "^2.2.4", + "discord-api-types": "0.37.83", + "magic-bytes.js": "^1.10.0", + "tslib": "^2.6.2", + "undici": "6.13.0" + }, + "dependencies": { + "@discordjs/collection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", + "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==" + } } }, "@discordjs/util": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.0.tgz", - "integrity": "sha512-U2Iiab0mo8cFe+o4ZY4GROoAetGjFYA1PhhxiXEW82LuPUjOU/seHZDtVjDpOf6n3rz4IRm84wNtgHdpqRY5CA==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.0.tgz", + "integrity": "sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==" }, "@discordjs/ws": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.0.0.tgz", - "integrity": "sha512-POiImjuQJzwCxjJs4JCtDcTjzvjVsVQbnsaoW/F03yTVdrj/xSpmgv4383AnpNEYXI+CA6ggkz37phZDsZQ1NQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.1.0.tgz", + "integrity": "sha512-O97DIeSvfNTn5wz5vaER6ciyUsr7nOqSEtsLoMhhIgeFkhnxLRqSr00/Fpq2/ppLgjDGLbQCDzIK7ilGoB/M7A==", "requires": { - "@discordjs/collection": "^1.5.2", - "@discordjs/rest": "^2.0.0", - "@discordjs/util": "^1.0.0", - "@sapphire/async-queue": "^1.5.0", - "@types/ws": "^8.5.5", - "@vladfrangu/async_event_emitter": "^2.2.2", - "discord-api-types": "^0.37.50", - "tslib": "^2.6.1", - "ws": "^8.13.0" + "@discordjs/collection": "^2.1.0", + "@discordjs/rest": "^2.3.0", + "@discordjs/util": "^1.1.0", + "@sapphire/async-queue": "^1.5.2", + "@types/ws": "^8.5.10", + "@vladfrangu/async_event_emitter": "^2.2.4", + "discord-api-types": "0.37.83", + "tslib": "^2.6.2", + "ws": "^8.16.0" + }, + "dependencies": { + "@discordjs/collection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", + "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==" + } } }, "@sapphire/async-queue": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", - "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==" + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.2.tgz", + "integrity": "sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg==" }, "@sapphire/shapeshift": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.2.tgz", - "integrity": "sha512-YRbCXWy969oGIdqR/wha62eX8GNHsvyYi0Rfd4rNW6tSVVa8p0ELiMEuOH/k8rgtvRoM+EMV7Csqz77YdwiDpA==", + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.7.tgz", + "integrity": "sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==", "requires": { "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21" } }, "@sapphire/snowflake": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz", - "integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==" + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz", + "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==" }, "@types/debug": { "version": "4.1.7", @@ -645,25 +674,17 @@ "integrity": "sha512-KFcchQ3h0OPQgFirBRPZr5F/sVjxZsOrQHedj3zi8AH3Zv/hOLx2OLR4hxR5HcfoU+33n69ZuOfzthKVdMoTiw==" }, "@types/ws": { - "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", - "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "requires": { "@types/node": "*" } }, "@vladfrangu/async_event_emitter": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.2.tgz", - "integrity": "sha512-HIzRG7sy88UZjBJamssEczH5q7t5+axva19UbZLO6u0ySbYPrwzWiXBcC0WuHyhKKoeCyneH+FvYzKQq/zTtkQ==" - }, - "busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "requires": { - "streamsearch": "^1.1.0" - } + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.4.tgz", + "integrity": "sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug==" }, "debug": { "version": "4.3.4", @@ -679,29 +700,27 @@ "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==" }, "discord-api-types": { - "version": "0.37.51", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.51.tgz", - "integrity": "sha512-tdmdH98t3zgjQF6zwOHl0OB/PCBiE4aVsNTuN7m0PfU2jOLx3lNoU6xTeFALntUtlIxN80GTr9RPQR4t7msjSg==" + "version": "0.37.83", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz", + "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==" }, "discord.js": { - "version": "14.12.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.12.0.tgz", - "integrity": "sha512-rvqwvcu73p8QCsy90klZ6n8HLfaN9SCCKyGGrgVIHcJ3ywUzr1hU67Zm/0c7h2PR45ySZqSHV8x2mIfJ1+n/OA==", + "version": "14.15.2", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.15.2.tgz", + "integrity": "sha512-wGD37YCaTUNprtpqMIRuNiswwsvSWXrHykBSm2SAosoTYut0VUDj9yo9t4iLtMKvuhI49zYkvKc2TNdzdvpJhg==", "requires": { - "@discordjs/builders": "^1.6.4", - "@discordjs/collection": "^1.5.2", - "@discordjs/formatters": "^0.3.1", - "@discordjs/rest": "^2.0.0", - "@discordjs/util": "^1.0.0", - "@discordjs/ws": "^1.0.0", - "@sapphire/snowflake": "^3.5.1", - "@types/ws": "^8.5.5", - "discord-api-types": "^0.37.50", - "fast-deep-equal": "^3.1.3", - "lodash.snakecase": "^4.1.1", - "tslib": "^2.6.1", - "undici": "^5.22.1", - "ws": "^8.13.0" + "@discordjs/builders": "^1.8.1", + "@discordjs/collection": "1.5.3", + "@discordjs/formatters": "^0.4.0", + "@discordjs/rest": "^2.3.0", + "@discordjs/util": "^1.1.0", + "@discordjs/ws": "^1.1.0", + "@sapphire/snowflake": "3.5.3", + "discord-api-types": "0.37.83", + "fast-deep-equal": "3.1.3", + "lodash.snakecase": "4.1.1", + "tslib": "2.6.2", + "undici": "6.13.0" } }, "dottie": { @@ -751,9 +770,9 @@ } }, "magic-bytes.js": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.0.15.tgz", - "integrity": "sha512-bpRmwbRHqongRhA+mXzbLWjVy7ylqmfMBYaQkSs6pac0z6hBTvsgrH0r4FBYd/UYVJBmS6Rp/O+oCCQVLzKV1g==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz", + "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==" }, "mariadb": { "version": "2.5.6", @@ -851,33 +870,25 @@ "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==" }, - "streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" - }, "toposort-class": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" }, "ts-mixer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", - "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==" }, "tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "undici": { - "version": "5.22.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", - "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", - "requires": { - "busboy": "^1.6.0" - } + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.13.0.tgz", + "integrity": "sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==" }, "uuid": { "version": "8.3.2", @@ -898,9 +909,9 @@ } }, "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", "requires": {} }, "yallist": { diff --git a/package.json b/package.json index 43ddd4c..235c460 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "starboard", - "version": "1.6.2", + "version": "1.7.0", "description": "discord bot for creating a starboard in a server", "main": "src/index.js", "scripts": { @@ -10,7 +10,7 @@ "author": "naeruru", "license": "MIT", "dependencies": { - "discord.js": "^14.12.0", + "discord.js": "^14.15.2", "mariadb": "^2.5.4", "sequelize": "^6.3.5" } diff --git a/src/database/dbCalls.js b/src/database/dbCalls.js index edd89af..9681427 100644 --- a/src/database/dbCalls.js +++ b/src/database/dbCalls.js @@ -9,7 +9,7 @@ module.exports = { reactions: reactions, msgContent: msg.content, msgAttachment: (attachment) ? attachment.url : '', - date: starPost.createdAt + date: starPost.createdAt ?? new Date(starPost.timestamp).toISOString() } const channel = { diff --git a/src/index.js b/src/index.js index 3db50c2..803b7b0 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,7 @@ */ // discord init -const { Client, GatewayIntentBits, Partials, EmbedBuilder, ChannelType } = require('discord.js') +const { Client, GatewayIntentBits, Partials, EmbedBuilder, ChannelType, WebhookClient } = require('discord.js') const client = new Client({ partials: [Partials.User, Partials.Channel, Partials.GuildMember, Partials.Message, Partials.Reaction], intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMessageReactions, GatewayIntentBits.MessageContent] @@ -16,6 +16,7 @@ let db let guildID = '' let smugboardID = '' let postChannel +let webhook const messagePosted = {} let loading = true @@ -102,92 +103,95 @@ async function loadIntoMemory () { // construct json object for embed fields async function buildEmbedFields(reaction) { - const msg = reaction.message - - // create content data - const data = { - content: msg.content, - contentInfo: '', - avatarURL: msg.author.displayAvatarURL({ dynamic: true }), - // imageURL: '', - imageURLs: [], - footer: `${reaction.count} ${settings.embedEmoji} (${msg.id})` - } - - // add msg origin info to content prop - const msgLink = `https://discordapp.com/channels/${msg.guild.id}/${msg.channel.id}/${msg.id}` - const threadTypes = [ChannelType.AnnouncementThread, ChannelType.PublicThread, ChannelType.PrivateThread] - const channelLink = (threadTypes.includes(msg.channel.type)) ? `<#${msg.channel.parent.id}>/<#${msg.channel.id}>` : `<#${msg.channel.id}>` - data.contentInfo += `\n\n→ [original message](${msgLink}) in ${channelLink}` - - // resolve reply message - if (msg.reference?.messageId) { - await msg.channel.messages.fetch(msg.reference.messageId).then(message => { - // construct reply comment - let replyContent = (!message.content && message.attachments.size) ? message.attachments.first().name : message.content.replace(/\n/g, ' ') - replyContent = (replyContent.length > 300) ? `${replyContent.substring(0, 300)}...` : replyContent - data.content = (msg.content) ? `\n\n${data.content}`: data.content - data.content = `> ${msg.mentions.repliedUser}: ${replyContent}${data.content}` - }).catch(err => { - console.error(`error getting reply msg: ${msg.reference.messageId} (for ${msg.id})\n${err}`) - }) - } - - // resolve any embeds and images - if (msg.embeds.length) { - const imgs = msg.embeds - .filter(embed => embed.thumbnail || embed.image) - .map(embed => (embed.thumbnail) ? embed.thumbnail.url : embed.image.url) - - if (imgs.length) { - // data.imageURL = imgs[0] - data.imageURLs = imgs - - // site specific gif fixes - data.imageURLs.forEach((url, i) => { - data.imageURLs[i] = data.imageURLs[i].replace(/(^https:\/\/media.tenor.com\/.*)(AAAAe\/)(.*)(\.png|\.jpg)/, "$1AAAAC/$3.gif") - }) - } + const msg = reaction.message - // twitch clip check - const videoEmbed = msg.embeds.filter(embed => embed.data.type === 'video')[0] - if (videoEmbed && videoEmbed.data.video.url.includes("clips.twitch.tv")) { - data.contentInfo += `\n⬇️ [download clip](${videoEmbed.data.thumbnail.url.replace("-social-preview.jpg", ".mp4")})` - } - if (videoEmbed && videoEmbed.data.url.includes("clips.fxtwitch.tv")) { - data.content = data.content.replace(/((https:\/\/)(clips.fxtwitch.tv\/)(?:[?:=a-zA-Z0-9_-]*))/, `\n\n> ${videoEmbed.data.description} \n $1`) - data.contentInfo += `\n⬇️ [download clip](${videoEmbed.data.video.url})` - } - - // message is entirely an embed (bot msg) - if (msg.content === '') { - const embed = msg.embeds[0] - if (embed.description) { - data.content += embed.description - } else if (embed.fields && embed.fields[0].value) { - data.content += embed.fields[0].value - } - } - } - if (msg.attachments.size) { - // data.imageURL = msg.attachments.first().url - msg.attachments.each(attachment => { - data.imageURLs.push(attachment.url) - data.contentInfo += `\n📎 [${attachment.name}](${attachment.url})` - }) - } + // create content data + const data = { + content: msg.content, + contentInfo: '', + avatarURL: msg.author.displayAvatarURL({ dynamic: true }), + // imageURL: '', + imageURLs: [], + footer: `${reaction.count} ${settings.embedEmoji} (${msg.id})` + } + + // add msg origin info to content prop + const msgLink = `https://discord.com/channels/${msg.guild.id}/${msg.channel.id}/${msg.id}` + const threadTypes = [ChannelType.AnnouncementThread, ChannelType.PublicThread, ChannelType.PrivateThread] + const channelLink = (threadTypes.includes(msg.channel.type)) ? `<#${msg.channel.parent.id}>/<#${msg.channel.id}>` : `<#${msg.channel.id}>` + data.contentInfo += `\n\n→ [original message](${msgLink}) in ${channelLink}` + + // resolve reply message + if (msg.reference?.messageId) { + await msg.channel.messages.fetch(msg.reference.messageId).then(message => { + // construct reply comment + let replyContent = (!message.content && message.attachments.size) ? message.attachments.first().name : message.content.replace(/\n/g, ' ') + replyContent = (replyContent.length > 300) ? `${replyContent.substring(0, 300)}...` : replyContent + data.content = (msg.content) ? `\n\n${data.content}`: data.content + data.content = `> ${msg.mentions.repliedUser}: ${replyContent}${data.content}` + }).catch(err => { + console.error(`error getting reply msg: ${msg.reference.messageId} (for ${msg.id})\n${err}`) + }) + } + + // resolve any embeds and images + if (msg.embeds.length) { + const imgs = msg.embeds + .filter(embed => embed.thumbnail || embed.image) + .map(embed => (embed.thumbnail) ? embed.thumbnail.url : embed.image.url) + + if (imgs.length) { + // data.imageURL = imgs[0] + data.imageURLs = imgs + + // site specific gif fixes + data.imageURLs.forEach((url, i) => { + data.imageURLs[i] = data.imageURLs[i].replace(/(^https:\/\/media.tenor.com\/.*)(AAAAe\/)(.*)(\.png|\.jpg)/, "$1AAAAC/$3.gif") + }) + } + + // twitch clip check + const videoEmbed = msg.embeds.filter(embed => embed.data.type === 'video')[0] + if (videoEmbed && videoEmbed.data.video.url.includes("clips.twitch.tv")) { + data.contentInfo += `\n⬇️ [download clip](${videoEmbed.data.thumbnail.url.replace("-social-preview.jpg", ".mp4")})` + } + if (videoEmbed && videoEmbed.data.url.includes("clips.fxtwitch.tv")) { + data.content = data.content.replace(/((https:\/\/)(clips.fxtwitch.tv\/)(?:[?:=a-zA-Z0-9_-]*))/, `\n\n> ${videoEmbed.data.description} \n $1`) + data.contentInfo += `\n⬇️ [download clip](${videoEmbed.data.video.url})` + } + + // message is entirely an embed (bot msg) + if (msg.content === '') { + const embed = msg.embeds[0] + if (embed.description) { + data.content += embed.description + } else if (embed.fields && embed.fields[0].value) { + data.content += embed.fields[0].value + } + } + } + if (msg.attachments.size) { + // data.imageURL = msg.attachments.first().url + msg.attachments.each(attachment => { + data.imageURLs.push(attachment.url) + data.contentInfo += `\n📎 [${attachment.name}](${attachment.url})` + }) + } + + // max length message + if (data.content.length > MAXLENGTH - data.contentInfo.length) + data.content = `${data.content.substring(0, MAXLENGTH - data.contentInfo.length)}...` - // max length message - if (data.content.length > MAXLENGTH - data.contentInfo.length) - data.content = `${data.content.substring(0, MAXLENGTH - data.contentInfo.length)}...` - - return data + return data } // update embed -function editEmbed(reaction, editableMessageID, forceUpdate=false) { +async function editEmbed(reaction, editableMessageID, forceUpdate=false) { if (reaction.count) console.log(`updating count of message with ID ${editableMessageID}. reaction count: ${reaction.count}`) - postChannel.messages.fetch(editableMessageID).then(async message => { + + try { + const message = await postChannel.messages.fetch(editableMessageID) + // rebuild embeds const origEmbed = message.embeds[0] if (!origEmbed) throw `original embed could not be fetched` @@ -212,22 +216,24 @@ function editEmbed(reaction, editableMessageID, forceUpdate=false) { updatedEmbeds = updatedEmbeds.concat(message.embeds.slice(1)) } - message.edit({ embeds: updatedEmbeds }).then(starMessage => { - // if db - if (db) - db.updatePost(starMessage, reaction.message, reaction.count, starMessage.embeds[0].image) - }) + let starMessage + if (message.webhookId) { + starMessage = await webhook.editMessage(message.id, { embeds: updatedEmbeds }) + } else { + starMessage = await message.edit({ embeds: updatedEmbeds }) + } - }).catch(err => { + if (db) + db.updatePost(starMessage, reaction.message, reaction.count, starMessage.embeds[0].image) + + } catch (err) { console.error(`error updating post: ${editableMessageID}\noriginal message: ${reaction.message.id}\n${err}`) - }) + } } // manage the message board on reaction add/remove async function manageBoard (reaction) { - const msg = reaction.message - // const postChannel = client.guilds.cache.get(guildID).channels.cache.get(smugboardID) // if message is older than set amount const dateDiff = (new Date()) - msg.createdAt @@ -259,13 +265,15 @@ async function manageBoard (reaction) { // set first image const first_image = (data.imageURLs.length) ? data.imageURLs.shift() : null // set message embed color - const hexcolor = (settings.hexcolor) ? settings.hexcolor : parseInt(msg.channel.id).toString(16).substring(2, 8) + const hexcolor = settings.hexcolor ?? parseInt(msg.channel.id).toString(16).substring(2, 8) + + const authorName = msg.author.globalName ?? msg.author.username // attach all embeds const embeds = [ new EmbedBuilder() .setURL(first_image) - .setAuthor({ name: msg.author.globalName ?? msg.author.username, iconURL: data.avatarURL, url: `https://discordapp.com/users/${msg.author.id}`}) + .setAuthor({ name: authorName, iconURL: data.avatarURL, url: `https://discord.com/users/${msg.author.id}`}) .setColor(hexcolor) .setDescription(data.content + data.contentInfo) .setImage(first_image) @@ -276,42 +284,76 @@ async function manageBoard (reaction) { embeds.push(new EmbedBuilder().setURL(first_image).setImage(url)) }) + const payload = { + embeds + } + // post embed - postChannel.send({ embeds: embeds }).then(starMessage => { + let starMessage + try { + // as webhook + if (webhook) { + if (settings.authorAsUsername) { + embeds[0].setAuthor(null) + payload.username = authorName + payload.avatarURL = data.avatarURL + } else { + payload.username = client.user.username + payload.avatarURL = client.user.avatarURL() + } + starMessage = await webhook.send(payload) + + // as bot + } else { + starMessage = await postChannel.send(payload) + } + + // save message id to memory messagePosted[msg.id] = starMessage.id - // if db if (db) db.updatePost(starMessage, msg, reaction.count, starMessage.embeds[0].image) - }) + } catch (err) { + console.error(`error reposting msg: ${msg.id}\n${err}`) + } } } } // delete a post -function deletePost (msg) { - // const postChannel = client.guilds.cache.get(guildID).channels.cache.get(smugboardID) +async function deletePost (msg) { // if posted to channel board before if (messagePosted[msg.id]) { const editableMessageID = messagePosted[msg.id] - postChannel.messages.fetch(editableMessageID).then((message) => { - delete messagePosted[msg.id] - message.delete() - .then(msg => console.log(`Removed message with ID ${editableMessageID}. Reaction count reached 0.`)) - .catch(console.error) + let deletableMessage + try { + deletableMessage = await postChannel.messages.fetch(editableMessageID) + if (deletableMessage.webhookId) { + await webhook.deleteMessage(editableMessageID) + } else { + await deletableMessage.delete() + } + } catch(e) { + console.error(`Error deleting message ${editableMessageID}\n${e}`) + } + + delete messagePosted[msg.id] + console.log(`Removed message with ID ${editableMessageID}. Reaction count reached 0.`) - if (db) - db.setDeleted(message.id) - }) + if (db) + db.setDeleted(editableMessageID) } } // ON READY -client.on('ready', () => { +client.on('ready', async () => { console.log(`Logged in as ${client.user.username}!`) guildID = settings.serverID smugboardID = settings.channelID + + if (settings.webhook) webhook = new WebhookClient({ url: settings.webhook }) postChannel = client.guilds.cache.get(guildID).channels.cache.get(smugboardID) + // fetch existing posts loadIntoMemory() })