2021-06-07 01:26:12 +08:00
|
|
|
const MonkeyError = require("../handlers/error");
|
2021-06-07 00:32:37 +08:00
|
|
|
const { mongoDB } = require("../init/mongodb");
|
2021-07-10 00:21:16 +08:00
|
|
|
const { ObjectID } = require("mongodb");
|
2021-06-09 06:49:54 +08:00
|
|
|
const { checkAndUpdatePb } = require("../handlers/pb");
|
2021-06-09 07:08:22 +08:00
|
|
|
const { updateAuthEmail } = require("../handlers/auth");
|
2021-06-09 06:49:54 +08:00
|
|
|
|
2021-06-07 00:32:37 +08:00
|
|
|
class UsersDAO {
|
|
|
|
static async addUser(name, email, uid) {
|
|
|
|
return await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.insertOne({ name, email, uid, addedAt: Date.now() });
|
|
|
|
}
|
|
|
|
|
2021-06-17 03:20:16 +08:00
|
|
|
static async deleteUser(uid) {
|
2021-07-07 21:04:12 +08:00
|
|
|
return await mongoDB().collection("users").deleteOne({ uid });
|
2021-06-17 03:20:16 +08:00
|
|
|
}
|
|
|
|
|
2021-06-07 00:32:37 +08:00
|
|
|
static async updateName(uid, name) {
|
|
|
|
const nameDoc = await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.findOne({ name: { $regex: new RegExp(`^${name}$`, "i") } });
|
2021-06-07 01:26:12 +08:00
|
|
|
if (nameDoc) throw new MonkeyError(409, "Username already taken");
|
2021-06-07 00:32:37 +08:00
|
|
|
return await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.updateOne({ uid }, { $set: { name } });
|
|
|
|
}
|
|
|
|
|
2021-06-16 07:45:28 +08:00
|
|
|
static async isNameAvailable(name) {
|
2021-07-07 21:04:12 +08:00
|
|
|
const nameDoc = await mongoDB().collection("users").findOne({ name });
|
|
|
|
if (nameDoc) {
|
2021-06-16 07:45:28 +08:00
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-09 07:08:22 +08:00
|
|
|
static async updateEmail(uid, email) {
|
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
return await updateAuthEmail(uid, email);
|
|
|
|
}
|
|
|
|
|
2021-06-07 00:32:37 +08:00
|
|
|
static async getUser(uid) {
|
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
2021-06-07 01:26:12 +08:00
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
2021-06-07 00:32:37 +08:00
|
|
|
return user;
|
|
|
|
}
|
2021-06-09 05:57:58 +08:00
|
|
|
|
2021-06-12 21:00:21 +08:00
|
|
|
static async getUserByDiscordId(discordId) {
|
|
|
|
const user = await mongoDB().collection("users").findOne({ discordId });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
return user;
|
|
|
|
}
|
|
|
|
|
2021-06-09 05:57:58 +08:00
|
|
|
static async addTag(uid, name) {
|
2021-07-10 00:21:16 +08:00
|
|
|
let _id = ObjectID();
|
2021-07-09 06:27:47 +08:00
|
|
|
await mongoDB()
|
2021-06-09 05:57:58 +08:00
|
|
|
.collection("users")
|
2021-07-10 00:21:16 +08:00
|
|
|
.updateOne({ uid }, { $push: { tags: { _id, name } } });
|
2021-07-09 06:27:47 +08:00
|
|
|
return {
|
2021-07-10 00:21:16 +08:00
|
|
|
_id,
|
2021-07-09 06:27:47 +08:00
|
|
|
name,
|
|
|
|
};
|
2021-06-09 05:57:58 +08:00
|
|
|
}
|
|
|
|
|
2021-07-07 21:04:12 +08:00
|
|
|
static async getTags(uid) {
|
2021-06-13 00:51:58 +08:00
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
return user.tags;
|
|
|
|
}
|
|
|
|
|
2021-07-10 00:21:16 +08:00
|
|
|
static async editTag(uid, _id, name) {
|
2021-06-09 05:57:58 +08:00
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
if (
|
|
|
|
user.tags === undefined ||
|
2021-07-10 00:21:16 +08:00
|
|
|
user.tags.filter((t) => t._id == _id).length === 0
|
2021-06-09 05:57:58 +08:00
|
|
|
)
|
|
|
|
throw new MonkeyError(404, "Tag not found");
|
|
|
|
return await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.updateOne(
|
|
|
|
{
|
|
|
|
uid: uid,
|
2021-07-10 00:21:16 +08:00
|
|
|
"tags._id": ObjectID(_id),
|
2021-06-09 05:57:58 +08:00
|
|
|
},
|
2021-07-08 23:03:52 +08:00
|
|
|
{ $set: { "tags.$.name": name } }
|
2021-06-09 05:57:58 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-07-10 00:21:16 +08:00
|
|
|
static async removeTag(uid, _id) {
|
2021-06-09 05:57:58 +08:00
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
if (
|
|
|
|
user.tags === undefined ||
|
2021-07-10 00:21:16 +08:00
|
|
|
user.tags.filter((t) => t._id == _id).length === 0
|
2021-06-09 05:57:58 +08:00
|
|
|
)
|
|
|
|
throw new MonkeyError(404, "Tag not found");
|
|
|
|
return await mongoDB()
|
|
|
|
.collection("users")
|
2021-07-08 23:03:52 +08:00
|
|
|
.updateOne(
|
|
|
|
{
|
|
|
|
uid: uid,
|
2021-07-10 00:21:16 +08:00
|
|
|
"tags._id": ObjectID(_id),
|
2021-07-08 23:03:52 +08:00
|
|
|
},
|
2021-07-10 00:21:16 +08:00
|
|
|
{ $pull: { tags: { _id: ObjectID(_id) } } }
|
2021-07-08 23:03:52 +08:00
|
|
|
);
|
2021-06-09 05:57:58 +08:00
|
|
|
}
|
2021-06-09 06:02:11 +08:00
|
|
|
|
2021-07-10 00:21:16 +08:00
|
|
|
static async removeTagPb(uid, _id) {
|
2021-06-09 06:02:11 +08:00
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
if (
|
|
|
|
user.tags === undefined ||
|
2021-07-10 00:21:16 +08:00
|
|
|
user.tags.filter((t) => t._id == _id).length === 0
|
2021-06-09 06:02:11 +08:00
|
|
|
)
|
|
|
|
throw new MonkeyError(404, "Tag not found");
|
|
|
|
return await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.updateOne(
|
|
|
|
{
|
|
|
|
uid: uid,
|
2021-07-10 00:21:16 +08:00
|
|
|
"tags._id": ObjectID(_id),
|
2021-06-09 06:02:11 +08:00
|
|
|
},
|
2021-07-08 23:03:52 +08:00
|
|
|
{ $set: { "tags.$.personalBests": {} } }
|
2021-06-09 06:02:11 +08:00
|
|
|
);
|
|
|
|
}
|
2021-06-09 06:49:54 +08:00
|
|
|
|
2021-07-07 21:04:12 +08:00
|
|
|
static async checkIfPb(uid, result) {
|
2021-06-09 06:49:54 +08:00
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
|
2021-06-13 02:01:49 +08:00
|
|
|
const {
|
|
|
|
mode,
|
|
|
|
mode2,
|
|
|
|
acc,
|
|
|
|
consistency,
|
|
|
|
difficulty,
|
|
|
|
language,
|
|
|
|
punctuation,
|
2021-07-07 21:04:12 +08:00
|
|
|
rawWpm,
|
|
|
|
wpm,
|
2021-07-09 05:19:34 +08:00
|
|
|
funbox,
|
2021-06-13 02:01:49 +08:00
|
|
|
} = result;
|
|
|
|
|
2021-07-09 05:19:34 +08:00
|
|
|
if (funbox !== "none" && funbox !== "plus_one" && funbox !== "plus_two") {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-06-09 06:49:54 +08:00
|
|
|
let pb = checkAndUpdatePb(
|
|
|
|
user.personalBests,
|
|
|
|
mode,
|
|
|
|
mode2,
|
|
|
|
acc,
|
|
|
|
consistency,
|
|
|
|
difficulty,
|
|
|
|
language,
|
|
|
|
punctuation,
|
2021-07-07 21:04:12 +08:00
|
|
|
rawWpm,
|
2021-06-09 06:49:54 +08:00
|
|
|
wpm
|
|
|
|
);
|
|
|
|
|
|
|
|
if (pb.isPb) {
|
|
|
|
await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.updateOne({ uid }, { $set: { personalBests: pb.obj } });
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-07 21:04:12 +08:00
|
|
|
static async checkIfTagPb(uid, result) {
|
2021-06-09 06:49:54 +08:00
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
|
|
|
|
if (user.tags === undefined || user.tags.length === 0) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2021-06-13 02:01:49 +08:00
|
|
|
const {
|
|
|
|
mode,
|
|
|
|
mode2,
|
|
|
|
acc,
|
|
|
|
consistency,
|
|
|
|
difficulty,
|
|
|
|
language,
|
|
|
|
punctuation,
|
2021-07-07 21:04:12 +08:00
|
|
|
rawWpm,
|
2021-06-14 03:18:23 +08:00
|
|
|
wpm,
|
2021-07-07 21:04:12 +08:00
|
|
|
tags,
|
2021-07-10 04:41:33 +08:00
|
|
|
funbox,
|
2021-06-13 02:01:49 +08:00
|
|
|
} = result;
|
|
|
|
|
2021-07-10 04:41:33 +08:00
|
|
|
if (funbox !== "none" && funbox !== "plus_one" && funbox !== "plus_two") {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2021-07-08 23:03:52 +08:00
|
|
|
if (mode === "quote") {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
let tagsToCheck = [];
|
|
|
|
user.tags.forEach((tag) => {
|
2021-07-10 04:41:33 +08:00
|
|
|
tags.forEach((resultTag) => {
|
|
|
|
if (resultTag == tag._id) {
|
|
|
|
tagsToCheck.push(tag);
|
|
|
|
}
|
|
|
|
});
|
2021-07-08 23:03:52 +08:00
|
|
|
});
|
|
|
|
|
2021-06-09 06:49:54 +08:00
|
|
|
let ret = [];
|
|
|
|
|
2021-07-08 23:03:52 +08:00
|
|
|
tagsToCheck.forEach(async (tag) => {
|
2021-06-09 06:49:54 +08:00
|
|
|
let tagpb = checkAndUpdatePb(
|
|
|
|
tag.personalBests,
|
|
|
|
mode,
|
|
|
|
mode2,
|
|
|
|
acc,
|
|
|
|
consistency,
|
|
|
|
difficulty,
|
|
|
|
language,
|
|
|
|
punctuation,
|
2021-07-07 21:04:12 +08:00
|
|
|
rawWpm,
|
2021-06-09 06:49:54 +08:00
|
|
|
wpm
|
|
|
|
);
|
|
|
|
if (tagpb.isPb) {
|
2021-07-10 00:21:16 +08:00
|
|
|
ret.push(tag._id);
|
2021-06-09 06:49:54 +08:00
|
|
|
await mongoDB()
|
|
|
|
.collection("users")
|
2021-07-08 23:03:52 +08:00
|
|
|
.updateOne(
|
2021-07-10 00:21:16 +08:00
|
|
|
{ uid, "tags._id": ObjectID(tag._id) },
|
2021-07-08 23:03:52 +08:00
|
|
|
{ $set: { "tags.$.personalBests": tagpb.obj } }
|
|
|
|
);
|
2021-06-09 06:49:54 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2021-06-09 07:08:22 +08:00
|
|
|
|
|
|
|
static async resetPb(uid) {
|
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
return await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.updateOne({ uid }, { $set: { personalBests: {} } });
|
|
|
|
}
|
|
|
|
|
|
|
|
static async updateTypingStats(uid, restartCount, timeTyping) {
|
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
|
|
|
|
return await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.updateOne(
|
|
|
|
{ uid },
|
|
|
|
{
|
|
|
|
$inc: {
|
2021-07-07 21:04:12 +08:00
|
|
|
startedTests: restartCount + 1,
|
2021-06-09 07:08:22 +08:00
|
|
|
completedTests: 1,
|
|
|
|
timeTyping,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-06-12 21:00:21 +08:00
|
|
|
static async linkDiscord(uid, discordId) {
|
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
return await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.updateOne({ uid }, { $set: { discordId } });
|
|
|
|
}
|
|
|
|
|
2021-06-09 07:08:22 +08:00
|
|
|
static async unlinkDiscord(uid) {
|
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
return await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.updateOne({ uid }, { $set: { discordId: null } });
|
|
|
|
}
|
2021-06-12 20:33:23 +08:00
|
|
|
|
2021-07-07 21:04:12 +08:00
|
|
|
static async incrementBananas(uid, wpm) {
|
2021-06-12 20:33:23 +08:00
|
|
|
const user = await mongoDB().collection("users").findOne({ uid });
|
|
|
|
if (!user) throw new MonkeyError(404, "User not found");
|
|
|
|
|
|
|
|
let best60;
|
2021-07-07 21:04:12 +08:00
|
|
|
try {
|
2021-06-12 20:33:23 +08:00
|
|
|
best60 = Math.max(...user.personalBests.time[60].map((best) => best.wpm));
|
2021-07-07 21:04:12 +08:00
|
|
|
} catch (e) {
|
2021-06-12 20:33:23 +08:00
|
|
|
best60 = undefined;
|
|
|
|
}
|
|
|
|
|
2021-07-07 21:04:12 +08:00
|
|
|
if (best60 === undefined || wpm >= best60 - best60 * 0.25) {
|
2021-06-12 20:33:23 +08:00
|
|
|
//increment when no record found or wpm is within 25% of the record
|
2021-07-07 21:04:12 +08:00
|
|
|
return await mongoDB()
|
|
|
|
.collection("users")
|
|
|
|
.updateOne({ uid }, { $inc: { bananas: 1 } });
|
|
|
|
} else {
|
2021-06-12 20:33:23 +08:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2021-06-07 00:32:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = UsersDAO;
|