initial stats collection
This commit is contained in:
parent
4e2afcc7f8
commit
ff5cc9c4aa
7 changed files with 186 additions and 19 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -7,3 +7,5 @@ dist
|
|||
.env.local
|
||||
|
||||
eslint_report.json
|
||||
|
||||
/_test.ts
|
||||
|
|
|
@ -10,10 +10,13 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@discordjs/rest": "^1.3.0",
|
||||
"date-fns": "^2.29.3",
|
||||
"discord.js": "^14.6.0",
|
||||
"gray-matter": "^4.0.3",
|
||||
"just-random": "^3.1.1",
|
||||
"kleur": "^4.1.5",
|
||||
"node-fetch": "^3.2.10",
|
||||
"redis": "^4.5.0",
|
||||
"remove-markdown": "^0.5.0",
|
||||
"tsx": "^3.10.3",
|
||||
"url-regex": "^5.0.0"
|
||||
|
@ -23,9 +26,7 @@
|
|||
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
||||
"@typescript-eslint/parser": "^5.40.1",
|
||||
"dotenv": "^16.0.3",
|
||||
"esbuild": "^0.15.11",
|
||||
"eslint": "^8.25.0",
|
||||
"gray-matter": "^4.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
|
|
33
src/index.ts
33
src/index.ts
|
@ -20,6 +20,7 @@ import { jokeCommand } from './commands/joke';
|
|||
import random from 'just-random';
|
||||
import { green, bold, yellow } from 'kleur/colors';
|
||||
import 'dotenv/config';
|
||||
import { collectStats } from './stats';
|
||||
|
||||
const client = new Client({
|
||||
intents: [
|
||||
|
@ -69,25 +70,27 @@ client.once('ready', async () => {
|
|||
activities: [{ name: `Minecraft ${mcVersion}` }],
|
||||
status: 'online',
|
||||
});
|
||||
});
|
||||
|
||||
client.on('messageCreate', async (e) => {
|
||||
if (!e.content) return;
|
||||
if (!e.channel.isTextBased()) return;
|
||||
client.on('messageCreate', async (e) => {
|
||||
if (!e.content) return;
|
||||
if (!e.channel.isTextBased()) return;
|
||||
|
||||
if (e.author === client.user) return;
|
||||
if (e.author === client.user) return;
|
||||
|
||||
if (e.cleanContent.match(BuildConfig.ETA_REGEX)) {
|
||||
await e.reply(
|
||||
`${random(BuildConfig.ETA_MESSAGES)} <:pofat:1031701005559144458>`
|
||||
);
|
||||
}
|
||||
if (e.cleanContent.match(BuildConfig.ETA_REGEX)) {
|
||||
await e.reply(
|
||||
`${random(BuildConfig.ETA_MESSAGES)} <:pofat:1031701005559144458>`
|
||||
);
|
||||
}
|
||||
|
||||
const log = await parseLog(e.content);
|
||||
if (log != null) {
|
||||
e.reply({ embeds: [log] });
|
||||
return;
|
||||
}
|
||||
});
|
||||
const log = await parseLog(e.content);
|
||||
if (log != null) {
|
||||
e.reply({ embeds: [log] });
|
||||
return;
|
||||
}
|
||||
|
||||
await collectStats(e);
|
||||
});
|
||||
|
||||
client.on('interactionCreate', async (interaction) => {
|
||||
|
|
7
src/stats/datetime.ts
Normal file
7
src/stats/datetime.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { addMinutes, format } from 'date-fns';
|
||||
|
||||
export const getTimeIntervalID = () => {
|
||||
const today = new Date();
|
||||
|
||||
return format(addMinutes(today, today.getTimezoneOffset()), 'yyyy.MM.dd.HH');
|
||||
};
|
61
src/stats/index.ts
Normal file
61
src/stats/index.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { ChannelType, Message, PermissionFlagsBits } from 'discord.js';
|
||||
|
||||
import { getTimeIntervalID } from './datetime';
|
||||
import { incr } from './redis';
|
||||
|
||||
const processMember = async (msg: Message<boolean>) => {
|
||||
const id = msg.author.id;
|
||||
|
||||
await incr(`member:${id}:${getTimeIntervalID()}`, true);
|
||||
};
|
||||
|
||||
const processChannel = async (msg: Message<boolean>) => {
|
||||
const guildChannel = await msg.guild!.channels.fetch(msg.channelId);
|
||||
if (!guildChannel) return;
|
||||
if (
|
||||
guildChannel.type === ChannelType.GuildStageVoice ||
|
||||
guildChannel.type === ChannelType.GuildVoice
|
||||
)
|
||||
return;
|
||||
|
||||
let channelId = guildChannel.id;
|
||||
|
||||
// this is a text thread or forum post
|
||||
if (
|
||||
guildChannel.parent &&
|
||||
(guildChannel.parent.type === ChannelType.GuildText ||
|
||||
guildChannel.parent.type === ChannelType.GuildForum)
|
||||
) {
|
||||
channelId = guildChannel.parent.id;
|
||||
|
||||
// if this is a thread in a text channel, track the thread as well
|
||||
if (guildChannel.parent.type === ChannelType.GuildText) {
|
||||
await incr(`thread:${guildChannel.id}:${getTimeIntervalID()}`, true);
|
||||
}
|
||||
}
|
||||
|
||||
await incr(`channel:${channelId}:${getTimeIntervalID()}`, true);
|
||||
};
|
||||
|
||||
export const collectStats = async (msg: Message<boolean>) => {
|
||||
// reject bots (and webhooks)
|
||||
if (msg.author.bot) return;
|
||||
|
||||
// only collect stats on publicly accessible channels
|
||||
if (!msg.guild) return;
|
||||
const guildChannel = await msg.guild.channels.fetch(msg.channelId);
|
||||
if (!guildChannel) return;
|
||||
|
||||
const everyonesPermsInChannel = guildChannel.permissionsFor(
|
||||
msg.guild.roles.everyone,
|
||||
false
|
||||
);
|
||||
|
||||
if (!everyonesPermsInChannel.has(PermissionFlagsBits.ViewChannel, false))
|
||||
return;
|
||||
|
||||
await incr(`total:forever`);
|
||||
await incr(`total:${getTimeIntervalID()}`, true);
|
||||
await processMember(msg);
|
||||
await processChannel(msg);
|
||||
};
|
32
src/stats/redis.ts
Normal file
32
src/stats/redis.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { createClient } from 'redis';
|
||||
|
||||
const ONE_MONTH_IN_SECONDS = 2629746;
|
||||
|
||||
const client = createClient({ url: process.env.REDIS_URI });
|
||||
|
||||
export const get = async (key: string) => {
|
||||
await client.connect();
|
||||
const data = await client.get(key);
|
||||
await client.disconnect();
|
||||
return data;
|
||||
};
|
||||
|
||||
export const set = async (key: string, value: string, autoExpire = false) => {
|
||||
await client.connect();
|
||||
await client.set(key, value);
|
||||
if (autoExpire && (await client.ttl(key)) === -1) {
|
||||
await client.expire(key, ONE_MONTH_IN_SECONDS);
|
||||
}
|
||||
await client.disconnect();
|
||||
};
|
||||
|
||||
export const incr = async (key: string, autoExpire = false) => {
|
||||
await client.connect();
|
||||
|
||||
await client.incr(key);
|
||||
if (autoExpire && (await client.ttl(key)) === -1) {
|
||||
await client.expire(key, ONE_MONTH_IN_SECONDS);
|
||||
}
|
||||
|
||||
await client.disconnect();
|
||||
};
|
65
yarn.lock
65
yarn.lock
|
@ -127,6 +127,40 @@
|
|||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@redis/bloom@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.1.0.tgz#64e310ddee72010676e14296076329e594a1f6c7"
|
||||
integrity sha512-9QovlxmpRtvxVbN0UBcv8WfdSMudNZZTFqCsnBszcQXqaZb/TVe30ScgGEO7u1EAIacTPAo7/oCYjYAxiHLanQ==
|
||||
|
||||
"@redis/client@1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@redis/client/-/client-1.4.0.tgz#d2c56ce26c3e2fe3412db5cfb1814169662167eb"
|
||||
integrity sha512-1gEj1AkyXPlkcC/9/T5xpDcQF8ntERURjLBgEWMTdUZqe181zfI9BY3jc2OzjTLkvZh5GV7VT4ktoJG2fV2ufw==
|
||||
dependencies:
|
||||
cluster-key-slot "1.1.1"
|
||||
generic-pool "3.9.0"
|
||||
yallist "4.0.0"
|
||||
|
||||
"@redis/graph@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@redis/graph/-/graph-1.1.0.tgz#cc2b82e5141a29ada2cce7d267a6b74baa6dd519"
|
||||
integrity sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==
|
||||
|
||||
"@redis/json@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@redis/json/-/json-1.0.4.tgz#f372b5f93324e6ffb7f16aadcbcb4e5c3d39bda1"
|
||||
integrity sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==
|
||||
|
||||
"@redis/search@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@redis/search/-/search-1.1.0.tgz#7abb18d431f27ceafe6bcb4dd83a3fa67e9ab4df"
|
||||
integrity sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==
|
||||
|
||||
"@redis/time-series@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.4.tgz#af85eb080f6934580e4d3b58046026b6c2b18717"
|
||||
integrity sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==
|
||||
|
||||
"@sapphire/async-queue@^1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.5.0.tgz#2f255a3f186635c4fb5a2381e375d3dfbc5312d8"
|
||||
|
@ -353,6 +387,11 @@ chalk@^4.0.0:
|
|||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
cluster-key-slot@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz#10ccb9ded0729464b6d2e7d714b100a2d1259d43"
|
||||
integrity sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==
|
||||
|
||||
color-convert@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
|
||||
|
@ -384,6 +423,11 @@ data-uri-to-buffer@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b"
|
||||
integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==
|
||||
|
||||
date-fns@^2.29.3:
|
||||
version "2.29.3"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
|
||||
integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==
|
||||
|
||||
debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
|
@ -538,7 +582,7 @@ esbuild-windows-arm64@0.15.11:
|
|||
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.11.tgz#018624023b5c3f0cca334cc99f5ef7134d396333"
|
||||
integrity sha512-VwUHFACuBahrvntdcMKZteUZ9HaYrBRODoKe4tIWxguQRvvYoYb7iu5LrcRS/FQx8KPZNaa72zuqwVtHeXsITw==
|
||||
|
||||
esbuild@^0.15.11, esbuild@~0.15.10:
|
||||
esbuild@~0.15.10:
|
||||
version "0.15.11"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.11.tgz#524d48612a9aa7edc1753c83459cb6fcae0cb66e"
|
||||
integrity sha512-OgHGuhlfZ//mToxjte1D5iiiQgWfJ2GByVMwEC/IuoXsBGkuyK1+KrjYu0laSpnN/L1UmLUCv0s25vObdc1bVg==
|
||||
|
@ -800,6 +844,11 @@ fsevents@~2.3.2:
|
|||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
generic-pool@3.9.0:
|
||||
version "3.9.0"
|
||||
resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4"
|
||||
integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==
|
||||
|
||||
get-tsconfig@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.2.0.tgz#ff368dd7104dab47bf923404eb93838245c66543"
|
||||
|
@ -1170,6 +1219,18 @@ readable-web-to-node-stream@^3.0.2:
|
|||
dependencies:
|
||||
readable-stream "^3.6.0"
|
||||
|
||||
redis@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/redis/-/redis-4.5.0.tgz#8a461c8718e380ea899ba3711aa0bb217b112089"
|
||||
integrity sha512-oZGAmOKG+RPnHo0UxM5GGjJ0dBd/Vi4fs3MYwM1p2baDoXC0wpm0yOdpxVS9K+0hM84ycdysp2eHg2xGoQ4FEw==
|
||||
dependencies:
|
||||
"@redis/bloom" "1.1.0"
|
||||
"@redis/client" "1.4.0"
|
||||
"@redis/graph" "1.1.0"
|
||||
"@redis/json" "1.0.4"
|
||||
"@redis/search" "1.1.0"
|
||||
"@redis/time-series" "1.0.4"
|
||||
|
||||
regexpp@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
|
||||
|
@ -1432,7 +1493,7 @@ ws@^8.9.0:
|
|||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.9.0.tgz#2a994bb67144be1b53fe2d23c53c028adeb7f45e"
|
||||
integrity sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==
|
||||
|
||||
yallist@^4.0.0:
|
||||
yallist@4.0.0, yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue