2020-07-03 08:35:45 +08:00
|
|
|
const functions = require("firebase-functions");
|
|
|
|
const admin = require("firebase-admin");
|
2020-06-06 01:17:59 +08:00
|
|
|
|
2020-06-08 07:26:57 +08:00
|
|
|
let key = "./serviceAccountKey.json";
|
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
if (process.env.GCLOUD_PROJECT === "monkey-type") {
|
|
|
|
key = "./serviceAccountKey_live.json";
|
2020-06-08 07:26:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
var serviceAccount = require(key);
|
2020-06-06 01:17:59 +08:00
|
|
|
|
|
|
|
admin.initializeApp({
|
2020-07-03 08:35:45 +08:00
|
|
|
credential: admin.credential.cert(serviceAccount),
|
2020-06-06 01:17:59 +08:00
|
|
|
});
|
|
|
|
|
2020-07-07 20:28:01 +08:00
|
|
|
const db = admin.firestore();
|
2020-06-06 01:17:59 +08:00
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
exports.moveResults = functions
|
|
|
|
.runWith({ timeoutSeconds: 540, memory: "2GB" })
|
|
|
|
.https.onCall((request, response) => {
|
2020-07-07 20:26:52 +08:00
|
|
|
return db
|
2020-07-03 08:35:45 +08:00
|
|
|
.collection("results")
|
|
|
|
.orderBy("timestamp", "desc")
|
|
|
|
.limit(2000)
|
|
|
|
.get()
|
|
|
|
.then((data) => {
|
|
|
|
data.docs.forEach((doc) => {
|
|
|
|
let result = doc.data();
|
|
|
|
if (result.moved === undefined || result.moved === false) {
|
2020-07-07 20:26:52 +08:00
|
|
|
db.collection(`results`).doc(doc.id).update({ moved: true });
|
|
|
|
db.collection(`users/${result.uid}/results`).add(result);
|
2020-07-03 08:35:45 +08:00
|
|
|
console.log(`moving doc ${doc.id}`);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
function getAllNames() {
|
|
|
|
return admin
|
|
|
|
.auth()
|
|
|
|
.listUsers()
|
|
|
|
.then((data) => {
|
|
|
|
let names = [];
|
|
|
|
data.users.forEach((user) => {
|
|
|
|
names.push(user.displayName);
|
|
|
|
});
|
|
|
|
return names;
|
|
|
|
});
|
2020-06-06 23:47:38 +08:00
|
|
|
}
|
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
function getAllUsers() {
|
|
|
|
return admin
|
|
|
|
.auth()
|
|
|
|
.listUsers()
|
|
|
|
.then((data) => {
|
|
|
|
return data.users;
|
|
|
|
});
|
2020-06-06 23:47:38 +08:00
|
|
|
}
|
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
function isUsernameValid(name) {
|
|
|
|
if (name === null || name === undefined || name === "") return false;
|
2020-07-07 05:51:03 +08:00
|
|
|
if (/miodec/.test(name.toLowerCase())) return false;
|
2020-07-03 08:35:45 +08:00
|
|
|
if (name.length > 12) return false;
|
|
|
|
return /^[0-9a-zA-Z_.-]+$/.test(name);
|
2020-06-06 23:47:38 +08:00
|
|
|
}
|
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
exports.checkNameAvailability = functions.https.onCall((request, response) => {
|
|
|
|
// 1 - available
|
|
|
|
// -1 - unavailable (taken)
|
|
|
|
// -2 - not valid name
|
|
|
|
// -999 - unknown error
|
|
|
|
try {
|
|
|
|
if (!isUsernameValid(request.name)) return -2;
|
|
|
|
return getAllNames().then((data) => {
|
|
|
|
let available = 1;
|
|
|
|
data.forEach((name) => {
|
|
|
|
try {
|
|
|
|
if (name.toLowerCase() === request.name.toLowerCase()) available = -1;
|
|
|
|
} catch (e) {
|
|
|
|
//
|
2020-06-06 23:47:38 +08:00
|
|
|
}
|
2020-07-03 08:35:45 +08:00
|
|
|
});
|
|
|
|
return available;
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
return -999;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
exports.changeName = functions.https.onCall((request, response) => {
|
|
|
|
try {
|
|
|
|
if (!isUsernameValid(request.name)) {
|
|
|
|
console.warn(
|
|
|
|
`${request.uid} tried to change their name to ${request.name} - not valid`
|
|
|
|
);
|
|
|
|
return 0;
|
2020-06-06 23:47:38 +08:00
|
|
|
}
|
2020-07-03 08:35:45 +08:00
|
|
|
return getAllNames().then((data) => {
|
|
|
|
let available = 1;
|
|
|
|
data.forEach((name) => {
|
|
|
|
try {
|
|
|
|
if (name.toLowerCase() === request.name.toLowerCase()) available = 0;
|
|
|
|
} catch (e) {
|
|
|
|
//
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (available === 1) {
|
|
|
|
return admin
|
|
|
|
.auth()
|
|
|
|
.updateUser(request.uid, {
|
|
|
|
displayName: request.name,
|
|
|
|
})
|
|
|
|
.then((d) => {
|
|
|
|
console.log(
|
|
|
|
`${request.uid} changed their name to ${request.name} - done`
|
|
|
|
);
|
|
|
|
return 1;
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(
|
|
|
|
`${request.uid} tried to change their name to ${request.name} - ${e.message}`
|
|
|
|
);
|
|
|
|
return -1;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
console.warn(
|
|
|
|
`${request.uid} tried to change their name to ${request.name} - already taken`
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
console.error(
|
|
|
|
`${request.uid} tried to change their name to ${request.name} - ${e}`
|
|
|
|
);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
});
|
2020-06-06 23:47:38 +08:00
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
exports.checkIfNeedsToChangeName = functions.https.onCall(
|
|
|
|
(request, response) => {
|
|
|
|
try {
|
2020-07-08 07:14:03 +08:00
|
|
|
return db
|
2020-07-04 05:09:29 +08:00
|
|
|
.collection("users")
|
|
|
|
.doc(request.uid)
|
|
|
|
.get()
|
|
|
|
.then((doc) => {
|
|
|
|
if (doc.data().name === undefined) {
|
|
|
|
return admin
|
|
|
|
.auth()
|
|
|
|
.getUser(request.uid)
|
|
|
|
.then((requestUser) => {
|
|
|
|
if (!isUsernameValid(requestUser.displayName)) {
|
|
|
|
//invalid name, needs to change
|
2020-07-03 08:35:45 +08:00
|
|
|
console.log(
|
|
|
|
`user ${requestUser.uid} ${requestUser.displayName} needs to change name`
|
|
|
|
);
|
2020-07-04 05:09:29 +08:00
|
|
|
return 1;
|
2020-07-03 08:35:45 +08:00
|
|
|
} else {
|
2020-07-04 05:09:29 +08:00
|
|
|
//valid name, but need to change if not duplicate
|
|
|
|
|
2020-07-04 20:08:25 +08:00
|
|
|
return getAllUsers()
|
|
|
|
.then((users) => {
|
|
|
|
let sameName = [];
|
|
|
|
|
|
|
|
//look for name names
|
|
|
|
users.forEach((user) => {
|
|
|
|
if (user.uid !== requestUser.uid) {
|
|
|
|
try {
|
|
|
|
if (
|
|
|
|
user.displayName.toLowerCase() ===
|
|
|
|
requestUser.displayName.toLowerCase()
|
|
|
|
) {
|
|
|
|
sameName.push(user);
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
//
|
2020-07-04 05:09:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-07-04 20:08:25 +08:00
|
|
|
if (sameName.length === 0) {
|
2020-07-08 07:14:03 +08:00
|
|
|
db.collection("users")
|
2020-07-04 05:09:29 +08:00
|
|
|
.doc(request.uid)
|
|
|
|
.update({ name: requestUser.displayName })
|
|
|
|
.then(() => {
|
|
|
|
return 0;
|
|
|
|
});
|
2020-07-04 20:08:25 +08:00
|
|
|
} else {
|
|
|
|
//check when the request user made the account compared to others
|
|
|
|
let earliestTimestamp = 999999999999999;
|
|
|
|
sameName.forEach((sn) => {
|
|
|
|
let ts =
|
|
|
|
new Date(sn.metadata.creationTime).getTime() / 1000;
|
|
|
|
if (ts <= earliestTimestamp) {
|
|
|
|
earliestTimestamp = ts;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (
|
|
|
|
new Date(
|
|
|
|
requestUser.metadata.creationTime
|
|
|
|
).getTime() /
|
|
|
|
1000 >
|
|
|
|
earliestTimestamp
|
|
|
|
) {
|
|
|
|
console.log(
|
|
|
|
`user ${requestUser.uid} ${requestUser.displayName} needs to change name`
|
|
|
|
);
|
|
|
|
return 2;
|
|
|
|
} else {
|
2020-07-08 07:14:03 +08:00
|
|
|
db.collection("users")
|
2020-07-04 20:08:25 +08:00
|
|
|
.doc(request.uid)
|
|
|
|
.update({ name: requestUser.displayName })
|
|
|
|
.then(() => {
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
}
|
2020-07-04 05:09:29 +08:00
|
|
|
}
|
2020-07-04 20:08:25 +08:00
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(`error getting all users - ${e}`);
|
|
|
|
});
|
2020-07-03 08:35:45 +08:00
|
|
|
}
|
2020-07-04 05:09:29 +08:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
console.log("name is good");
|
2020-07-04 20:08:25 +08:00
|
|
|
return 0;
|
2020-07-03 08:35:45 +08:00
|
|
|
}
|
2020-06-06 23:47:38 +08:00
|
|
|
});
|
2020-07-03 08:35:45 +08:00
|
|
|
} catch (e) {
|
|
|
|
return -1;
|
2020-06-06 23:47:38 +08:00
|
|
|
}
|
2020-07-03 08:35:45 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
function checkIfPB(uid, obj) {
|
2020-07-07 20:26:52 +08:00
|
|
|
return db
|
2020-07-03 08:35:45 +08:00
|
|
|
.collection(`users`)
|
|
|
|
.doc(uid)
|
|
|
|
.get()
|
|
|
|
.then((data) => {
|
|
|
|
let pbs = null;
|
|
|
|
try {
|
|
|
|
pbs = data.data().personalBests;
|
|
|
|
if (pbs === undefined) {
|
|
|
|
throw new Error("pb is undefined");
|
2020-06-08 09:24:24 +08:00
|
|
|
}
|
2020-07-03 08:35:45 +08:00
|
|
|
} catch (e) {
|
2020-07-07 20:26:52 +08:00
|
|
|
return db
|
2020-07-03 08:35:45 +08:00
|
|
|
.collection("users")
|
|
|
|
.doc(uid)
|
|
|
|
.update({
|
|
|
|
personalBests: {
|
|
|
|
[obj.mode]: {
|
|
|
|
[obj.mode2]: [
|
|
|
|
{
|
2020-06-08 09:24:24 +08:00
|
|
|
language: obj.language,
|
|
|
|
difficulty: obj.difficulty,
|
|
|
|
punctuation: obj.punctuation,
|
2020-07-03 08:35:45 +08:00
|
|
|
wpm: obj.wpm,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.then((e) => {
|
|
|
|
return true;
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
2020-07-07 20:26:52 +08:00
|
|
|
return db
|
2020-07-03 08:35:45 +08:00
|
|
|
.collection("users")
|
|
|
|
.doc(uid)
|
|
|
|
.set({
|
|
|
|
personalBests: {
|
|
|
|
[obj.mode]: {
|
|
|
|
[obj.mode2]: [
|
|
|
|
{
|
|
|
|
language: obj.language,
|
|
|
|
difficulty: obj.difficulty,
|
|
|
|
punctuation: obj.punctuation,
|
|
|
|
wpm: obj.wpm,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.then((e) => {
|
2020-06-08 09:24:24 +08:00
|
|
|
return true;
|
2020-07-03 08:35:45 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
// //check mode, mode2, punctuation, language and difficulty
|
|
|
|
|
|
|
|
let toUpdate = false;
|
|
|
|
let found = false;
|
|
|
|
try {
|
2020-07-08 23:32:22 +08:00
|
|
|
if (pbs[obj.mode][obj.mode2] === undefined) {
|
|
|
|
pbs[obj.mode][obj.mode2] = [];
|
|
|
|
}
|
2020-07-03 08:35:45 +08:00
|
|
|
pbs[obj.mode][obj.mode2].forEach((pb) => {
|
|
|
|
if (
|
|
|
|
pb.punctuation === obj.punctuation &&
|
|
|
|
pb.difficulty === obj.difficulty &&
|
|
|
|
pb.language === obj.language
|
|
|
|
) {
|
|
|
|
//entry like this already exists, compare wpm
|
|
|
|
found = true;
|
|
|
|
if (pb.wpm < obj.wpm) {
|
|
|
|
//new pb
|
|
|
|
pb.wpm = obj.wpm;
|
|
|
|
toUpdate = true;
|
|
|
|
} else {
|
|
|
|
//no pb
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
//checked all pbs, nothing found - meaning this is a new pb
|
|
|
|
if (!found) {
|
|
|
|
pbs[obj.mode][obj.mode2].push({
|
|
|
|
language: obj.language,
|
|
|
|
difficulty: obj.difficulty,
|
|
|
|
punctuation: obj.punctuation,
|
|
|
|
wpm: obj.wpm,
|
|
|
|
});
|
|
|
|
toUpdate = true;
|
2020-06-08 09:24:24 +08:00
|
|
|
}
|
2020-07-03 08:35:45 +08:00
|
|
|
} catch (e) {
|
|
|
|
// console.log(e);
|
|
|
|
pbs[obj.mode] = {};
|
|
|
|
pbs[obj.mode][obj.mode2] = [
|
|
|
|
{
|
|
|
|
language: obj.language,
|
|
|
|
difficulty: obj.difficulty,
|
|
|
|
punctuation: obj.punctuation,
|
|
|
|
wpm: obj.wpm,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
toUpdate = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (toUpdate) {
|
2020-07-07 20:26:52 +08:00
|
|
|
return db
|
2020-07-03 08:35:45 +08:00
|
|
|
.collection("users")
|
|
|
|
.doc(uid)
|
|
|
|
.update({ personalBests: pbs })
|
|
|
|
.then((e) => {
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
2020-06-08 07:26:57 +08:00
|
|
|
}
|
|
|
|
|
2020-07-07 02:40:52 +08:00
|
|
|
function stdDev(array) {
|
|
|
|
const n = array.length;
|
|
|
|
const mean = array.reduce((a, b) => a + b) / n;
|
|
|
|
return Math.sqrt(
|
|
|
|
array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
exports.testCompleted = functions.https.onCall((request, response) => {
|
|
|
|
try {
|
|
|
|
if (request.uid === undefined || request.obj === undefined) {
|
|
|
|
console.error(`error saving result for ${request.uid} - missing input`);
|
2020-07-07 02:40:52 +08:00
|
|
|
return { resultCode: -999 };
|
2020-07-03 08:35:45 +08:00
|
|
|
}
|
2020-06-08 06:43:01 +08:00
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
let obj = request.obj;
|
2020-06-08 06:43:01 +08:00
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
let err = false;
|
|
|
|
Object.keys(obj).forEach((key) => {
|
|
|
|
let val = obj[key];
|
|
|
|
if (Array.isArray(val)) {
|
|
|
|
val.forEach((valarr) => {
|
|
|
|
if (!/^[0-9a-zA-Z._]+$/.test(valarr)) err = true;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
if (val === undefined || !/^[0-9a-zA-Z._]+$/.test(val)) err = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (err) {
|
|
|
|
console.error(
|
|
|
|
`error saving result for ${request.uid} - bad input - ${JSON.stringify(
|
|
|
|
request.obj
|
|
|
|
)}`
|
|
|
|
);
|
2020-07-04 02:18:36 +08:00
|
|
|
return -1;
|
2020-07-03 08:35:45 +08:00
|
|
|
}
|
2020-06-08 06:43:01 +08:00
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
if (obj.wpm <= 0 || obj.wpm > 350 || obj.acc < 50 || obj.acc > 100) {
|
2020-07-04 02:18:36 +08:00
|
|
|
return -1;
|
2020-07-03 08:35:45 +08:00
|
|
|
}
|
2020-06-28 05:17:08 +08:00
|
|
|
|
2020-07-09 23:20:52 +08:00
|
|
|
let keySpacing = null;
|
|
|
|
let keyDuration = null;
|
|
|
|
|
2020-07-09 23:22:00 +08:00
|
|
|
try {
|
2020-07-09 23:20:52 +08:00
|
|
|
keySpacing = {
|
|
|
|
average:
|
|
|
|
obj.keySpacing.reduce((previous, current) => (current += previous)) /
|
|
|
|
obj.keySpacing.length,
|
|
|
|
sd: stdDev(obj.keySpacing),
|
|
|
|
};
|
2020-07-09 23:22:00 +08:00
|
|
|
|
2020-07-09 23:20:52 +08:00
|
|
|
keyDuration = {
|
|
|
|
average:
|
|
|
|
obj.keyDuration.reduce((previous, current) => (current += previous)) /
|
|
|
|
obj.keyDuration.length,
|
|
|
|
sd: stdDev(obj.keyDuration),
|
|
|
|
};
|
2020-07-09 23:22:00 +08:00
|
|
|
} catch (e) {
|
|
|
|
console.error(
|
|
|
|
`cant verify key spacing or duration! - ${e} - ${obj.keySpacing} ${obj.keyDuration}`
|
|
|
|
);
|
2020-07-09 23:20:52 +08:00
|
|
|
}
|
2020-07-07 02:40:52 +08:00
|
|
|
|
2020-07-08 23:32:22 +08:00
|
|
|
return db
|
|
|
|
.collection("users")
|
2020-07-08 04:44:03 +08:00
|
|
|
.doc(request.uid)
|
|
|
|
.get()
|
|
|
|
.then((ret) => {
|
|
|
|
let userdata = ret.data();
|
2020-07-09 22:02:19 +08:00
|
|
|
let name = userdata.name === undefined ? false : userdata.name;
|
|
|
|
let banned = userdata.banned === undefined ? false : userdata.banned;
|
2020-07-07 02:40:52 +08:00
|
|
|
let verified =
|
2020-07-09 22:02:19 +08:00
|
|
|
userdata.verified === undefined ? false : userdata.verified;
|
2020-07-07 02:40:52 +08:00
|
|
|
|
2020-07-08 07:14:03 +08:00
|
|
|
request.obj.name = name;
|
|
|
|
|
2020-07-07 02:40:52 +08:00
|
|
|
//check keyspacing and duration here
|
|
|
|
if (!verified) {
|
2020-07-09 23:22:00 +08:00
|
|
|
if (keySpacing !== null && keyDuration !== null) {
|
2020-07-09 23:20:52 +08:00
|
|
|
if (
|
|
|
|
keySpacing.sd < 15 ||
|
|
|
|
keyDuration.sd < 15 ||
|
|
|
|
keyDuration.average < 15
|
|
|
|
) {
|
|
|
|
console.error(
|
|
|
|
`possible bot detected by user ${
|
|
|
|
request.uid
|
|
|
|
} ${name} - spacing ${JSON.stringify(
|
|
|
|
keySpacing
|
|
|
|
)} duration ${JSON.stringify(keyDuration)}`
|
|
|
|
);
|
|
|
|
return { resultCode: -2 };
|
|
|
|
}
|
2020-07-04 06:24:36 +08:00
|
|
|
}
|
2020-07-07 02:40:52 +08:00
|
|
|
}
|
|
|
|
|
2020-07-08 04:44:03 +08:00
|
|
|
return db
|
|
|
|
.collection(`users/${request.uid}/results`)
|
|
|
|
.add(obj)
|
|
|
|
.then((e) => {
|
2020-07-07 02:40:52 +08:00
|
|
|
return Promise.all([
|
2020-07-07 05:51:03 +08:00
|
|
|
checkLeaderboards(request.obj, "global", banned, name),
|
|
|
|
checkLeaderboards(request.obj, "daily", banned, name),
|
2020-07-07 02:40:52 +08:00
|
|
|
checkIfPB(request.uid, request.obj),
|
|
|
|
]).then((values) => {
|
|
|
|
let globallb = values[0].insertedAt;
|
|
|
|
let dailylb = values[1].insertedAt;
|
|
|
|
let ispb = values[2];
|
|
|
|
// console.log(values);
|
|
|
|
|
2020-07-09 22:55:02 +08:00
|
|
|
let usr =
|
|
|
|
userdata.discordId !== undefined
|
|
|
|
? userdata.discordId
|
|
|
|
: userdata.name;
|
|
|
|
|
|
|
|
if (
|
|
|
|
globallb !== null &&
|
|
|
|
[1, 2, 3].includes(globallb.insertedAt + 1) &&
|
|
|
|
globallb.newBest
|
|
|
|
) {
|
|
|
|
let lbstring = `${obj.mode} ${obj.mode2} global`;
|
|
|
|
console.log(
|
|
|
|
`sending command to the bot to announce lb update ${
|
|
|
|
userdata.discordId
|
|
|
|
} ${globallb + 1} ${lbstring} ${obj.wpm}`
|
|
|
|
);
|
|
|
|
|
|
|
|
announceLbUpdate(
|
|
|
|
usr,
|
|
|
|
globallb.insertedAt + 1,
|
|
|
|
lbstring,
|
|
|
|
obj.wpm
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-07-07 02:40:52 +08:00
|
|
|
let returnobj = {
|
|
|
|
resultCode: null,
|
|
|
|
globalLeaderboard: globallb,
|
|
|
|
dailyLeaderboard: dailylb,
|
|
|
|
lbBanned: banned,
|
2020-07-07 05:51:03 +08:00
|
|
|
name: name,
|
2020-07-07 02:40:52 +08:00
|
|
|
};
|
|
|
|
request.obj.keySpacing = "removed";
|
|
|
|
request.obj.keyDuration = "removed";
|
|
|
|
if (ispb) {
|
2020-07-08 04:44:03 +08:00
|
|
|
console.log(
|
|
|
|
`saved result for ${request.uid} (new PB) - ${JSON.stringify(
|
|
|
|
request.obj
|
|
|
|
)}`
|
|
|
|
);
|
2020-07-08 04:47:51 +08:00
|
|
|
if (
|
|
|
|
obj.mode === "time" &&
|
|
|
|
String(obj.mode2) === "60" &&
|
|
|
|
userdata.discordId !== null &&
|
|
|
|
userdata.discordId !== undefined
|
|
|
|
) {
|
2020-07-09 19:14:00 +08:00
|
|
|
console.log(
|
|
|
|
`sending command to the bot to update the role for user ${request.uid} with wpm ${obj.wpm}`
|
|
|
|
);
|
|
|
|
updateDiscordRole(userdata.discordId, Math.round(obj.wpm));
|
2020-07-08 03:42:26 +08:00
|
|
|
return;
|
2020-07-08 04:44:03 +08:00
|
|
|
}
|
2020-07-07 02:40:52 +08:00
|
|
|
returnobj.resultCode = 2;
|
2020-07-08 04:44:03 +08:00
|
|
|
} else {
|
|
|
|
console.log(
|
|
|
|
`saved result for ${request.uid} - ${JSON.stringify(
|
|
|
|
request.obj
|
|
|
|
)}`
|
|
|
|
);
|
2020-07-07 02:40:52 +08:00
|
|
|
returnobj.resultCode = 1;
|
2020-07-08 04:44:03 +08:00
|
|
|
}
|
2020-07-07 02:40:52 +08:00
|
|
|
// console.log(returnobj);
|
|
|
|
return returnobj;
|
2020-07-08 04:44:03 +08:00
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(
|
2020-07-07 02:40:52 +08:00
|
|
|
`error saving result when checking for PB / checking leaderboards for ${request.uid} - ${e.message}`
|
2020-07-04 02:18:36 +08:00
|
|
|
);
|
2020-07-07 02:40:52 +08:00
|
|
|
return { resultCode: -999 };
|
2020-07-08 04:44:03 +08:00
|
|
|
});
|
2020-07-03 08:35:45 +08:00
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(
|
2020-07-07 02:40:52 +08:00
|
|
|
`error saving result when getting user data for ${request.uid} - ${e.message}`
|
2020-07-03 08:35:45 +08:00
|
|
|
);
|
2020-07-07 02:40:52 +08:00
|
|
|
return { resultCode: -999 };
|
2020-07-03 08:35:45 +08:00
|
|
|
});
|
|
|
|
} catch (e) {
|
2020-07-09 23:20:52 +08:00
|
|
|
console.error(
|
|
|
|
`error saving result for ${request.uid} - ${JSON.stringify(
|
|
|
|
request.obj
|
|
|
|
)} - ${e}`
|
|
|
|
);
|
2020-07-07 02:40:52 +08:00
|
|
|
return { resultCode: -999 };
|
2020-07-03 08:35:45 +08:00
|
|
|
}
|
|
|
|
});
|
2020-06-12 01:48:15 +08:00
|
|
|
|
2020-07-07 23:39:10 +08:00
|
|
|
function updateDiscordRole(discordId, wpm) {
|
|
|
|
db.collection("bot-commands").add({
|
|
|
|
command: "updateRole",
|
|
|
|
arguments: [discordId, wpm],
|
|
|
|
executed: false,
|
|
|
|
requestTimestamp: Date.now(),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
function isTagValid(name) {
|
|
|
|
if (name === null || name === undefined || name === "") return false;
|
|
|
|
if (name.length > 16) return false;
|
|
|
|
return /^[0-9a-zA-Z_.-]+$/.test(name);
|
2020-06-12 01:48:15 +08:00
|
|
|
}
|
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
exports.addTag = functions.https.onCall((request, response) => {
|
|
|
|
try {
|
|
|
|
if (!isTagValid(request.name)) {
|
|
|
|
return { resultCode: -1 };
|
|
|
|
} else {
|
2020-07-07 20:26:52 +08:00
|
|
|
return db
|
2020-07-03 08:35:45 +08:00
|
|
|
.collection(`users/${request.uid}/tags`)
|
|
|
|
.add({
|
|
|
|
name: request.name,
|
|
|
|
})
|
|
|
|
.then((e) => {
|
|
|
|
console.log(`user ${request.uid} created a tag: ${request.name}`);
|
|
|
|
return {
|
|
|
|
resultCode: 1,
|
|
|
|
id: e.id,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(
|
|
|
|
`error while creating tag for user ${request.uid}: ${e.message}`
|
|
|
|
);
|
|
|
|
return { resultCode: -999 };
|
|
|
|
});
|
2020-06-12 01:48:15 +08:00
|
|
|
}
|
2020-07-03 08:35:45 +08:00
|
|
|
} catch (e) {
|
|
|
|
console.error(`error adding tag for ${request.uid} - ${e}`);
|
|
|
|
return { resultCode: -999 };
|
|
|
|
}
|
|
|
|
});
|
2020-06-12 02:38:24 +08:00
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
exports.editTag = functions.https.onCall((request, response) => {
|
|
|
|
try {
|
|
|
|
if (!isTagValid(request.name)) {
|
|
|
|
return { resultCode: -1 };
|
|
|
|
} else {
|
2020-07-07 20:26:52 +08:00
|
|
|
return db
|
2020-07-03 08:35:45 +08:00
|
|
|
.collection(`users/${request.uid}/tags`)
|
|
|
|
.doc(request.tagid)
|
|
|
|
.update({
|
|
|
|
name: request.name,
|
|
|
|
})
|
|
|
|
.then((e) => {
|
|
|
|
console.log(`user ${request.uid} updated a tag: ${request.name}`);
|
|
|
|
return {
|
|
|
|
resultCode: 1,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(
|
|
|
|
`error while updating tag for user ${request.uid}: ${e.message}`
|
|
|
|
);
|
|
|
|
return { resultCode: -999 };
|
|
|
|
});
|
2020-06-12 02:38:24 +08:00
|
|
|
}
|
2020-07-03 08:35:45 +08:00
|
|
|
} catch (e) {
|
|
|
|
console.error(`error updating tag for ${request.uid} - ${e}`);
|
|
|
|
return { resultCode: -999 };
|
|
|
|
}
|
|
|
|
});
|
2020-06-24 07:54:32 +08:00
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
exports.removeTag = functions.https.onCall((request, response) => {
|
|
|
|
try {
|
2020-07-07 20:26:52 +08:00
|
|
|
return db
|
2020-07-03 08:35:45 +08:00
|
|
|
.collection(`users/${request.uid}/tags`)
|
|
|
|
.doc(request.tagid)
|
|
|
|
.delete()
|
|
|
|
.then((e) => {
|
|
|
|
console.log(`user ${request.uid} deleted a tag`);
|
|
|
|
return {
|
|
|
|
resultCode: 1,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(
|
|
|
|
`error deleting tag for user ${request.uid}: ${e.message}`
|
|
|
|
);
|
|
|
|
return { resultCode: -999 };
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
console.error(`error deleting tag for ${request.uid} - ${e}`);
|
|
|
|
return { resultCode: -999 };
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
exports.updateResultTags = functions.https.onCall((request, response) => {
|
|
|
|
try {
|
|
|
|
let validTags = true;
|
|
|
|
request.tags.forEach((tag) => {
|
|
|
|
if (!/^[0-9a-zA-Z]+$/.test(tag)) validTags = false;
|
|
|
|
});
|
|
|
|
if (validTags) {
|
2020-07-07 20:26:52 +08:00
|
|
|
return db
|
2020-07-03 08:35:45 +08:00
|
|
|
.collection(`users/${request.uid}/results`)
|
|
|
|
.doc(request.resultid)
|
|
|
|
.update({
|
|
|
|
tags: request.tags,
|
2020-06-24 07:54:32 +08:00
|
|
|
})
|
2020-07-03 08:35:45 +08:00
|
|
|
.then((e) => {
|
|
|
|
console.log(
|
|
|
|
`user ${request.uid} updated tags for result ${request.resultid}`
|
|
|
|
);
|
|
|
|
return {
|
|
|
|
resultCode: 1,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(
|
|
|
|
`error while updating tags for result by user ${request.uid}: ${e.message}`
|
|
|
|
);
|
|
|
|
return { resultCode: -999 };
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
console.error(`invalid tags for user ${request.uid}: ${request.tags}`);
|
|
|
|
return { resultCode: -1 };
|
2020-06-24 07:54:32 +08:00
|
|
|
}
|
2020-07-03 08:35:45 +08:00
|
|
|
} catch (e) {
|
|
|
|
console.error(`error updating tags by ${request.uid} - ${e}`);
|
|
|
|
return { resultCode: -999 };
|
|
|
|
}
|
|
|
|
});
|
2020-06-28 06:45:24 +08:00
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
function isConfigKeyValid(name) {
|
|
|
|
if (name === null || name === undefined || name === "") return false;
|
|
|
|
if (name.length > 30) return false;
|
|
|
|
return /^[0-9a-zA-Z_.\-#]+$/.test(name);
|
2020-06-28 06:45:24 +08:00
|
|
|
}
|
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
exports.saveConfig = functions.https.onCall((request, response) => {
|
|
|
|
try {
|
|
|
|
if (request.uid === undefined || request.obj === undefined) {
|
|
|
|
console.error(`error saving config for ${request.uid} - missing input`);
|
|
|
|
return -1;
|
|
|
|
}
|
2020-06-28 06:45:24 +08:00
|
|
|
|
2020-07-03 08:35:45 +08:00
|
|
|
let obj = request.obj;
|
|
|
|
|
|
|
|
let err = false;
|
|
|
|
Object.keys(obj).forEach((key) => {
|
|
|
|
let val = obj[key];
|
|
|
|
if (Array.isArray(val)) {
|
|
|
|
val.forEach((valarr) => {
|
|
|
|
if (!isConfigKeyValid(valarr)) {
|
|
|
|
err = true;
|
|
|
|
console.error(`${key}: ${valarr} failed regex check`);
|
|
|
|
}
|
2020-06-28 06:45:24 +08:00
|
|
|
});
|
2020-07-03 08:35:45 +08:00
|
|
|
} else {
|
|
|
|
if (!isConfigKeyValid(val)) {
|
|
|
|
err = true;
|
|
|
|
console.error(`${key}: ${val} failed regex check`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (err) {
|
|
|
|
console.error(
|
|
|
|
`error saving config for ${request.uid} - bad input - ${JSON.stringify(
|
|
|
|
request.obj
|
|
|
|
)}`
|
|
|
|
);
|
|
|
|
return -1;
|
2020-06-28 06:45:24 +08:00
|
|
|
}
|
2020-07-03 08:35:45 +08:00
|
|
|
|
2020-07-07 20:26:52 +08:00
|
|
|
return db
|
2020-07-03 08:35:45 +08:00
|
|
|
.collection(`users`)
|
|
|
|
.doc(request.uid)
|
|
|
|
.set(
|
|
|
|
{
|
|
|
|
config: obj,
|
|
|
|
},
|
|
|
|
{ merge: true }
|
|
|
|
)
|
|
|
|
.then((e) => {
|
|
|
|
return 1;
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(
|
|
|
|
`error saving config to DB for ${request.uid} - ${e.message}`
|
|
|
|
);
|
|
|
|
return -1;
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
console.error(`error saving config for ${request.uid} - ${e}`);
|
|
|
|
return { resultCode: -999 };
|
|
|
|
}
|
|
|
|
});
|
2020-06-28 06:45:24 +08:00
|
|
|
|
2020-07-07 20:50:24 +08:00
|
|
|
function generate(n) {
|
|
|
|
var add = 1,
|
|
|
|
max = 12 - add;
|
|
|
|
|
|
|
|
if (n > max) {
|
|
|
|
return generate(max) + generate(n - max);
|
|
|
|
}
|
|
|
|
|
|
|
|
max = Math.pow(10, n + add);
|
|
|
|
var min = max / 10; // Math.pow(10, n) basically
|
|
|
|
var number = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
|
|
|
|
|
|
return ("" + number).substring(add);
|
|
|
|
}
|
|
|
|
|
2020-07-04 02:15:46 +08:00
|
|
|
class Leaderboard {
|
|
|
|
constructor(size, mode, mode2, type, starting) {
|
|
|
|
this.size = size;
|
|
|
|
this.board = [];
|
|
|
|
this.mode = mode;
|
|
|
|
this.mode2 = mode2;
|
|
|
|
this.type = type;
|
|
|
|
if (starting !== undefined && starting !== null) {
|
|
|
|
starting.forEach((entry) => {
|
|
|
|
if (entry.mode === this.mode && entry.mode2 === this.mode2) {
|
|
|
|
this.board.push({
|
|
|
|
uid: entry.uid,
|
2020-07-09 23:20:52 +08:00
|
|
|
name: entry.name,
|
2020-07-04 02:15:46 +08:00
|
|
|
wpm: parseFloat(entry.wpm),
|
2020-07-04 02:29:48 +08:00
|
|
|
raw: parseFloat(entry.raw),
|
2020-07-04 02:15:46 +08:00
|
|
|
acc: parseFloat(entry.acc),
|
|
|
|
mode: entry.mode,
|
|
|
|
mode2: entry.mode2,
|
|
|
|
timestamp: entry.timestamp,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
this.sortBoard();
|
|
|
|
this.clipBoard();
|
|
|
|
}
|
|
|
|
sortBoard() {
|
|
|
|
this.board.sort((a, b) => {
|
|
|
|
if (a.wpm === b.wpm) {
|
|
|
|
if (a.acc === b.acc) {
|
|
|
|
return a.timestamp - b.timestamp;
|
|
|
|
} else {
|
|
|
|
return b.acc - a.acc;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return b.wpm - a.wpm;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
clipBoard() {
|
|
|
|
let boardLength = this.board.length;
|
|
|
|
if (boardLength > this.size) {
|
|
|
|
while (this.board.length !== this.size) {
|
|
|
|
this.board.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
logBoard() {
|
|
|
|
console.log(this.board);
|
|
|
|
}
|
2020-07-04 06:24:36 +08:00
|
|
|
removeDuplicates(insertedAt, uid) {
|
|
|
|
//return true if a better result is found
|
|
|
|
let found = false;
|
2020-07-04 21:15:15 +08:00
|
|
|
// let ret;
|
|
|
|
let foundAt = null;
|
2020-07-04 06:24:36 +08:00
|
|
|
if (this.board !== undefined) {
|
|
|
|
this.board.forEach((entry, index) => {
|
|
|
|
if (entry.uid === uid) {
|
|
|
|
if (found) {
|
|
|
|
this.board.splice(index, 1);
|
2020-07-04 21:15:15 +08:00
|
|
|
// if (index > insertedAt) {
|
|
|
|
// //removed old result
|
|
|
|
// ret = false;
|
|
|
|
// } else {
|
|
|
|
// ret = true;
|
|
|
|
// }
|
2020-07-04 06:24:36 +08:00
|
|
|
} else {
|
|
|
|
found = true;
|
2020-07-04 21:15:15 +08:00
|
|
|
foundAt = index;
|
2020-07-04 06:24:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2020-07-04 06:41:42 +08:00
|
|
|
// console.log(ret);
|
2020-07-04 21:15:15 +08:00
|
|
|
// return ret;
|
|
|
|
return foundAt;
|
2020-07-04 06:24:36 +08:00
|
|
|
}
|
2020-07-04 02:15:46 +08:00
|
|
|
insert(a) {
|
|
|
|
let insertedAt = -1;
|
|
|
|
if (a.mode === this.mode && a.mode2 === this.mode2) {
|
|
|
|
this.board.forEach((b, index) => {
|
|
|
|
if (insertedAt !== -1) return;
|
|
|
|
if (a.wpm === b.wpm) {
|
|
|
|
if (a.acc === b.acc) {
|
|
|
|
if (a.timestamp < b.timestamp) {
|
|
|
|
this.board.splice(index, 0, {
|
|
|
|
uid: a.uid,
|
2020-07-08 07:14:03 +08:00
|
|
|
name: a.name,
|
2020-07-04 02:15:46 +08:00
|
|
|
wpm: parseFloat(a.wpm),
|
2020-07-04 03:10:22 +08:00
|
|
|
raw: parseFloat(a.rawWpm),
|
2020-07-04 02:15:46 +08:00
|
|
|
acc: parseFloat(a.acc),
|
|
|
|
mode: a.mode,
|
|
|
|
mode2: a.mode2,
|
|
|
|
timestamp: a.timestamp,
|
|
|
|
});
|
|
|
|
insertedAt = index;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (a.acc > b.acc) {
|
|
|
|
this.board.splice(index, 0, {
|
|
|
|
uid: a.uid,
|
2020-07-08 07:14:03 +08:00
|
|
|
name: a.name,
|
2020-07-04 02:15:46 +08:00
|
|
|
wpm: parseFloat(a.wpm),
|
2020-07-04 03:10:22 +08:00
|
|
|
raw: parseFloat(a.rawWpm),
|
2020-07-04 02:15:46 +08:00
|
|
|
acc: parseFloat(a.acc),
|
|
|
|
mode: a.mode,
|
|
|
|
mode2: a.mode2,
|
|
|
|
timestamp: a.timestamp,
|
|
|
|
});
|
|
|
|
insertedAt = index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (a.wpm > b.wpm) {
|
|
|
|
this.board.splice(index, 0, {
|
|
|
|
uid: a.uid,
|
2020-07-08 07:14:03 +08:00
|
|
|
name: a.name,
|
2020-07-04 02:15:46 +08:00
|
|
|
wpm: parseFloat(a.wpm),
|
2020-07-04 03:10:22 +08:00
|
|
|
raw: parseFloat(a.rawWpm),
|
2020-07-04 02:15:46 +08:00
|
|
|
acc: parseFloat(a.acc),
|
|
|
|
mode: a.mode,
|
|
|
|
mode2: a.mode2,
|
|
|
|
timestamp: a.timestamp,
|
|
|
|
});
|
|
|
|
insertedAt = index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (this.board.length < this.size && insertedAt === -1) {
|
|
|
|
this.board.push({
|
|
|
|
uid: a.uid,
|
2020-07-08 07:14:03 +08:00
|
|
|
name: a.name,
|
2020-07-04 02:15:46 +08:00
|
|
|
wpm: parseFloat(a.wpm),
|
2020-07-04 03:10:22 +08:00
|
|
|
raw: parseFloat(a.rawWpm),
|
2020-07-04 02:15:46 +08:00
|
|
|
acc: parseFloat(a.acc),
|
|
|
|
mode: a.mode,
|
|
|
|
mode2: a.mode2,
|
|
|
|
timestamp: a.timestamp,
|
|
|
|
});
|
|
|
|
insertedAt = this.board.length - 1;
|
|
|
|
}
|
2020-07-04 06:24:36 +08:00
|
|
|
// console.log("before duplicate remove");
|
|
|
|
// console.log(this.board);
|
2020-07-04 21:15:15 +08:00
|
|
|
let newBest = false;
|
2020-07-04 23:43:48 +08:00
|
|
|
let foundAt = null;
|
2020-07-04 06:24:36 +08:00
|
|
|
if (insertedAt >= 0) {
|
2020-07-04 21:15:15 +08:00
|
|
|
// if (this.removeDuplicates(insertedAt, a.uid)) {
|
|
|
|
// insertedAt = -2;
|
|
|
|
// }
|
2020-07-04 23:43:48 +08:00
|
|
|
foundAt = this.removeDuplicates(insertedAt, a.uid);
|
2020-07-04 21:15:15 +08:00
|
|
|
|
2020-07-05 07:27:24 +08:00
|
|
|
if (foundAt >= insertedAt) {
|
2020-07-04 21:15:15 +08:00
|
|
|
//new better result
|
|
|
|
newBest = true;
|
2020-07-04 06:24:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// console.log(this.board);
|
2020-07-04 02:15:46 +08:00
|
|
|
this.clipBoard();
|
2020-07-04 21:15:15 +08:00
|
|
|
return {
|
|
|
|
insertedAt: insertedAt,
|
|
|
|
newBest: newBest,
|
2020-07-04 23:43:48 +08:00
|
|
|
foundAt: foundAt,
|
2020-07-04 21:15:15 +08:00
|
|
|
};
|
2020-07-04 02:15:46 +08:00
|
|
|
} else {
|
2020-07-04 21:15:15 +08:00
|
|
|
return {
|
|
|
|
insertedAt: -999,
|
|
|
|
};
|
2020-07-04 02:15:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-07 20:50:24 +08:00
|
|
|
exports.generatePairingCode = functions.https.onCall((request, response) => {
|
|
|
|
try {
|
|
|
|
if (request === null) {
|
|
|
|
console.error(
|
|
|
|
`error while trying to generate discord pairing code - no input`
|
|
|
|
);
|
|
|
|
return {
|
|
|
|
status: -999,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return db
|
|
|
|
.collection("users")
|
|
|
|
.doc(request.uid)
|
|
|
|
.get()
|
|
|
|
.then((userDoc) => {
|
|
|
|
userDocData = userDoc.data();
|
|
|
|
if (userDocData.discordPairingCode !== undefined) {
|
|
|
|
console.log(
|
|
|
|
`user ${request.uid} already has code ${userDocData.discordPairingCode}`
|
|
|
|
);
|
|
|
|
return {
|
|
|
|
status: 2,
|
|
|
|
pairingCode: userDocData.discordPairingCode,
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
return db
|
|
|
|
.collection("users")
|
|
|
|
.get()
|
|
|
|
.then((res) => {
|
|
|
|
let existingCodes = [];
|
|
|
|
|
|
|
|
res.docs.forEach((doc) => {
|
|
|
|
let docData = doc.data();
|
|
|
|
if (docData.discordPairingCode !== undefined) {
|
|
|
|
existingCodes.push(docData.discordPairingCode);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
console.log(`existing codes ${JSON.stringify(existingCodes)}`);
|
|
|
|
|
|
|
|
let randomCode = generate(9);
|
|
|
|
|
|
|
|
while (existingCodes.includes(randomCode)) {
|
|
|
|
randomCode = generate(9);
|
|
|
|
}
|
|
|
|
|
|
|
|
return db
|
|
|
|
.collection("users")
|
|
|
|
.doc(request.uid)
|
|
|
|
.update(
|
|
|
|
{
|
|
|
|
discordPairingCode: randomCode,
|
|
|
|
},
|
|
|
|
{ merge: true }
|
|
|
|
)
|
|
|
|
.then((res) => {
|
|
|
|
console.log(
|
|
|
|
`generated ${randomCode} for user ${request.uid}`
|
|
|
|
);
|
|
|
|
return {
|
|
|
|
status: 1,
|
|
|
|
pairingCode: randomCode,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(
|
|
|
|
`error while trying to set discord pairing code ${randomCode} for user ${request.uid} - ${e}`
|
|
|
|
);
|
|
|
|
return {
|
|
|
|
status: -999,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
console.error(
|
|
|
|
`error while trying to generate discord pairing code for user ${request.uid} - ${e}`
|
|
|
|
);
|
|
|
|
return {
|
|
|
|
status: -999,
|
|
|
|
};
|
|
|
|
}
|
2020-07-07 20:26:52 +08:00
|
|
|
});
|
|
|
|
|
2020-07-07 05:51:03 +08:00
|
|
|
async function checkLeaderboards(resultObj, type, banned, name) {
|
2020-07-09 23:20:52 +08:00
|
|
|
return {
|
|
|
|
insertedAt: null,
|
|
|
|
};
|
2020-07-04 07:32:45 +08:00
|
|
|
try {
|
2020-07-07 05:51:03 +08:00
|
|
|
if (!name)
|
|
|
|
return {
|
|
|
|
insertedAt: null,
|
|
|
|
noName: true,
|
|
|
|
};
|
2020-07-07 02:40:52 +08:00
|
|
|
if (banned)
|
|
|
|
return {
|
|
|
|
insertedAt: null,
|
|
|
|
banned: true,
|
|
|
|
};
|
2020-07-04 08:39:29 +08:00
|
|
|
if (
|
2020-07-08 07:14:03 +08:00
|
|
|
resultObj.mode === "time" &&
|
|
|
|
["15", "60"].includes(String(resultObj.mode2)) &&
|
2020-07-05 23:29:57 +08:00
|
|
|
resultObj.language === "english"
|
2020-07-04 08:39:29 +08:00
|
|
|
) {
|
2020-07-08 07:14:03 +08:00
|
|
|
return db
|
2020-07-04 08:39:29 +08:00
|
|
|
.collection("leaderboards")
|
|
|
|
.where("mode", "==", String(resultObj.mode))
|
|
|
|
.where("mode2", "==", String(resultObj.mode2))
|
|
|
|
.where("type", "==", type)
|
|
|
|
.get()
|
|
|
|
.then((ret) => {
|
|
|
|
if (ret.docs.length === 0) {
|
|
|
|
//no lb found, create
|
|
|
|
console.log(
|
|
|
|
`no ${resultObj.mode} ${resultObj.mode2} ${type} leaderboard found - creating`
|
|
|
|
);
|
|
|
|
let toAdd = {
|
|
|
|
size: 20,
|
|
|
|
mode: String(resultObj.mode),
|
|
|
|
mode2: String(resultObj.mode2),
|
|
|
|
type: type,
|
|
|
|
};
|
2020-07-08 07:14:03 +08:00
|
|
|
return db
|
2020-07-04 08:39:29 +08:00
|
|
|
.collection("leaderboards")
|
|
|
|
.doc(
|
|
|
|
`${String(resultObj.mode)}_${String(resultObj.mode2)}_${type}`
|
|
|
|
)
|
|
|
|
.set(toAdd)
|
|
|
|
.then((ret) => {
|
|
|
|
return cont(
|
|
|
|
`${String(resultObj.mode)}_${String(
|
|
|
|
resultObj.mode2
|
|
|
|
)}_${type}`,
|
|
|
|
toAdd
|
|
|
|
);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
//continue
|
2020-07-04 20:08:25 +08:00
|
|
|
return cont(
|
|
|
|
`${String(resultObj.mode)}_${String(resultObj.mode2)}_${type}`,
|
|
|
|
ret.docs[0].data()
|
|
|
|
);
|
2020-07-04 08:39:29 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
function cont(docid, documentData) {
|
|
|
|
let boardInfo = documentData;
|
2020-07-04 07:32:45 +08:00
|
|
|
let boardData = boardInfo.board;
|
|
|
|
|
|
|
|
// console.log(`info ${JSON.stringify(boardInfo)}`);
|
|
|
|
// console.log(`data ${JSON.stringify(boardData)}`);
|
|
|
|
|
|
|
|
let lb = new Leaderboard(
|
|
|
|
boardInfo.size,
|
|
|
|
resultObj.mode,
|
|
|
|
resultObj.mode2,
|
|
|
|
boardInfo.type,
|
|
|
|
boardData
|
|
|
|
);
|
2020-07-04 02:15:46 +08:00
|
|
|
|
2020-07-04 07:32:45 +08:00
|
|
|
// console.log("board created");
|
|
|
|
// lb.logBoard();
|
2020-07-04 02:15:46 +08:00
|
|
|
|
2020-07-04 07:32:45 +08:00
|
|
|
let insertResult = lb.insert(resultObj);
|
2020-07-04 02:15:46 +08:00
|
|
|
|
2020-07-04 07:32:45 +08:00
|
|
|
// console.log("board after inseft");
|
|
|
|
// lb.logBoard();
|
2020-07-04 02:15:46 +08:00
|
|
|
|
2020-07-04 21:15:15 +08:00
|
|
|
if (insertResult.insertedAt >= 0) {
|
2020-07-04 07:32:45 +08:00
|
|
|
//update the database here
|
|
|
|
console.log(
|
2020-07-04 07:53:29 +08:00
|
|
|
`leaderboard changed ${resultObj.mode} ${
|
|
|
|
resultObj.mode2
|
|
|
|
} ${type} - ${JSON.stringify(lb.board)}`
|
2020-07-04 07:32:45 +08:00
|
|
|
);
|
2020-07-08 07:14:03 +08:00
|
|
|
db.collection("leaderboards").doc(docid).set(
|
2020-07-04 07:32:45 +08:00
|
|
|
{
|
|
|
|
size: lb.size,
|
|
|
|
type: lb.type,
|
|
|
|
board: lb.board,
|
|
|
|
},
|
|
|
|
{ merge: true }
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
// console.log("board is the same");
|
|
|
|
}
|
2020-07-04 02:15:46 +08:00
|
|
|
|
2020-07-07 02:40:52 +08:00
|
|
|
return {
|
|
|
|
insertedAt: insertResult,
|
|
|
|
};
|
2020-07-04 08:39:29 +08:00
|
|
|
}
|
2020-07-07 05:28:04 +08:00
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
insertedAt: null,
|
|
|
|
};
|
2020-07-04 08:39:29 +08:00
|
|
|
}
|
2020-07-04 07:32:45 +08:00
|
|
|
} catch (e) {
|
|
|
|
console.error(
|
|
|
|
`error while checking leaderboards - ${e} - ${type} ${resultObj}`
|
|
|
|
);
|
2020-07-09 23:20:52 +08:00
|
|
|
return {
|
|
|
|
insertedAt: null,
|
|
|
|
};
|
2020-07-04 07:32:45 +08:00
|
|
|
}
|
2020-07-04 02:15:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
exports.getLeaderboard = functions.https.onCall((request, response) => {
|
2020-07-08 07:14:03 +08:00
|
|
|
return db
|
2020-07-04 02:15:46 +08:00
|
|
|
.collection("leaderboards")
|
|
|
|
.where("mode", "==", String(request.mode))
|
|
|
|
.where("mode2", "==", String(request.mode2))
|
2020-07-04 03:10:22 +08:00
|
|
|
.where("type", "==", String(request.type))
|
2020-07-04 02:15:46 +08:00
|
|
|
.get()
|
|
|
|
.then(async (data) => {
|
2020-07-04 07:58:49 +08:00
|
|
|
// console.log("got data");
|
2020-07-04 03:10:22 +08:00
|
|
|
if (data.docs.length === 0) return null;
|
2020-07-04 02:15:46 +08:00
|
|
|
let lbdata = data.docs[0].data();
|
2020-07-04 03:10:22 +08:00
|
|
|
if (lbdata.board !== undefined) {
|
2020-07-04 07:58:49 +08:00
|
|
|
// console.log("replacing users");
|
2020-07-04 05:09:29 +08:00
|
|
|
|
2020-07-08 07:14:03 +08:00
|
|
|
// for (let i = 0; i < lbdata.board.length; i++) {
|
|
|
|
// await db
|
|
|
|
// .collection("users")
|
|
|
|
// .doc(lbdata.board[i].uid)
|
|
|
|
// .get()
|
|
|
|
// .then((doc) => {
|
|
|
|
// if (
|
|
|
|
// lbdata.board[i].uid !== null &&
|
|
|
|
// lbdata.board[i].uid === request.uid
|
|
|
|
// ) {
|
|
|
|
// lbdata.board[i].currentUser = true;
|
|
|
|
// }
|
|
|
|
// lbdata.board[i].name = doc.data().name;
|
|
|
|
// lbdata.board[i].uid = null;
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
|
|
|
|
lbdata.board.forEach((boardentry) => {
|
|
|
|
if (boardentry.uid !== null && boardentry.uid === request.uid) {
|
|
|
|
boardentry.currentUser = true;
|
|
|
|
}
|
|
|
|
boardentry.uid = null;
|
|
|
|
});
|
|
|
|
|
2020-07-04 21:15:15 +08:00
|
|
|
// console.log(lbdata);
|
2020-07-06 00:02:02 +08:00
|
|
|
if (request.type === "daily") {
|
2020-07-06 00:56:16 +08:00
|
|
|
let resetTime = new Date(Date.now());
|
2020-07-06 00:02:02 +08:00
|
|
|
resetTime.setHours(0, 0, 0, 0);
|
2020-07-06 00:27:18 +08:00
|
|
|
resetTime.setDate(resetTime.getUTCDate() + 1);
|
2020-07-06 00:02:02 +08:00
|
|
|
resetTime = resetTime.valueOf();
|
|
|
|
lbdata.resetTime = resetTime;
|
|
|
|
}
|
2020-07-04 05:09:29 +08:00
|
|
|
|
2020-07-04 03:10:22 +08:00
|
|
|
return lbdata;
|
|
|
|
} else {
|
2020-07-04 09:44:08 +08:00
|
|
|
if (
|
|
|
|
lbdata.board === undefined ||
|
|
|
|
lbdata.board === [] ||
|
|
|
|
lbdata.board.length === 0
|
|
|
|
) {
|
|
|
|
return lbdata;
|
|
|
|
} else {
|
|
|
|
return [];
|
|
|
|
}
|
2020-07-04 02:15:46 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-07-04 07:11:26 +08:00
|
|
|
exports.scheduledFunctionCrontab = functions.pubsub
|
2020-07-05 23:38:08 +08:00
|
|
|
.schedule("00 00 * * *")
|
2020-07-06 08:09:17 +08:00
|
|
|
.timeZone("Africa/Abidjan")
|
2020-07-04 07:11:26 +08:00
|
|
|
.onRun((context) => {
|
2020-07-04 07:32:45 +08:00
|
|
|
try {
|
|
|
|
console.log("moving daily leaderboards to history");
|
2020-07-08 07:14:03 +08:00
|
|
|
db.collection("leaderboards")
|
2020-07-04 07:32:45 +08:00
|
|
|
.where("type", "==", "daily")
|
|
|
|
.get()
|
|
|
|
.then((res) => {
|
|
|
|
res.docs.forEach((doc) => {
|
|
|
|
let lbdata = doc.data();
|
|
|
|
t = new Date();
|
2020-07-08 07:14:03 +08:00
|
|
|
db.collection("leaderboards_history")
|
2020-07-05 23:36:55 +08:00
|
|
|
.doc(
|
2020-07-06 00:27:18 +08:00
|
|
|
`${t.getUTCDate()}_${t.getUTCMonth()}_${t.getUTCFullYear()}_${
|
2020-07-05 23:36:55 +08:00
|
|
|
lbdata.mode
|
|
|
|
}_${lbdata.mode2}`
|
|
|
|
)
|
2020-07-04 07:32:45 +08:00
|
|
|
.set(lbdata);
|
2020-07-08 07:14:03 +08:00
|
|
|
db.collection("leaderboards").doc(doc.id).set(
|
2020-07-04 07:32:45 +08:00
|
|
|
{
|
|
|
|
board: [],
|
|
|
|
},
|
|
|
|
{ merge: true }
|
|
|
|
);
|
|
|
|
});
|
2020-07-04 07:11:26 +08:00
|
|
|
});
|
2020-07-04 07:32:45 +08:00
|
|
|
return null;
|
|
|
|
} catch (e) {
|
|
|
|
console.error(`error while moving daily leaderboards to history - ${e}`);
|
|
|
|
}
|
2020-07-04 07:11:26 +08:00
|
|
|
});
|
2020-07-09 21:45:47 +08:00
|
|
|
|
|
|
|
async function announceLbUpdate(discordId, pos, lb, wpm) {
|
|
|
|
db.collection("bot-commands").add({
|
2020-07-09 22:55:02 +08:00
|
|
|
command: "sayLbUpdate",
|
2020-07-09 21:45:47 +08:00
|
|
|
arguments: [discordId, pos, lb, wpm],
|
|
|
|
executed: false,
|
|
|
|
requestTimestamp: Date.now(),
|
|
|
|
});
|
|
|
|
}
|