feat: analytics
Node.js CI / Lint and Test (push) Successful in 52s

This commit is contained in:
2025-10-07 18:26:02 -07:00
parent 7eaa4416d5
commit b9214d6ff1
4 changed files with 66 additions and 7 deletions
+2 -1
View File
@@ -22,7 +22,8 @@
"typescript": "5.8.3" "typescript": "5.8.3"
}, },
"dependencies": { "dependencies": {
"@nhcarrigan/logger": "1.0.0", "@nhcarrigan/discord-analytics": "0.0.5",
"@nhcarrigan/logger": "1.1.1",
"@prisma/client": "6.12.0", "@prisma/client": "6.12.0",
"discord.js": "14.21.0", "discord.js": "14.21.0",
"fastify": "5.4.0" "fastify": "5.4.0"
+54 -5
View File
@@ -8,9 +8,12 @@ importers:
.: .:
dependencies: dependencies:
'@nhcarrigan/discord-analytics':
specifier: 0.0.5
version: 0.0.5(@nhcarrigan/logger@1.1.1)(discord.js@14.21.0)
'@nhcarrigan/logger': '@nhcarrigan/logger':
specifier: 1.0.0 specifier: 1.1.1
version: 1.0.0 version: 1.1.1
'@prisma/client': '@prisma/client':
specifier: 6.12.0 specifier: 6.12.0
version: 6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3) version: 6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3)
@@ -337,6 +340,12 @@ packages:
'@jridgewell/sourcemap-codec@1.5.4': '@jridgewell/sourcemap-codec@1.5.4':
resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==}
'@nhcarrigan/discord-analytics@0.0.5':
resolution: {integrity: sha512-dxkXFB/o12AEPWGmv2/d+rQYZ+rzm1tkW9gjeVs/8JMadk+gDIDlSdOlWZrov/VhQGWLpHJFfZD2Y9qcnPf8kg==}
peerDependencies:
'@nhcarrigan/logger': '>=1.1.0-hotfix'
discord.js: ^14.0.0
'@nhcarrigan/eslint-config@5.2.0': '@nhcarrigan/eslint-config@5.2.0':
resolution: {integrity: sha512-YpTTqhviKMlRwKF+RC/GYiA5i2jTCmg8uftuiufldneNV5HMbGpTfBbV7tpa8++5mpYJc4+eZaf40QbDiz84dQ==} resolution: {integrity: sha512-YpTTqhviKMlRwKF+RC/GYiA5i2jTCmg8uftuiufldneNV5HMbGpTfBbV7tpa8++5mpYJc4+eZaf40QbDiz84dQ==}
engines: {node: '>=22', pnpm: '>=9'} engines: {node: '>=22', pnpm: '>=9'}
@@ -347,8 +356,8 @@ packages:
typescript: '>=5' typescript: '>=5'
vitest: '>=2' vitest: '>=2'
'@nhcarrigan/logger@1.0.0': '@nhcarrigan/logger@1.1.1':
resolution: {integrity: sha512-2e19Bie+ZKb6yKPKjhawqsENkhHatYkvBAmFZx9eToOXdOca+CYi51tldRMtejg6e0+4hOOf2bo5zdBQKmH0dw==} resolution: {integrity: sha512-P6OEQFHDtf6psybYGljuCxkSW6DLQCsx1aZZ3w4YKBXHBFjDbhuvpM9K1kPhVN48hakitx2WPLEoIFr6YZELYw==}
'@nhcarrigan/typescript-config@4.0.0': '@nhcarrigan/typescript-config@4.0.0':
resolution: {integrity: sha512-969HVha7A/Sg77fuMwOm6p14a+7C5iE6g55OD71srqwKIgksQl+Ex/hAI/pyzTQFDQ/FBJbpnHlR4Ov25QV/rw==} resolution: {integrity: sha512-969HVha7A/Sg77fuMwOm6p14a+7C5iE6g55OD71srqwKIgksQl+Ex/hAI/pyzTQFDQ/FBJbpnHlR4Ov25QV/rw==}
@@ -888,6 +897,10 @@ packages:
core-js-compat@3.44.0: core-js-compat@3.44.0:
resolution: {integrity: sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==} resolution: {integrity: sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==}
cron-parser@4.9.0:
resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==}
engines: {node: '>=12.0.0'}
cross-spawn@7.0.6: cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@@ -1537,6 +1550,9 @@ packages:
lodash@4.17.21: lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
long-timeout@0.1.1:
resolution: {integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==}
loose-envify@1.4.0: loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true hasBin: true
@@ -1544,6 +1560,10 @@ packages:
loupe@3.1.4: loupe@3.1.4:
resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==} resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==}
luxon@3.7.2:
resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==}
engines: {node: '>=12'}
magic-bytes.js@1.12.1: magic-bytes.js@1.12.1:
resolution: {integrity: sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==} resolution: {integrity: sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==}
@@ -1590,6 +1610,10 @@ packages:
node-releases@2.0.19: node-releases@2.0.19:
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
node-schedule@2.1.1:
resolution: {integrity: sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==}
engines: {node: '>=6'}
normalize-package-data@2.5.0: normalize-package-data@2.5.0:
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
@@ -1929,6 +1953,9 @@ packages:
sonic-boom@4.2.0: sonic-boom@4.2.0:
resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==}
sorted-array-functions@1.3.0:
resolution: {integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==}
source-map-js@1.2.1: source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -2490,6 +2517,12 @@ snapshots:
'@jridgewell/sourcemap-codec@1.5.4': {} '@jridgewell/sourcemap-codec@1.5.4': {}
'@nhcarrigan/discord-analytics@0.0.5(@nhcarrigan/logger@1.1.1)(discord.js@14.21.0)':
dependencies:
'@nhcarrigan/logger': 1.1.1
discord.js: 14.21.0
node-schedule: 2.1.1
'@nhcarrigan/eslint-config@5.2.0(@typescript-eslint/utils@8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.31.0(jiti@2.4.2))(playwright@1.54.1)(react@19.1.0)(typescript@5.8.3)(vitest@3.2.4(@types/node@24.0.15)(jiti@2.4.2))': '@nhcarrigan/eslint-config@5.2.0(@typescript-eslint/utils@8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.31.0(jiti@2.4.2))(playwright@1.54.1)(react@19.1.0)(typescript@5.8.3)(vitest@3.2.4(@types/node@24.0.15)(jiti@2.4.2))':
dependencies: dependencies:
'@eslint-community/eslint-plugin-eslint-comments': 4.4.1(eslint@9.31.0(jiti@2.4.2)) '@eslint-community/eslint-plugin-eslint-comments': 4.4.1(eslint@9.31.0(jiti@2.4.2))
@@ -2519,7 +2552,7 @@ snapshots:
- eslint-import-resolver-webpack - eslint-import-resolver-webpack
- supports-color - supports-color
'@nhcarrigan/logger@1.0.0': {} '@nhcarrigan/logger@1.1.1': {}
'@nhcarrigan/typescript-config@4.0.0(typescript@5.8.3)': '@nhcarrigan/typescript-config@4.0.0(typescript@5.8.3)':
dependencies: dependencies:
@@ -3101,6 +3134,10 @@ snapshots:
dependencies: dependencies:
browserslist: 4.25.1 browserslist: 4.25.1
cron-parser@4.9.0:
dependencies:
luxon: 3.7.2
cross-spawn@7.0.6: cross-spawn@7.0.6:
dependencies: dependencies:
path-key: 3.1.1 path-key: 3.1.1
@@ -3953,12 +3990,16 @@ snapshots:
lodash@4.17.21: {} lodash@4.17.21: {}
long-timeout@0.1.1: {}
loose-envify@1.4.0: loose-envify@1.4.0:
dependencies: dependencies:
js-tokens: 4.0.0 js-tokens: 4.0.0
loupe@3.1.4: {} loupe@3.1.4: {}
luxon@3.7.2: {}
magic-bytes.js@1.12.1: {} magic-bytes.js@1.12.1: {}
magic-string@0.30.17: magic-string@0.30.17:
@@ -3994,6 +4035,12 @@ snapshots:
node-releases@2.0.19: {} node-releases@2.0.19: {}
node-schedule@2.1.1:
dependencies:
cron-parser: 4.9.0
long-timeout: 0.1.1
sorted-array-functions: 1.3.0
normalize-package-data@2.5.0: normalize-package-data@2.5.0:
dependencies: dependencies:
hosted-git-info: 2.8.9 hosted-git-info: 2.8.9
@@ -4375,6 +4422,8 @@ snapshots:
dependencies: dependencies:
atomic-sleep: 1.0.0 atomic-sleep: 1.0.0
sorted-array-functions@1.3.0: {}
source-map-js@1.2.1: {} source-map-js@1.2.1: {}
spdx-correct@3.2.0: spdx-correct@3.2.0:
+5
View File
@@ -15,6 +15,7 @@ import {
type Message, type Message,
} from "discord.js"; } from "discord.js";
import { checkGuildEntitlement } from "../utils/checkEntitlement.js"; import { checkGuildEntitlement } from "../utils/checkEntitlement.js";
import { logger } from "../utils/logger.js";
import type { Liora } from "../interfaces/liora.js"; import type { Liora } from "../interfaces/liora.js";
/** /**
@@ -41,6 +42,10 @@ const messageCreate = async(
return; return;
} }
await logger.metric("highlight_triggered", highlights.length, {
guildId: message.guild.id,
});
await Promise.all( await Promise.all(
// eslint-disable-next-line max-lines-per-function -- It's mostly components. // eslint-disable-next-line max-lines-per-function -- It's mostly components.
highlights.map(async(record) => { highlights.map(async(record) => {
+5 -1
View File
@@ -4,6 +4,7 @@
* @author Naomi Carrigan * @author Naomi Carrigan
*/ */
import { DiscordAnalytics } from "@nhcarrigan/discord-analytics";
import { PrismaClient } from "@prisma/client"; import { PrismaClient } from "@prisma/client";
import { import {
Client, Client,
@@ -25,17 +26,20 @@ const liora: Liora = {
GatewayIntentBits.MessageContent, GatewayIntentBits.MessageContent,
], ],
}), }),
}; };
const analytics = new DiscordAnalytics(liora.discord, logger);
liora.discord.once(Events.ClientReady, () => { liora.discord.once(Events.ClientReady, () => {
void logger.log( void logger.log(
"debug", "debug",
`Logged in as ${liora.discord.user?.username ?? "unknown"}`, `Logged in as ${liora.discord.user?.username ?? "unknown"}`,
); );
analytics.startCron();
}); });
liora.discord.on(Events.InteractionCreate, (interaction) => { liora.discord.on(Events.InteractionCreate, (interaction) => {
void analytics.logGatewayEvent(Events.InteractionCreate, { ...interaction });
if (interaction.isChatInputCommand()) { if (interaction.isChatInputCommand()) {
if (!interaction.inCachedGuild()) { if (!interaction.inCachedGuild()) {
void interaction.reply({ void interaction.reply({