+21
LICENSE
+21
LICENSE
···
1
+
MIT License
2
+
3
+
Copyright (c) 2025 Dane Miller
4
+
5
+
Permission is hereby granted, free of charge, to any person obtaining a copy
6
+
of this software and associated documentation files (the "Software"), to deal
7
+
in the Software without restriction, including without limitation the rights
8
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+
copies of the Software, and to permit persons to whom the Software is
10
+
furnished to do so, subject to the following conditions:
11
+
12
+
The above copyright notice and this permission notice shall be included in all
13
+
copies or substantial portions of the Software.
14
+
15
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+
SOFTWARE.
+22
apps/bot/package.json
+22
apps/bot/package.json
···
1
+
{
2
+
"name": "bot",
3
+
"version": "0.0.1",
4
+
"type": "module",
5
+
"private": true,
6
+
"scripts": {
7
+
"dev": "tsx main.ts",
8
+
"deploy-commands": "tsx deploy-commands.ts",
9
+
"build": "tsc",
10
+
"typecheck": "tsc --noEmit"
11
+
},
12
+
"dependencies": {
13
+
"@tealfmbot/common": "workspace:*",
14
+
"@tealfmbot/tsconfig": "workspace:*",
15
+
"discord.js": "^14.25.1"
16
+
},
17
+
"devDependencies": {
18
+
"@types/node": "^25.0.3",
19
+
"tsx": "^4.21.0",
20
+
"typescript": "^5.9.3"
21
+
}
22
+
}
+9
apps/bot/tsconfig.json
+9
apps/bot/tsconfig.json
+21
apps/tapper/package.json
+21
apps/tapper/package.json
···
1
+
{
2
+
"name": "tapper",
3
+
"version": "0.0.1",
4
+
"type": "module",
5
+
"private": true,
6
+
"scripts": {
7
+
"dev": "NODE_ENV=development tsx index.ts",
8
+
"start": "NODE_ENV=production tsx index.ts",
9
+
"typecheck": "tsc --noEmit"
10
+
},
11
+
"dependencies": {
12
+
"@atproto/tap": "^0.0.2",
13
+
"@tealfmbot/common": "workspace:*",
14
+
"@tealfmbot/tsconfig": "workspace:*"
15
+
},
16
+
"devDependencies": {
17
+
"@types/node": "^25.0.3",
18
+
"tsx": "^4.21.0",
19
+
"typescript": "^5.9.3"
20
+
}
21
+
}
+9
apps/tapper/tsconfig.json
+9
apps/tapper/tsconfig.json
+1
-1
commands/auth.ts
apps/bot/commands/auth.ts
+1
-1
commands/auth.ts
apps/bot/commands/auth.ts
+1
-1
commands/ping.ts
apps/bot/commands/ping.ts
+1
-1
commands/ping.ts
apps/bot/commands/ping.ts
+1
-1
commands/top.ts
apps/bot/commands/top.ts
+1
-1
commands/top.ts
apps/bot/commands/top.ts
+2
-1
constants.ts
packages/common/constants.ts
+2
-1
constants.ts
packages/common/constants.ts
···
1
1
import { loadEnvFile } from "node:process"
2
+
import path from "node:path"
2
3
3
-
loadEnvFile()
4
+
loadEnvFile(path.join(import.meta.dirname, "../../.env"))
4
5
5
6
export const DISCORD_BOT_TOKEN = process.env.DISCORD_BOT_TOKEN as string;
6
7
export const DISCORD_APPLICATION_ID = process.env.DISCORD_APPLICATION_ID as string;
+1
-1
deploy-commands.ts
apps/bot/deploy-commands.ts
+1
-1
deploy-commands.ts
apps/bot/deploy-commands.ts
discord.d.ts
apps/bot/discord.d.ts
discord.d.ts
apps/bot/discord.d.ts
+1
-1
kysely/db.ts
packages/database/db.ts
+1
-1
kysely/db.ts
packages/database/db.ts
···
1
1
import type { DB } from "kysely-codegen"
2
2
import { Pool } from "pg"
3
3
import { Kysely, PostgresDialect } from "kysely"
4
-
import { DATABASE_URL } from "../constants.ts"
4
+
import { DATABASE_URL } from "@tealfmbot/common/constants.ts"
5
5
6
6
const dialect = new PostgresDialect({
7
7
pool: new Pool({
+1
-1
kysely/migrator.ts
packages/database/migrator.ts
+1
-1
kysely/migrator.ts
packages/database/migrator.ts
···
3
3
import fs from "node:fs/promises"
4
4
import type { DB } from "kysely-codegen"
5
5
import { Kysely, Migrator, PostgresDialect, FileMigrationProvider } from "kysely"
6
-
import { DATABASE_URL } from "../constants.ts"
6
+
import { DATABASE_URL } from "@tealfmbot/common/constants.ts"
7
7
8
8
async function migrateToLatest() {
9
9
const db = new Kysely<DB>({
kysely/seed.ts
packages/database/seed.ts
kysely/seed.ts
packages/database/seed.ts
logger.ts
packages/common/logger.ts
logger.ts
packages/common/logger.ts
+2
-2
main.ts
apps/bot/main.ts
+2
-2
main.ts
apps/bot/main.ts
···
7
7
} from "discord.js";
8
8
import fs from "node:fs";
9
9
import path from "node:path";
10
-
import { DISCORD_BOT_TOKEN } from "./constants.ts";
11
-
import { logger } from "./logger.ts";
10
+
import { DISCORD_BOT_TOKEN } from "@tealfmbot/common/constants.ts";
11
+
import { logger } from "@tealfmbot/common/logger.ts";
12
12
13
13
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
14
14
migrations/schema.ts
packages/database/migrations/schema.ts
migrations/schema.ts
packages/database/migrations/schema.ts
+4
-22
package.json
+4
-22
package.json
···
1
1
{
2
2
"name": "tealfmbot",
3
3
"version": "0.0.1",
4
-
"type": "module",
4
+
"private": true,
5
5
"description": "A discord bot for teal.fm",
6
-
"main": "main.ts",
7
6
"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
-
"migrate": "tsx kysely/migrator.ts",
13
-
"codegen": "kysely-codegen --dialect postgres",
14
-
"seed": "tsx kysely/seed.ts",
15
-
"typecheck": "tsc --noEmit"
7
+
"bot": "pnpm --filter bot dev",
8
+
"tap": "pnpm --filter tapper dev",
9
+
"typecheck": "pnpm --filter './{packages,apps}/**' typecheck"
16
10
},
17
11
"keywords": [
18
12
"teal.fm",
···
22
16
"author": "Dane Miller <me@dane.computer>",
23
17
"license": "MIT",
24
18
"packageManager": "pnpm@10.15.0",
25
-
"dependencies": {
26
-
"@atproto/tap": "^0.0.2",
27
-
"discord.js": "^14.25.1",
28
-
"kysely": "^0.28.9",
29
-
"pg": "^8.16.3",
30
-
"pino": "^10.1.0"
31
-
},
32
19
"devDependencies": {
33
-
"@types/node": "^25.0.3",
34
-
"@types/pg": "^8.16.0",
35
-
"kysely-codegen": "^0.19.0",
36
-
"pino-pretty": "^13.1.3",
37
-
"tsx": "^4.21.0",
38
20
"typescript": "^5.9.3"
39
21
}
40
22
}
+21
packages/common/package.json
+21
packages/common/package.json
···
1
+
{
2
+
"name": "@tealfmbot/common",
3
+
"version": "0.0.0",
4
+
"type": "module",
5
+
"private": true,
6
+
"exports": {
7
+
"./*": "./*"
8
+
},
9
+
"scripts": {
10
+
"typecheck": "tsc --noEmit"
11
+
},
12
+
"devDependencies": {
13
+
"@tealfmbot/tsconfig": "workspace:*",
14
+
"@types/node": "^22.15.3",
15
+
"typescript": "5.9.2",
16
+
"pino-pretty": "^13.1.3"
17
+
},
18
+
"dependencies": {
19
+
"pino": "^10.1.0"
20
+
}
21
+
}
+3
packages/common/tsconfig.json
+3
packages/common/tsconfig.json
+28
packages/database/package.json
+28
packages/database/package.json
···
1
+
{
2
+
"name": "@tealfmbot/database",
3
+
"version": "0.0.0",
4
+
"type": "module",
5
+
"private": true,
6
+
"exports": {
7
+
"./db.ts": "./db.ts"
8
+
},
9
+
"scripts": {
10
+
"migrate": "tsx migrator.ts",
11
+
"codegen": "kysely-codegen --dialect postgres --env-file='../../.env'",
12
+
"seed": "tsx seed.ts",
13
+
"typecheck": "tsc --noEmit"
14
+
},
15
+
"devDependencies": {
16
+
"@types/node": "^22.15.3",
17
+
"@types/pg": "^8.16.0",
18
+
"kysely-codegen": "^0.19.0",
19
+
"tsx": "^4.21.0",
20
+
"typescript": "5.9.2"
21
+
},
22
+
"dependencies": {
23
+
"@tealfmbot/common": "workspace:*",
24
+
"@tealfmbot/tsconfig": "workspace:*",
25
+
"kysely": "^0.28.9",
26
+
"pg": "^8.16.3"
27
+
}
28
+
}
+6
packages/database/tsconfig.json
+6
packages/database/tsconfig.json
+9
packages/tsconfig/package.json
+9
packages/tsconfig/package.json
+11
packages/tsconfig/tsconfig.node.json
+11
packages/tsconfig/tsconfig.node.json
+103
-19
pnpm-lock.yaml
+103
-19
pnpm-lock.yaml
···
7
7
importers:
8
8
9
9
.:
10
+
devDependencies:
11
+
typescript:
12
+
specifier: ^5.9.3
13
+
version: 5.9.3
14
+
15
+
apps/bot:
16
+
dependencies:
17
+
'@tealfmbot/common':
18
+
specifier: workspace:*
19
+
version: link:../../packages/common
20
+
'@tealfmbot/tsconfig':
21
+
specifier: workspace:*
22
+
version: link:../../packages/tsconfig
23
+
discord.js:
24
+
specifier: ^14.25.1
25
+
version: 14.25.1
26
+
devDependencies:
27
+
'@types/node':
28
+
specifier: ^25.0.3
29
+
version: 25.0.3
30
+
tsx:
31
+
specifier: ^4.21.0
32
+
version: 4.21.0
33
+
typescript:
34
+
specifier: ^5.9.3
35
+
version: 5.9.3
36
+
37
+
apps/tapper:
10
38
dependencies:
11
39
'@atproto/tap':
12
40
specifier: ^0.0.2
13
41
version: 0.0.2
14
-
discord.js:
15
-
specifier: ^14.25.1
16
-
version: 14.25.1
42
+
'@tealfmbot/common':
43
+
specifier: workspace:*
44
+
version: link:../../packages/common
45
+
'@tealfmbot/tsconfig':
46
+
specifier: workspace:*
47
+
version: link:../../packages/tsconfig
48
+
devDependencies:
49
+
'@types/node':
50
+
specifier: ^25.0.3
51
+
version: 25.0.3
52
+
tsx:
53
+
specifier: ^4.21.0
54
+
version: 4.21.0
55
+
typescript:
56
+
specifier: ^5.9.3
57
+
version: 5.9.3
58
+
59
+
packages/common:
60
+
dependencies:
61
+
pino:
62
+
specifier: ^10.1.0
63
+
version: 10.1.0
64
+
devDependencies:
65
+
'@tealfmbot/tsconfig':
66
+
specifier: workspace:*
67
+
version: link:../tsconfig
68
+
'@types/node':
69
+
specifier: ^22.15.3
70
+
version: 22.19.3
71
+
pino-pretty:
72
+
specifier: ^13.1.3
73
+
version: 13.1.3
74
+
typescript:
75
+
specifier: 5.9.2
76
+
version: 5.9.2
77
+
78
+
packages/database:
79
+
dependencies:
80
+
'@tealfmbot/common':
81
+
specifier: workspace:*
82
+
version: link:../common
83
+
'@tealfmbot/tsconfig':
84
+
specifier: workspace:*
85
+
version: link:../tsconfig
17
86
kysely:
18
87
specifier: ^0.28.9
19
88
version: 0.28.9
20
89
pg:
21
90
specifier: ^8.16.3
22
91
version: 8.16.3
23
-
pino:
24
-
specifier: ^10.1.0
25
-
version: 10.1.0
26
92
devDependencies:
27
93
'@types/node':
28
-
specifier: ^25.0.3
29
-
version: 25.0.3
94
+
specifier: ^22.15.3
95
+
version: 22.19.3
30
96
'@types/pg':
31
97
specifier: ^8.16.0
32
98
version: 8.16.0
33
99
kysely-codegen:
34
100
specifier: ^0.19.0
35
-
version: 0.19.0(kysely@0.28.9)(pg@8.16.3)(typescript@5.9.3)
36
-
pino-pretty:
37
-
specifier: ^13.1.3
38
-
version: 13.1.3
101
+
version: 0.19.0(kysely@0.28.9)(pg@8.16.3)(typescript@5.9.2)
39
102
tsx:
40
103
specifier: ^4.21.0
41
104
version: 4.21.0
42
105
typescript:
43
-
specifier: ^5.9.3
44
-
version: 5.9.3
106
+
specifier: 5.9.2
107
+
version: 5.9.2
108
+
109
+
packages/tsconfig: {}
45
110
46
111
packages:
47
112
···
278
343
'@sapphire/snowflake@3.5.3':
279
344
resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==}
280
345
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
346
+
347
+
'@types/node@22.19.3':
348
+
resolution: {integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==}
281
349
282
350
'@types/node@25.0.3':
283
351
resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==}
···
807
875
engines: {node: '>=18.0.0'}
808
876
hasBin: true
809
877
878
+
typescript@5.9.2:
879
+
resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==}
880
+
engines: {node: '>=14.17'}
881
+
hasBin: true
882
+
810
883
typescript@5.9.3:
811
884
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
812
885
engines: {node: '>=14.17'}
···
814
887
815
888
uint8arrays@3.0.0:
816
889
resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==}
890
+
891
+
undici-types@6.21.0:
892
+
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
817
893
818
894
undici-types@7.16.0:
819
895
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
···
1053
1129
1054
1130
'@sapphire/snowflake@3.5.3': {}
1055
1131
1132
+
'@types/node@22.19.3':
1133
+
dependencies:
1134
+
undici-types: 6.21.0
1135
+
1056
1136
'@types/node@25.0.3':
1057
1137
dependencies:
1058
1138
undici-types: 7.16.0
1059
1139
1060
1140
'@types/pg@8.16.0':
1061
1141
dependencies:
1062
-
'@types/node': 25.0.3
1142
+
'@types/node': 22.19.3
1063
1143
pg-protocol: 1.10.3
1064
1144
pg-types: 2.2.0
1065
1145
···
1132
1212
1133
1213
concat-map@0.0.1: {}
1134
1214
1135
-
cosmiconfig@9.0.0(typescript@5.9.3):
1215
+
cosmiconfig@9.0.0(typescript@5.9.2):
1136
1216
dependencies:
1137
1217
env-paths: 2.2.1
1138
1218
import-fresh: 3.3.1
1139
1219
js-yaml: 4.1.1
1140
1220
parse-json: 5.2.0
1141
1221
optionalDependencies:
1142
-
typescript: 5.9.3
1222
+
typescript: 5.9.2
1143
1223
1144
1224
dateformat@4.6.3: {}
1145
1225
···
1305
1385
1306
1386
json-parse-even-better-errors@2.3.1: {}
1307
1387
1308
-
kysely-codegen@0.19.0(kysely@0.28.9)(pg@8.16.3)(typescript@5.9.3):
1388
+
kysely-codegen@0.19.0(kysely@0.28.9)(pg@8.16.3)(typescript@5.9.2):
1309
1389
dependencies:
1310
1390
chalk: 4.1.2
1311
-
cosmiconfig: 9.0.0(typescript@5.9.3)
1391
+
cosmiconfig: 9.0.0(typescript@5.9.2)
1312
1392
dotenv: 17.2.3
1313
1393
dotenv-expand: 12.0.3
1314
1394
git-diff: 2.0.6
···
1580
1660
optionalDependencies:
1581
1661
fsevents: 2.3.3
1582
1662
1663
+
typescript@5.9.2: {}
1664
+
1583
1665
typescript@5.9.3: {}
1584
1666
1585
1667
uint8arrays@3.0.0:
1586
1668
dependencies:
1587
1669
multiformats: 9.9.0
1670
+
1671
+
undici-types@6.21.0: {}
1588
1672
1589
1673
undici-types@7.16.0: {}
1590
1674
+4
pnpm-workspace.yaml
+4
pnpm-workspace.yaml
+2
-1
tapper.ts
apps/tapper/index.ts
+2
-1
tapper.ts
apps/tapper/index.ts
···
1
1
import { SimpleIndexer, Tap } from "@atproto/tap";
2
-
import { TAP_ADMIN_PASSWORD } from "./constants.ts";
2
+
import { TAP_ADMIN_PASSWORD } from "@tealfmbot/common/constants.ts";
3
3
// import { db } from "./kysely/db.ts"
4
4
5
5
const tap = new Tap("https://tap.xero.systems", {
···
21
21
} else {
22
22
console.log(`deleted: ${uri}`);
23
23
}
24
+
24
25
25
26
if (process.env.NODE_ENV === "development") {
26
27
// we don't want to ack in development
-7
tsconfig.json
packages/tsconfig/tsconfig.base.json
-7
tsconfig.json
packages/tsconfig/tsconfig.base.json
types.ts
packages/database/types.ts
types.ts
packages/database/types.ts