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:40:37 +08:00
parent b5b2d9d7e2
commit b6a31ff1e7
3 changed files with 285 additions and 92 deletions

View file

@ -3,7 +3,7 @@ const configs = (function () {
// settings
const enableLimit = true; // true or false
const limit = 20; // integer
const limit = 5; // integer
// animation
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",
];
// 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
const adminDeleteCommands = [
"!taskadel",
@ -179,14 +187,17 @@ const configs = (function () {
const noTaskAdded =
"Looks like you already hit the limit of incomplete tasks, {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 duplicateTask =
"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 taskFinished = "Good job on finishing the task '{task}', {user}!";
const taskFinished = 'Good job on finishing the task "{task}", {user}!';
const taskEdited =
"Task '{originalTask}' has been edited to '{task}' successfully, {user}";
const noTaskEdit = "Try doing !edit [index] [new task] {user}";
@ -283,6 +294,7 @@ const configs = (function () {
checkCommands,
clearMyDoneCommands,
adminDeleteCommands,
adminClearNotStreamerCommands,
adminClearDoneCommands,
adminClearAllCommands,
additionalCommands,
@ -302,6 +314,7 @@ const configs = (function () {
noTaskA,
notMod,
help,
clearTasksExceptBroadcaster,
adminDeleteTasks,
clearedMyDone,
clearedAll,

View file

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

View file

@ -13,6 +13,7 @@ const settings = configs.settings;
const styles = configs.styles;
const scrollSpeed = configs.animation.scrollSpeed;
let scrolling = false;
let primaryAnimation, secondaryAnimation;
function loadGoogleFont(font) {
WebFont.load({
@ -183,22 +184,47 @@ function addTask(username, userColor, task) {
return 2;
}
let tasksFailedToAdd = [];
// if task has commas
if (task.includes(",")) {
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) {
tasks[username].todos.push({ text: t, done: false });
}
localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM();
return tasksToAdd.join('", "');
return {
task: tasksToAdd.join('", "'),
tasksFailedToAdd: tasksFailedToAdd.join('", "') || "",
};
}
tasks[username].todos.push({ text: task, done: false });
localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM();
return task;
return {
task: task,
tasksFailedToAdd: "",
};
}
// 0: user has no tasks
@ -206,17 +232,84 @@ function addTask(username, userColor, task) {
// removed task: success
function removeTask(username, task) {
const tasks = JSON.parse(localStorage.tasks);
const incompleteTasks = tasks[username].todos.filter((t) => !t.done);
if (!tasks[username] || tasks[username].todos.length === 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(
(t) => t.text.toLowerCase() === task.toLowerCase()
);
if (index === -1) {
if (isInt(task)) {
index = parseInt(task) - 1; // ACTUAL INDEX
} else if (tasks[username].todos.length === 1) {
index = 0;
} else if (incompleteTasks.length) {
index = tasks[username].todos.findIndex((t) => !t.done);
} else {
return 1;
}
@ -225,13 +318,17 @@ function removeTask(username, task) {
return 1;
}
}
let removedTask = tasks[username].todos[index].text;
task = tasks[username].todos[index].text;
tasks[username].todos.splice(index, 1);
localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM();
return removedTask;
return {
removedTasks: task,
failedTasks: "",
};
}
}
// function to determine if string is integer
@ -245,7 +342,7 @@ function isInt(value) {
// 0: user has no tasks
// 1: success
function markOwnTaskDone(username) {
function clearOwnDoneTasks(username) {
const tasks = JSON.parse(localStorage.tasks);
if (!tasks[username] || tasks[username].todos.length === 0) {
@ -268,25 +365,75 @@ function markOwnTaskDone(username) {
// task: succcess
function markTaskDone(username, task) {
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) {
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(
(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 (isInt(task)) {
index = parseInt(task) - 1; // ACTUAL INDEX
} else if (incompleteTasks.length) {
index = tasks[username].todos.findIndex((t) => !t.done);
} else {
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;
localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM();
return completedTask;
return {
markedTasks: task,
failedTasks: "",
};
}
}
// 0: user has no tasks
@ -406,13 +554,7 @@ function incompleteTasksCount(username) {
if (!tasks[username]) {
return 0;
}
let count = 0;
for (const task of tasks[username].todos) {
if (!task.done) {
count++;
}
}
return count;
return tasks[username].todos.filter((t) => !t.done).length;
}
function clearUserTasks(username) {
@ -421,6 +563,7 @@ function clearUserTasks(username) {
return;
}
tasks[username].todos = [];
localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM();
}
@ -430,16 +573,22 @@ function clearAllDoneTasks() {
for (const user in tasks) {
tasks[user].todos = tasks[user].todos.filter((t) => !t.done);
}
cancelAnimation();
scrolling = false;
checkToAnimate();
localStorage.setItem(`tasks`, JSON.stringify(tasks));
renderTaskListToDOM();
}
function clearAllTasks() {
resetDB();
cancelAnimation();
scrolling = false;
checkToAnimate();
renderTaskListToDOM();
}
function smutOnly(streamer) {
function clearAllExceptStreamer(streamer) {
// clear all tasks except for broadcasters
const tasks = JSON.parse(localStorage.tasks);
for (const user in tasks) {
@ -449,7 +598,13 @@ function smutOnly(streamer) {
}
localStorage.setItem(`tasks`, JSON.stringify(tasks));
clearAllDoneTasks();
cancelAnimation();
scrolling = false;
checkToAnimate();
renderTaskListToDOM();
}
@ -522,30 +677,30 @@ function tests1() {
let listOfStreamers = [
`cloudydayzzz`,
`berryspace`,
`MohFocus`,
`xeno_hiraeth`,
`euphie___`,
`unknownnie`,
`theyolotato`,
`charliosaurus`,
`jutstreams`,
`mikewhatwhere`,
`studypaws`,
`pcc_lanezzz`,
`workwithjandj`,
`studylena`,
// `MohFocus`,
// `xeno_hiraeth`,
// `euphie___`,
// `unknownnie`,
// `theyolotato`,
// `charliosaurus`,
// `jutstreams`,
// `mikewhatwhere`,
// `studypaws`,
// `pcc_lanezzz`,
// `workwithjandj`,
// `studylena`,
];
for (let i = 0; i < listOfStreamers.length; i++) {
addTask(listOfStreamers[i], "#ffc0cb", `task ${i + 1}`);
addTask(listOfStreamers[i], "#ffc0cb", `another task ${i + 1}`);
addTask(
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() {
// compare task container height and task wrapper height
@ -580,11 +735,11 @@ async function checkToAnimate() {
easing: "linear",
};
let primaryAnimation = document
primaryAnimation = document
.querySelector(".primary")
.animate(primaryKeyFrames, options);
let secondaryAnimation = document
secondaryAnimation = document
.querySelector(".secondary")
.animate(secondaryKeyFrames, options);
@ -598,22 +753,25 @@ async function checkToAnimate() {
scrolling = false;
checkToAnimate();
}
} else if (!scrolling) {
} else if (scrolling) {
document.querySelector(".secondary").style.display = "none";
// cancel animations
document
.querySelector(".task-container")
.getAnimations()
.forEach((a) => {
a.cancel();
});
cancelAnimation();
scrolling = false;
}
}
function cancelAnimation() {
if (primaryAnimation && secondaryAnimation) {
primaryAnimation.cancel();
secondaryAnimation.cancel();
}
}
(function () {
setupDB();
resetDB();
tests1();
importStyles();
renderTaskListToDOM();
})();