version 2.3

This commit is contained in:
liyunze 2024-05-25 10:07:17 +08:00
parent 81c350cf00
commit 24d58867c9
4 changed files with 298 additions and 59 deletions

View file

@ -9,6 +9,8 @@ const configs = (function () {
pointsName: "points", // string pointsName: "points", // string
pointsPerTask: 10, // integer pointsPerTask: 10, // integer
taskSeparator: [";", ","], // array of strings taskSeparator: [";", ","], // array of strings
openQuote: '"', // string
closeQuote: '"', // string
testTasks: false, // true or false testTasks: false, // true or false
headerGoogleFont: true, // true: use google font, false: use system font headerGoogleFont: true, // true: use google font, false: use system font
taskGoogleFont: true, // true: use google font, false: use system font taskGoogleFont: true, // true: use google font, false: use system font
@ -303,22 +305,22 @@ const configs = (function () {
const responses = { const responses = {
// Responses related to task addition // Responses related to task addition
taskAdded: 'The {taskName}(s) "{task}" has been added, {user}!', taskAdded: "The {taskName}(s) {task} has been added, {user}!",
noTaskAdded: noTaskAdded:
"Looks like you already hit the limit of incomplete {taskName}s, {user}", "Looks like you already hit the limit of incomplete {taskName}s, {user}",
noTaskContent: noTaskContent:
"Try using !task the-{taskName}-you-are-working-on {user}", "Try using !task the-{taskName}-you-are-working-on {user}",
duplicateTask: duplicateTask:
"Looks like you already have the {taskName} '{message}' up there {user}!", "Looks like you already have the {taskName} {message} up there {user}!",
taskEdited: taskEdited:
'{taskName} "{originalTask}" has been edited to "{task}" successfully, {user}', '{taskName} "{originalTask}" has been edited to {task} successfully, {user}',
noTaskEdit: "Try doing !edit [index] [new task] {user}", noTaskEdit: "Try doing !edit [index] [new task] {user}",
nowTask: nowTask:
'{taskName} "{task}" is now the task you are working on, {user}!', "{taskName} {task} is now the task you are working on, {user}!",
// Grouped by task progression responses // Grouped by task progression responses
taskNext: taskNext:
"Good job on finishing the task '{oldTask}'! Now moving onto '{newTask}', {user}!", "Good job on finishing the task {oldTask}! Now moving onto {newTask}, {user}!",
nextNoContent: "Try using !next the-task-you-want-to-do-next {user}", nextNoContent: "Try using !next the-task-you-want-to-do-next {user}",
taskNextFailed: taskNextFailed:
"Unable to perform command with multiple incomplete {taskName}s, {user}!", "Unable to perform command with multiple incomplete {taskName}s, {user}!",
@ -327,7 +329,7 @@ const configs = (function () {
clearedMyDone: clearedMyDone:
"All of your completed {taskName}s have been cleared, {user}!", "All of your completed {taskName}s have been cleared, {user}!",
taskDeleted: taskDeleted:
'{taskName}(s) "{task}" has been deleted successfully, {user}', "{taskName}(s) {task} has been deleted successfully, {user}",
specifyTaskIndex: specifyTaskIndex:
"Try specifying the index of the incomplete {taskName}(s) {user}", "Try specifying the index of the incomplete {taskName}(s) {user}",
clearTasksExceptBroadcaster: clearTasksExceptBroadcaster:
@ -338,11 +340,11 @@ const configs = (function () {
// Grouped by task completion responses // Grouped by task completion responses
taskFinished: taskFinished:
'Good job on finishing the {taskName}(s) "{task}", {user}! You have earned {pointCount} {pointName} and completed {doneCount} {taskName}(s) so far!', "Good job on finishing the {taskName}(s) {task}, {user}! You have earned {pointCount} {pointName} and completed {doneCount} {taskName}(s) so far!",
allTasksFinished: allTasksFinished:
"Good job on finishing all your {taskName}s, {user}! You have completed {doneCount} {taskName}(s) so far!", "Good job on finishing all your {taskName}s, {user}! You have completed {doneCount} {taskName}(s) so far!",
taskUnfinished: taskUnfinished:
'{taskName}(s) "{task}" has been unmarked as done, {user}!', "{taskName}(s) {task} has been unmarked as done, {user}!",
taskAlreadyFinished: taskAlreadyFinished:
"Looks like you already finished that {taskName} {user}", "Looks like you already finished that {taskName} {user}",
@ -354,7 +356,7 @@ const configs = (function () {
onlyOneFocus: "You can only focus one task at a time {user}!", onlyOneFocus: "You can only focus one task at a time {user}!",
specifyFocusTask: specifyFocusTask:
"Try specifying an incomplete {taskName} to focus {user}!", "Try specifying an incomplete {taskName} to focus {user}!",
taskFocused: 'Task "{task}" has been focused, {user}!', taskFocused: "Task {task} has been focused, {user}!",
// Grouped by task existence responses // Grouped by task existence responses
noTask: "Looks like you don't have a task up there {user}", noTask: "Looks like you don't have a task up there {user}",

View file

@ -5,15 +5,17 @@ const defaultConfigs = (function () {
enableLimit: false, // true or false enableLimit: false, // true or false
limit: 10, // integer limit: 10, // integer
automaticDoneIndex: false, // true or false - Automatically assume first unfinished task is complete automaticDoneIndex: false, // true or false - Automatically assume first unfinished task is complete
taskName: "task", // string taskName: "task", // string (singular)
pointsName: "points", // string pointsName: "points", // string
pointsPerTask: 10, // integer pointsPerTask: 10, // integer
taskSeparator: [";", ","], // array of strings taskSeparator: [";", ","], // array of strings
openQuote: '"', // string
closeQuote: '"', // string
testTasks: false, // true or false testTasks: false, // true or false
headerGoogleFont: true, // true: use google font, false: use system font headerGoogleFont: true, // true: use google font, false: use system font
taskGoogleFont: true, // true: use google font, false: use system font taskGoogleFont: true, // true: use google font, false: use system font
displayTaskCount: true, // true or false displayTaskCount: true, // true or false
enableTaskMaster: false, // true or false enableTaskMaster: true, // true or false
}; };
const animation = { const animation = {
@ -303,31 +305,31 @@ const defaultConfigs = (function () {
const responses = { const responses = {
// Responses related to task addition // Responses related to task addition
taskAdded: 'The {taskName}(s) "{task}" has been added, {user}!', taskAdded: "The {taskName}(s) {task} has been added, {user}!",
noTaskAdded: noTaskAdded:
"Looks like you already hit the limit of incomplete {taskName}s, {user}", "Looks like you already hit the limit of incomplete {taskName}s, {user}",
noTaskContent: noTaskContent:
"Try using !task the-{taskName}-you-are-working-on {user}", "Try using !task the-{taskName}-you-are-working-on {user}",
duplicateTask: duplicateTask:
"Looks like you already have the {taskName} '{message}' up there {user}!", "Looks like you already have that {taskName} up there {user}!",
taskEdited: taskEdited:
'{taskName} "{originalTask}" has been edited to "{task}" successfully, {user}', '{taskName} "{originalTask}" has been edited to {task} successfully, {user}',
noTaskEdit: "Try doing !edit [index] [new task] {user}", noTaskEdit: "Try doing !edit [index] [new task] {user}",
nowTask: nowTask:
'{taskName} "{task}" is now the task you are working on, {user}!', "{taskName} {task} is now the task you are working on, {user}!",
// Grouped by task progression responses // Grouped by task progression responses
taskNext: taskNext:
"Good job on finishing the task '{oldTask}'! Now moving onto '{newTask}', {user}!", "Good job on finishing the task {oldTask}! Now moving onto {newTask}, {user}!",
nextNoContent: "Try using !next the-task-you-want-to-do-next {user}", nextNoContent: "Try using !next the-task-you-want-to-do-next {user}",
taskNextFailed: taskNextFailed:
"Unable to perform command with multiple incomplete tasks, {user}!", "Unable to perform command with multiple incomplete {taskName}s, {user}!",
// Grouped by task deletion responses // Grouped by task deletion responses
clearedMyDone: clearedMyDone:
"All of your completed {taskName}s have been cleared, {user}!", "All of your completed {taskName}s have been cleared, {user}!",
taskDeleted: taskDeleted:
'{taskName}(s) "{task}" has been deleted successfully, {user}', "{taskName}(s) {task} has been deleted successfully, {user}",
specifyTaskIndex: specifyTaskIndex:
"Try specifying the index of the incomplete {taskName}(s) {user}", "Try specifying the index of the incomplete {taskName}(s) {user}",
clearTasksExceptBroadcaster: clearTasksExceptBroadcaster:
@ -335,15 +337,14 @@ const defaultConfigs = (function () {
clearedTasks: "All {taskName}s have been cleared, {user}!", clearedTasks: "All {taskName}s have been cleared, {user}!",
adminDeleteTasks: "All of {mentioned}'s {taskName}s have been deleted", adminDeleteTasks: "All of {mentioned}'s {taskName}s have been deleted",
clearedAll: "All {taskName}s and points have been cleared, {user}!", clearedAll: "All {taskName}s and points have been cleared, {user}!",
clearedDone: "All completed {taskName}s have been cleared, {user}!",
// Grouped by task completion responses // Grouped by task completion responses
taskFinished: taskFinished:
'Good job on finishing the {taskName}(s) "{task}", {user}! You have earned {pointCount} {pointName} and completed {doneCount} {taskName}(s) so far!', "Good job on finishing the {taskName}(s) {task}, {user}! You have earned {pointCount} {pointName} and completed {doneCount} {taskName}(s) so far!",
allTasksFinished: allTasksFinished:
"Good job on finishing all your {taskName}s, {user}! You have completed {doneCount} {taskName}(s) so far!", "Good job on finishing all your {taskName}s, {user}! You have completed {doneCount} {taskName}(s) so far!",
taskUnfinished: taskUnfinished:
'{taskName}(s) "{task}" has been unmarked as done, {user}!', "{taskName}(s) {task} has been unmarked as done, {user}!",
taskAlreadyFinished: taskAlreadyFinished:
"Looks like you already finished that {taskName} {user}", "Looks like you already finished that {taskName} {user}",
@ -355,7 +356,7 @@ const defaultConfigs = (function () {
onlyOneFocus: "You can only focus one task at a time {user}!", onlyOneFocus: "You can only focus one task at a time {user}!",
specifyFocusTask: specifyFocusTask:
"Try specifying an incomplete {taskName} to focus {user}!", "Try specifying an incomplete {taskName} to focus {user}!",
taskFocused: 'Task "{task}" has been focused, {user}!', taskFocused: "Task {task} has been focused, {user}!",
// Grouped by task existence responses // Grouped by task existence responses
noTask: "Looks like you don't have a task up there {user}", noTask: "Looks like you don't have a task up there {user}",
@ -379,7 +380,7 @@ const defaultConfigs = (function () {
"Everyone has completed {doneCount} {taskName}(s) so far, {user}!", "Everyone has completed {doneCount} {taskName}(s) so far, {user}!",
noCountAll: "Looks like no one has completed a {taskName} yet {user}", noCountAll: "Looks like no one has completed a {taskName} yet {user}",
leaderboard: "Leaderboard: {leaderboard}", leaderboard: "Leaderboard: {leaderboard}",
setUserTaskCount: "{mentioned} now has {taskCount} {taskName}s!", setUserTaskCount: "{mentioned} now has {taskCount} tasks!",
// Grouped by taskmaster-related responses // Grouped by taskmaster-related responses
taskMaster: "{user} Task Master: {taskMaster} [{taskMasterCount}]", taskMaster: "{user} Task Master: {taskMaster} [{taskMasterCount}]",

View file

@ -1,4 +1,6 @@
var commands = configs.commands; var commands = configs.commands;
var openQuote = getSetting("openQuote");
var closeQuote = getSetting("closeQuote");
async function processCommand(user, command, message, flags, extra) { async function processCommand(user, command, message, flags, extra) {
params = { params = {
@ -17,7 +19,7 @@ async function processCommand(user, command, message, flags, extra) {
} }
let addedResponse = getResponse("taskAdded"); let addedResponse = getResponse("taskAdded");
params.task = addRequest.body.task; params.task = `${openQuote}${addRequest.body.task}${closeQuote}`;
if (addRequest.body.tasksFailedToAdd !== "") { if (addRequest.body.tasksFailedToAdd !== "") {
addedResponse += ` | Failed to add task(s): "${addRequest.body.tasksFailedToAdd}"`; addedResponse += ` | Failed to add task(s): "${addRequest.body.tasksFailedToAdd}"`;
@ -35,8 +37,8 @@ async function processCommand(user, command, message, flags, extra) {
let originalTask = editRequest.body.originalTask; let originalTask = editRequest.body.originalTask;
let newTask = editRequest.body.newTask; let newTask = editRequest.body.newTask;
params.task = newTask; params.task = `${openQuote}${newTask}${closeQuote}`;
params.originalTask = originalTask; params.originalTask = `${openQuote}${originalTask}${closeQuote}`;
respond(getResponse("taskEdited"), params); respond(getResponse("taskEdited"), params);
} else if (getCommand("deleteTaskCommands").includes(command)) { } else if (getCommand("deleteTaskCommands").includes(command)) {
@ -48,13 +50,13 @@ async function processCommand(user, command, message, flags, extra) {
} }
let deletedResponse = getResponse("taskDeleted"); let deletedResponse = getResponse("taskDeleted");
let removedTasks = removeRequest.body.removedTasks; let removedTasks = `${openQuote}${removeRequest.body.removedTasks}${closeQuote}`;
let failedTasks = removeRequest.body.failedTasks; let failedTasks = removeRequest.body.failedTasks;
params.task = removedTasks; params.task = removedTasks;
if (failedTasks !== "") { if (failedTasks !== "") {
deletedResponse += ` | Failed to delete task(s): "${failedTasks}"`; deletedResponse += ` | Failed to delete task(s): ${openQuote}${failedTasks}${closeQuote}`;
} }
respond(deletedResponse, params); respond(deletedResponse, params);
@ -69,6 +71,15 @@ async function processCommand(user, command, message, flags, extra) {
let finishedAllResponse = getResponse("allTasksFinished"); let finishedAllResponse = getResponse("allTasksFinished");
params.doneCount = await completedTasksCount(user); params.doneCount = await completedTasksCount(user);
finishedAllResponse = finishedAllResponse.replaceAll(
"{pointName}",
getSetting("pointsName")
);
finishedAllResponse = finishedAllResponse.replaceAll(
"{taskName}",
getSetting("taskName")
);
respond(finishedAllResponse, params); respond(finishedAllResponse, params);
return; return;
@ -82,7 +93,7 @@ async function processCommand(user, command, message, flags, extra) {
} }
let finishedResponse = getResponse("taskFinished"); let finishedResponse = getResponse("taskFinished");
params.task = finishRequest.body.markedTasks; params.task = `${openQuote}${finishRequest.body.markedTasks}${closeQuote}`;
params.doneCount = await completedTasksCount(user); params.doneCount = await completedTasksCount(user);
params.pointCount = params.pointCount =
finishRequest.body.markedTasksCount * getSetting("pointsPerTask"); finishRequest.body.markedTasksCount * getSetting("pointsPerTask");
@ -113,7 +124,7 @@ async function processCommand(user, command, message, flags, extra) {
// task unfinished // task unfinished
let unfinishedResponse = getResponse("taskUnfinished"); let unfinishedResponse = getResponse("taskUnfinished");
params.task = unfinishRequest.body.markedTasks; params.task = `${openQuote}${unfinishRequest.body.unmarkedTasks}${closeQuote}`;
if (unfinishRequest.body.failedTasks !== "") { if (unfinishRequest.body.failedTasks !== "") {
unfinishedResponse += ` | Failed to unfinish task(s): "${unfinishRequest.body.failedTasks}"`; unfinishedResponse += ` | Failed to unfinish task(s): "${unfinishRequest.body.failedTasks}"`;
@ -124,15 +135,15 @@ async function processCommand(user, command, message, flags, extra) {
let nextRequest = await nextTask(user, message); let nextRequest = await nextTask(user, message);
if (nextRequest.status !== 200) { if (nextRequest.status !== 200) {
respond(nextRequest.body.error, params); await respond(nextRequest.body.error, params);
return; return;
} }
// task next // task next
let nextResponse = getResponse("taskNext"); let nextResponse = getResponse("taskNext");
params.oldTask = nextRequest.body.oldTask; params.oldTask = `${openQuote}${nextRequest.body.oldTask}${closeQuote}`;
params.newTask = nextRequest.body.newTask; params.newTask = `${openQuote}${nextRequest.body.newTask}${closeQuote}`;
respond(nextResponse, params); respond(nextResponse, params);
} else if (getCommand("nowTaskCommands").includes(command)) { } else if (getCommand("nowTaskCommands").includes(command)) {
@ -146,7 +157,7 @@ async function processCommand(user, command, message, flags, extra) {
// task now // task now
let nowResponse = getResponse("nowTask"); let nowResponse = getResponse("nowTask");
params.task = nowRequest.body.task; params.task = `${openQuote}${nowRequest.body.task}${closeQuote}`;
respond(nowResponse, params); respond(nowResponse, params);
} else if (getCommand("focusTaskCommands").includes(command)) { } else if (getCommand("focusTaskCommands").includes(command)) {
@ -160,9 +171,9 @@ async function processCommand(user, command, message, flags, extra) {
// task focused // task focused
let focusedResponse = getResponse("taskFocused"); let focusedResponse = getResponse("taskFocused");
params.task = focusRequest.body.focusedTask; params.task = `${openQuote}${focusRequest.body.focusedTask}${closeQuote}`;
respond(focusedResponse, params); await respond(focusedResponse, params);
} else if (getCommand("unfocusTaskCommands").includes(command)) { } else if (getCommand("unfocusTaskCommands").includes(command)) {
let unfocusRequest = await unfocusTask(user); let unfocusRequest = await unfocusTask(user);
@ -287,7 +298,7 @@ async function processCommand(user, command, message, flags, extra) {
} }
await clearMemory(); await clearMemory();
await clearAllExceptStreamer(configs.StreamerUsernames); await clearAllExceptStreamer(auth.channel);
respond(getResponse("clearTasksExceptBroadcaster"), params); respond(getResponse("clearTasksExceptBroadcaster"), params);
} else if (getCommand("adminClearTasksCommands").includes(command)) { } else if (getCommand("adminClearTasksCommands").includes(command)) {
if (!isStreamer(flags)) { if (!isStreamer(flags)) {

View file

@ -23,6 +23,8 @@ DB structure:
const styles = configs.styles; const styles = configs.styles;
const scrollSpeed = configs.animation.scrollSpeed; const scrollSpeed = configs.animation.scrollSpeed;
const responses = configs.responses; const responses = configs.responses;
var openQuote = getSetting("openQuote");
var closeQuote = getSetting("closeQuote");
let scrolling = false; let scrolling = false;
let primaryAnimation, secondaryAnimation; let primaryAnimation, secondaryAnimation;
const taskSeparator = getSetting("taskSeparator"); const taskSeparator = getSetting("taskSeparator");
@ -809,7 +811,8 @@ async function addTask(username, userColor, task) {
const taskExists = tasks[username].todos.find( const taskExists = tasks[username].todos.find(
(t) => t.text.toLowerCase() === task.toLowerCase() (t) => t.text.toLowerCase() === task.toLowerCase()
); );
const taskIsInvalid = !task || !task.trim() || task.toLowerCase() === "all"; const taskIsInvalid =
!task || !task.trim() || task.toLowerCase() === "all" || isInt(task);
const userHasReachedTaskLimit = const userHasReachedTaskLimit =
incompleteTasksCount(username) >= getSetting("limit") && incompleteTasksCount(username) >= getSetting("limit") &&
getSetting("enableLimit"); getSetting("enableLimit");
@ -845,7 +848,11 @@ async function addTask(username, userColor, task) {
const tasksFailedToAdd = []; const tasksFailedToAdd = [];
tasksToAdd.forEach((t) => { tasksToAdd.forEach((t) => {
if (t && !tasks[username].todos.find((task) => task.text === t)) { if (
t &&
!tasks[username].todos.find((task) => task.text === t) &&
!isInt(t)
) {
tasks[username].todos.push({ text: t, done: false, focus: false }); tasks[username].todos.push({ text: t, done: false, focus: false });
taskListMemory.totalTaskCount++; taskListMemory.totalTaskCount++;
} else { } else {
@ -861,8 +868,9 @@ async function addTask(username, userColor, task) {
return { return {
status: 200, status: 200,
body: { body: {
task: tasksToAdd.join('", "'), task: tasksToAdd.join(`${closeQuote}, ${openQuote}`),
tasksFailedToAdd: tasksFailedToAdd.join('", "') || "", tasksFailedToAdd:
tasksFailedToAdd.join(`${closeQuote}, ${openQuote}`) || "",
}, },
}; };
} }
@ -1105,6 +1113,14 @@ async function focusTask(username, task) {
); );
} }
// if task is already completed, return 1
if (tasks[username].todos[index].done) {
return createErrorResponse(
`@${username} task is already completed`,
responses.specifyTaskIndex
);
}
// set all tasks to unfocused // set all tasks to unfocused
tasks[username].todos.forEach((task) => { tasks[username].todos.forEach((task) => {
task.focus = false; task.focus = false;
@ -1267,8 +1283,10 @@ async function removeTask(username, task) {
return { return {
status: 200, status: 200,
body: { body: {
removedTasks: tasksRemoved.join('", "'), removedTasks: tasksRemoved.join(`${closeQuote}, ${openQuote}`),
failedTasks: tasksFailedToRemove.join('", "'), failedTasks: tasksFailedToRemove.join(
`${closeQuote}, ${openQuote}`
),
}, },
}; };
} else { } else {
@ -1318,6 +1336,82 @@ async function removeTask(username, task) {
} }
} }
async function getFocusedTask(username) {
const tasks = await DBHandler.get("tasks");
if (!tasks[username] || tasks[username].todos.length === 0) {
return {
status: 0,
body: {
"error message": `@${username} has no tasks`,
error: getResponse("noTask"),
},
};
}
let focusedTask = tasks[username].todos.find((t) => t.focus);
if (!focusedTask) {
return {
status: 0,
body: {
"error message": `@${username} has no focused task`,
error: getResponse("noFocusedTask"),
},
};
}
return {
status: 200,
body: {
focusedTask: focusedTask.text,
},
};
}
async function checkIfTaskExists(username, task) {
const tasks = await DBHandler.get("tasks");
if (!tasks[username] || tasks[username].todos.length === 0) {
return {
status: 0,
body: {
"error message": `@${username} has no tasks`,
error: getResponse("noTask"),
},
};
}
let taskExistsBasedOnText = tasks[username].todos.find(
(t) => t.text.toLowerCase() === task.toLowerCase()
)
? true
: false;
// check if task exists based on index, has to be incomplete
let taskExistsBasedOnIndex = false;
if (tasks[username]) {
taskExistsBasedOnIndex =
isInt(task) &&
parseInt(task) > 0 &&
parseInt(task) <= tasks[username].todos.length;
}
return {
text: taskExistsBasedOnText,
index: taskExistsBasedOnIndex,
};
}
/**
* This function marks the current task of a user as complete and adds a new task to the user's task list.
*
* @param {string} username - The name of the user who is completing the current task and adding a new one.
* @param {string} task - The text description of the new task to be added.
*
* @returns {Object} - An object containing the status of the operation and a body with either the old and new task or an error message.
*/
/** /**
* This function marks the current task of a user as complete and adds a new task to the user's task list. * This function marks the current task of a user as complete and adds a new task to the user's task list.
* *
@ -1333,7 +1427,7 @@ async function nextTask(username, task) {
status: 0, status: 0,
body: { body: {
"error message": `@${username} has no tasks`, "error message": `@${username} has no tasks`,
error: responses.noTask, error: getResponse("noTask"),
}, },
}; };
} }
@ -1343,19 +1437,128 @@ async function nextTask(username, task) {
status: 1, status: 1,
body: { body: {
"error message": `@${username} empty task`, "error message": `@${username} empty task`,
error: responses.nextNoContent, error: getResponse("nextNoContent"),
}, },
}; };
} }
const incompleteTasks = tasks[username].todos.filter((t) => !t.done); const incompleteTasks = tasks[username].todos.filter((t) => !t.done);
if (incompleteTasks.length !== 1) { const taskExists = await checkIfTaskExists(username, task);
const textTaskExists = taskExists.text;
const indexTaskExists = taskExists.index;
const focusedTaskExists = incompleteTasks.find((t) => t.focus);
// check if there's a focused task
if (!focusedTaskExists && incompleteTasks.length > 1) {
return { return {
status: 0, status: 0,
body: { body: {
"error message": `@${username} has more than one incomplete task`, "error message": `@${username} does not have a focused task`,
error: responses.taskNextFailed, error: getResponse("noFocusedTask"),
},
};
} else if (textTaskExists || indexTaskExists) {
let index = tasks[username].todos.findIndex((t) => t.focus);
let oldTask = tasks[username].todos[index].text;
// if old task is the same as an existing task, return 1
if (textTaskExists) {
if (tasks[username].todos.find((t) => t.text === task)) {
return {
status: 1,
body: {
"error message": `@${username} already has this task`,
error: getResponse("duplicateTask"),
},
};
}
} else {
if (tasks[username].todos[parseInt(task) - 1].done) {
return {
status: 1,
body: {
"error message": `@${username} already finished this task`,
error: getResponse("taskAlreadyFinished"),
},
};
}
}
// mark focused task as complete then focus on the existing task
// mark task as done
tasks[username].todos[index].done = true;
tasks[username].todos[index].focus = false;
let newFocusTask = null;
// focus on the new task
if (textTaskExists) {
let newIndex = tasks[username].todos.findIndex(
(t) => t.text.toLowerCase() === task.toLowerCase()
);
newFocusTask = tasks[username].todos[newIndex];
} else {
newFocusTask = tasks[username].todos[parseInt(task) - 1];
}
newFocusTask.focus = true;
await addDoneCount(username, 1);
await DBHandler.set("tasks", tasks);
if (!scrolling) {
await renderTaskListToDOM();
}
return {
status: 200,
body: {
oldTask: oldTask,
newTask: newFocusTask.text,
},
};
} else if (focusedTaskExists) {
if (!indexTaskExists && isInt(task)) {
return {
status: 1,
body: {
"error message": `@${username} invalid input`,
error: getResponse("specifyTaskIndex"),
},
};
}
// mark the focused task as complete, then add a new task "task"
// find index of focused task
let index = tasks[username].todos.findIndex((t) => t.focus);
let oldTask = tasks[username].todos[index].text;
// mark task as done
tasks[username].todos[index].done = true;
tasks[username].todos[index].focus = false;
// add new task
tasks[username].todos.push({ text: task, done: false, focus: true });
taskListMemory.totalTaskCount++;
await addDoneCount(username, 1);
await DBHandler.set("tasks", tasks);
if (!scrolling) {
await renderTaskListToDOM();
}
return {
status: 200,
body: {
oldTask: oldTask,
newTask: task,
}, },
}; };
} else { } else {
@ -1376,6 +1579,10 @@ async function nextTask(username, task) {
await DBHandler.set("tasks", tasks); await DBHandler.set("tasks", tasks);
if (!scrolling) {
await renderTaskListToDOM();
}
return { return {
status: 200, status: 200,
body: { body: {
@ -1554,8 +1761,12 @@ async function markTaskDone(username, task) {
return { return {
status: 200, status: 200,
body: { body: {
markedTasks: tasksMarkedComplete.join('", "'), markedTasks: tasksMarkedComplete.join(
failedTasks: tasksFailedToComplete.join('", "'), `${closeQuote}, ${openQuote}`
),
failedTasks: tasksFailedToComplete.join(
`${closeQuote}, ${openQuote}`
),
markedTasksCount: tasksMarkedComplete.length, markedTasksCount: tasksMarkedComplete.length,
}, },
}; };
@ -1756,8 +1967,12 @@ async function markTaskUndone(username, task) {
return { return {
status: 200, status: 200,
body: { body: {
markedTasks: tasksMarkedUndone.join('", "'), markedTasks: tasksMarkedUndone.join(
failedTasks: tasksFailedToMarkUndone.join('", "'), `${closeQuote}, ${openQuote}`
),
failedTasks: tasksFailedToMarkUndone.join(
`${closeQuote}, ${openQuote}`
),
}, },
}; };
} else { } else {
@ -1919,17 +2134,27 @@ async function editTask(username, message) {
/** /**
* Checks the tasks of a given user. If the user has tasks, the function returns an object with a status of 200 and a formatted string of the user's tasks. If the user has no tasks, the function returns an object with a status indicating the error and an error message. * Checks the tasks of a given user. If the user has tasks, the function returns an object with a status of 200 and a formatted string of the user's tasks. If the user has no tasks, the function returns an object with a status indicating the error and an error message.
* *
* @param {string} username - The name of the user whose tasks are to be checked. * @param {string} name - The name of the user whose tasks are to be checked.
* @returns {Object} An object with a status and body. The status is 200 if the user has tasks, and the body contains a formatted string of the user's tasks. If the user has no tasks, the status indicates the error and the body contains an error message. * @returns {Object} An object with a status and body. The status is 200 if the user has tasks, and the body contains a formatted string of the user's tasks. If the user has no tasks, the status indicates the error and the body contains an error message.
*/ */
async function checkTasks(username) { async function checkTasks(name) {
const tasks = await DBHandler.get("tasks"); const tasks = await DBHandler.get("tasks");
// Go through keys of tasks, find match of lowercased username // Go through keys of tasks, find match of lowercased username
username = Object.keys(tasks).find( let username = Object.keys(tasks).find(
(user) => user.toLowerCase() === username.toLowerCase() (user) => user.toLowerCase() === name.toLowerCase()
); );
if (!username) {
return {
status: 0,
body: {
"error message": `@${name} has no tasks`,
error: getResponse("noTask"),
},
};
}
if (!tasks[username]) { if (!tasks[username]) {
return { return {
status: 0, status: 0,
@ -1945,7 +2170,7 @@ async function checkTasks(username) {
const completedTasks = tasks[username].todos.filter((t) => t.done); const completedTasks = tasks[username].todos.filter((t) => t.done);
// format incomplete tasks into string: 1. task 1 | 2. task 2 | 3. task 3... // format incomplete tasks into string: 1. task 1 | 2. task 2 | 3. task 3...
let reply = `incomplete {taskName}(s) (${incompleteTasks.length}) : `; let reply = `${name}'s incomplete {taskName}s (${incompleteTasks.length}) : `;
let taskIndex; let taskIndex;
for (let i = 0; i < incompleteTasks.length; i++) { for (let i = 0; i < incompleteTasks.length; i++) {
// get index of task by task name // get index of task by task name
@ -2115,7 +2340,7 @@ async function clearAll() {
* Clears all tasks from the local storage except for those belonging to specified streamer usernames. * Clears all tasks from the local storage except for those belonging to specified streamer usernames.
* After clearing, it also clears all done tasks, cancels any ongoing animation and re-renders the task list to the DOM. * After clearing, it also clears all done tasks, cancels any ongoing animation and re-renders the task list to the DOM.
* *
* @param {string[]} streamerUsernames - An array of streamer usernames whose tasks should not be cleared. * @param {string[]} streamerUsername - An array of streamer usernames whose tasks should not be cleared.
* @returns {Object} An object with a status property indicating the success of the operation (200 for success). * @returns {Object} An object with a status property indicating the success of the operation (200 for success).
*/ */
async function clearAllExceptStreamer(streamerUsername) { async function clearAllExceptStreamer(streamerUsername) {
@ -2124,7 +2349,7 @@ async function clearAllExceptStreamer(streamerUsername) {
for (const user in tasks) { for (const user in tasks) {
if (user.toLowerCase() === "id") continue; if (user.toLowerCase() === "id") continue;
if (user.toLowerCase() !== auth.channel.toLowerCase()) { if (user.toLowerCase() !== streamerUsername.toLowerCase()) {
tasks[user].todos = []; tasks[user].todos = [];
} }
} }