From 852e74ec209ff92884be2ac0b5abff1d0b93ebac Mon Sep 17 00:00:00 2001 From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:59:14 -0700 Subject: [PATCH] Introduce `add` and `remove` subcommands (#15) * introduce `add` subcommand * add `remove` subcommand * run `deno task all` --- app_schema.ts | 51 ++++++---- deno.jsonc | 2 +- deno.lock | 84 +++++++++++++++- deps.ts | 6 +- docs/HANDBOOK.md | 4 +- lib/shorter/shorter.ts | 6 ++ main.ts | 216 +++++++++++++++++++++++++++-------------- 7 files changed, 267 insertions(+), 102 deletions(-) diff --git a/app_schema.ts b/app_schema.ts index 9d63917..1649819 100644 --- a/app_schema.ts +++ b/app_schema.ts @@ -4,25 +4,40 @@ import type { AppSchema } from "shorter/deps.ts"; export const appSchema = { chatInput: { name: "shorter", - description: "Shorten a URL", - options: { - alias: { - type: discord.ApplicationCommandOptionType.String, - description: "The alias of the shortlink", - required: true, + description: "Manage shortlinks.", + subcommands: { + add: { + description: "Add a shortlink.", + options: { + alias: { + type: discord.ApplicationCommandOptionType.String, + description: "The alias of the shortlink", + required: true, + }, + destination: { + type: discord.ApplicationCommandOptionType.String, + description: "The destination of the shortlink", + required: true, + }, + force: { + type: discord.ApplicationCommandOptionType.Boolean, + description: "Whether to overwrite an existing shortlink", + }, + ttl: { + type: discord.ApplicationCommandOptionType.String, + description: "The time-to-live of the shortlink", + }, + }, }, - destination: { - type: discord.ApplicationCommandOptionType.String, - description: "The destination of the shortlink", - required: true, - }, - force: { - type: discord.ApplicationCommandOptionType.Boolean, - description: "Whether to overwrite an existing shortlink", - }, - ttl: { - type: discord.ApplicationCommandOptionType.String, - description: "The time-to-live of the shortlink", + remove: { + description: "Remove a shortlink.", + options: { + alias: { + type: discord.ApplicationCommandOptionType.String, + description: "The alias of the shortlink", + required: true, + }, + }, }, }, }, diff --git a/deno.jsonc b/deno.jsonc index ae19755..a1b44f5 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -4,7 +4,7 @@ "udd": "deno run -r --allow-read=. --allow-write=. --allow-net https://deno.land/x/udd/main.ts deps.ts && deno task lock", "lock": "deno cache --lock=deno.lock --lock-write deps.ts", "all": "deno task udd && deno lint && deno fmt", - "start": "deno run -A main.ts", + "start": "deno run -A --unstable-kv main.ts", "ngrok": "ngrok http 8080" }, "imports": { diff --git a/deno.lock b/deno.lock index d6c32cf..ae773d9 100644 --- a/deno.lock +++ b/deno.lock @@ -118,7 +118,9 @@ "https://deno.land/std@0.191.0/dotenv/mod.ts": "f5a8123741d1561ae8184a7f043bc097b15132c5171c651142b804b6dbc21853", "https://deno.land/std@0.191.0/http/http_errors.ts": "b9a18ef97d6c5966964de95e04d1f9f88a0f8bd8577c26fd402d9d632fb03a42", "https://deno.land/std@0.191.0/http/http_status.ts": "8a7bcfe3ac025199ad804075385e57f63d055b2aed539d943ccc277616d6f932", - "https://deno.land/std@0.208.0/dotenv/mod.ts": "039468f5c87d39b69d7ca6c3d68ebca82f206ec0ff5e011d48205eea292ea5a6", + "https://deno.land/std@0.222.1/dotenv/mod.ts": "0180eaeedaaf88647318811cdaa418cc64dc51fb08354f91f5f480d0a1309f7d", + "https://deno.land/std@0.222.1/dotenv/parse.ts": "09977ff88dfd1f24f9973a338f0f91bbdb9307eb5ff6085446e7c423e4c7ba0c", + "https://deno.land/std@0.222.1/dotenv/stringify.ts": "275da322c409170160440836342eaa7cf012a1d11a7e700d8ca4e7f2f8aa4615", "https://deno.land/x/codemod@0.0.5/deps.ts": "5e27f88433fb872ab1873b104c4301825d2d16c5c37165a7b989a71e62ae908a", "https://deno.land/x/codemod@0.0.5/github/api/github_api_client.ts": "0574f97e834c215f6151e420cf821bceb745750a7a4d4fcc60eb897b486d1f98", "https://deno.land/x/codemod@0.0.5/github/api/github_api_client_interface.ts": "16e7466539ad7f50dc6fa2a3d1fcdee4407336ffb94643ab3e783e76f03e309b", @@ -221,15 +223,89 @@ "https://deno.land/x/discord_api_types@0.37.65/utils/internals.ts": "cb70895ba89f7947c38f7fa447b0190cb14b5585be323414cda53d2ccb19b16c", "https://deno.land/x/discord_api_types@0.37.65/utils/v10.ts": "056bd036f8c65365ff28eb63ec6897811d51921cca6d068392dd1ca5b397ae62", "https://deno.land/x/discord_api_types@0.37.65/v10.ts": "f3f23492c59e77859aba5b34431edf3668c37f722d7f70c2e1ef7ba4bcda3010", + "https://deno.land/x/discord_api_types@0.37.79/gateway/common.ts": "c568382f2e1a8bdf5c5d37b622c32ad5428b70ea9eb6abef40914ce4e4de56a0", + "https://deno.land/x/discord_api_types@0.37.79/gateway/v10.ts": "572a1c3bfc7f564cffcd0312d282c6e0b494cd14fef7106edd77f96c7fc97fa2", + "https://deno.land/x/discord_api_types@0.37.79/globals.ts": "7d8879654c4741ac071668ad52f2659bcdb66694cfe7da306c8437ec752807a7", + "https://deno.land/x/discord_api_types@0.37.79/payloads/common.ts": "f4e3a52801ec5e93c55177531a0a09b6ee9d0b5d7172e1e51c042bd58cce8c2e", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/attachment.ts": "c66dccd54c1b84d073f2e1caa466e551b8045a84a2e8a88a1bfbc7e2c64a703d", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/base.ts": "f6a2556e14d489e1f0e5ddeb3a0303e2603e25330530dd9263e176013c5f51eb", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/boolean.ts": "65e29561b61785ca4ede4b1b4a88c5fc0696cfdf1fa74d5197588c196ee7ae98", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/channel.ts": "73c7fc49de242e1ce3be958375fd810750aed83553ef3860e3cddf858f9eb464", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/integer.ts": "a25d24a3e54d647c7039b99e3208fc0fc2228d174f6dcc421e93919b8154a011", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/mentionable.ts": "742e42857465866e0c08b587d7fb5ccd81d4705c61ce4cd6b97ad5692e88e969", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/number.ts": "be974ea68f5fdf55d7a7f5d3faf48a3193777d432b1aa9087afc204bcb916284", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/role.ts": "a57114d0f7eeee4ab7cf217a865dd9dbd9096d007c556aec6185d64257100f41", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/shared.ts": "de4aee14f9cd21e8dbff6c523cb90be9f4273893347fef00930919a976f598b6", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/string.ts": "33ab12dab64544a70729b9b66b5a9790964ea779f05d4ab1a1e190e7c1b59e98", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/subcommand.ts": "0013737da6d2b54e2f413fbf31cf9c84ea51bd9204b615cb4fd19b420f856cb2", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/subcommandGroup.ts": "db5cc701bcb3d68c094de409da39c9a2b8834dc0d5038e5f963c96e5eaf412ac", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/_chatInput/user.ts": "ed2871693744298225ba53ddfb18d3e7afff20a34f413822d5b1193918aea27f", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/chatInput.ts": "1f88245356202857d7a38d21af8ea1c96a65d7da5563734e5ea4af67ba51d1ae", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/contextMenu.ts": "e40500fa8c61f624575a789516e12d6219ce5299fa88da657963c97772ac00df", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/internals.ts": "5eb5ea13a1247c73c0611886dea09ab8d632a9c5555ff0f33d44cd379fd75a08", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/_applicationCommands/permissions.ts": "5af8dd6bac57e87d1339ab5e1c7465aab5c4e4f4aeac7a4808ff2cc3d1a315fc", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/applicationCommands.ts": "8c42e0a2416819a17b028878780f90f926f889b649f7195a8b95816a1ba9085f", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/autocomplete.ts": "821ae50ff9845cac4b03169dbd4c4b187d8399765eb1f0d658d477c68e4c6136", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/base.ts": "ae318712d1befd8ef225916ef83c236b821f59555f988c158e5399e98289eff6", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/messageComponents.ts": "9248c572492a5ea11a05c4f8f58c99f94b41425794b1133d5dd389127197eabf", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/modalSubmit.ts": "3a02d2d7df5bcdb1ffcd089f15e0d82ab65dcc0cefa904c6e0621f46edac041e", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/ping.ts": "096ce582e9af373649fd5355cccd7424adceaffb73367b5301f1594ef5a3c264", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/_interactions/responses.ts": "ae34794d507b38c2feb7e653fe1f436df194fcef6f945a25deb1ab0842db5b66", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/application.ts": "7ec267bf4b809534c8c5e919a7b1da7b33190f9d545445146e007ddb9d0554f5", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/auditLog.ts": "5a4f411a807665442dfdcc41a3e7d2ce23be902a2e57c365e8f3785d104e3db2", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/autoModeration.ts": "9ccb4408f1c6392d9619fac159997e08e660080b3f9567a1619163a40329e3a2", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/channel.ts": "469d3fe37ae22e6b39c0243dbb38a4927cc419cd346054f39aba681ae95539e2", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/emoji.ts": "b9a30b16e1ec4dc15d6149e59aa48b02ad57a51335b7be5a7f5368db0491b3dd", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/gateway.ts": "a00dd57a6756a98a024502d76381b57a66321b4d91d663de14e325e5ff21ae48", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/guild.ts": "99a524ceebdeec5721262dd436e02051848f154b2830ea94ba7efd4f2b0e2b23", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/guildScheduledEvent.ts": "16073e6dc7193eac59d6de79c1ab1070daf02b9466dccc866100cb7a3780be59", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/interactions.ts": "d2c31c147ec49663dc26c314eb2e764537dbf7f2f82eb1e659ae4dea9609ba41", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/invite.ts": "9785b4467016f73f8d2633cf31f7fd3470e94bfa4ce7ad22fe9ff2dcf1e67ad8", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/mod.ts": "83d68247652307f1587d71ac6983fd795ad7b9d5c92540a65207ea9293b09812", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/monetization.ts": "9a91c8dbb4f4c505e561630f0205f821e6877a5ea74faf4eaad9c154f5cc0d02", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/oauth2.ts": "dfb9f09fb44bf5faaa73ad4488ebe408905907d5fd46404895317f4e7c378489", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/permissions.ts": "5e7990e6dad3e35f8c130dc52de4bbf63afe5d6ad98e1c56b09da3ead94ad5a4", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/stageInstance.ts": "0f7ebce1aba67578f178a7c2aba783b4ec0e639c99d0a353888d678a92685c5c", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/sticker.ts": "6afaf40e19632cad9e3935477ab7d77a163a5d7419f6fdcc122d4762982513ec", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/teams.ts": "101044d8c48a3cbabb60048eff9f69588bdd1ea84d1825de0372b4e23ad7ccbe", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/template.ts": "c6bee171ed0ce61fc8b59de42541a023bdcde62718deb42325397e5c82efdc27", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/user.ts": "27284259de8fc67091cc652c7a6dd91c9e0286c2a6caf329eb17038762a02cc9", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/voice.ts": "62d03a540f2e78e5f3989f71a0ee1ec682ef7306a4fa096f89118cbd82351d47", + "https://deno.land/x/discord_api_types@0.37.79/payloads/v10/webhook.ts": "7fc370f40a84f12a6e57ddda7cf2814f15039d6320b46979db0b49d5b91e303b", + "https://deno.land/x/discord_api_types@0.37.79/rest/common.ts": "a9a9021e7dda3413dbeffd7584304fb467173f1a44f71d53ca1bb204f57afe2d", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/application.ts": "2a1cbde372ed9a4c9c6486bb5a59448f15565374ed055f93bb44401e028b87ca", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/auditLog.ts": "39a0914b6c51445023d82c3e3e66c9866cbb3cb6774d3e7eac63414ea9bcbfec", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/autoModeration.ts": "3d388fd9a91c34f04b5e3e1b6ffe12029fb48b511f37ff88042325ec6cbc6605", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/channel.ts": "a3dc29bfbe589eb0fdf461bfe32d3efb2cfd16685f88787130438d51b097fcb8", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/emoji.ts": "9f694a1bd63886c62a87b4320f3bfa5d4f534b2d87c317d77d572d10522df3aa", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/gateway.ts": "747cb95c9a8bca4e52423c780d5fc492fb0dab2b6015cd7e51e890e8d51acf29", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/guild.ts": "e6e28477a878897454b02dfa40ba86f30647c54e2a07fa6ddea093f55d438769", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/guildScheduledEvent.ts": "29d361f395d8cd1ecb47550615d19e10793d513cc5ad8d32895da2cc9cd0fd89", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/interactions.ts": "5ffe19bba79304ecc0bf7caa7d8e747688b02440372be537e303750d9ade2e10", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/invite.ts": "28f8e740bdaa782c9d9d504049323762b5c1180348019dc5f9e0a900ec11213e", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/mod.ts": "d1f5103f2d5ac5fd351c824281834abb7810d5dc614d0e14e323910b46336e86", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/monetization.ts": "4ce23e105519637eb0a46aed552d7e71c33924ed927390dc9c5e4a1aa6eeb5da", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/oauth2.ts": "72c27a1d44d4e5dff8ae10619989ad8786a783b477d7f84b9bebfbdd75481006", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/stageInstance.ts": "a090ff8b54f77188323af5d06cdef9c42738edf9a9b0eba8aad3c89d5ac5569f", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/sticker.ts": "1f7f2729308a0ec1fe373b5df7ac71bafc200132f1a06df7e75bf5ce1d1069c1", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/template.ts": "0ad41c3c85571d3c5b0bec3914c678a21f376ec162ef0d3f1f7731a8d1d1009c", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/user.ts": "8ea167fc3537f4af0ec4618a3ee4f74819de9b8eeb588ec228583943844b6e0c", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/voice.ts": "cdbe9d6c39c8f44635d8632bf62a95b8c15877b92c56ddf69df2072bb1a74edc", + "https://deno.land/x/discord_api_types@0.37.79/rest/v10/webhook.ts": "7e2b75d68bc543f58c893bc41e268731a85d18b765618b6a3d477c46e76adee1", + "https://deno.land/x/discord_api_types@0.37.79/rpc/common.ts": "a693352ffd86ae9e995fb3fbfbfd2be30896257ecb83c5611050f060b08de4ef", + "https://deno.land/x/discord_api_types@0.37.79/rpc/v10.ts": "fbaad9f3d73fce88e76b0e52ad5345093f18077e4293937c9ec0ee24415b9a93", + "https://deno.land/x/discord_api_types@0.37.79/utils/internals.ts": "9a8b59a45efe216ad88d73036005babe17a475a470a80cbe5d4bba2f5bb7660e", + "https://deno.land/x/discord_api_types@0.37.79/utils/v10.ts": "2bf6a001a02e9958d1da37df412c11b04cd6ae2a6df6cfbae6c051088c37474b", + "https://deno.land/x/discord_api_types@0.37.79/v10.ts": "f3f23492c59e77859aba5b34431edf3668c37f722d7f70c2e1ef7ba4bcda3010", "https://deno.land/x/discord_app@0.0.4/app.ts": "9ae505a728d3a43d2fa42cf443605da2115e371df7b42c1d67201ca0cb904515", "https://deno.land/x/discord_app@0.0.4/app_handler.ts": "8bd6cb6e4bd897c27322e0478c869ced87276e44c0bb7ccf5cbbabaecba9f5fa", "https://deno.land/x/discord_app@0.0.4/deps.ts": "33b3ad17eef3ae09dd8aaf9a6201e6dcba2f5c412af60c9193f9f956d25903bb", "https://deno.land/x/discord_app@0.0.4/discord_api.ts": "398d7fec0898fba51735b3d44bd6d012a8203fc0893fa826f7101fbf914bce57", "https://deno.land/x/discord_app@0.0.4/discord_api_types.ts": "7231c7ecff41407628097a4fe2d08e4afd74f189d2d4346c56c3224b01dd4ebd", "https://deno.land/x/discord_app@0.0.4/mod.ts": "bbad0ae8c89db1e43ed9dce108854729ddd7a962d41fc4b6035d3d3f7aa8a752", - "https://deno.land/x/durationjs@v4.1.0/mod.ts": "a7f9d3f38823caa9965f3e61f74a75fb09be548cca2517bd91be7ce15e4b35f1", - "https://deno.land/x/durationjs@v4.1.0/src/duration.ts": "e0c9a09311c22a6dafb7429081802c85a7920176213215315cbf587c5ea7a5ac", - "https://deno.land/x/durationjs@v4.1.0/src/in_words.ts": "1839490e2cb17fec2871bf87d6c7f7435c68416f9360d9f140777936d4680137", + "https://deno.land/x/durationjs@v4.1.1/mod.ts": "a7f9d3f38823caa9965f3e61f74a75fb09be548cca2517bd91be7ce15e4b35f1", + "https://deno.land/x/durationjs@v4.1.1/src/duration.ts": "dd82b556c311c83513b1e0e7184e27bacb7f1fa992518b56dfbdd69b7b79cb5b", + "https://deno.land/x/durationjs@v4.1.1/src/in_words.ts": "1839490e2cb17fec2871bf87d6c7f7435c68416f9360d9f140777936d4680137", "https://deno.land/x/github_api_types@2023-05-17-05-41/mod.ts": "dc3a5cd3176c78085b49601e9c3fccac24809b037929230293255edabafbd0bb", "https://esm.sh/fast-json-patch@3.1.1": "fd59bab1fabdb3e7e2ce8204aa92113dc451708797021fff6f96b8ff265faedf", "https://esm.sh/tweetnacl@1.0.3": "4ed2ed58ad038fc065ff844177a0a3a216aedb87e6e25329899ecafb744a6f58", diff --git a/deps.ts b/deps.ts index 568eb66..967ae66 100644 --- a/deps.ts +++ b/deps.ts @@ -1,8 +1,8 @@ -export * as dotenv from "https://deno.land/std@0.208.0/dotenv/mod.ts"; -export * as discord from "https://deno.land/x/discord_api_types@0.37.65/v10.ts"; +export * as dotenv from "https://deno.land/std@0.222.1/dotenv/mod.ts"; +export * as discord from "https://deno.land/x/discord_api_types@0.37.79/v10.ts"; export * from "https://deno.land/x/codemod@0.0.5/github/mod.ts"; export type { GitHubAPIClientOptions } from "https://deno.land/x/codemod@0.0.5/github/api/mod.ts"; -export { Duration } from "https://deno.land/x/durationjs@v4.1.0/mod.ts"; +export { Duration } from "https://deno.land/x/durationjs@v4.1.1/mod.ts"; export { type AppSchema, createApp, diff --git a/docs/HANDBOOK.md b/docs/HANDBOOK.md index c7ae98c..916ff7a 100644 --- a/docs/HANDBOOK.md +++ b/docs/HANDBOOK.md @@ -116,13 +116,13 @@ on the [ACM CSUF Discord server](https://acmcsuf.com/discord). - This slash command is only available to members with the `Board` role. - This slash command is available in all text channels of the [ACM CSUF Discord server](https://acmcsuf.com/discord). -- Type `/shorter` in any text channel to use the tool. +- Type `/shorter add` in any text channel to add a new shortlink. - Populate both required fields `alias` and `destination` with your desired alias string and destination string, respectively. - Press Enter to submit the update. - Wait for the response from the slash command to confirm the update. This may take around 3 seconds. -- Wait for redeployment to complete. This may take around 30 seconds. +- Wait for redeployment to complete. This may take up to 60 seconds. --- diff --git a/lib/shorter/shorter.ts b/lib/shorter/shorter.ts index bd1ed07..956284a 100644 --- a/lib/shorter/shorter.ts +++ b/lib/shorter/shorter.ts @@ -21,6 +21,12 @@ export async function shorter(options: ShorterOptions): Promise { } if (isAliasToBeRemoved) { + if (data[options.data.alias] === undefined) { + throw new Error( + `the alias \`${options.data.alias}\` does not exist`, + ); + } + delete data[options.data.alias]; } else { data[options.data.alias] = options.data.destination; diff --git a/main.ts b/main.ts index 2468655..32e97a9 100644 --- a/main.ts +++ b/main.ts @@ -46,89 +46,156 @@ export async function main() { register: { token: DISCORD_TOKEN }, schema: appSchema, }, - (interaction) => { - if (!interaction.member?.user) { - throw new Error("Invalid request"); - } - - if ( - !interaction.member.roles.some((role) => DISCORD_ROLE_ID === role) - ) { - throw new Error("Invalid request"); - } - - // Make shorter options. - const shorterOptions: ShorterOptions = { - githubPAT: GITHUB_TOKEN, - actor: { - tag: interaction.member.user.username, - nick: interaction.member.nick || undefined, - }, - data: { - alias: interaction.data.parsedOptions.alias, - destination: interaction.data.parsedOptions.destination, - force: interaction.data.parsedOptions.force, - }, - }; - - // Invoke the Shorter operation. - shorter(shorterOptions) - .then(async (result) => { - // Parse the TTL duration. - const ttlDuration = interaction.data.parsedOptions.ttl && - Duration.fromString(interaction.data.parsedOptions.ttl); - - // Compose the commit message. - let content = - `Created commit [${result.message}](https://acmcsuf.com/code/commit/${result.sha})!`; - if (ttlDuration) { - // Render to Discord timestamp format. - // https://gist.github.com/LeviSnoot/d9147767abeef2f770e9ddcd91eb85aa - const discordTimestamp = toDiscordTimestamp( - (Date.now() + ttlDuration.raw) * 0.001, + { + add(interaction) { + if (!interaction.member?.user) { + throw new Error("Invalid request"); + } + + if ( + !interaction.member.roles.some((role) => DISCORD_ROLE_ID === role) + ) { + return { + type: discord.InteractionResponseType.ChannelMessageWithSource, + data: { + flags: discord.MessageFlags.Ephemeral, + content: "You do not have permission to use this command.", + }, + }; + } + + // Make shorter options. + const shorterOptions: ShorterOptions = { + githubPAT: GITHUB_TOKEN, + actor: { + tag: interaction.member.user.username, + nick: interaction.member.nick || undefined, + }, + data: { + alias: interaction.data.parsedOptions.alias, + destination: interaction.data.parsedOptions.destination, + force: interaction.data.parsedOptions.force, + }, + }; + + // Invoke the Shorter operation. + shorter(shorterOptions) + .then(async (result) => { + // Parse the TTL duration. + const ttlDuration = interaction.data.parsedOptions.ttl && + Duration.fromString(interaction.data.parsedOptions.ttl); + + // Compose the commit message. + let content = + `Created commit [${result.message}](https://acmcsuf.com/code/commit/${result.sha})!`; + if (ttlDuration) { + // Render to Discord timestamp format. + // https://gist.github.com/LeviSnoot/d9147767abeef2f770e9ddcd91eb85aa + const discordTimestamp = toDiscordTimestamp( + (Date.now() + ttlDuration.raw) * 0.001, + ); + content += `\n\nThis shortlink will expire ${discordTimestamp}.`; + } + + // Send the success message. + await discordAPI.editOriginalInteractionResponse({ + botID: DISCORD_CLIENT_ID, + botToken: DISCORD_TOKEN, + interactionToken: interaction.token, + content, + }); + + // Enqueue the delete operation if TTL is set. + if (!ttlDuration) { + return; + } + + await addTTLMessage( + kv, + { + alias: shorterOptions.data.alias, + actor: shorterOptions.actor, + }, + ttlDuration.raw, ); - content += `\n\nThis shortlink will expire ${discordTimestamp}.`; - } - - // Send the success message. - await discordAPI.editOriginalInteractionResponse({ - botID: DISCORD_CLIENT_ID, - botToken: DISCORD_TOKEN, - interactionToken: interaction.token, - content, + }) + .catch((error) => { + if (error instanceof Error) { + discordAPI.editOriginalInteractionResponse({ + botID: DISCORD_CLIENT_ID, + botToken: DISCORD_TOKEN, + interactionToken: interaction.token, + content: `Error: ${error.message}`, + }); + } + + console.error(error); }); - // Enqueue the delete operation if TTL is set. - if (!ttlDuration) { - return; - } - - await addTTLMessage( - kv, - { - alias: shorterOptions.data.alias, - actor: shorterOptions.actor, + // Acknowledge the interaction. + return { + type: + discord.InteractionResponseType.DeferredChannelMessageWithSource, + } satisfies discord.APIInteractionResponseDeferredChannelMessageWithSource; + }, + remove(interaction) { + if (!interaction.member?.user) { + throw new Error("Invalid request"); + } + + if ( + !interaction.member.roles.some((role) => DISCORD_ROLE_ID === role) + ) { + return { + type: discord.InteractionResponseType.ChannelMessageWithSource, + data: { + flags: discord.MessageFlags.Ephemeral, + content: "You do not have permission to use this command.", }, - ttlDuration.raw, - ); - }) - .catch((error) => { - if (error instanceof Error) { - discordAPI.editOriginalInteractionResponse({ + }; + } + + // Make shorter options. + const shorterOptions: ShorterOptions = { + githubPAT: GITHUB_TOKEN, + actor: { + tag: interaction.member.user.username, + nick: interaction.member.nick || undefined, + }, + data: { alias: interaction.data.parsedOptions.alias }, + }; + + // Invoke the Shorter operation. + shorter(shorterOptions) + .then(async (result) => { + // Send the success message. + await discordAPI.editOriginalInteractionResponse({ botID: DISCORD_CLIENT_ID, botToken: DISCORD_TOKEN, interactionToken: interaction.token, - content: `Error: ${error.message}`, + content: + `Removed \`${interaction.data.parsedOptions.alias}\` in commit [${result.message}](https://acmcsuf.com/code/commit/${result.sha}).`, }); - } - - console.error(error); - }); + }) + .catch((error) => { + if (error instanceof Error) { + discordAPI.editOriginalInteractionResponse({ + botID: DISCORD_CLIENT_ID, + botToken: DISCORD_TOKEN, + interactionToken: interaction.token, + content: `Error: ${error.message}`, + }); + } + + console.error(error); + }); - // Acknowledge the interaction. - return { - type: discord.InteractionResponseType.DeferredChannelMessageWithSource, - } satisfies discord.APIInteractionResponseDeferredChannelMessageWithSource; + // Acknowledge the interaction. + return { + type: + discord.InteractionResponseType.DeferredChannelMessageWithSource, + } satisfies discord.APIInteractionResponseDeferredChannelMessageWithSource; + }, }, ); @@ -147,6 +214,7 @@ export async function main() { handleInteraction, ); } + function toDiscordTimestamp(timestamp: number) { return ``; }