Skip to content

Commit 59d741a

Browse files
committed
Count messages
1 parent 1937436 commit 59d741a

File tree

3 files changed

+1381
-340
lines changed

3 files changed

+1381
-340
lines changed

count-messages.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import Discord, { Intents } from 'discord.js';
2+
import { MongoClient } from 'mongodb';
3+
import fetch from 'node-fetch';
4+
5+
import { getConfig } from './src/config';
6+
7+
/* eslint-disable @typescript-eslint/no-unsafe-call */
8+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
9+
if (process.env.NODE_ENV === 'production') {
10+
require('dotenv').config({ path: '.env' });
11+
} else {
12+
require('dotenv').config({ path: '.env.dev' });
13+
}
14+
15+
const API_URL = `https://discord.com/api/v9`;
16+
const GUILD_ID = `440163731704643589`;
17+
18+
const personalToken = getConfig('PERSONAL_TOKEN');
19+
20+
async function init() {
21+
const intents = new Intents([
22+
Intents.NON_PRIVILEGED, // include all non-privileged intents, would be better to specify which ones you actually need
23+
'GUILD_MEMBERS', // lets you request guild members (i.e. fixes the issue)
24+
]);
25+
const client = new Discord.Client({ ws: { intents } });
26+
await client.login(getConfig('DISCORD_BOT_TOKEN'));
27+
28+
const guild = await client.guilds.fetch(GUILD_ID);
29+
const members = await guild.members.fetch({ limit: 100 });
30+
31+
const mongoClient = new MongoClient(getConfig('MONGO_URL'));
32+
await mongoClient.connect();
33+
const db = mongoClient.db('bot');
34+
const statsCollection = db.collection('stats');
35+
36+
await members.reduce(async (acc, member) => {
37+
await acc;
38+
const messagesCount = await getMemberMessagesCount(member.id);
39+
const result = await statsCollection.updateOne(
40+
{ memberId: member.id },
41+
{
42+
$set: {
43+
memberId: member.id,
44+
memberName: member.displayName,
45+
messagesCount,
46+
updatedAt: new Date(),
47+
},
48+
},
49+
{ upsert: true },
50+
);
51+
console.log({ memberId: member.id, memberName: member.displayName, messagesCount, result });
52+
}, Promise.resolve());
53+
// console.log({ guild: guild.toJSON() });
54+
// console.log(guild.members.cache.toJSON());
55+
// await guild.members.fetch({ force: true });
56+
// console.log({ members: members.toJSON() });
57+
58+
process.exit(0);
59+
}
60+
61+
init().catch((err) => console.error(err));
62+
63+
type Response =
64+
| { readonly total_results?: number; readonly retry_after?: undefined }
65+
| { readonly total_results?: undefined; readonly retry_after: number };
66+
67+
async function getMemberMessagesCount(memberId: string): Promise<number | undefined> {
68+
const res = await fetch(
69+
`${API_URL}/guilds/440163731704643589/messages/search?author_id=${memberId}`,
70+
{
71+
headers: {
72+
authorization: personalToken,
73+
},
74+
method: 'GET',
75+
},
76+
);
77+
const json = (await res.json()) as Response;
78+
79+
if (json.retry_after) {
80+
console.log(json);
81+
await wait(json.retry_after * 1000);
82+
return getMemberMessagesCount(memberId);
83+
}
84+
85+
// try to overcome rate limiting
86+
await wait(1000);
87+
return json.total_results;
88+
}
89+
90+
function wait(ms: number) {
91+
return new Promise((resolve) => setTimeout(resolve, ms));
92+
}

package.json

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,48 +25,49 @@
2525
"dependencies": {
2626
"bufferutil": "4.0.3",
2727
"discord.js": "12.5.3",
28-
"dotenv": "8.2.0",
29-
"isolated-vm": "4.1.0",
30-
"monitorss": "6.12.7",
28+
"dotenv": "10.0.0",
29+
"isolated-vm": "4.2.0",
30+
"mongodb": "4.0.0-beta.5",
31+
"monitorss": "6.13.19",
3132
"node-cache": "5.1.2",
3233
"node-fetch": "2.6.1",
3334
"polish-plurals": "1.1.0",
3435
"request": "2.88.2",
3536
"request-promise": "4.2.6",
3637
"secure-json-parse": "2.4.0",
37-
"typescript": "4.2.4",
38+
"typescript": "4.3.2",
3839
"zlib-sync": "0.1.7"
3940
},
4041
"devDependencies": {
41-
"@types/chai": "4.2.16",
42-
"@types/chai-as-promised": "7.1.3",
42+
"@types/chai": "4.2.18",
43+
"@types/chai-as-promised": "7.1.4",
4344
"@types/dotenv": "8.2.0",
4445
"@types/mocha": "8.2.2",
4546
"@types/nock": "11.1.0",
4647
"@types/node": "14.14.41",
4748
"@types/node-fetch": "2.5.10",
4849
"@types/secure-json-parse": "1.0.2",
49-
"@types/sinon": "10.0.0",
50+
"@types/sinon": "10.0.2",
5051
"@types/sinon-chai": "3.2.5",
51-
"@typescript-eslint/eslint-plugin": "4.22.0",
52-
"@typescript-eslint/parser": "4.22.0",
52+
"@typescript-eslint/eslint-plugin": "4.26.0",
53+
"@typescript-eslint/parser": "4.26.0",
5354
"chai": "4.3.4",
5455
"chai-as-promised": "7.1.1",
55-
"eslint": "7.25.0",
56+
"eslint": "7.27.0",
5657
"eslint-config-prettier": "8.3.0",
5758
"eslint-plugin-functional": "3.2.1",
58-
"eslint-plugin-import": "2.22.1",
59+
"eslint-plugin-import": "2.23.4",
5960
"husky": "6.0.0",
60-
"lint-staged": "10.5.4",
61-
"mocha": "8.3.2",
62-
"nock": "13.0.11",
61+
"lint-staged": "11.0.0",
62+
"mocha": "8.4.0",
63+
"nock": "13.1.0",
6364
"nyc": "15.1.0",
64-
"prettier": "2.2.1",
65-
"sinon": "10.0.0",
66-
"sinon-chai": "3.6.0",
65+
"prettier": "2.3.0",
66+
"sinon": "11.1.1",
67+
"sinon-chai": "3.7.0",
6768
"source-map-support": "0.5.19",
68-
"ts-node": "9.1.1",
69-
"tsc-watch": "4.2.9"
69+
"ts-node": "10.0.0",
70+
"tsc-watch": "4.4.0"
7071
},
7172
"lint-staged": {
7273
"**/*.ts": [

0 commit comments

Comments
 (0)