upgraded commands, new command, fixed bugs

- finish / remove multiple tasks in 1 command
- fixed add task to satisfy incomplete task limit
- "!clearns" clears all tasks except streamer's incomplete tasks
- animations will cancel and restart upon any "clear" commands except clearmydone
This commit is contained in:
liyunze 2023-08-11 15:54:08 +08:00
parent b5b2d9d7e2
commit 971e41502f
3 changed files with 283 additions and 91 deletions

View file

@ -3,7 +3,7 @@ const configs = (function () {
// settings // settings
const enableLimit = true; // true or false const enableLimit = true; // true or false
const limit = 20; // integer const limit = 5; // integer
// animation // animation
const scrollSpeed = 30; // milliseconds (DO NOT PUT BELOW 5, COMPUTER MIGHT CRASH) the lower the value, the faster the scroll const scrollSpeed = 30; // milliseconds (DO NOT PUT BELOW 5, COMPUTER MIGHT CRASH) the lower the value, the faster the scroll
@ -149,6 +149,14 @@ const configs = (function () {
"!help", "!help",
]; ];
// Admin clear all except streamer - please add commands following the exact format
const adminClearNotStreamerCommands = [
"!clearnotstreamer",
"!aclearnotstreamer",
"!adminclearnotstreamer",
"!clearns",
];
// Admin delete - please add commands following the exact format // Admin delete - please add commands following the exact format
const adminDeleteCommands = [ const adminDeleteCommands = [
"!taskadel", "!taskadel",
@ -179,14 +187,17 @@ const configs = (function () {
const noTaskAdded = const noTaskAdded =
"Looks like you already hit the limit of incomplete tasks, {user}"; "Looks like you already hit the limit of incomplete tasks, {user}";
const noTaskContent = "Try using !task the-task-you-are-working-on {user}"; const noTaskContent = "Try using !task the-task-you-are-working-on {user}";
const taskDeleted = "Task '{task}' has been deleted successfully, {user}"; const taskDeleted = 'Task "{task}" has been deleted successfully, {user}';
const specifyTaskIndex = "Try specifying the index of the task {user}"; const specifyTaskIndex = "Try specifying the index of the task {user}";
const duplicateTask = const duplicateTask =
"Looks like you already have the task '{message}' up there {user}!"; "Looks like you already have the task '{message}' up there {user}!";
const clearTasksExceptBroadcaster =
"All tasks have been cleared except for the streamer's, {user}!";
const adminDeleteTasks = "All of {mentioned}'s tasks have been deleted"; const adminDeleteTasks = "All of {mentioned}'s tasks have been deleted";
const taskFinished = "Good job on finishing the task '{task}', {user}!"; const taskFinished = 'Good job on finishing the task "{task}", {user}!';
const taskEdited = const taskEdited =
"Task '{originalTask}' has been edited to '{task}' successfully, {user}"; "Task '{originalTask}' has been edited to '{task}' successfully, {user}";
const noTaskEdit = "Try doing !edit [index] [new task] {user}"; const noTaskEdit = "Try doing !edit [index] [new task] {user}";
@ -283,6 +294,7 @@ const configs = (function () {
checkCommands, checkCommands,
clearMyDoneCommands, clearMyDoneCommands,
adminDeleteCommands, adminDeleteCommands,
adminClearNotStreamerCommands,
adminClearDoneCommands, adminClearDoneCommands,
adminClearAllCommands, adminClearAllCommands,
additionalCommands, additionalCommands,
@ -302,6 +314,7 @@ const configs = (function () {
noTaskA, noTaskA,
notMod, notMod,
help, help,
clearTasksExceptBroadcaster,
adminDeleteTasks, adminDeleteTasks,
clearedMyDone, clearedMyDone,
clearedAll, clearedAll,

View file

@ -42,9 +42,15 @@ ComfyJS.onCommand = (user, command, message, flags, extra) => {
// task has no content // task has no content
respond(responses.noTaskContent, params); respond(responses.noTaskContent, params);
} else { } else {
params.task = addStatus; let addResponse = responses.taskAdded;
params.task = addStatus.task;
if (addStatus.tasksFailedToAdd !== "") {
addResponse += ` | Failed to add task(s): "${addStatus.tasksFailedToAdd}"`;
}
// task added // task added
respond(responses.taskAdded, params); respond(addResponse, params);
} }
} else if (commands.editTaskCommands.includes(command)) { } else if (commands.editTaskCommands.includes(command)) {
let editStatus = editTask(user, message); let editStatus = editTask(user, message);
@ -71,8 +77,14 @@ ComfyJS.onCommand = (user, command, message, flags, extra) => {
respond(responses.specifyTaskIndex, params); respond(responses.specifyTaskIndex, params);
} else { } else {
// task deleted // task deleted
params.task = removeStatus; let deletedResponse = responses.taskDeleted;
respond(responses.taskDeleted, params); params.task = removeStatus.removedTasks;
if (removeStatus.failedTasks !== "") {
deletedResponse += ` | Failed to delete task(s): "${removeStatus.failedTasks}"`;
}
respond(deletedResponse, params);
} }
} else if (commands.finishTaskCommands.includes(command)) { } else if (commands.finishTaskCommands.includes(command)) {
let finishStatus = markTaskDone(user, message); let finishStatus = markTaskDone(user, message);
@ -85,8 +97,15 @@ ComfyJS.onCommand = (user, command, message, flags, extra) => {
respond(responses.specifyTaskIndex, params); respond(responses.specifyTaskIndex, params);
} else { } else {
// task finished // task finished
params.task = finishStatus; let finishedResponse = responses.taskFinished;
respond(responses.taskFinished, params);
params.task = finishStatus.markedTasks;
if (finishStatus.failedTasks !== "") {
finishedResponse += ` | Failed to finish task(s): "${finishStatus.failedTasks}"`;
}
respond(finishedResponse, params);
} }
} else if (commands.checkCommands.includes(command)) { } else if (commands.checkCommands.includes(command)) {
if (message === "") { if (message === "") {
@ -137,7 +156,7 @@ ComfyJS.onCommand = (user, command, message, flags, extra) => {
respond(responses.clearedAll, params); respond(responses.clearedAll, params);
} }
} else if (commands.clearMyDoneCommands.includes(command)) { } else if (commands.clearMyDoneCommands.includes(command)) {
let response = markOwnTaskDone(user); let response = clearOwnDoneTasks(user);
if (response === 0) { if (response === 0) {
// no tasks // no tasks
@ -146,6 +165,9 @@ ComfyJS.onCommand = (user, command, message, flags, extra) => {
} }
respond(responses.clearedMyDone, params); respond(responses.clearedMyDone, params);
} else if (commands.adminClearNotStreamerCommands.includes(command)) {
clearAllExceptStreamer(auth.channel);
respond(responses.clearTasksExceptBroadcaster, params);
} else if (commands.helpCommands.includes(command)) { } else if (commands.helpCommands.includes(command)) {
respond(responses.help, params); respond(responses.help, params);
} else if (commands.additionalCommands[command]) { } else if (commands.additionalCommands[command]) {

View file

@ -13,6 +13,7 @@ const settings = configs.settings;
const styles = configs.styles; const styles = configs.styles;
const scrollSpeed = configs.animation.scrollSpeed; const scrollSpeed = configs.animation.scrollSpeed;
let scrolling = false; let scrolling = false;
let primaryAnimation, secondaryAnimation;
function loadGoogleFont(font) { function loadGoogleFont(font) {
WebFont.load({ WebFont.load({
@ -183,22 +184,47 @@ function addTask(username, userColor, task) {
return 2; return 2;
} }
let tasksFailedToAdd = [];
// if task has commas // if task has commas
if (task.includes(",")) { if (task.includes(",")) {
let tasksToAdd = task.split(",").map((t) => t.trim()); let tasksToAdd = task.split(",").map((t) => t.trim());
if (
incompleteTasksCount(username) + tasksToAdd.length >
settings.limit &&
settings.enableLimit
) {
tasksFailedToAdd = tasksToAdd.slice(
settings.limit - incompleteTasksCount(username),
tasksToAdd.length
);
tasksToAdd = tasksToAdd.slice(
0,
settings.limit - incompleteTasksCount(username)
);
}
for (const t of tasksToAdd) { for (const t of tasksToAdd) {
tasks[username].todos.push({ text: t, done: false }); tasks[username].todos.push({ text: t, done: false });
} }
localStorage.setItem(`tasks`, JSON.stringify(tasks)); localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM(); renderTaskListToDOM();
return tasksToAdd.join('", "'); return {
task: tasksToAdd.join('", "'),
tasksFailedToAdd: tasksFailedToAdd.join('", "') || "",
};
} }
tasks[username].todos.push({ text: task, done: false }); tasks[username].todos.push({ text: task, done: false });
localStorage.setItem(`tasks`, JSON.stringify(tasks)); localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM(); renderTaskListToDOM();
return task; return {
task: task,
tasksFailedToAdd: "",
};
} }
// 0: user has no tasks // 0: user has no tasks
@ -206,17 +232,84 @@ function addTask(username, userColor, task) {
// removed task: success // removed task: success
function removeTask(username, task) { function removeTask(username, task) {
const tasks = JSON.parse(localStorage.tasks); const tasks = JSON.parse(localStorage.tasks);
const incompleteTasks = tasks[username].todos.filter((t) => !t.done);
if (!tasks[username] || tasks[username].todos.length === 0) { if (!tasks[username] || tasks[username].todos.length === 0) {
return 0; return 0;
} }
// match regex: integers separated by space e.g. '1 2 3 4'
if (task.match(/^(\d+ )*\d+$/)) {
// insert commas between integers
task = task.replace(/(\d+)/g, "$1,");
// remove trailing comma
task = task.slice(0, -1);
}
let removedTaskIndex = [];
let tasksRemoved = [];
let tasksFailedToRemove = [];
// check if there's a comma in the task (multiple tasks)
if (task.includes(",")) {
let tasksToRemove = task.split(",").map((t) => t.trim());
for (const t of tasksToRemove) {
let index = tasks[username].todos.findIndex(
(task) => task.text.toLowerCase() === t.toLowerCase()
);
if (index === -1) {
if (isInt(t)) {
index = parseInt(t) - 1; // ACTUAL INDEX
} else if (incompleteTasks.length) {
index = tasks[username].todos.findIndex((t) => !t.done);
tasksRemoved.push(tasks[username].todos[index].text);
removedTaskIndex.push(index);
} else {
tasksFailedToRemove.push(t);
continue;
}
if (index < 0 || index > tasks[username].todos.length - 1) {
tasksFailedToRemove.push(t);
continue;
} else {
tasksRemoved.push(tasks[username].todos[index].text);
removedTaskIndex.push(index);
}
} else {
tasksRemoved.push(tasks[username].todos[index].text);
removedTaskIndex.push(index);
}
}
if (tasksRemoved.length === 0) {
return 1;
}
// sort removedTaskIndex in descending order
removedTaskIndex.sort((a, b) => b - a);
// remove tasks from tasks array
for (const index of removedTaskIndex) {
tasks[username].todos.splice(index, 1);
}
localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM();
return {
removedTasks: tasksRemoved.join('", "'),
failedTasks: tasksFailedToRemove.join('", "'),
};
} else {
let index = tasks[username].todos.findIndex( let index = tasks[username].todos.findIndex(
(t) => t.text.toLowerCase() === task.toLowerCase() (t) => t.text.toLowerCase() === task.toLowerCase()
); );
if (index === -1) { if (index === -1) {
if (isInt(task)) { if (isInt(task)) {
index = parseInt(task) - 1; // ACTUAL INDEX index = parseInt(task) - 1; // ACTUAL INDEX
} else if (tasks[username].todos.length === 1) { } else if (incompleteTasks.length) {
index = 0; index = tasks[username].todos.findIndex((t) => !t.done);
} else { } else {
return 1; return 1;
} }
@ -225,13 +318,17 @@ function removeTask(username, task) {
return 1; return 1;
} }
} }
let removedTask = tasks[username].todos[index].text;
task = tasks[username].todos[index].text;
tasks[username].todos.splice(index, 1); tasks[username].todos.splice(index, 1);
localStorage.setItem(`tasks`, JSON.stringify(tasks)); localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM(); renderTaskListToDOM();
return {
return removedTask; removedTasks: task,
failedTasks: "",
};
}
} }
// function to determine if string is integer // function to determine if string is integer
@ -245,7 +342,7 @@ function isInt(value) {
// 0: user has no tasks // 0: user has no tasks
// 1: success // 1: success
function markOwnTaskDone(username) { function clearOwnDoneTasks(username) {
const tasks = JSON.parse(localStorage.tasks); const tasks = JSON.parse(localStorage.tasks);
if (!tasks[username] || tasks[username].todos.length === 0) { if (!tasks[username] || tasks[username].todos.length === 0) {
@ -268,25 +365,75 @@ function markOwnTaskDone(username) {
// task: succcess // task: succcess
function markTaskDone(username, task) { function markTaskDone(username, task) {
const tasks = JSON.parse(localStorage.tasks); const tasks = JSON.parse(localStorage.tasks);
const incompleteTasks = tasks[username].todos.filter((t) => !t.done);
// user does not have any tasks
if (!tasks[username] || tasks[username].todos.length === 0) { if (!tasks[username] || tasks[username].todos.length === 0) {
return 0; return 0;
} }
// match regex: integers separated by space e.g. '1 2 3 4'
if (task.match(/^(\d+ )*\d+$/)) {
// insert commas between integers
task = task.replace(/(\d+)/g, "$1,");
// remove trailing comma
task = task.slice(0, -1);
}
let tasksMarkedComplete = [];
let tasksFailedToComplete = [];
// check if there's a comma in the task (multiple tasks)
if (task.includes(",")) {
let tasksToMarkDone = task.split(",").map((t) => t.trim());
for (const t of tasksToMarkDone) {
let index = tasks[username].todos.findIndex(
(task) => task.text.toLowerCase() === t.toLowerCase()
);
if (index === -1) {
if (isInt(t)) {
index = parseInt(t) - 1; // ACTUAL INDEX
} else if (incompleteTasks.length) {
index = tasks[username].todos.findIndex((t) => !t.done);
tasksMarkedComplete.push(tasks[username].todos[index].text);
} else {
tasksFailedToComplete.push(t);
continue;
}
if (index < 0 || index > tasks[username].todos.length - 1) {
tasksFailedToComplete.push(t);
continue;
} else {
tasksMarkedComplete.push(tasks[username].todos[index].text);
}
} else {
tasksMarkedComplete.push(tasks[username].todos[index].text);
}
tasks[username].todos[index].done = true;
}
if (tasksMarkedComplete.length === 0) {
return 1;
}
localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM();
return {
markedTasks: tasksMarkedComplete.join('", "'),
failedTasks: tasksFailedToComplete.join('", "'),
};
} else {
let index = tasks[username].todos.findIndex( let index = tasks[username].todos.findIndex(
(t) => t.text.toLowerCase() === task.toLowerCase() (t) => t.text.toLowerCase() === task.toLowerCase()
); );
// filter by t.done is false
let incompleteTaskCount = tasks[username].todos.filter(
(t) => !t.done
).length;
if (incompleteTaskCount === 1) {
index = tasks[username].todos.findIndex((t) => !t.done);
}
if (index === -1) { if (index === -1) {
if (isInt(task)) { if (isInt(task)) {
index = parseInt(task) - 1; // ACTUAL INDEX index = parseInt(task) - 1; // ACTUAL INDEX
} else if (incompleteTasks.length) {
index = tasks[username].todos.findIndex((t) => !t.done);
} else { } else {
return 1; return 1;
} }
@ -296,14 +443,15 @@ function markTaskDone(username, task) {
} }
} }
let completedTask = tasks[username].todos[index].text; task = tasks[username].todos[index].text;
tasks[username].todos[index].done = true; tasks[username].todos[index].done = true;
localStorage.setItem(`tasks`, JSON.stringify(tasks)); localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM(); renderTaskListToDOM();
return {
return completedTask; markedTasks: task,
failedTasks: "",
};
}
} }
// 0: user has no tasks // 0: user has no tasks
@ -406,13 +554,7 @@ function incompleteTasksCount(username) {
if (!tasks[username]) { if (!tasks[username]) {
return 0; return 0;
} }
let count = 0; return tasks[username].todos.filter((t) => !t.done).length;
for (const task of tasks[username].todos) {
if (!task.done) {
count++;
}
}
return count;
} }
function clearUserTasks(username) { function clearUserTasks(username) {
@ -421,6 +563,7 @@ function clearUserTasks(username) {
return; return;
} }
tasks[username].todos = []; tasks[username].todos = [];
localStorage.setItem(`tasks`, JSON.stringify(tasks)); localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM(); renderTaskListToDOM();
} }
@ -430,16 +573,22 @@ function clearAllDoneTasks() {
for (const user in tasks) { for (const user in tasks) {
tasks[user].todos = tasks[user].todos.filter((t) => !t.done); tasks[user].todos = tasks[user].todos.filter((t) => !t.done);
} }
cancelAnimation();
scrolling = false;
checkToAnimate();
localStorage.setItem(`tasks`, JSON.stringify(tasks)); localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM(); renderTaskListToDOM();
} }
function clearAllTasks() { function clearAllTasks() {
resetDB(); resetDB();
cancelAnimation();
scrolling = false;
checkToAnimate();
renderTaskListToDOM(); renderTaskListToDOM();
} }
function smutOnly(streamer) { function clearAllExceptStreamer(streamer) {
// clear all tasks except for broadcasters // clear all tasks except for broadcasters
const tasks = JSON.parse(localStorage.tasks); const tasks = JSON.parse(localStorage.tasks);
for (const user in tasks) { for (const user in tasks) {
@ -449,7 +598,13 @@ function smutOnly(streamer) {
} }
localStorage.setItem(`tasks`, JSON.stringify(tasks)); localStorage.setItem(`tasks`, JSON.stringify(tasks));
clearAllDoneTasks(); clearAllDoneTasks();
cancelAnimation();
scrolling = false;
checkToAnimate();
renderTaskListToDOM(); renderTaskListToDOM();
} }
@ -522,30 +677,30 @@ function tests1() {
let listOfStreamers = [ let listOfStreamers = [
`cloudydayzzz`, `cloudydayzzz`,
`berryspace`, `berryspace`,
`MohFocus`, // `MohFocus`,
`xeno_hiraeth`, // `xeno_hiraeth`,
`euphie___`, // `euphie___`,
`unknownnie`, // `unknownnie`,
`theyolotato`, // `theyolotato`,
`charliosaurus`, // `charliosaurus`,
`jutstreams`, // `jutstreams`,
`mikewhatwhere`, // `mikewhatwhere`,
`studypaws`, // `studypaws`,
`pcc_lanezzz`, // `pcc_lanezzz`,
`workwithjandj`, // `workwithjandj`,
`studylena`, // `studylena`,
]; ];
for (let i = 0; i < listOfStreamers.length; i++) { for (let i = 0; i < listOfStreamers.length; i++) {
addTask(listOfStreamers[i], "#ffc0cb", `task ${i + 1}`); addTask(
addTask(listOfStreamers[i], "#ffc0cb", `another task ${i + 1}`); listOfStreamers[i],
"#ffc0cb",
`task 1, task 2, task 3, task 4, task 5`
);
markTaskDone(listOfStreamers[i], `1, 2, 3, 4, 5`);
} }
} }
function tests2() {
smutOnly("theyolotato");
}
async function checkToAnimate() { async function checkToAnimate() {
// compare task container height and task wrapper height // compare task container height and task wrapper height
@ -580,11 +735,11 @@ async function checkToAnimate() {
easing: "linear", easing: "linear",
}; };
let primaryAnimation = document primaryAnimation = document
.querySelector(".primary") .querySelector(".primary")
.animate(primaryKeyFrames, options); .animate(primaryKeyFrames, options);
let secondaryAnimation = document secondaryAnimation = document
.querySelector(".secondary") .querySelector(".secondary")
.animate(secondaryKeyFrames, options); .animate(secondaryKeyFrames, options);
@ -598,20 +753,22 @@ async function checkToAnimate() {
scrolling = false; scrolling = false;
checkToAnimate(); checkToAnimate();
} }
} else if (!scrolling) { } else if (scrolling) {
document.querySelector(".secondary").style.display = "none"; document.querySelector(".secondary").style.display = "none";
// cancel animations // cancel animations
document cancelAnimation();
.querySelector(".task-container")
.getAnimations()
.forEach((a) => {
a.cancel();
});
scrolling = false; scrolling = false;
} }
} }
function cancelAnimation() {
if (primaryAnimation && secondaryAnimation) {
primaryAnimation.cancel();
secondaryAnimation.cancel();
}
}
(function () { (function () {
setupDB(); setupDB();
importStyles(); importStyles();