diff --git a/README.md b/README.md index 0a19363..fcb8d01 100644 --- a/README.md +++ b/README.md @@ -93,13 +93,6 @@ can help! Just say `@handbook terms` and Charlie will search the Handbook for `terms` for you (replace `terms` with whatever you want). If it finds anything, it'll post links in a threaded response to your request. -##### HugMe - -Need to see a little hug in your life? Friends from TTS past have left us a gift -and Charlie will deliver it whenever you need. Just say `@charlie hug me` or -`@charlie hug bomb ` to get a little happiness dropped right on your -screen. - ##### OPM's DC offices status Working in DC and want to know if the office is closed due to snow or, perhaps, diff --git a/package-lock.json b/package-lock.json index a5b73aa..22d8478 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "dependencies": { "@18f/us-federal-holidays": "^4.0.0", "@slack/bolt": "^4.1.0", - "aws-sdk": "^2.1354.0", "axios": "^1.7.7", "cfenv": "^1.2.3", "cheerio": "^1.0.0-rc.12", @@ -1693,6 +1692,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -1703,27 +1703,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-sdk": { - "version": "2.1692.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1692.0.tgz", - "integrity": "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw==", - "hasInstallScript": true, - "dependencies": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.16.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "util": "^0.12.4", - "uuid": "8.0.0", - "xml2js": "0.6.2" - }, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/axios": { "version": "1.7.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", @@ -1850,25 +1829,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/body-parser": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.0.2.tgz", @@ -2001,16 +1961,6 @@ "node-int64": "^0.4.0" } }, - "node_modules/buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -3167,14 +3117,6 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, - "node_modules/events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -3462,6 +3404,7 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, "dependencies": { "is-callable": "^1.1.3" } @@ -3766,6 +3709,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -3854,11 +3798,6 @@ "node": ">=0.10.0" } }, - "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3950,21 +3889,6 @@ "node": ">= 0.10" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -4019,6 +3943,7 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -4103,20 +4028,6 @@ "node": ">=6" } }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -4255,6 +4166,7 @@ "version": "1.1.13", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, "dependencies": { "which-typed-array": "^1.1.14" }, @@ -4277,11 +4189,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4933,14 +4840,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jmespath": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5948,6 +5847,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -6106,15 +6006,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -6385,11 +6276,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" - }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -7052,32 +6938,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -7086,14 +6946,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", - "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -7179,6 +7031,7 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -7257,26 +7110,6 @@ } } }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 1c535d7..279255d 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "dependencies": { "@18f/us-federal-holidays": "^4.0.0", "@slack/bolt": "^4.1.0", - "aws-sdk": "^2.1354.0", "axios": "^1.7.7", "cfenv": "^1.2.3", "cheerio": "^1.0.0-rc.12", diff --git a/src/scripts/hugme.js b/src/scripts/hugme.js deleted file mode 100644 index 72eef57..0000000 --- a/src/scripts/hugme.js +++ /dev/null @@ -1,113 +0,0 @@ -// Description: -// Hugme is the most important thing in life -// -// Dependencies: -// None -// -// Configuration: -// None -// -// Commands: -// @bot hug me - Receive a hug -// @bot hug bomb N - get N hugs -// -// Notes: -// Images are stored in a bucket in S3. - -const { directMention } = require("@slack/bolt"); -const CFENV = require("cfenv"); -const AWS = require("aws-sdk"); -const { - helpMessage, - slack: { getChannelID }, - stats: { incrementStats }, -} = require("../utils"); - -module.exports = (app) => { - const appEnv = CFENV.getAppEnv(); - const s3Creds = appEnv.getServiceCreds("charlie-bucket"); - - if (s3Creds !== null) { - helpMessage.registerInteractive( - "Hug Me", - "hug me", - "Need a hug? Friends from TTS past have left us images of themselves providing a hug as a gift, and Charlie will deliver one whenever you need!", - true, - ); - helpMessage.registerInteractive( - "Hug Bomb", - "hug bomb [number]", - "Need more than one hug? Charlie will happily deliver multiple! Delivers three images of hugs from friends of TTS past.", - true, - ); - - const creds = new AWS.Credentials( - s3Creds.access_key_id, - s3Creds.secret_access_key, - ); - const BUCKET = s3Creds.bucket; - const REGION = s3Creds.region; - - const s3 = new AWS.S3({ region: REGION, credentials: creds }); - - const hugUrl = ({ Key }) => { - const rand = Math.floor(Math.random() * 10000); - return `https://s3-${REGION}.amazonaws.com/${BUCKET}/${Key}?rnd=${rand}`; - }; - - module.exports.hugBomb = (count, { say }) => - new Promise((resolve) => { - s3.listObjects({ Bucket: BUCKET }, async (err, data) => { - if (err) { - say(`Error retrieving images: ${err}`); - resolve(); - } else { - // Get some random things - const s3Objects = [...Array(count)].map(() => - data.Contents.splice( - Math.floor(Math.random() * data.Contents.length), - 1, - ).pop(), - ); - - const blocks = s3Objects.map((s3Object) => ({ - type: "image", - title: { type: "plain_text", text: "Please enjoy this warm hug" }, - image_url: hugUrl(s3Object), - alt_text: "Someone giving you a nice hug", - })); - - const channelID = await getChannelID("bots"); - - blocks.push({ - type: "section", - text: { - type: "mrkdwn", - text: `_If you would like to be added, send a picture in <#${channelID}>_`, - }, - }); - - say({ blocks }); - resolve(); - } - }); - }); - - app.message(directMention, /hug me/i, (msg) => { - incrementStats("hug bot - single hug"); - module.exports.hugBomb(1, msg); - }); - - app.message( - directMention, - /hug bomb( (\d+))?/i, - ({ context: { matches }, ...msg }) => { - incrementStats("hug bot - multiple hugs"); - const count = +matches[2] || 3; - module.exports.hugBomb(count, msg); - }, - ); - } else { - app.logger.warn("Unable to find service creds for 'charlie-bucket'."); - } -}; diff --git a/src/scripts/hugme.test.js b/src/scripts/hugme.test.js deleted file mode 100644 index ab7e952..0000000 --- a/src/scripts/hugme.test.js +++ /dev/null @@ -1,180 +0,0 @@ -const aws = require("aws-sdk"); -const cfenv = require("cfenv"); -const { - getApp, - utils: { - slack: { getChannelID }, - }, -} = require("../utils/test"); - -jest.mock("aws-sdk"); -jest.mock("cfenv"); - -describe("the hug bot", () => { - const app = getApp(); - const getServiceCreds = jest.fn(); - - beforeEach(() => { - jest.resetAllMocks(); - - cfenv.getAppEnv.mockReturnValue({ getServiceCreds }); - - getServiceCreds.mockReturnValue({ - access_key_id: "access key id", - bucket: "bucket", - region: "region", - secret_access_key: "secret access key", - }); - }); - - const load = async () => - new Promise((resolve) => { - jest.isolateModules(() => { - const module = require("./hugme"); // eslint-disable-line global-require - resolve(module); - }); - }); - - it("doesn't provide a handler if the S3 credentials are unset", async () => { - getServiceCreds.mockReturnValue(null); - const bot = await load(); - bot(app); - - expect(app.message).not.toHaveBeenCalled(); - }); - - it("sets up handlers if S3 credentials are set", async () => { - const bot = await load(); - bot(app); - - expect(app.message.mock.calls.length).toBe(2); - - expect(app.message).toHaveBeenCalledWith( - expect.any(Function), - /hug me/i, - expect.any(Function), - ); - - expect(app.message).toHaveBeenCalledWith( - expect.any(Function), - /hug bomb( (\d+))?/i, - expect.any(Function), - ); - }); - - it("handles a single hug request", async () => { - const bot = await load(); - bot(app); - jest.spyOn(bot, "hugBomb").mockReturnValue({}); - - const handler = app.getHandler(); - handler("message"); - - expect(bot.hugBomb).toHaveBeenCalledWith(1, "message"); - }); - - it("handles a multi-hug request", async () => { - const bot = await load(); - bot(app); - jest.spyOn(bot, "hugBomb").mockReturnValue({}); - - const handler = app.getHandler(1); - const message = { - context: { matches: ["whole", "number with spaces", 30] }, - other: "stuff", - }; - handler(message); - - // We expect the context part of the message to be consumed by the handler - // and not passed into the hugBomb method. - expect(bot.hugBomb).toHaveBeenCalledWith(30, { other: "stuff" }); - }); - - it("can't do the hugs if there's an S3 error", async () => { - const listObjects = jest.fn().mockImplementation((_, callback) => { - callback("error", null); - }); - - aws.S3.mockImplementation(() => ({ listObjects })); - - const bot = await load(); - bot(app); - - const say = jest.fn(); - await bot.hugBomb(5, { say }); - - expect(say).toHaveBeenCalledWith("Error retrieving images: error"); - }); - - it("hugs the hugs", async () => { - getChannelID.mockResolvedValue("channel id"); - - const listObjects = jest.fn().mockImplementation((_, callback) => { - callback(null, { - Contents: [ - { Key: "url1" }, - { Key: "url2" }, - { Key: "url3" }, - { Key: "url4" }, - { Key: "url5" }, - ], - }); - }); - - jest.spyOn(global.Math, "random").mockReturnValue(0); - - aws.S3.mockImplementation(() => ({ listObjects })); - - const bot = await load(); - bot(app); - - const say = jest.fn(); - await bot.hugBomb(5, { say }); - - expect(listObjects).toHaveBeenCalledWith( - { Bucket: "bucket" }, - expect.any(Function), - ); - expect(say).toHaveBeenCalledWith({ - blocks: [ - { - type: "image", - title: { type: "plain_text", text: "Please enjoy this warm hug" }, - image_url: "https://s3-region.amazonaws.com/bucket/url1?rnd=0", - alt_text: "Someone giving you a nice hug", - }, - { - type: "image", - title: { type: "plain_text", text: "Please enjoy this warm hug" }, - image_url: "https://s3-region.amazonaws.com/bucket/url2?rnd=0", - alt_text: "Someone giving you a nice hug", - }, - { - type: "image", - title: { type: "plain_text", text: "Please enjoy this warm hug" }, - image_url: "https://s3-region.amazonaws.com/bucket/url3?rnd=0", - alt_text: "Someone giving you a nice hug", - }, - { - type: "image", - title: { type: "plain_text", text: "Please enjoy this warm hug" }, - image_url: "https://s3-region.amazonaws.com/bucket/url4?rnd=0", - alt_text: "Someone giving you a nice hug", - }, - { - type: "image", - title: { type: "plain_text", text: "Please enjoy this warm hug" }, - image_url: "https://s3-region.amazonaws.com/bucket/url5?rnd=0", - alt_text: "Someone giving you a nice hug", - }, - { - type: "section", - text: { - type: "mrkdwn", - text: "_If you would like to be added, send a picture in <#channel id>_", - }, - }, - ], - }); - }); -});