A discord bot for teal.fm
discord tealfm music

am i cooking

+3
.gitignore
··· 1 + .env 2 + node_modules 3 + dist
+3
README.md
··· 1 + # Teal.fm Discord Bot 2 + 3 + who knows if i'll finish this
+10
commands/utility/ping.ts
··· 1 + import { CommandInteraction, SlashCommandBuilder } from "discord.js"; 2 + 3 + export default { 4 + data: new SlashCommandBuilder().setName("ping").setDescription( 5 + "replies with pong", 6 + ), 7 + async execute(interaction: CommandInteraction) { 8 + await interaction.reply("pong lol"); 9 + }, 10 + };
+8
constants.ts
··· 1 + import { loadEnvFile } from "node:process" 2 + 3 + loadEnvFile() 4 + 5 + export const DISCORD_BOT_TOKEN = process.env.DISCORD_BOT_TOKEN as string; 6 + export const DISCORD_APPLICATION_ID = process.env.DISCORD_APPLICATION_ID as string; 7 + export const DISCORD_GUILD_ID = process.env.DISCORD_GUILD_ID as string; 8 + export const TAP_ADMIN_PASSWORD = process.env.TAP_ADMIN_PASSWORD as string;
+51
deploy-commands.ts
··· 1 + import { REST, Routes } from "discord.js"; 2 + import fs from "node:fs"; 3 + import path from "node:path"; 4 + import { 5 + DISCORD_APPLICATION_ID, 6 + DISCORD_BOT_TOKEN, 7 + DISCORD_GUILD_ID, 8 + } from "./constants.ts"; 9 + 10 + const commands = []; 11 + const foldersPath = path.join(import.meta.dirname as string, "commands"); 12 + const commandFolders = fs.readdirSync(foldersPath); 13 + 14 + for (const folder of commandFolders) { 15 + const commandsPath = path.join(foldersPath, folder); 16 + const commandFiles = fs.readdirSync(commandsPath).filter((file) => 17 + file.endsWith(".ts") 18 + ); 19 + for await (const file of commandFiles) { 20 + const filePath = path.join(commandsPath, file); 21 + const command = await import(filePath); 22 + if ("data" in command.default && "execute" in command.default) { 23 + commands.push(command.default.data); 24 + } else { 25 + console.warn( 26 + `[Warning] The command at ${filePath} is missing a required "data" or "execute" property.`, 27 + ); 28 + } 29 + } 30 + } 31 + 32 + const rest = new REST().setToken(DISCORD_BOT_TOKEN); 33 + 34 + (async () => { 35 + try { 36 + console.log( 37 + `Started refreshing ${commands.length} application (/) commands.`, 38 + ); 39 + 40 + const data = await rest.put( 41 + Routes.applicationGuildCommands(DISCORD_APPLICATION_ID, DISCORD_GUILD_ID), 42 + { body: commands }, 43 + ) as unknown[]; 44 + 45 + console.log( 46 + `Successfully reloaded ${data.length} application (/) commands.`, 47 + ); 48 + } catch (error) { 49 + console.error(error); 50 + } 51 + })();
+7
discord.d.ts
··· 1 + import { Collection } from "discord.js"; 2 + 3 + declare module "discord.js" { 4 + export interface Client { 5 + commands: Collection<unknown, any> 6 + } 7 + }
docker-compose.yml

This is a binary file and will not be displayed.

