Skip to content

Commit ef1d79f

Browse files
committed
added improved Settings Manager
- real database used, instead of a json file --> a remote mysql db - selective updating of rows and values - generally better usages of the old settings manager will be replaced in the following days
1 parent 4744898 commit ef1d79f

File tree

6 files changed

+114
-9
lines changed

6 files changed

+114
-9
lines changed

commands/join.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ function joinChannel(message, cid, cb=()=>{}, ecb=()=>{}) {
4242
});
4343
})
4444
p.on("message", (m) => {
45-
if ((this.settingsMgr.getServer(message.channel.serverId).get("songAnnouncements")) == "false") return;
45+
if ((this.getSettings(message).get("songAnnouncements")) == "false") return;
4646
message.channel.sendMessage(this.em(m, message))
4747
});
4848
p.on("roomfetched", () => {

commands/settings.js

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ module.exports = {
4545
if (failed) return message.reply(this.em(failed, message), false);
4646
set.set(data.get("setting").value, data.get("value").value);
4747
message.reply(this.em("Settings changed!", message), false);
48-
this.settingsMgr.saveAsync();
4948
break;
5049
case "getSettings":
5150
const setting = data.get("setting").value;

index.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const { Revoice } = require("revoice.js");
44
const { Client } = require("revolt.js");
55
const path = require("path");
66
const fs = require("fs");
7-
const { SettingsManager } = require("./settings/Settings.js");
7+
const { SettingsManager, RemoteSettingsManager } = require("./settings/Settings.js");
88
if (!process.execArgv.includes("--inspect")) require('console-stamp')(console, 'HH:MM:ss.l');
99
const YTDlpWrap = require("yt-dlp-wrap-extended").default;
1010

@@ -38,6 +38,9 @@ class Remix {
3838

3939
this.settingsMgr = new SettingsManager();
4040
this.settingsMgr.loadDefaultsSync("./storage/defaults.json");
41+
// updated settings manager based on a mysql database:
42+
// TODO: add self-hosting instr
43+
this.rSettingsMgr = new RemoteSettingsManager(this.config.mysql, "./storage/defaults.json");
4144

4245
this.uploader = new Uploader(this.client);
4346

@@ -120,6 +123,7 @@ class Remix {
120123

121124
if (!this.config.fetchUsers) return;
122125
this.fetchUsers(); // TODO: find out why I did this, there is a reason (Mabye caching?) but I have no clue and am scared to remove this
126+
// future me here: most likely caching. This shouldn't be the reason for rate limits.
123127
setInterval(() => this.fetchUsers, 60 * 1000 * 30);
124128
});
125129
this.client.on("messageCreate", (m) => {
@@ -549,7 +553,7 @@ class Remix {
549553
}
550554
getSettings(message) {
551555
const serverId = message.channel.serverId;
552-
return this.settingsMgr.getServer(serverId);
556+
return this.rSettingsMgr.getServer(serverId);
553557
}
554558
observeUser(id, channel, cb) {
555559
this.observedUsers.set(id + ";" + channel, cb);

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"youtubei.js": "^5.1.0",
3131
"yt-dlp-wrap-extended": "^2.3.15",
3232
"yt-search": "^2.10.4",
33-
"ytdl-core": "npm:@distube/ytdl-core@^4.15.8"
33+
"ytdl-core": "npm:@distube/ytdl-core@^4.16.4"
3434
},
3535
"scripts": {
3636
"dev": "node --inspect index.js --trace-warnings",

settings/Settings.js

+102-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const fs = require("fs");
2+
const mysql = require("mysql")
23

34
class ServerSettings { // TODO: switch to better db system
45
id;
@@ -36,7 +37,7 @@ class ServerSettings { // TODO: switch to better db system
3637
}
3738
}
3839
checkDefaults(d) {
39-
for (key in d) {
40+
for (let key in d) {
4041
if (!this.data[key]) this.data[key] = d[key];
4142
}
4243
}
@@ -155,4 +156,103 @@ class SettingsManager {
155156
}
156157
}
157158

158-
module.exports = { SettingsManager, ServerSettings };
159+
class RemoteSettingsManager { // mysql based manager
160+
guilds = new Map();
161+
descriptions = {};
162+
defaults = {};
163+
164+
serverConfig = null;
165+
166+
db = null;
167+
168+
constructor(config, defaultsPath) {
169+
this.db = mysql.createPool({
170+
connectionLimit : 15,
171+
...config
172+
});
173+
174+
this.loadDefaultsSync(defaultsPath);
175+
176+
this.load();
177+
178+
return this;
179+
}
180+
181+
query(query) {
182+
return new Promise(res => {
183+
this.db.query(query, (error, results, fields) => { res({ error, results, fields })});
184+
});
185+
}
186+
187+
async load() {
188+
const res = await this.query("SELECT * FROM settings");
189+
if (res.error) {
190+
console.error("settings init error; ", res.error);
191+
console.error("retrying in 2 seconds");
192+
return setTimeout(() => {
193+
this.load();
194+
}, 2000);
195+
}
196+
197+
const results = res.results;
198+
results.forEach((r) => {
199+
let server = new ServerSettings(r.id, this);
200+
server.deserialize(JSON.parse(r.data));
201+
server.checkDefaults(this.defaults);
202+
this.guilds.set(server.id, server);
203+
});
204+
}
205+
async remoteUpdate(server, key) {
206+
const r = await this.query("UPDATE settings SET 'data' = JSON_SET('data', $." + key + ", '" + server.data[key] + "')")
207+
if (r.error) console.error("settings update error; ", r.error);
208+
}
209+
async remoteSave(server) {
210+
const r = await this.query("UPDATE settings SET 'data' = '" + JSON.stringify(server.data) + "' WHERE id='" + server.id + "'");
211+
if (r.error) console.error("settings server save error; ", r.error);
212+
}
213+
214+
loadDefaultsSync(filePath) {
215+
const d = fs.readFileSync(filePath, "utf8");
216+
let parsed = JSON.parse(d);
217+
this.descriptions = parsed.descriptions;
218+
this.defaults = parsed.values;
219+
}
220+
221+
saveAsync() {
222+
return new Promise(async (res) => {
223+
const p = []; // promises
224+
this.guilds.forEach((val, _k) => {
225+
p.push(this.remoteSave(val));
226+
});
227+
228+
await Promise.all(p);
229+
res();
230+
});
231+
}
232+
async create(id, server) {
233+
const r = await this.query("INSERT INTO settings (id, data) VALUES ('" + id + "', '" + JSON.stringify(server.data) + "')");
234+
if (r.error) console.error("settings create server error; ", r.error);
235+
}
236+
237+
update(server, key) {
238+
if (!this.guilds.has(server.id)) {
239+
this.guilds.set(server.id, server);
240+
this.create(server.id, server);
241+
}
242+
const s = this.guilds.get(server.id);
243+
s.data[key] = server.data[key];
244+
this.remoteUpdate(server, key);
245+
}
246+
isOption(key) {
247+
return key in this.defaults;
248+
}
249+
250+
hasServer(id) {
251+
return this.guilds.has(id);
252+
}
253+
getServer(id) {
254+
return (!this.guilds.has(id)) ? new ServerSettings(id, this) : this.guilds.get(id);
255+
}
256+
}
257+
258+
module.exports = { SettingsManager, RemoteSettingsManager, ServerSettings };

storage/defaults.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
"songAnnouncements": false,
44
"prefix": "%",
55
"pfp": "default",
6-
"locale": "en"
6+
"locale": "en",
7+
"restrictVolume": false
78
},
89
"descriptions": {
910
"songAnnouncements": "Wether the bot should announce every song when it starts playing it.",
1011
"prefix": "The prefix that is used to trigger commands. Alternatively, you can use a ping with a space after it.",
1112
"pfp": "What profile picture the bot should use. `default | dark | light | mono | <custom url>`",
12-
"locale": "The preferred language of your server. For valid language codes please see the github repository."
13+
"locale": "The preferred language of your server. For valid language codes please see the github repository.",
14+
"restrictVolume": "If this is set to anything else than `false`, every user in the server will be able to change the volume. Otherwise only users with the `ManageChannel` permission can."
1315
}
1416
}

0 commit comments

Comments
 (0)