-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
135 lines (110 loc) · 3.55 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//Import dependencies
import {
AutojoinRoomsMixin,
MatrixClient,
SimpleFsStorageProvider,
RichRepliesPreprocessor,
} from "matrix-bot-sdk";
import { readFileSync } from "node:fs";
import { parse } from "yaml";
import { WordCount } from "./word-counting.js";
//Parse YAML configuration file
const loginFile = readFileSync("./db/login.yaml", "utf8");
const loginParsed = parse(loginFile);
const homeserver = loginParsed["homeserver-url"];
const accessToken = loginParsed["login-token"];
//prefix
const prefix = ".";
//the bot sync something idk bro it was here in the example so i dont touch it ;-;
const storage = new SimpleFsStorageProvider("bot.json");
//login to client
const client = new MatrixClient(homeserver, accessToken, storage);
AutojoinRoomsMixin.setupOnClient(client);
//do not include replied message in message
client.addPreprocessor(new RichRepliesPreprocessor(false));
const counter = new WordCount();
//preallocate variables so they have a global scope
let mxid;
const filter = {
//dont expect any presence from m.org, but in the case presence shows up its irrelevant to this bot
presence: { senders: [] },
room: {
//ephemeral events are never used in this bot, are mostly inconsequentail and irrelevant
ephemeral: { senders: [] },
//we fetch state manually later, hopefully with better load balancing
state: {
senders: [],
types: [],
lazy_load_members: true,
},
//we will manually fetch events anyways, this is just limiting how much backfill bot gets as to not
//respond to events far out of view
timeline: {
limit: 1000,
},
},
};
//Start Client
client.start(filter).then(async (filter) => {
console.log("Client started!");
//get mxid
mxid = await client.getUserId().catch(() => {});
});
//when the client recieves an event
client.on("room.event", async (roomId, event) => {
//ignore events sent by self, unless its a banlist policy update
if (event.sender === mxid) {
return;
}
//we just want raw text tbh
if (!event?.content?.body) return;
const body = event.content.body.toLowerCase();
if (body.startsWith(`${prefix}help`)) {
client.replyNotice(
roomId,
event,
"You can find usage information and source code available at https://github.com/jjj333-p/matrix-word-counter",
);
} else if (body.startsWith(`${prefix}count`)) {
//get word param
const word = body.split(" ")[1];
//get stats map
const wordstats = counter.perRoom.get(roomId)?.get(word);
//if no stats
if (!wordstats) {
client.replyNotice(roomId, event, "❌ | That word has not been used");
return;
}
let count = 0;
// biome-ignore lint/complexity/noForEach: <explanation>
wordstats.forEach((a) => {
count += a;
});
//get all users
const users = Array.from(wordstats.keys());
//generate human readable string
let msg = `<b>Total</b>: ${count}<br><br>`;
for (const user of users) {
msg += `<b>${user}</b>: ${wordstats.get(user)}<br>`;
}
client.replyHtmlNotice(roomId, event, msg);
} else {
//split on regex and and filter out empty words
const words = body.split(/[^a-z0-9]/gi).filter((w) => w);
const wordCounts = new Map();
for (const word of words) {
// If the word already exists in wordCounts, increment its count
if (wordCounts.has(word)) {
wordCounts.set(word, wordCounts.get(word) + 1);
} else {
// If the word doesn't exist, initialize its count to 1
wordCounts.set(word, 1);
}
}
//add each count to the user
const countedWords = wordCounts.keys();
for (const word of countedWords) {
counter.addToUser(roomId, word, event.sender, wordCounts.get(word));
}
}
});