+65
main.ts
··· 1 + import { 2 + Client, 3 + Collection, 4 + Events, 5 + GatewayIntentBits, 6 + MessageFlags, 7 + } from "discord.js"; 8 + import fs from "node:fs"; 9 + import path from "node:path"; 10 + import { DISCORD_BOT_TOKEN } from "./constants.ts"; 11 + 12 + const client = new Client({ intents: [GatewayIntentBits.Guilds] }); 13 + 14 + client.once(Events.ClientReady, (readyClient) => { 15 + console.log(`teal.fm bot ready and logged in as ${readyClient.user.tag}`); 16 + }); 17 + 18 + client.login(DISCORD_BOT_TOKEN); 19 + 20 + client.on(Events.InteractionCreate, async (interaction) => { 21 + if (!interaction.isChatInputCommand()) return; 22 + const command = interaction.client.commands.get(interaction.commandName); 23 + if (!command) { 24 + console.error(`No command matching ${interaction.commandName} was found.`); 25 + return; 26 + } 27 + try { 28 + await command.execute(interaction); 29 + } catch (error) { 30 + console.error(error); 31 + if (interaction.replied || interaction.deferred) { 32 + await interaction.followUp({ 33 + content: "There was an error while executing this command!", 34 + flags: MessageFlags.Ephemeral, 35 + }); 36 + } else { 37 + await interaction.reply({ 38 + content: "There was an error while executing this command!", 39 + flags: MessageFlags.Ephemeral, 40 + }); 41 + } 42 + } 43 + }); 44 + 45 + client.commands = new Collection(); 46 + 47 + const foldersPath = path.join(import.meta.dirname as string, "commands"); 48 + const commandFolders = fs.readdirSync(foldersPath); 49 + for (const folder of commandFolders) { 50 + const commandsPath = path.join(foldersPath, folder); 51 + const commandFiles = fs.readdirSync(commandsPath).filter((file) => 52 + file.endsWith(".ts") 53 + ); 54 + for await (const file of commandFiles) { 55 + const filePath = path.join(commandsPath, file); 56 + const command = await import(filePath); 57 + if ("data" in command.default && "execute" in command.default) { 58 + client.commands.set(command.default.data.name, command.default); 59 + } else { 60 + console.warn( 61 + `[Warning] The command at ${filePath} is missing a required "data" or "execute" property.`, 62 + ); 63 + } 64 + } 65 + }
+31
package.json
··· 1 + { 2 + "name": "tealfmbot", 3 + "version": "0.0.1", 4 + "type": "module", 5 + "description": "A discord bot for teal.fm", 6 + "main": "main.ts", 7 + "scripts": { 8 + "dev": "tsx main.ts", 9 + "deploy-commands": "tsx deploy-commands.ts", 10 + "tapper:dev": "NODE_ENV=development tsx tapper.ts", 11 + "tapper:prod": "NODE_ENV=production tsx tapper.ts", 12 + "typecheck": "tsc --noEmit" 13 + }, 14 + "keywords": [ 15 + "teal.fm", 16 + "atprotocol" 17 + ], 18 + "author": "Dane Miller <me@dane.computer>", 19 + "license": "MIT", 20 + "packageManager": "pnpm@10.15.0", 21 + "dependencies": { 22 + "@atproto/tap": "^0.0.2", 23 + "discord.js": "^14.25.1", 24 + "kysely": "^0.28.9" 25 + }, 26 + "devDependencies": { 27 + "@types/node": "^25.0.3", 28 + "tsx": "^4.21.0", 29 + "typescript": "^5.9.3" 30 + } 31 + }
+815
pnpm-lock.yaml
··· 1 + lockfileVersion: '9.0' 2 + 3 + settings: 4 + autoInstallPeers: true 5 + excludeLinksFromLockfile: false 6 + 7 + importers: 8 + 9 + .: 10 + dependencies: 11 + '@atproto/tap': 12 + specifier: ^0.0.2 13 + version: 0.0.2 14 + discord.js: 15 + specifier: ^14.25.1 16 + version: 14.25.1 17 + kysely: 18 + specifier: ^0.28.9 19 + version: 0.28.9 20 + devDependencies: 21 + '@types/node': 22 + specifier: ^25.0.3 23 + version: 25.0.3 24 + tsx: 25 + specifier: ^4.21.0 26 + version: 4.21.0 27 + typescript: 28 + specifier: ^5.9.3 29 + version: 5.9.3 30 + 31 + packages: 32 + 33 + '@atproto/common-web@0.4.7': 34 + resolution: {integrity: sha512-vjw2+81KPo2/SAbbARGn64Ln+6JTI0FTI4xk8if0ebBfDxFRmHb2oSN1y77hzNq/ybGHqA2mecfhS03pxC5+lg==} 35 + 36 + '@atproto/common@0.5.3': 37 + resolution: {integrity: sha512-jMC9ikl8QbJcnh21upe9Gb9mIaSJWsdp8sgaelmntUtChWnxxvCC/pI3TBX11PT7XlHUE6UyuvY+S3hh6WZVEg==} 38 + engines: {node: '>=18.7.0'} 39 + 40 + '@atproto/lex-cbor@0.0.3': 41 + resolution: {integrity: sha512-N8lCV3kK5ZcjSOWxKLWqzlnaSpK4isjXRZ0EqApl/5y9KB64s78hQ/U3KIE5qnPRlBbW5kSH3YACoU27u9nTOA==} 42 + 43 + '@atproto/lex-data@0.0.3': 44 + resolution: {integrity: sha512-ivo1IpY/EX+RIpxPgCf4cPhQo5bfu4nrpa1vJCt8hCm9SfoonJkDFGa0n4SMw4JnXZoUcGcrJ46L+D8bH6GI2g==} 45 + 46 + '@atproto/lex-json@0.0.3': 47 + resolution: {integrity: sha512-ZVcY7XlRfdPYvQQ2WroKUepee0+NCovrSXgXURM3Xv+n5jflJCoczguROeRr8sN0xvT0ZbzMrDNHCUYKNnxcjw==} 48 + 49 + '@atproto/syntax@0.4.2': 50 + resolution: {integrity: sha512-X9XSRPinBy/0VQ677j8VXlBsYSsUXaiqxWVpGGxJYsAhugdQRb0jqaVKJFtm6RskeNkV6y9xclSUi9UYG/COrA==} 51 + 52 + '@atproto/tap@0.0.2': 53 + resolution: {integrity: sha512-CrfJWrvozuSIokOQLMeSFcF5ZpstpxIZ9PnBpgIkbLQQKb3wO+0dn90xZN5jlLjczPHvT4PrF1z8uYgVlujTlg==} 54 + engines: {node: '>=18.7.0'} 55 + 56 + '@atproto/ws-client@0.0.4': 57 + resolution: {integrity: sha512-dox1XIymuC7/ZRhUqKezIGgooZS45C6vHCfu0PnWjfvsLCK2kAlnvX4IBkA/WpcoijDhQ9ejChnFbo/sLmgvAg==} 58 + engines: {node: '>=18.7.0'} 59 + 60 + '@discordjs/builders@1.13.1': 61 + resolution: {integrity: sha512-cOU0UDHc3lp/5nKByDxkmRiNZBpdp0kx55aarbiAfakfKJHlxv/yFW1zmIqCAmwH5CRlrH9iMFKJMpvW4DPB+w==} 62 + engines: {node: '>=16.11.0'} 63 + 64 + '@discordjs/collection@1.5.3': 65 + resolution: {integrity: sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==} 66 + engines: {node: '>=16.11.0'} 67 + 68 + '@discordjs/collection@2.1.1': 69 + resolution: {integrity: sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==} 70 + engines: {node: '>=18'} 71 + 72 + '@discordjs/formatters@0.6.2': 73 + resolution: {integrity: sha512-y4UPwWhH6vChKRkGdMB4odasUbHOUwy7KL+OVwF86PvT6QVOwElx+TiI1/6kcmcEe+g5YRXJFiXSXUdabqZOvQ==} 74 + engines: {node: '>=16.11.0'} 75 + 76 + '@discordjs/rest@2.6.0': 77 + resolution: {integrity: sha512-RDYrhmpB7mTvmCKcpj+pc5k7POKszS4E2O9TYc+U+Y4iaCP+r910QdO43qmpOja8LRr1RJ0b3U+CqVsnPqzf4w==} 78 + engines: {node: '>=18'} 79 + 80 + '@discordjs/util@1.2.0': 81 + resolution: {integrity: sha512-3LKP7F2+atl9vJFhaBjn4nOaSWahZ/yWjOvA4e5pnXkt2qyXRCHLxoBQy81GFtLGCq7K9lPm9R517M1U+/90Qg==} 82 + engines: {node: '>=18'} 83 + 84 + '@discordjs/ws@1.2.3': 85 + resolution: {integrity: sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw==} 86 + engines: {node: '>=16.11.0'} 87 + 88 + '@esbuild/aix-ppc64@0.27.2': 89 + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} 90 + engines: {node: '>=18'} 91 + cpu: [ppc64] 92 + os: [aix] 93 + 94 + '@esbuild/android-arm64@0.27.2': 95 + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} 96 + engines: {node: '>=18'} 97 + cpu: [arm64] 98 + os: [android] 99 + 100 + '@esbuild/android-arm@0.27.2': 101 + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} 102 + engines: {node: '>=18'} 103 + cpu: [arm] 104 + os: [android] 105 + 106 + '@esbuild/android-x64@0.27.2': 107 + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} 108 + engines: {node: '>=18'} 109 + cpu: [x64] 110 + os: [android] 111 + 112 + '@esbuild/darwin-arm64@0.27.2': 113 + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} 114 + engines: {node: '>=18'} 115 + cpu: [arm64] 116 + os: [darwin] 117 + 118 + '@esbuild/darwin-x64@0.27.2': 119 + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} 120 + engines: {node: '>=18'} 121 + cpu: [x64] 122 + os: [darwin] 123 + 124 + '@esbuild/freebsd-arm64@0.27.2': 125 + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} 126 + engines: {node: '>=18'} 127 + cpu: [arm64] 128 + os: [freebsd] 129 + 130 + '@esbuild/freebsd-x64@0.27.2': 131 + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} 132 + engines: {node: '>=18'} 133 + cpu: [x64] 134 + os: [freebsd] 135 + 136 + '@esbuild/linux-arm64@0.27.2': 137 + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} 138 + engines: {node: '>=18'} 139 + cpu: [arm64] 140 + os: [linux] 141 + 142 + '@esbuild/linux-arm@0.27.2': 143 + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} 144 + engines: {node: '>=18'} 145 + cpu: [arm] 146 + os: [linux] 147 + 148 + '@esbuild/linux-ia32@0.27.2': 149 + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} 150 + engines: {node: '>=18'} 151 + cpu: [ia32] 152 + os: [linux] 153 + 154 + '@esbuild/linux-loong64@0.27.2': 155 + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} 156 + engines: {node: '>=18'} 157 + cpu: [loong64] 158 + os: [linux] 159 + 160 + '@esbuild/linux-mips64el@0.27.2': 161 + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} 162 + engines: {node: '>=18'} 163 + cpu: [mips64el] 164 + os: [linux] 165 + 166 + '@esbuild/linux-ppc64@0.27.2': 167 + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} 168 + engines: {node: '>=18'} 169 + cpu: [ppc64] 170 + os: [linux] 171 + 172 + '@esbuild/linux-riscv64@0.27.2': 173 + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} 174 + engines: {node: '>=18'} 175 + cpu: [riscv64] 176 + os: [linux] 177 + 178 + '@esbuild/linux-s390x@0.27.2': 179 + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} 180 + engines: {node: '>=18'} 181 + cpu: [s390x] 182 + os: [linux] 183 + 184 + '@esbuild/linux-x64@0.27.2': 185 + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} 186 + engines: {node: '>=18'} 187 + cpu: [x64] 188 + os: [linux] 189 + 190 + '@esbuild/netbsd-arm64@0.27.2': 191 + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} 192 + engines: {node: '>=18'} 193 + cpu: [arm64] 194 + os: [netbsd] 195 + 196 + '@esbuild/netbsd-x64@0.27.2': 197 + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} 198 + engines: {node: '>=18'} 199 + cpu: [x64] 200 + os: [netbsd] 201 + 202 + '@esbuild/openbsd-arm64@0.27.2': 203 + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} 204 + engines: {node: '>=18'} 205 + cpu: [arm64] 206 + os: [openbsd] 207 + 208 + '@esbuild/openbsd-x64@0.27.2': 209 + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} 210 + engines: {node: '>=18'} 211 + cpu: [x64] 212 + os: [openbsd] 213 + 214 + '@esbuild/openharmony-arm64@0.27.2': 215 + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} 216 + engines: {node: '>=18'} 217 + cpu: [arm64] 218 + os: [openharmony] 219 + 220 + '@esbuild/sunos-x64@0.27.2': 221 + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} 222 + engines: {node: '>=18'} 223 + cpu: [x64] 224 + os: [sunos] 225 + 226 + '@esbuild/win32-arm64@0.27.2': 227 + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} 228 + engines: {node: '>=18'} 229 + cpu: [arm64] 230 + os: [win32] 231 + 232 + '@esbuild/win32-ia32@0.27.2': 233 + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} 234 + engines: {node: '>=18'} 235 + cpu: [ia32] 236 + os: [win32] 237 + 238 + '@esbuild/win32-x64@0.27.2': 239 + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} 240 + engines: {node: '>=18'} 241 + cpu: [x64] 242 + os: [win32] 243 + 244 + '@sapphire/async-queue@1.5.5': 245 + resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==} 246 + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} 247 + 248 + '@sapphire/shapeshift@4.0.0': 249 + resolution: {integrity: sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==} 250 + engines: {node: '>=v16'} 251 + 252 + '@sapphire/snowflake@3.5.3': 253 + resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==} 254 + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} 255 + 256 + '@types/node@25.0.3': 257 + resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==} 258 + 259 + '@types/ws@8.18.1': 260 + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} 261 + 262 + '@vladfrangu/async_event_emitter@2.4.7': 263 + resolution: {integrity: sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g==} 264 + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} 265 + 266 + abort-controller@3.0.0: 267 + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} 268 + engines: {node: '>=6.5'} 269 + 270 + atomic-sleep@1.0.0: 271 + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} 272 + engines: {node: '>=8.0.0'} 273 + 274 + base64-js@1.5.1: 275 + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 276 + 277 + buffer@6.0.3: 278 + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} 279 + 280 + discord-api-types@0.38.37: 281 + resolution: {integrity: sha512-Cv47jzY1jkGkh5sv0bfHYqGgKOWO1peOrGMkDFM4UmaGMOTgOW8QSexhvixa9sVOiz8MnVOBryWYyw/CEVhj7w==} 282 + 283 + discord.js@14.25.1: 284 + resolution: {integrity: sha512-2l0gsPOLPs5t6GFZfQZKnL1OJNYFcuC/ETWsW4VtKVD/tg4ICa9x+jb9bkPffkMdRpRpuUaO/fKkHCBeiCKh8g==} 285 + engines: {node: '>=18'} 286 + 287 + esbuild@0.27.2: 288 + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} 289 + engines: {node: '>=18'} 290 + hasBin: true 291 + 292 + event-target-shim@5.0.1: 293 + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} 294 + engines: {node: '>=6'} 295 + 296 + events@3.3.0: 297 + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} 298 + engines: {node: '>=0.8.x'} 299 + 300 + fast-deep-equal@3.1.3: 301 + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 302 + 303 + fast-redact@3.5.0: 304 + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} 305 + engines: {node: '>=6'} 306 + 307 + fsevents@2.3.3: 308 + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 309 + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 310 + os: [darwin] 311 + 312 + get-tsconfig@4.13.0: 313 + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} 314 + 315 + ieee754@1.2.1: 316 + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 317 + 318 + iso-datestring-validator@2.2.2: 319 + resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==} 320 + 321 + kysely@0.28.9: 322 + resolution: {integrity: sha512-3BeXMoiOhpOwu62CiVpO6lxfq4eS6KMYfQdMsN/2kUCRNuF2YiEr7u0HLHaQU+O4Xu8YXE3bHVkwaQ85i72EuA==} 323 + engines: {node: '>=20.0.0'} 324 + 325 + lodash.snakecase@4.1.1: 326 + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} 327 + 328 + lodash@4.17.21: 329 + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 330 + 331 + magic-bytes.js@1.12.1: 332 + resolution: {integrity: sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==} 333 + 334 + multiformats@9.9.0: 335 + resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} 336 + 337 + on-exit-leak-free@2.1.2: 338 + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} 339 + engines: {node: '>=14.0.0'} 340 + 341 + pino-abstract-transport@1.2.0: 342 + resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} 343 + 344 + pino-std-serializers@6.2.2: 345 + resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} 346 + 347 + pino@8.21.0: 348 + resolution: {integrity: sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==} 349 + hasBin: true 350 + 351 + process-warning@3.0.0: 352 + resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} 353 + 354 + process@0.11.10: 355 + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} 356 + engines: {node: '>= 0.6.0'} 357 + 358 + quick-format-unescaped@4.0.4: 359 + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} 360 + 361 + readable-stream@4.7.0: 362 + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} 363 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 364 + 365 + real-require@0.2.0: 366 + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} 367 + engines: {node: '>= 12.13.0'} 368 + 369 + resolve-pkg-maps@1.0.0: 370 + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} 371 + 372 + safe-buffer@5.2.1: 373 + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 374 + 375 + safe-stable-stringify@2.5.0: 376 + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} 377 + engines: {node: '>=10'} 378 + 379 + sonic-boom@3.8.1: 380 + resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} 381 + 382 + split2@4.2.0: 383 + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} 384 + engines: {node: '>= 10.x'} 385 + 386 + string_decoder@1.3.0: 387 + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 388 + 389 + thread-stream@2.7.0: 390 + resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==} 391 + 392 + ts-mixer@6.0.4: 393 + resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} 394 + 395 + tslib@2.8.1: 396 + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 397 + 398 + tsx@4.21.0: 399 + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} 400 + engines: {node: '>=18.0.0'} 401 + hasBin: true 402 + 403 + typescript@5.9.3: 404 + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} 405 + engines: {node: '>=14.17'} 406 + hasBin: true 407 + 408 + uint8arrays@3.0.0: 409 + resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==} 410 + 411 + undici-types@7.16.0: 412 + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} 413 + 414 + undici@6.21.3: 415 + resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==} 416 + engines: {node: '>=18.17'} 417 + 418 + unicode-segmenter@0.14.4: 419 + resolution: {integrity: sha512-pR5VCiCrLrKOL6FRW61jnk9+wyMtKKowq+jyFY9oc6uHbWKhDL4yVRiI4YZPksGMK72Pahh8m0cn/0JvbDDyJg==} 420 + 421 + ws@8.18.3: 422 + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} 423 + engines: {node: '>=10.0.0'} 424 + peerDependencies: 425 + bufferutil: ^4.0.1 426 + utf-8-validate: '>=5.0.2' 427 + peerDependenciesMeta: 428 + bufferutil: 429 + optional: true 430 + utf-8-validate: 431 + optional: true 432 + 433 + zod@3.25.76: 434 + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} 435 + 436 + snapshots: 437 + 438 + '@atproto/common-web@0.4.7': 439 + dependencies: 440 + '@atproto/lex-data': 0.0.3 441 + '@atproto/lex-json': 0.0.3 442 + zod: 3.25.76 443 + 444 + '@atproto/common@0.5.3': 445 + dependencies: 446 + '@atproto/common-web': 0.4.7 447 + '@atproto/lex-cbor': 0.0.3 448 + '@atproto/lex-data': 0.0.3 449 + iso-datestring-validator: 2.2.2 450 + multiformats: 9.9.0 451 + pino: 8.21.0 452 + 453 + '@atproto/lex-cbor@0.0.3': 454 + dependencies: 455 + '@atproto/lex-data': 0.0.3 456 + multiformats: 9.9.0 457 + tslib: 2.8.1 458 + 459 + '@atproto/lex-data@0.0.3': 460 + dependencies: 461 + '@atproto/syntax': 0.4.2 462 + multiformats: 9.9.0 463 + tslib: 2.8.1 464 + uint8arrays: 3.0.0 465 + unicode-segmenter: 0.14.4 466 + 467 + '@atproto/lex-json@0.0.3': 468 + dependencies: 469 + '@atproto/lex-data': 0.0.3 470 + tslib: 2.8.1 471 + 472 + '@atproto/syntax@0.4.2': {} 473 + 474 + '@atproto/tap@0.0.2': 475 + dependencies: 476 + '@atproto/common': 0.5.3 477 + '@atproto/syntax': 0.4.2 478 + '@atproto/ws-client': 0.0.4 479 + ws: 8.18.3 480 + zod: 3.25.76 481 + transitivePeerDependencies: 482 + - bufferutil 483 + - utf-8-validate 484 + 485 + '@atproto/ws-client@0.0.4': 486 + dependencies: 487 + '@atproto/common': 0.5.3 488 + ws: 8.18.3 489 + transitivePeerDependencies: 490 + - bufferutil 491 + - utf-8-validate 492 + 493 + '@discordjs/builders@1.13.1': 494 + dependencies: 495 + '@discordjs/formatters': 0.6.2 496 + '@discordjs/util': 1.2.0 497 + '@sapphire/shapeshift': 4.0.0 498 + discord-api-types: 0.38.37 499 + fast-deep-equal: 3.1.3 500 + ts-mixer: 6.0.4 501 + tslib: 2.8.1 502 + 503 + '@discordjs/collection@1.5.3': {} 504 + 505 + '@discordjs/collection@2.1.1': {} 506 + 507 + '@discordjs/formatters@0.6.2': 508 + dependencies: 509 + discord-api-types: 0.38.37 510 + 511 + '@discordjs/rest@2.6.0': 512 + dependencies: 513 + '@discordjs/collection': 2.1.1 514 + '@discordjs/util': 1.2.0 515 + '@sapphire/async-queue': 1.5.5 516 + '@sapphire/snowflake': 3.5.3 517 + '@vladfrangu/async_event_emitter': 2.4.7 518 + discord-api-types: 0.38.37 519 + magic-bytes.js: 1.12.1 520 + tslib: 2.8.1 521 + undici: 6.21.3 522 + 523 + '@discordjs/util@1.2.0': 524 + dependencies: 525 + discord-api-types: 0.38.37 526 + 527 + '@discordjs/ws@1.2.3': 528 + dependencies: 529 + '@discordjs/collection': 2.1.1 530 + '@discordjs/rest': 2.6.0 531 + '@discordjs/util': 1.2.0 532 + '@sapphire/async-queue': 1.5.5 533 + '@types/ws': 8.18.1 534 + '@vladfrangu/async_event_emitter': 2.4.7 535 + discord-api-types: 0.38.37 536 + tslib: 2.8.1 537 + ws: 8.18.3 538 + transitivePeerDependencies: 539 + - bufferutil 540 + - utf-8-validate 541 + 542 + '@esbuild/aix-ppc64@0.27.2': 543 + optional: true 544 + 545 + '@esbuild/android-arm64@0.27.2': 546 + optional: true 547 + 548 + '@esbuild/android-arm@0.27.2': 549 + optional: true 550 + 551 + '@esbuild/android-x64@0.27.2': 552 + optional: true 553 + 554 + '@esbuild/darwin-arm64@0.27.2': 555 + optional: true 556 + 557 + '@esbuild/darwin-x64@0.27.2': 558 + optional: true 559 + 560 + '@esbuild/freebsd-arm64@0.27.2': 561 + optional: true 562 + 563 + '@esbuild/freebsd-x64@0.27.2': 564 + optional: true 565 + 566 + '@esbuild/linux-arm64@0.27.2': 567 + optional: true 568 + 569 + '@esbuild/linux-arm@0.27.2': 570 + optional: true 571 + 572 + '@esbuild/linux-ia32@0.27.2': 573 + optional: true 574 + 575 + '@esbuild/linux-loong64@0.27.2': 576 + optional: true 577 + 578 + '@esbuild/linux-mips64el@0.27.2': 579 + optional: true 580 + 581 + '@esbuild/linux-ppc64@0.27.2': 582 + optional: true 583 + 584 + '@esbuild/linux-riscv64@0.27.2': 585 + optional: true 586 + 587 + '@esbuild/linux-s390x@0.27.2': 588 + optional: true 589 + 590 + '@esbuild/linux-x64@0.27.2': 591 + optional: true 592 + 593 + '@esbuild/netbsd-arm64@0.27.2': 594 + optional: true 595 + 596 + '@esbuild/netbsd-x64@0.27.2': 597 + optional: true 598 + 599 + '@esbuild/openbsd-arm64@0.27.2': 600 + optional: true 601 + 602 + '@esbuild/openbsd-x64@0.27.2': 603 + optional: true 604 + 605 + '@esbuild/openharmony-arm64@0.27.2': 606 + optional: true 607 + 608 + '@esbuild/sunos-x64@0.27.2': 609 + optional: true 610 + 611 + '@esbuild/win32-arm64@0.27.2': 612 + optional: true 613 + 614 + '@esbuild/win32-ia32@0.27.2': 615 + optional: true 616 + 617 + '@esbuild/win32-x64@0.27.2': 618 + optional: true 619 + 620 + '@sapphire/async-queue@1.5.5': {} 621 + 622 + '@sapphire/shapeshift@4.0.0': 623 + dependencies: 624 + fast-deep-equal: 3.1.3 625 + lodash: 4.17.21 626 + 627 + '@sapphire/snowflake@3.5.3': {} 628 + 629 + '@types/node@25.0.3': 630 + dependencies: 631 + undici-types: 7.16.0 632 + 633 + '@types/ws@8.18.1': 634 + dependencies: 635 + '@types/node': 25.0.3 636 + 637 + '@vladfrangu/async_event_emitter@2.4.7': {} 638 + 639 + abort-controller@3.0.0: 640 + dependencies: 641 + event-target-shim: 5.0.1 642 + 643 + atomic-sleep@1.0.0: {} 644 + 645 + base64-js@1.5.1: {} 646 + 647 + buffer@6.0.3: 648 + dependencies: 649 + base64-js: 1.5.1 650 + ieee754: 1.2.1 651 + 652 + discord-api-types@0.38.37: {} 653 + 654 + discord.js@14.25.1: 655 + dependencies: 656 + '@discordjs/builders': 1.13.1 657 + '@discordjs/collection': 1.5.3 658 + '@discordjs/formatters': 0.6.2 659 + '@discordjs/rest': 2.6.0 660 + '@discordjs/util': 1.2.0 661 + '@discordjs/ws': 1.2.3 662 + '@sapphire/snowflake': 3.5.3 663 + discord-api-types: 0.38.37 664 + fast-deep-equal: 3.1.3 665 + lodash.snakecase: 4.1.1 666 + magic-bytes.js: 1.12.1 667 + tslib: 2.8.1 668 + undici: 6.21.3 669 + transitivePeerDependencies: 670 + - bufferutil 671 + - utf-8-validate 672 + 673 + esbuild@0.27.2: 674 + optionalDependencies: 675 + '@esbuild/aix-ppc64': 0.27.2 676 + '@esbuild/android-arm': 0.27.2 677 + '@esbuild/android-arm64': 0.27.2 678 + '@esbuild/android-x64': 0.27.2 679 + '@esbuild/darwin-arm64': 0.27.2 680 + '@esbuild/darwin-x64': 0.27.2 681 + '@esbuild/freebsd-arm64': 0.27.2 682 + '@esbuild/freebsd-x64': 0.27.2 683 + '@esbuild/linux-arm': 0.27.2 684 + '@esbuild/linux-arm64': 0.27.2 685 + '@esbuild/linux-ia32': 0.27.2 686 + '@esbuild/linux-loong64': 0.27.2 687 + '@esbuild/linux-mips64el': 0.27.2 688 + '@esbuild/linux-ppc64': 0.27.2 689 + '@esbuild/linux-riscv64': 0.27.2 690 + '@esbuild/linux-s390x': 0.27.2 691 + '@esbuild/linux-x64': 0.27.2 692 + '@esbuild/netbsd-arm64': 0.27.2 693 + '@esbuild/netbsd-x64': 0.27.2 694 + '@esbuild/openbsd-arm64': 0.27.2 695 + '@esbuild/openbsd-x64': 0.27.2 696 + '@esbuild/openharmony-arm64': 0.27.2 697 + '@esbuild/sunos-x64': 0.27.2 698 + '@esbuild/win32-arm64': 0.27.2 699 + '@esbuild/win32-ia32': 0.27.2 700 + '@esbuild/win32-x64': 0.27.2 701 + 702 + event-target-shim@5.0.1: {} 703 + 704 + events@3.3.0: {} 705 + 706 + fast-deep-equal@3.1.3: {} 707 + 708 + fast-redact@3.5.0: {} 709 + 710 + fsevents@2.3.3: 711 + optional: true 712 + 713 + get-tsconfig@4.13.0: 714 + dependencies: 715 + resolve-pkg-maps: 1.0.0 716 + 717 + ieee754@1.2.1: {} 718 + 719 + iso-datestring-validator@2.2.2: {} 720 + 721 + kysely@0.28.9: {} 722 + 723 + lodash.snakecase@4.1.1: {} 724 + 725 + lodash@4.17.21: {} 726 + 727 + magic-bytes.js@1.12.1: {} 728 + 729 + multiformats@9.9.0: {} 730 + 731 + on-exit-leak-free@2.1.2: {} 732 + 733 + pino-abstract-transport@1.2.0: 734 + dependencies: 735 + readable-stream: 4.7.0 736 + split2: 4.2.0 737 + 738 + pino-std-serializers@6.2.2: {} 739 + 740 + pino@8.21.0: 741 + dependencies: 742 + atomic-sleep: 1.0.0 743 + fast-redact: 3.5.0 744 + on-exit-leak-free: 2.1.2 745 + pino-abstract-transport: 1.2.0 746 + pino-std-serializers: 6.2.2 747 + process-warning: 3.0.0 748 + quick-format-unescaped: 4.0.4 749 + real-require: 0.2.0 750 + safe-stable-stringify: 2.5.0 751 + sonic-boom: 3.8.1 752 + thread-stream: 2.7.0 753 + 754 + process-warning@3.0.0: {} 755 + 756 + process@0.11.10: {} 757 + 758 + quick-format-unescaped@4.0.4: {} 759 + 760 + readable-stream@4.7.0: 761 + dependencies: 762 + abort-controller: 3.0.0 763 + buffer: 6.0.3 764 + events: 3.3.0 765 + process: 0.11.10 766 + string_decoder: 1.3.0 767 + 768 + real-require@0.2.0: {} 769 + 770 + resolve-pkg-maps@1.0.0: {} 771 + 772 + safe-buffer@5.2.1: {} 773 + 774 + safe-stable-stringify@2.5.0: {} 775 + 776 + sonic-boom@3.8.1: 777 + dependencies: 778 + atomic-sleep: 1.0.0 779 + 780 + split2@4.2.0: {} 781 + 782 + string_decoder@1.3.0: 783 + dependencies: 784 + safe-buffer: 5.2.1 785 + 786 + thread-stream@2.7.0: 787 + dependencies: 788 + real-require: 0.2.0 789 + 790 + ts-mixer@6.0.4: {} 791 + 792 + tslib@2.8.1: {} 793 + 794 + tsx@4.21.0: 795 + dependencies: 796 + esbuild: 0.27.2 797 + get-tsconfig: 4.13.0 798 + optionalDependencies: 799 + fsevents: 2.3.3 800 + 801 + typescript@5.9.3: {} 802 + 803 + uint8arrays@3.0.0: 804 + dependencies: 805 + multiformats: 9.9.0 806 + 807 + undici-types@7.16.0: {} 808 + 809 + undici@6.21.3: {} 810 + 811 + unicode-segmenter@0.14.4: {} 812 + 813 + ws@8.18.3: {} 814 + 815 + zod@3.25.76: {}
+2
pnpm-workspace.yaml
··· 1 + onlyBuiltDependencies: 2 + - esbuild
+28
tapper.ts
··· 1 + import { SimpleIndexer, Tap } from "@atproto/tap"; 2 + import { TAP_ADMIN_PASSWORD } from "./constants.ts"; 3 + 4 + const tap = new Tap("https://tap.xero.systems", { 5 + adminPassword: TAP_ADMIN_PASSWORD, 6 + }); 7 + 8 + const indexer = new SimpleIndexer(); 9 + 10 + indexer.record(async (evt, opts) => { 11 + const uri = `at://${evt.did}/${evt.collection}/${evt.rkey}`; 12 + if (evt.action === "create" || evt.action === "update") { 13 + console.log(evt.record); 14 + } else { 15 + console.log(`deleted: ${uri}`); 16 + } 17 + 18 + if (process.env.NODE_ENV === "development") { 19 + // we don't want to ack in development 20 + // @ts-ignore 21 + opts.ack = () => console.log('"acknowledged"'); 22 + } 23 + }); 24 + 25 + indexer.error((err) => console.error(err)); 26 + 27 + const channel = tap.channel(indexer); 28 + channel.start();
+24
tsconfig.json
··· 1 + { 2 + "compilerOptions": { 3 + "outDir": "./dist", 4 + "module": "nodenext", 5 + "target": "esnext", 6 + "lib": [ 7 + "esnext" 8 + ], 9 + "types": [ 10 + "node" 11 + ], 12 + "esModuleInterop": true, 13 + "sourceMap": true, 14 + "noUncheckedIndexedAccess": true, 15 + "exactOptionalPropertyTypes": true, 16 + "strict": true, 17 + "verbatimModuleSyntax": true, 18 + "isolatedModules": true, 19 + "allowImportingTsExtensions": true, 20 + "noUncheckedSideEffectImports": true, 21 + "moduleDetection": "force", 22 + "skipLibCheck": true, 23 + } 24 + }