From 9c6a097708c7e50539ec4579066922f4e1a16cee Mon Sep 17 00:00:00 2001 From: Blueberryy <36592509+Blueberryy@users.noreply.github.com> Date: Thu, 29 Jun 2023 21:25:51 +0500 Subject: [PATCH 01/43] russian translation --- src/data/lang/russian.json | 132 +++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/data/lang/russian.json diff --git a/src/data/lang/russian.json b/src/data/lang/russian.json new file mode 100644 index 00000000..148b1534 --- /dev/null +++ b/src/data/lang/russian.json @@ -0,0 +1,132 @@ +{ + "note": "Этот файл содержит почти все сообщения, которые бот посылает пользователям. Если вы хотите изменить сообщения, прочтите эту страницу: https://github.com/HerrEurobeat/steam-comment-service-bot/wiki/How-to-add-custom-messages", + + "updaterautoupdatedisabled": "Вы отключили автоматическое обновление. Хотите ли вы обновить его сейчас?\nЕсли да, пожалуйста, запустите обновление с помощью команды: cmdprefixupdate true", + + "commentcmdusageowner": "«cmdprefixcomment amount/\"all\" id» для запроса количества комментариев (или максимально возможного количества).\nУкажите ID профиля, группы или общего файла (скриншот, иллюстрация или руководство), если вы хотите комментировать не на своем профиле, а где-то ещё.", + "commentcmdusageowner2": "«cmdprefixcomment 1 id». Укажите ID профиля, группы или общего файла (скриншота, иллюстрации или руководства), если вы хотите комментировать не в своём профиле, а где-то ещё.", + "commentcmdusage": "«cmdprefixcomment кол-во/\"all\"» для запроса количества комментариев (или максимально возможного количества) на вашем профиле.", + "commentcmdusage2": "«cmdprefixcomment», чтобы запросить комментарий к своему профилю!", + "commentrequesttoohigh": "Вы можете запросить максимум комментариев maxRequestAmount.\nИспользование команды: commentcmdusage", + "commentinvalidid": "Это не похоже на действительный ID профиля, группы или общего файла (скриншот, иллюстрация или руководство).\nПожалуйста, убедитесь, что вы предоставили либо полную ссылку, либо только пустое значение, либо только ID, указывающий на существующий профиль, группу или общий файл.\n\nИспользование команды: commentcmdusage", + "commentprofileidowneronly": "Указание ID разрешено только для владельцев ботов.\nЕсли вы являетесь владельцем бота, пожалуйста, убедитесь, что вы добавили свой ID в параметр ownerid в config.json.", + "commentmissingnumberofcomments": "Пожалуйста, укажите, сколько комментариев из maxRequestAmount вы хотите запросить.\nИспользование команды: commentcmdusage", + "commentzeroavailableaccs": "Извините, но в настоящее время нет достаточного количества аккаунтов для выполнения вашего запроса. Пожалуйста, подождите waittime и повторите попытку!", + "commentnotenoughavailableaccs": "Извините, но в настоящее время нет достаточного количества аккаунтов для выполнения вашего запроса. Пожалуйста, подождите waittime и повторите попытку или запросите availablenow комментариев.", + "commentnoaccounts": "Извините, но для выполнения этого запроса нет аккаунтов. Пожалуйста, свяжитесь с администратором бота этого экземпляра.\nИспользуйте команду cmdprefixowner, чтобы получить информацию о том, кто управляет этим экземпляром.", + "commentnounlimitedaccs": "Извините, но нет неограниченных аккаунтов, которые необходимы для выполнения этого запроса. Пожалуйста, свяжитесь с администратором бота этого экземпляра.\nИспользуйте команду cmdprefixowner, чтобы получить информацию о том, кто управляет этим экземпляром.", + "commentaddbotaccounts": "Пожалуйста, добавьте эти аккаунты, а затем запросите снова: (ограниченные аккаунты)", + "commentuserprofileprivate": "Ваш/полученный профиль кажется скрытым. Пожалуйста, измените настройки приватности, чтобы разрешить комментарии, и повторите попытку!", + "commenterroroccurred": "Опаньки, произошла ошибка! К сожалению, я не смог её прокомментировать.", + "commentprocessstarted": "Примерное время ожидания для NumberOfComments комментариев: waittime.", + "commentfailedcmdreference": "Чтобы получить подробную информацию о том, почему комментарий не сработал, введите «cmdprefixfailed». Вы можете прочитать, что, вероятно, вызвало вашу ошибку, здесь: https://github.com/HerrEurobeat/steam-comment-service-bot/wiki/Errors,-FAQ-&-Common-problems", + + "comment429stop": "Остановлен процесс комментирования, поскольку все прокси-серверы выдали ошибку HTTP 429 (восстановление IP). Пожалуйста, повторите попытку позже. Не удалось: failedamount/numberOfComments", + "commentretrying": "failedamount/numberOfComments комментариев были неудачными. Я собираюсь повторить попытку неудачных комментариев в untilStr. (Попытка thisattempt/maxattempt)", + "commentsuccess": "Все комментарии были отправлены. Не удалось: failedamount/numberOfComments\nЕсли вы хороший человек, то, пожалуйста, прокомментируйте и мой профиль!", + + "votenoaccounts": "Извините, но нет неограниченных аккаунтов, которые ещё не голосовали по этому пункту.", + "voterequestless": "В настоящее время доступно availablenow бот-аккаунтов, которые ещё не голосовали по этому пункту.", + "votenotenoughavailableaccs": "Извините, но в настоящее время недостаточно доступных аккаунтов, которые ещё не голосовали по этому пункту. Пожалуйста, подождите waittime и повторите попытку или запросите availablenow доступных сейчас.", + "voteprocessstarted": "Примерное время ожидания для NumberOfVotes голосов: waittime.", + "votesuccess": "Все голоса были отправлены. Не удалось: failedamount/numberOfVotes", + + "favoritenoaccounts": "Извините, но для данного запроса нет доступных аккаунтов на этом ID.", + "favoriterequestless": "Сейчас для этого запроса на этом ID доступны только availablenow бот-аккаунтов.", + "favoritenotenoughavailableaccs": "Извините, но в настоящее время для этого запроса не хватает аккаунтов на этом ID. Пожалуйста, подождите waittime и повторите попытку, или запросите availablenow доступных сейчас.", + "favoriteprocessstarted": "Примерное время ожидания для numberOfFavs добавлений/удалений в избранное: waittime.", + "favoritesuccess": "Все добавления/удаления в избранное были отправлены. Не удалось: failedamount/numberOfFavs", + + "useradded": "Здравствуйте! Спасибо, что добавили меня!\nЗапросите бесплатный комментарий с помощью cmdprefixcomment\nВведите cmdprefixhelp для получения дополнительных команд или cmdprefixabout для получения дополнительной информации!", + "userunfriend": "Вы были удалены из друзей за неактивность в течение ForceFriendlistSpaceTime дн., так как в списке друзей было мало места.\nЕсли я вам снова понадоблюсь, добавляйте меня снова!", + "userforceunfriend": "Вы были удалены из друзей за неактивность в течение unfriendtime дн.\nЕсли я вам снова понадоблюсь, не стесняйтесь добавить меня снова!", + + "userspamblock": "Вы были заблокированы на 90 секунд за спам.", + "usernotfriend": "Пожалуйста, добавьте меня, прежде чем использовать команду!", + "botnotready": "Бот ещё не полностью запущен. Пожалуйста, подождите немного, прежде чем использовать команду.", + "commandnotfound": "Я не знаю этой команды. Введите cmdprefixhelp для получения дополнительной информации.", + "commandowneronly": "Эта команда доступна только для владельцев.\nЕсли вы являетесь владельцем бота, убедитесь, что вы добавили свой ownerid в config.json.", + + "invalidnumber": "Это не похоже на действительное число!\n\nИспользование команды: cmdusage", + "invalidprofileid": "Похоже, что это не действительный ID или ссылка, или вы указали неправильный тип ID для этой команды!\nПожалуйста, убедитесь, что вы указали либо полную ссылку, либо только пустое значение, либо только ID, указывающий на существующий профиль, группу или общий файл.", + "invalidgroupid": "Это не правильный ID группы или ссылка группы! \nID группы должен выглядеть следующим образом: «103582791464712227» \n...или ссылка группы должна выглядеть следующим образом: «https://steamcommunity.com/groups/3urobeatGroup»", + "invalidsharedfileid": "Похоже, что это не действительный ID общего файла!\nПожалуйста, убедитесь, что вы указали либо полную ссылку: https://steamcommunity.com/sharedfiles/filedetails/?id=2980913451 ...либо только ID: 2980913451 ...который указывает на существующий скриншот, иллюстрацию или руководство.\n\nИспользование команды: cmdusage", + "errloadingsharedfile": "Извините, но при загрузке предоставленного вами файла sharedfile произошла ошибка:", + "idisownererror": "Вам не разрешается предоставлять ID владельца!", + "idalreadyreceiving": "У этого пользователя или ID уже есть активный запрос! Пожалуйста, подождите, пока он будет завершён, прежде чем запрашивать снова.", + "idoncooldown": "Вы только недавно начали запрос. Пожалуйста, подождите оставшиеся remainingcooldown, прежде чем начинать другой запрос.", + "requestaborted": "Ваш активный запрос был вручную прерван вами или владельцем.\nsuccessAmount/totalAmount были отправлены успешно.", + + "reloadcmdreloaded": "Перезагружены все команды и плагины.", + "activerelog": "В настоящее время бот ожидает завершения последних активных запросов, чтобы заново войти.\nПожалуйста, подождите несколько минут и повторите попытку.", + "updatecmdforce": "Принудительное обновление из ветки branchname...", + "updatecmdcheck": "Проверка наличия обновления в ветке branchname...", + "restartcmdrestarting": "Перезагрузка...", + "stopcmdstopping": "Остановка...", + + "helpcommandlist": "Список команд:", + "helpcommentowner1": "Запросить x или максимальное количество комментариев (максимум maxOwnerComments). Укажите ID профиля, чтобы прокомментировать конкретный профиль.", + "helpcommentowner2": "Запросить 1 комментарий (максимальное количество при текущих настройках). Укажите ID профиля, чтобы прокомментировать конкретный профиль.", + "helpcommentuser1": "Запросить x или максимальное количество комментариев (максимум maxComments).", + "helpcommentuser2": "Запросить комментарий к своему профилю!", + "helpping": "Получить пинг и время отклика от Steam в мс.", + "helpinfo": "Получить полезную информацию о боте и о себе.", + "helpabort": "Прервать процесс комментирования по собственному запросу.", + "helpabout": "Выдать информацию об этом боте, включая ссылку на GitHub.", + "helpowner": "Получить ссылку на профиль оператора/организатора данного экземпляра бота.", + "helpjoingroup": "Присоединяйтесь к моей «cmdprefixgroup»!", + "helpreadothercmdshere": "Чтобы сделать это сообщение коротким, пожалуйста, прочитайте все остальные команды здесь:", + + "pingcmdmessage": "Понг! 🏓\nВремя ответа steamcommunity.com/: pingtimems", + "ownercmdnolink": "Оператор этого бота не указал ссылку на себя).", + "ownercmdmsg": "Посмотрите профиль моего владельца: (для получения дополнительной информации о боте введите cmdprefixabout)", + "groupcmdnolink": "Ботовладелец данного экземпляра не предоставил никакой группы или группа не существует.", + "groupcmdinvitesent": "Я отправил вам приглашение! Спасибо, что присоединились!", + "groupcmdinvitelink": "Присоединяйтесь к моей группе здесь: ", + "abortcmdnoprocess": "Для этого ID нет действующего процесса комментирования.\nЕсли вы запрашивали комментарии для другого профиля или для группы, пожалуйста, укажите ID в качестве аргумента!", + "abortcmdsuccess": "Прерывание действующего процесса комментирования...", + + "resetcooldowncmdcooldowndisabled": "В конфигурации отключено время восстановления!", + "resetcooldowncmdglobalreset": "Время восстановления всех аккаунтов ботов было сброшено.", + "resetcooldowncmdsuccess": "Время восстановления profileid было сброшено.", + + "settingscmdfailedread": "Не удалось прочитать конфигурацию для вывода текущих настроек: ", + "settingscmdcurrentsettings": "Текущие настройки:", + "settingscmdblockedvalues": "enableevalcmd, ownerid и owner не могут быть изменены через команду settings по соображениям безопасности. Пожалуйста, сделайте это непосредственно в конфигурационном файле.", + "settingscmdkeynotfound": "Не могу найти этот ключ в конфигурации.", + "settingscmdsamevalue": "Запрашиваемый ключ уже является значением.", + "settingscmdvaluetoobig": "Ваше новое значение слишком велико. (Ограничение на 32-разрядное целое число)\nПожалуйста, выберите меньшее значение.", + "settingscmdvaluechanged": "targetkey был изменен со oldvalue на newvalue.\nПомните, что для вступления в силу некоторых значений может потребоваться перезапуск. Вы можете сделать это, введя cmdprefixrestart.", + + "failedcmdnothingfound": "Я не могу вспомнить ни одного неудачного комментария на вашем/этом профиле.\nЕсли вы запрашивали комментарии для другого профиля или для группы, пожалуйста, укажите ID в качестве аргумента!", + "failedcmdmsg": "Ваш последний запрос «steamID64» от «requesttime» (время GMT) содержал эти ошибки:", + + "sessionscmdnosessions": "В настоящее время нет активных сессий и нет бот-аккаунтов в режиме ожидания.", + "sessionscmdmsg": "В настоящее время есть amount активных сессий:", + "mysessionscmdnosessions": "В настоящее время нет активных сессий, которые вы начали.", + + "addfriendcmdacclimited": "Невозможно добавить profileid в друзья с помощью bot0, потому что аккаунт бота ограничен.", + "addfriendcmdsuccess": "Добавление profileid в друзья ко всем аккаунтам ботов... Это займёт ~estimatedtime сек. Пожалуйста, проверьте журнал на наличие возможных ошибок.", + "unfriendcmdsuccess": "Я удаляю вас из друзей со всех аккаунтов ботов. Это займёт некоторое время...\nВы можете отправить мне запрос в друзья в любое время.", + "unfriendidcmdsuccess": "Удалён profileid из друзей из всех аккаунтов ботов.", + + "unfriendallcmdabort": "Прерывание процесса удаления из списка друзей, если он активен...", + "unfriendallcmdpending": "Удаление всех людей (кроме владельцев) со всех аккаунтов бота за 30 секунд...\nВведите «cmdprefixunfriendall abort» для прерывания/остановки процесса.", + "unfriendallcmdstart": "Начинаю всех удалять из друзей...", + + "joingroupcmdsuccess": "Вступление в группу «groupid» со всеми аккаунтами ботов...", + + "leavegroupcmdsuccess": "Покидаю группу «groupid» со всеми аккаунтами ботов...", + + "leaveallgroupscmdabort": "Прерывание процесса покидания группы, если он активен...", + "leaveallgroupscmdpending": "Выход из всех групп (кроме yourgroup и botsgroup) со всеми аккаунтами ботов через 15 секунд...\nВведите «cmdprefixleaveallgroups abort» для прерывания/остановки процесса.", + "leaveallgroupscmdstart": "Начинаю покидать все группы...", + + "blockcmdsuccess": "profileid заблокирован во всех бот-аккаунтах.", + "unblockcmdsuccess": "profileid разблокирован во всех бот-аккаунтах.", + + "evalcmdturnedoff": "Команда eval была отключена!", + "evalcmdlogininfoblock": "Ваш код включает «logininfo». В целях защиты паролей это запрещено.", + + "childbotmessage": "Это один аккаунт, работающий в группе ботов.\nПожалуйста, добавьте главного бота и отправьте ему сообщение cmdprefixhelp.\nЕсли вы хотите проверить, в чём дело, введите: cmdprefixabout" +} \ No newline at end of file From e60fd4993a06b739d08a2d3bb138f0846fb09f7e Mon Sep 17 00:00:00 2001 From: Blueberryy <36592509+Blueberryy@users.noreply.github.com> Date: Thu, 29 Jun 2023 21:36:57 +0500 Subject: [PATCH 02/43] fixed some placeholders in russian file --- src/data/lang/russian.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/data/lang/russian.json b/src/data/lang/russian.json index 148b1534..e28388fb 100644 --- a/src/data/lang/russian.json +++ b/src/data/lang/russian.json @@ -3,9 +3,9 @@ "updaterautoupdatedisabled": "Вы отключили автоматическое обновление. Хотите ли вы обновить его сейчас?\nЕсли да, пожалуйста, запустите обновление с помощью команды: cmdprefixupdate true", - "commentcmdusageowner": "«cmdprefixcomment amount/\"all\" id» для запроса количества комментариев (или максимально возможного количества).\nУкажите ID профиля, группы или общего файла (скриншот, иллюстрация или руководство), если вы хотите комментировать не на своем профиле, а где-то ещё.", + "commentcmdusageowner": "«cmdprefixcomment кол-во/\"all\" id» для запроса amount комментариев (или максимально amount).\nУкажите ID профиля, группы или общего файла (скриншот, иллюстрация или руководство), если вы хотите комментировать не на своем профиле, а где-то ещё.", "commentcmdusageowner2": "«cmdprefixcomment 1 id». Укажите ID профиля, группы или общего файла (скриншота, иллюстрации или руководства), если вы хотите комментировать не в своём профиле, а где-то ещё.", - "commentcmdusage": "«cmdprefixcomment кол-во/\"all\"» для запроса количества комментариев (или максимально возможного количества) на вашем профиле.", + "commentcmdusage": "«cmdprefixcomment кол-во/\"all\"» для запроса amount комментариев (или максимально amount) на вашем профиле.", "commentcmdusage2": "«cmdprefixcomment», чтобы запросить комментарий к своему профилю!", "commentrequesttoohigh": "Вы можете запросить максимум комментариев maxRequestAmount.\nИспользование команды: commentcmdusage", "commentinvalidid": "Это не похоже на действительный ID профиля, группы или общего файла (скриншот, иллюстрация или руководство).\nПожалуйста, убедитесь, что вы предоставили либо полную ссылку, либо только пустое значение, либо только ID, указывающий на существующий профиль, группу или общий файл.\n\nИспользование команды: commentcmdusage", @@ -49,7 +49,7 @@ "invalidnumber": "Это не похоже на действительное число!\n\nИспользование команды: cmdusage", "invalidprofileid": "Похоже, что это не действительный ID или ссылка, или вы указали неправильный тип ID для этой команды!\nПожалуйста, убедитесь, что вы указали либо полную ссылку, либо только пустое значение, либо только ID, указывающий на существующий профиль, группу или общий файл.", - "invalidgroupid": "Это не правильный ID группы или ссылка группы! \nID группы должен выглядеть следующим образом: «103582791464712227» \n...или ссылка группы должна выглядеть следующим образом: «https://steamcommunity.com/groups/3urobeatGroup»", + "invalidgroupid": "Это не правильный ID группы или ссылка группы! \ngroupid должен выглядеть следующим образом: «103582791464712227» \n...или ссылка группы должна выглядеть следующим образом: «https://steamcommunity.com/groups/3urobeatGroup»", "invalidsharedfileid": "Похоже, что это не действительный ID общего файла!\nПожалуйста, убедитесь, что вы указали либо полную ссылку: https://steamcommunity.com/sharedfiles/filedetails/?id=2980913451 ...либо только ID: 2980913451 ...который указывает на существующий скриншот, иллюстрацию или руководство.\n\nИспользование команды: cmdusage", "errloadingsharedfile": "Извините, но при загрузке предоставленного вами файла sharedfile произошла ошибка:", "idisownererror": "Вам не разрешается предоставлять ID владельца!", @@ -65,8 +65,8 @@ "stopcmdstopping": "Остановка...", "helpcommandlist": "Список команд:", - "helpcommentowner1": "Запросить x или максимальное количество комментариев (максимум maxOwnerComments). Укажите ID профиля, чтобы прокомментировать конкретный профиль.", - "helpcommentowner2": "Запросить 1 комментарий (максимальное количество при текущих настройках). Укажите ID профиля, чтобы прокомментировать конкретный профиль.", + "helpcommentowner1": "Запросить x или максимальное количество комментариев (максимум maxOwnerComments). Укажите profileid, чтобы прокомментировать конкретный профиль.", + "helpcommentowner2": "Запросить 1 комментарий (максимально amount при текущих настройках). Укажите ID профиля, чтобы прокомментировать конкретный профиль.", "helpcommentuser1": "Запросить x или максимальное количество комментариев (максимум maxComments).", "helpcommentuser2": "Запросить комментарий к своему профилю!", "helpping": "Получить пинг и время отклика от Steam в мс.", @@ -94,8 +94,8 @@ "settingscmdcurrentsettings": "Текущие настройки:", "settingscmdblockedvalues": "enableevalcmd, ownerid и owner не могут быть изменены через команду settings по соображениям безопасности. Пожалуйста, сделайте это непосредственно в конфигурационном файле.", "settingscmdkeynotfound": "Не могу найти этот ключ в конфигурации.", - "settingscmdsamevalue": "Запрашиваемый ключ уже является значением.", - "settingscmdvaluetoobig": "Ваше новое значение слишком велико. (Ограничение на 32-разрядное целое число)\nПожалуйста, выберите меньшее значение.", + "settingscmdsamevalue": "Запрашиваемый ключ уже является value.", + "settingscmdvaluetoobig": "Ваше новое value слишком велико. (Ограничение на 32-разрядное целое число)\nПожалуйста, выберите меньшее value.", "settingscmdvaluechanged": "targetkey был изменен со oldvalue на newvalue.\nПомните, что для вступления в силу некоторых значений может потребоваться перезапуск. Вы можете сделать это, введя cmdprefixrestart.", "failedcmdnothingfound": "Я не могу вспомнить ни одного неудачного комментария на вашем/этом профиле.\nЕсли вы запрашивали комментарии для другого профиля или для группы, пожалуйста, укажите ID в качестве аргумента!", From 536be82bbf4f70bc56394b9101e456213bfc3fd2 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+HerrEurobeat@users.noreply.github.com> Date: Thu, 29 Jun 2023 22:43:55 +0200 Subject: [PATCH 03/43] Switch branch back to beta-testing --- src/data/data.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/data.json b/src/data/data.json index 367c9f86..437a2cbf 100644 --- a/src/data/data.json +++ b/src/data/data.json @@ -1,9 +1,9 @@ { "version": "21304", "versionstr": "2.13.4", - "branch": "master", + "branch": "beta-testing", "filetostart": "./src/starter.js", - "filetostarturl": "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/src/starter.js", + "filetostarturl": "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/beta-testing/src/starter.js", "mestr": "3urobeat", "aboutstr": "This bot was created by 3urobeat.\nGitHub: https://github.com/3urobeat/steam-comment-service-bot \nSteam: https://steamcommunity.com/id/3urobeat \nIf you like my work, any donation would be appreciated! https://paypal.me/3urobeat", "firststart": true, From a6529709e5e4de48b27d9bf166317c71ea587387 Mon Sep 17 00:00:00 2001 From: Blueberryy <36592509+Blueberryy@users.noreply.github.com> Date: Fri, 30 Jun 2023 09:46:16 +0500 Subject: [PATCH 04/43] Update russian.json --- src/data/lang/russian.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/data/lang/russian.json b/src/data/lang/russian.json index e28388fb..ec803d7e 100644 --- a/src/data/lang/russian.json +++ b/src/data/lang/russian.json @@ -1,5 +1,5 @@ { - "note": "Этот файл содержит почти все сообщения, которые бот посылает пользователям. Если вы хотите изменить сообщения, прочтите эту страницу: https://github.com/HerrEurobeat/steam-comment-service-bot/wiki/How-to-add-custom-messages", + "note": "Этот файл содержит почти все сообщения, которые бот посылает пользователям. Если вы хотите изменить сообщения, прочтите эту страницу: https://github.com/3urobeat/steam-comment-service-bot/wiki/How-to-add-custom-messages", "updaterautoupdatedisabled": "Вы отключили автоматическое обновление. Хотите ли вы обновить его сейчас?\nЕсли да, пожалуйста, запустите обновление с помощью команды: cmdprefixupdate true", @@ -18,8 +18,8 @@ "commentaddbotaccounts": "Пожалуйста, добавьте эти аккаунты, а затем запросите снова: (ограниченные аккаунты)", "commentuserprofileprivate": "Ваш/полученный профиль кажется скрытым. Пожалуйста, измените настройки приватности, чтобы разрешить комментарии, и повторите попытку!", "commenterroroccurred": "Опаньки, произошла ошибка! К сожалению, я не смог её прокомментировать.", - "commentprocessstarted": "Примерное время ожидания для NumberOfComments комментариев: waittime.", - "commentfailedcmdreference": "Чтобы получить подробную информацию о том, почему комментарий не сработал, введите «cmdprefixfailed». Вы можете прочитать, что, вероятно, вызвало вашу ошибку, здесь: https://github.com/HerrEurobeat/steam-comment-service-bot/wiki/Errors,-FAQ-&-Common-problems", + "commentprocessstarted": "Примерное время ожидания для numberOfComments комментариев: waittime.", + "commentfailedcmdreference": "Чтобы получить подробную информацию о том, почему комментарий не сработал, введите «cmdprefixfailed». Вы можете прочитать, что, вероятно, вызвало вашу ошибку, здесь: https://github.com/3urobeat/steam-comment-service-bot/wiki/Errors,-FAQ-&-Common-problems", "comment429stop": "Остановлен процесс комментирования, поскольку все прокси-серверы выдали ошибку HTTP 429 (восстановление IP). Пожалуйста, повторите попытку позже. Не удалось: failedamount/numberOfComments", "commentretrying": "failedamount/numberOfComments комментариев были неудачными. Я собираюсь повторить попытку неудачных комментариев в untilStr. (Попытка thisattempt/maxattempt)", @@ -28,7 +28,7 @@ "votenoaccounts": "Извините, но нет неограниченных аккаунтов, которые ещё не голосовали по этому пункту.", "voterequestless": "В настоящее время доступно availablenow бот-аккаунтов, которые ещё не голосовали по этому пункту.", "votenotenoughavailableaccs": "Извините, но в настоящее время недостаточно доступных аккаунтов, которые ещё не голосовали по этому пункту. Пожалуйста, подождите waittime и повторите попытку или запросите availablenow доступных сейчас.", - "voteprocessstarted": "Примерное время ожидания для NumberOfVotes голосов: waittime.", + "voteprocessstarted": "Примерное время ожидания для numberOfVotes голосов: waittime.", "votesuccess": "Все голоса были отправлены. Не удалось: failedamount/numberOfVotes", "favoritenoaccounts": "Извините, но для данного запроса нет доступных аккаунтов на этом ID.", @@ -51,7 +51,7 @@ "invalidprofileid": "Похоже, что это не действительный ID или ссылка, или вы указали неправильный тип ID для этой команды!\nПожалуйста, убедитесь, что вы указали либо полную ссылку, либо только пустое значение, либо только ID, указывающий на существующий профиль, группу или общий файл.", "invalidgroupid": "Это не правильный ID группы или ссылка группы! \ngroupid должен выглядеть следующим образом: «103582791464712227» \n...или ссылка группы должна выглядеть следующим образом: «https://steamcommunity.com/groups/3urobeatGroup»", "invalidsharedfileid": "Похоже, что это не действительный ID общего файла!\nПожалуйста, убедитесь, что вы указали либо полную ссылку: https://steamcommunity.com/sharedfiles/filedetails/?id=2980913451 ...либо только ID: 2980913451 ...который указывает на существующий скриншот, иллюстрацию или руководство.\n\nИспользование команды: cmdusage", - "errloadingsharedfile": "Извините, но при загрузке предоставленного вами файла sharedfile произошла ошибка:", + "errloadingsharedfile": "Извините, но при загрузке предоставленного вами файла sharedfile произошла ошибка: ", "idisownererror": "Вам не разрешается предоставлять ID владельца!", "idalreadyreceiving": "У этого пользователя или ID уже есть активный запрос! Пожалуйста, подождите, пока он будет завершён, прежде чем запрашивать снова.", "idoncooldown": "Вы только недавно начали запрос. Пожалуйста, подождите оставшиеся remainingcooldown, прежде чем начинать другой запрос.", @@ -83,7 +83,7 @@ "groupcmdnolink": "Ботовладелец данного экземпляра не предоставил никакой группы или группа не существует.", "groupcmdinvitesent": "Я отправил вам приглашение! Спасибо, что присоединились!", "groupcmdinvitelink": "Присоединяйтесь к моей группе здесь: ", - "abortcmdnoprocess": "Для этого ID нет действующего процесса комментирования.\nЕсли вы запрашивали комментарии для другого профиля или для группы, пожалуйста, укажите ID в качестве аргумента!", + "abortcmdnoprocess": "Для этого ID нет действующего процесса комментирования.\nЕсли вы запрашивали комментарии для другого профиля, группы или общего файла, укажите этот ID в качестве аргумента!", "abortcmdsuccess": "Прерывание действующего процесса комментирования...", "resetcooldowncmdcooldowndisabled": "В конфигурации отключено время восстановления!", @@ -98,8 +98,8 @@ "settingscmdvaluetoobig": "Ваше новое value слишком велико. (Ограничение на 32-разрядное целое число)\nПожалуйста, выберите меньшее value.", "settingscmdvaluechanged": "targetkey был изменен со oldvalue на newvalue.\nПомните, что для вступления в силу некоторых значений может потребоваться перезапуск. Вы можете сделать это, введя cmdprefixrestart.", - "failedcmdnothingfound": "Я не могу вспомнить ни одного неудачного комментария на вашем/этом профиле.\nЕсли вы запрашивали комментарии для другого профиля или для группы, пожалуйста, укажите ID в качестве аргумента!", - "failedcmdmsg": "Ваш последний запрос «steamID64» от «requesttime» (время GMT) содержал эти ошибки:", + "failedcmdnothingfound": "Я не могу вспомнить ни одного неудачного комментария на вашем/этом ID.\nЕсли вы запрашивали комментарии для другого профиля, группы или общего файла, пожалуйста, укажите этот ID в качестве аргумента!", + "failedcmdmsg": "Ваш последний запрос «steamID64», выполненный в «requesttime» (время GMT), содержал эти ошибки:", "sessionscmdnosessions": "В настоящее время нет активных сессий и нет бот-аккаунтов в режиме ожидания.", "sessionscmdmsg": "В настоящее время есть amount активных сессий:", From ba3ec0fe5203941350746c5900928bf04a7b74ca Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Fri, 30 Jun 2023 09:35:56 +0200 Subject: [PATCH 05/43] Update old name in assume-unchanged files --- accounts.txt | 2 +- plugins/README.md | 2 +- proxies.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts.txt b/accounts.txt index 48dbbba4..54197aa8 100644 --- a/accounts.txt +++ b/accounts.txt @@ -1 +1 @@ -//Comment: This file is used to provide your bot accounts in the form of username:password. Read the instructions here: https://github.com/HerrEurobeat/steam-comment-service-bot#accounts \ No newline at end of file +//Comment: This file is used to provide your bot accounts in the form of username:password. Read the instructions here: https://github.com/3urobeat/steam-comment-service-bot#accounts \ No newline at end of file diff --git a/plugins/README.md b/plugins/README.md index 98e4717c..081a80ec 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -5,4 +5,4 @@ This folder holds folders for all your installed plugins, which contain a config You can also store locally packed `.tgz` packages here to install them via `npm install ./plugins/steam-comment-bot-myplugin-1.0.0.tgz` from the project root. -To create your own plugin, fork my template: https://github.com/HerrEurobeat/steam-comment-bot-template-plugin \ No newline at end of file +To create your own plugin, fork my template: https://github.com/3urobeat/steam-comment-bot-template-plugin \ No newline at end of file diff --git a/proxies.txt b/proxies.txt index c8e621c9..300aa211 100755 --- a/proxies.txt +++ b/proxies.txt @@ -1 +1 @@ -//Comment: This file is used to provide proxies to spread your accounts over multiple IPs. Read the instructions here: https://github.com/HerrEurobeat/steam-comment-service-bot/wiki/Adding-proxies \ No newline at end of file +//Comment: This file is used to provide proxies to spread your accounts over multiple IPs. Read the instructions here: https://github.com/3urobeat/steam-comment-service-bot/wiki/Adding-proxies \ No newline at end of file From 9adafde73854f476bb1b9cce85d991d31f14ba3a Mon Sep 17 00:00:00 2001 From: JLCD Date: Sun, 2 Jul 2023 14:22:17 +0200 Subject: [PATCH 06/43] feat(Plugin) Aggregate old config files for plugins --- src/dataManager/dataImport.js | 112 ++++++++++++------------ src/dataManager/dataManager.js | 9 +- src/dataManager/helpers/refreshCache.js | 16 ++-- src/pluginSystem/handlePluginData.js | 38 ++++---- src/pluginSystem/loadPlugins.js | 37 ++++---- src/pluginSystem/pluginSystem.js | 19 ++-- 6 files changed, 115 insertions(+), 116 deletions(-) diff --git a/src/dataManager/dataImport.js b/src/dataManager/dataImport.js index 04dbc57d..6dcbcbf8 100644 --- a/src/dataManager/dataImport.js +++ b/src/dataManager/dataImport.js @@ -14,30 +14,27 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see . */ - -const fs = require("fs"); -const path = require("path"); -const nedb = require("@seald-io/nedb"); +const fs = require("fs"); +const path = require("path"); +const nedb = require("@seald-io/nedb"); const DataManager = require("./dataManager.js"); - /** * Internal: Loads all config & data files from disk and handles potential errors * @returns {Promise.} Resolves promise when all files have been loaded successfully. The function will log an error and terminate the application should a fatal error occur. */ -DataManager.prototype._importFromDisk = function() { +DataManager.prototype._importFromDisk = function () { let _this = this; // Make this accessible within the functions below return new Promise((resolve) => { - (async () => { // Lets us use await inside a Promise without creating an antipattern + (async () => { + // Lets us use await inside a Promise without creating an antipattern function loadCache() { return new Promise((resolve) => { try { resolve(require(srcdir + "/data/cache.json")); - } catch (err) { - if (err) { logger("", "", true, true); logger("warn", "cache.json seems to have lost it's data/is corrupted. Trying to write/create...", true, true); @@ -45,7 +42,8 @@ DataManager.prototype._importFromDisk = function() { // Create the underlying folder structure to avoid error when trying to write the downloaded file fs.mkdirSync(path.dirname("./src/data/cache.json"), { recursive: true }); - fs.writeFile("./src/data/cache.json", "{}", (err) => { // Write empty valid json + fs.writeFile("./src/data/cache.json", "{}", (err) => { + // Write empty valid json if (err) { logger("error", "Error writing {} to cache.json.\nPlease do this manually: Go into 'src' folder, open 'cache.json', write '{}' and save.\nOtherwise the bot will always crash.\nError: " + err + "\n\nAborting...", true); return _this.controller.stop(); // Abort since writeFile was unable to write and any further execution would crash @@ -63,16 +61,15 @@ DataManager.prototype._importFromDisk = function() { return new Promise((resolve) => { try { resolve(require(srcdir + "/data/data.json")); - } catch (err) { - - if (err) { // Corrupted! + if (err) { + // Corrupted! logger("", "", true, true); logger("warn", "'data.json' seems to have lost it's data/is corrupted. Trying to restore from backup...", true); // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. if (_this.cachefile.datajson) _this._restoreBackup("data.json", srcdir + "/data/data.json", _this.cachefile.datajson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/src/data/data.json", resolve); - else _this._pullNewFile("data.json", "./src/data/data.json", resolve); + else _this._pullNewFile("data.json", "./src/data/data.json", resolve); } } }); @@ -82,10 +79,9 @@ DataManager.prototype._importFromDisk = function() { return new Promise((resolve) => { try { resolve(require(srcdir + "/../config.json")); - } catch (err) { - - if (err) { // Corrupted! + if (err) { + // Corrupted! logger("", "", true, true); logger("warn", "'config.json' seems to have lost it's data/is corrupted. Trying to restore from backup...", true); @@ -108,7 +104,7 @@ DataManager.prototype._importFromDisk = function() { setTimeout(() => { // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. if (_this.cachefile.configjson) _this._restoreBackup("config.json", srcdir + "/../config.json", _this.cachefile.configjson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/config.json", resolve); - else _this._pullNewFile("config.json", "./config.json", resolve); + else _this._pullNewFile("config.json", "./config.json", resolve); }, restoreTimeout); } } @@ -120,13 +116,14 @@ DataManager.prototype._importFromDisk = function() { try { resolve(require(srcdir + "/../advancedconfig.json")); } catch (err) { - if (err) { // Corrupted! + if (err) { + // Corrupted! logger("", "", true, true); logger("warn", "advancedconfig.json seems to have lost it's data/is corrupted. Trying to restore from backup...", true); // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. if (_this.cachefile.advancedconfigjson) _this._restoreBackup("advancedconfig.json", srcdir + "/../advancedconfig.json", _this.cachefile.advancedconfigjson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/advancedconfig.json", resolve); - else _this._pullNewFile("advancedconfig.json", "./advancedconfig.json", resolve); + else _this._pullNewFile("advancedconfig.json", "./advancedconfig.json", resolve); } } }); @@ -155,7 +152,7 @@ DataManager.prototype._importFromDisk = function() { password: e[1], sharedSecret: e[2], steamGuardCode: null, - machineName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-user + machineName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-user deviceFriendlyName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-session }; }); @@ -179,8 +176,8 @@ DataManager.prototype._importFromDisk = function() { password: logininfo[k][1], sharedSecret: logininfo[k][2], steamGuardCode: null, - machineName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-user - deviceFriendlyName: `${_this.datafile.mestr}'s Comment Bot` // For steam-session + machineName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-user + deviceFriendlyName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-session }; delete logininfo[k]; // Remove old entry @@ -204,14 +201,14 @@ DataManager.prototype._importFromDisk = function() { if (!fs.existsSync("./proxies.txt")) { logger("info", "Creating proxies.txt file as it doesn't exist yet...", false, true, logger.animation("loading")); - fs.writeFile(srcdir + "/../proxies.txt", "", err => { + fs.writeFile(srcdir + "/../proxies.txt", "", (err) => { if (err) logger("error", "error creating proxies.txt file: " + err); - else logger("info", "Successfully created proxies.txt file.", false, true, logger.animation("loading")); + else logger("info", "Successfully created proxies.txt file.", false, true, logger.animation("loading")); }); - - } else { // File does seem to exist so now we can try and read it + } else { + // File does seem to exist so now we can try and read it proxies = fs.readFileSync("./proxies.txt", "utf8").split("\n"); - proxies = proxies.filter(str => str != ""); // Remove empty lines + proxies = proxies.filter((str) => str != ""); // Remove empty lines if (proxies.length > 0 && proxies[0].startsWith("//Comment")) proxies = proxies.slice(1); // Remove comment from array @@ -235,15 +232,21 @@ DataManager.prototype._importFromDisk = function() { // Pull new file and call loadQuotes again, wait for it to resolve, and then resolve this promise. This is slightly hacky but relatively clean if (!fs.existsSync(srcdir + "/../quotes.txt")) { - return _this._pullNewFile("quotes.txt", "./quotes.txt", async () => { - resolve(await loadQuotes()); - }, true); + return _this._pullNewFile( + "quotes.txt", + "./quotes.txt", + async () => { + resolve(await loadQuotes()); + }, + true + ); } quotes = fs.readFileSync(srcdir + "/../quotes.txt", "utf8").split("\n"); // Get all quotes from the quotes.txt file into an array - quotes = quotes.filter(str => str != ""); // Remove empty quotes + quotes = quotes.filter((str) => str != ""); // Remove empty quotes - quotes.forEach((e, i) => { // Multi line strings that contain \n will get split to \\n -> remove second \ so that node-steamcommunity understands the quote when commenting + quotes.forEach((e, i) => { + // Multi line strings that contain \n will get split to \\n -> remove second \ so that node-steamcommunity understands the quote when commenting if (e.length > 999) { logger("warn", `The quote.txt line ${i} is longer than the limit of 999 characters. This quote will be ignored for now.`, true, false, logger.animation("loading")); quotes.splice(i, 1); // Remove this item from the array @@ -253,7 +256,8 @@ DataManager.prototype._importFromDisk = function() { quotes[i] = e.replace(/\\n/g, "\n").replace("\\n", "\n"); }); - if (quotes.length == 0) { // Check if quotes.txt is empty to avoid errors further down when trying to comment + if (quotes.length == 0) { + // Check if quotes.txt is empty to avoid errors further down when trying to comment logger("error", `${logger.colors.fgred}You haven't put any comment quotes into the quotes.txt file! Aborting...`, true); return _this.controller.stop(); } else { @@ -269,7 +273,8 @@ DataManager.prototype._importFromDisk = function() { try { resolve(require(srcdir + "/data/lang/defaultlang.json")); } catch (err) { - if (err) { // Corrupted! + if (err) { + // Corrupted! logger("", "", true, true); // Pull the file directly from GitHub. @@ -303,49 +308,44 @@ DataManager.prototype._importFromDisk = function() { customlangkeys++; } - if (i == Object.keys(customlang).length - 1) { // Check for last iteration + if (i == Object.keys(customlang).length - 1) { + // Check for last iteration if (customlangkeys > 0) logger("info", `${customlangkeys} customlang key imported!`, false, true, logger.animation("loading")); - else logger("info", "No customlang keys found.", false, true, logger.animation("loading")); + else logger("info", "No customlang keys found.", false, true, logger.animation("loading")); resolve(_this.lang); // Resolve lang object with our new keys } }); - } else { - logger("info", "No customlang.json file found...", false, true, logger.animation("loading")); resolve(_this.lang); // Resolve with default lang object } }); } - // Call all functions from above after another. This must be done async to avoid a check failing that depends on something from a previous function logger("info", "Importing data files and settings...", false, true, logger.animation("loading")); - this.cachefile = await loadCache(); - this.datafile = await loadData(); - this.config = await loadConfig(); + this.cachefile = await loadCache(); + this.datafile = await loadData(); + this.config = await loadConfig(); this.advancedconfig = await loadAdvancedConfig(); - this.logininfo = await loadLoginInfo(); - this.proxies = await loadProxies(); - this.quotes = await loadQuotes(); - this.lang = await loadLanguage(); - this.lang = await loadCustomLang(); - - this.lastCommentDB = new nedb({ filename: srcdir + "/data/lastcomment.db", autoload: true }); // Autoload + this.logininfo = await loadLoginInfo(); + this.proxies = await loadProxies(); + this.quotes = await loadQuotes(); + this.lang = await loadLanguage(); + this.lang = await loadCustomLang(); + this.pluginVersions = this.cachefile.pluginVersions; + + this.lastCommentDB = new nedb({ filename: srcdir + "/data/lastcomment.db", autoload: true }); // Autoload this.ratingHistoryDB = new nedb({ filename: srcdir + "/data/ratingHistory.db", autoload: true }); - this.tokensDB = new nedb({ filename: srcdir + "/data/tokens.db", autoload: true }); - + this.tokensDB = new nedb({ filename: srcdir + "/data/tokens.db", autoload: true }); // Check tokens.db every 24 hours for expired tokens to allow users to refresh them beforehand this._startExpiringTokensCheckInterval(); - // Resolve our promise to let caller know the dataImport is finished resolve(); - })(); }); - -}; \ No newline at end of file +}; diff --git a/src/dataManager/dataManager.js b/src/dataManager/dataManager.js index 41e9237b..9bf6551d 100644 --- a/src/dataManager/dataManager.js +++ b/src/dataManager/dataManager.js @@ -14,20 +14,17 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see . */ - const fs = require("fs"); const { default: Nedb } = require("@seald-io/nedb"); // eslint-disable-line const Controller = require("../controller/controller.js"); // eslint-disable-line - /** * Constructor - The dataManager system imports, checks, handles errors and provides a file updating service for all configuration files * @class * @param {Controller} controller Reference to the controller object */ const DataManager = function (controller) { - /** * Reference to the controller object * @type {Controller} @@ -106,7 +103,10 @@ const DataManager = function (controller) { * @type {Nedb} */ this.tokensDB = {}; - + /** + * The last seen plugin versions. + */ + this.pluginVersions = {}; // Dynamically load all helper files const loadHelpersFromFolder = (folder) => { @@ -122,7 +122,6 @@ const DataManager = function (controller) { loadHelpersFromFolder("./src/dataManager"); loadHelpersFromFolder("./src/dataManager/helpers"); - }; /* -------- Register functions to let the IntelliSense know what's going on in helper files -------- */ diff --git a/src/dataManager/helpers/refreshCache.js b/src/dataManager/helpers/refreshCache.js index b905888d..2acefd92 100644 --- a/src/dataManager/helpers/refreshCache.js +++ b/src/dataManager/helpers/refreshCache.js @@ -14,23 +14,22 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see . */ - -const fs = require("fs"); +const fs = require("fs"); const SteamID = require("steamid"); const DataManager = require("../dataManager"); - /** * Refreshes Backups in cache.json with new data */ -DataManager.prototype.refreshCache = function() { +DataManager.prototype.refreshCache = function () { logger("info", "Refreshing data backups in cache.json...", false, true, logger.animation("loading")); // Refresh cache of bot account ids, check if they inflict with owner settings let tempArr = []; - this.controller.getBots().forEach((e, i) => { // Get all online accounts + this.controller.getBots().forEach((e, i) => { + // Get all online accounts tempArr.push(new SteamID(String(e.user.steamID)).getSteamID64()); // Check if this bot account is listed as an owner id and display warning @@ -45,16 +44,15 @@ DataManager.prototype.refreshCache = function() { } }); - // Update Backups logger("debug", "Writing backups to cache.json...", false, true, logger.animation("loading")); this.cachefile["configjson"] = this.config; this.cachefile["advancedconfigjson"] = this.advancedconfig; this.cachefile["datajson"] = this.datafile; - + this.cachefile["pluginVersions"] = this.pluginVersions; // Write changes to file - fs.writeFile(srcdir + "/data/cache.json", JSON.stringify(this.cachefile, null, 4), err => { + fs.writeFile(srcdir + "/data/cache.json", JSON.stringify(this.cachefile, null, 4), (err) => { if (err) logger("error", "error writing file backups to cache.json: " + err); }); -}; \ No newline at end of file +}; diff --git a/src/pluginSystem/handlePluginData.js b/src/pluginSystem/handlePluginData.js index a4a07812..fca5786f 100644 --- a/src/pluginSystem/handlePluginData.js +++ b/src/pluginSystem/handlePluginData.js @@ -14,18 +14,17 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see . */ - const fs = require("fs"); const PluginSystem = require("./pluginSystem.js"); - +const { logger } = require("output-logger/lib/logger.js"); /** * Gets the path holding all data of a plugin. If no folder exists yet, one will be created * @param {string} pluginName Name of your plugin * @returns {string} Path to the folder containing your plugin data */ -PluginSystem.prototype.getPluginDataPath = function(pluginName) { +PluginSystem.prototype.getPluginDataPath = function (pluginName) { let path = `${srcdir}/../plugins/${pluginName}/`; if (!fs.existsSync(path)) fs.mkdirSync(path); @@ -33,7 +32,6 @@ PluginSystem.prototype.getPluginDataPath = function(pluginName) { return path; }; - /** * Loads a file from your plugin data folder. The data will remain unprocessed. Use `loadPluginConfig()` instead if you want to load your plugin config. * @param {string} pluginName Name of your plugin @@ -42,7 +40,6 @@ PluginSystem.prototype.getPluginDataPath = function(pluginName) { */ PluginSystem.prototype.loadPluginData = function (pluginName, filename) { return new Promise((resolve, reject) => { - // Get path let path = this.getPluginDataPath(pluginName); @@ -54,11 +51,9 @@ PluginSystem.prototype.loadPluginData = function (pluginName, filename) { resolve(data); }); - }); }; - /** * Writes a file to your plugin data folder. The data will remain unprocessed. Use `writePluginConfig()` instead if you want to write your plugin config. * @param {string} pluginName Name of your plugin @@ -68,7 +63,6 @@ PluginSystem.prototype.loadPluginData = function (pluginName, filename) { */ PluginSystem.prototype.writePluginData = function (pluginName, filename, data) { return new Promise((resolve, reject) => { - // Get path let path = this.getPluginDataPath(pluginName); @@ -80,11 +74,9 @@ PluginSystem.prototype.writePluginData = function (pluginName, filename, data) { resolve(); }); - }); }; - /** * Deletes a file in your plugin data folder if it exists. * @param {string} pluginName Name of your plugin @@ -93,7 +85,6 @@ PluginSystem.prototype.writePluginData = function (pluginName, filename, data) { */ PluginSystem.prototype.deletePluginData = function (pluginName, filename) { return new Promise((resolve, reject) => { - // Get path let path = this.getPluginDataPath(pluginName); @@ -109,11 +100,9 @@ PluginSystem.prototype.deletePluginData = function (pluginName, filename) { resolve(); }); - }); }; - /** * Loads your plugin config from the filesystem or creates a new one based on the default config provided by your plugin. The JSON data will be processed to an object. * @param {string} pluginName Name of your plugin @@ -121,7 +110,6 @@ PluginSystem.prototype.deletePluginData = function (pluginName, filename) { */ PluginSystem.prototype.loadPluginConfig = function (pluginName) { return new Promise((resolve, reject) => { - // Get path let path = this.getPluginDataPath(pluginName); @@ -131,7 +119,7 @@ PluginSystem.prototype.loadPluginConfig = function (pluginName) { try { fs.copyFileSync(`${srcdir}/../node_modules/${pluginName}/config.json`, path + "config.json"); - } catch(err) { + } catch (err) { logger("error", `Error copying default config provided by plugin '${pluginName}': ` + err); return reject(err); } @@ -144,10 +132,24 @@ PluginSystem.prototype.loadPluginConfig = function (pluginName) { logger("error", `PluginSystem: Failed to load config for plugin '${pluginName}': ${err.stack}`); return reject(err); } - }); }; +/** + * Integrates changes made to the config to the users config + * @param {string} pluginName + * @returns {Record} the config + */ +PluginSystem.prototype.aggregatePluginConfig = function (pluginName) { + let path = this.getPluginDataPath(pluginName); + if (!fs.existsSync(path + "config.json")) return; + + const standardConfig = require(`${srcdir}/../node_modules/${pluginName}/config.json`); + const config = require(path + "config.json"); + const aggregatedConfig = Object.assign(standardConfig, config); + fs.writeFileSync(path + "config.json", JSON.stringify(aggregatedConfig, null, 4)); + return aggregatedConfig; +}; /** * Writes your plugin config changes to the filesystem. The object data will be processed to JSON. @@ -157,7 +159,6 @@ PluginSystem.prototype.loadPluginConfig = function (pluginName) { */ PluginSystem.prototype.writePluginConfig = function (pluginName, pluginConfig) { return new Promise((resolve, reject) => { - // Get path let path = this.getPluginDataPath(pluginName); @@ -170,6 +171,5 @@ PluginSystem.prototype.writePluginConfig = function (pluginName, pluginConfig) { logger("error", `PluginSystem: Failed to write config for plugin '${pluginName}': ${err.stack}`); return reject(err); } - }); -}; \ No newline at end of file +}; diff --git a/src/pluginSystem/loadPlugins.js b/src/pluginSystem/loadPlugins.js index 7ece030c..c9f8bcdf 100644 --- a/src/pluginSystem/loadPlugins.js +++ b/src/pluginSystem/loadPlugins.js @@ -4,17 +4,16 @@ * Created Date: 04.06.2023 15:37:17 * Author: DerDeathraven * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.06.2023 19:31:20 * Modified By: 3urobeat * - * Copyright (c) 2023 3urobeat + * Copyright (c) 2023 3urobeat * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * You should have received a copy of the GNU General Public License along with this program. If not, see . */ - const PluginSystem = require("./pluginSystem.js"); const PLUGIN_REGEX = /^steam-comment-bot-/; @@ -26,13 +25,11 @@ const PLUGIN_EVENTS = { steamGuardInput: "steamGuardInput", }; - -// Attempt to load all plugins. If a critical check fails loading will be denied function loadPlugin(pluginName) { try { // Load plugin and pluginJson const importedPlugin = require(pluginName); - const pluginJson = require(`${srcdir}/../node_modules/${pluginName}/package.json`); + const pluginJson = require(`${srcdir}/../node_modules/${pluginName}/package.json`); // Check if plugin is missing required functions if (!(typeof importedPlugin === "function") || !importedPlugin.prototype || !importedPlugin.prototype.load) { @@ -40,43 +37,46 @@ function loadPlugin(pluginName) { return {}; } + // Display warning if the function is missing a unload function + if (!importedPlugin.prototype.unload) logger("warn", `Plugin '${pluginName}' does not have an unload function! This may prevent the reloading function from working properly.`); + // Create new plugin object const pluginInstance = new importedPlugin(this); - return { pluginName, pluginInstance, pluginJson }; } catch (e) { logger("error", `Plugin '${pluginName}' could not be instantiated: ${e.stack}`); - return { pluginName, pluginInstance: null, pluginJson: null }; } } - /** * Internal: Loads all plugin npm packages and populates pluginList */ PluginSystem.prototype._loadPlugins = async function () { - // Get all plugins with the matching regex const plugins = Object.entries(packageJson.dependencies).filter(([key, value]) => PLUGIN_REGEX.test(key)); // eslint-disable-line const initiatedPlugins = plugins.map(([plugin]) => loadPlugin.bind(this)(plugin)); // Initalize each plugin - for (const { pluginName, pluginInstance, pluginJson } of initiatedPlugins) { + for (const plugin of initiatedPlugins) { + const { pluginName, pluginInstance, pluginJson } = plugin; if (!pluginInstance) { logger("warn", `Skipping plugin '${pluginName}'...`, false, false, null, true); // Force print now continue; } - + let pluginConfig = {}; + const lastSeenVersion = this.controller.data.pluginVersions; + if (lastSeenVersion[pluginName] && lastSeenVersion[pluginName] !== pluginJson.version) { + logger("warn", `Plugin '${pluginName}' is outdated! Updating plugin...`, false, false, null, true); // Force print now + pluginConfig = this.aggregatePluginConfig(pluginName); + } else { + pluginConfig = await this.loadPluginConfig(pluginName).catch((err) => logger("error", `The config of plugin '${pluginName}' is fucked, skipping plugin. ${err}`)); + } // Skip plugin if it is disabled - let pluginConfig = await this.loadPluginConfig(pluginName).catch((err) => logger("error", `The config of plugin '${pluginName}' is fucked, skipping plugin. ${err}`)); if (!pluginConfig || !pluginConfig.enabled) { logger("debug", `Plugin '${pluginName}' is disabled. Skipping plugin...`); continue; } - // Display warning if the function is missing a unload function - if (!pluginInstance.unload) logger("warn", `Plugin '${pluginName}' does not have an unload function! This may prevent the reloading function from working properly.`); - logger("info", `PluginSystem: Loading plugin '${pluginName}' v${pluginJson.version} by ${pluginJson.author}...`, false, true, logger.animation("loading")); // Add plugin reference to pluginList and call load function @@ -84,9 +84,10 @@ PluginSystem.prototype._loadPlugins = async function () { pluginInstance.load(); // Call the exposed event functions if they exist - Object.entries(PLUGIN_EVENTS).forEach(([eventName, event]) => { // eslint-disable-line + Object.entries(PLUGIN_EVENTS).forEach(([eventName, event]) => { + // eslint-disable-line this.controller.events.on(event, (...args) => pluginInstance[event]?.call(pluginInstance, ...args)); }); + this.controller.data.pluginVersions[pluginName] = pluginJson.version; } - }; diff --git a/src/pluginSystem/pluginSystem.js b/src/pluginSystem/pluginSystem.js index b0da3453..84636657 100644 --- a/src/pluginSystem/pluginSystem.js +++ b/src/pluginSystem/pluginSystem.js @@ -14,11 +14,9 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see . */ - -const Controller = require("../controller/controller.js"); // eslint-disable-line +const Controller = require("../controller/controller.js"); // eslint-disable-line const CommandHandler = require("../commands/commandHandler.js"); // eslint-disable-line -const Bot = require("../../src/bot/bot.js"); // eslint-disable-line - +const Bot = require("../../src/bot/bot.js"); // eslint-disable-line /** * @typedef Plugin Documentation of the Plugin structure for IntelliSense support @@ -30,7 +28,6 @@ const Bot = require("../../src/bot/bot.js"); // eslint-disab * @property {function(Bot, function(string))} steamGuardInput Controller steamGuardInput event */ - /** * Constructor - The plugin system loads all plugins and provides functions for plugins to hook into * @class @@ -62,7 +59,6 @@ const PluginSystem = function (controller) { // The plugin system loads all plugins and provides functions for plugins to hook into module.exports = PluginSystem; - /** * Reloads all plugins and calls ready event after ~2.5 seconds. */ @@ -94,7 +90,6 @@ PluginSystem.prototype.reloadPlugins = function () { }, 3000); }; - /* -------- Register functions to let the IntelliSense know what's going on in helper files -------- */ /** @@ -116,7 +111,7 @@ PluginSystem.prototype._checkPlugin = function (folderName, thisPlugin, thisPlug * @param {string} pluginName Name of your plugin * @returns {string} Path to the folder containing your plugin data */ -PluginSystem.prototype.getPluginDataPath = function(pluginName) {}; // eslint-disable-line +PluginSystem.prototype.getPluginDataPath = function (pluginName) {}; // eslint-disable-line /** * Loads a file from your plugin data folder. The data will remain unprocessed. Use `loadPluginConfig()` instead if you want to load your plugin config. @@ -156,4 +151,10 @@ PluginSystem.prototype.loadPluginConfig = function (pluginName) {}; // eslint-di * @param {object} pluginConfig Config object of your plugin * @returns {Promise.} Resolves on success, rejects otherwise with an error */ -PluginSystem.prototype.writePluginConfig = function (pluginName, pluginConfig) {}; // eslint-disable-line \ No newline at end of file +PluginSystem.prototype.writePluginConfig = function (pluginName, pluginConfig) {}; // eslint-disable-line +/** + * Integrates changes made to the config to the users config + * @param {string} pluginName + * @returns {Record} the config + */ +PluginSystem.prototype.aggregatePluginConfig = function (pluginName) {}; // eslint-disable-line From 265928e433177f4671f5d8b15eb3f8c98d448b71 Mon Sep 17 00:00:00 2001 From: JLCD Date: Sun, 2 Jul 2023 14:23:23 +0200 Subject: [PATCH 07/43] fix(plugin) fixed edge case --- src/pluginSystem/handlePluginData.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pluginSystem/handlePluginData.js b/src/pluginSystem/handlePluginData.js index fca5786f..b8b27f93 100644 --- a/src/pluginSystem/handlePluginData.js +++ b/src/pluginSystem/handlePluginData.js @@ -143,6 +143,7 @@ PluginSystem.prototype.aggregatePluginConfig = function (pluginName) { let path = this.getPluginDataPath(pluginName); if (!fs.existsSync(path + "config.json")) return; + if (!fs.existsSync(`${srcdir}/../node_modules/${pluginName}/config.json`)) return; const standardConfig = require(`${srcdir}/../node_modules/${pluginName}/config.json`); const config = require(path + "config.json"); From 809c9f413ebe3f4970f2f7d9cf90f4404a0079c9 Mon Sep 17 00:00:00 2001 From: JLCD Date: Sun, 2 Jul 2023 14:39:24 +0200 Subject: [PATCH 08/43] feat(docs) updated the web server docs --- docs/wiki/integrating_into_your_app.md | 30 ++++++-------------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/docs/wiki/integrating_into_your_app.md b/docs/wiki/integrating_into_your_app.md index 2ce25d3e..5b63614b 100644 --- a/docs/wiki/integrating_into_your_app.md +++ b/docs/wiki/integrating_into_your_app.md @@ -1,30 +1,12 @@ # Integrating into your own application -[⬅️ Go back to wiki home](./) - -If you would like to integrate the comment command into your own application or you just don't want to deal with the Steam Chat then that is no problem! This can easily be done by pinging an URL. - -Note: The current webserver will be replaced with a better one in version 2.14, featuring a full fledged frontend. -First make sure that you started the bot at least once. -Go into your `plugins` and then `steam-comment-bot-webserver` folder, open `config.json` with a text editor, set `enabled` to `true` and save the file. -Start the bot again. You should see this message when the bot is ready: -``` -[INFO] Webserver is enabled: Server is listening on port 3034. - Visit it in your browser: http://localhost:3034 -``` - -If you now reopen the `config.json` you should see a new value at `requestKey`. Copy it as we will need it in a minute. -Do not share this key! It is used to authenticate yourself to the webserver and allow comment requests to be made in the name of the first owner! +[⬅️ Go back to wiki home](./) -Visit the URL in your webbrowser and you will see a page that instructs you how to use it. -If your bot is running on a different machine you will need to provide the IP of that machine instead of localhost but I will assume that you know basic networking here. To be able to reach the URL from outside your private network you will need to allow port 3034 in your router's settings and provide your public IP instead of localhost but this should also be basic networking knowledge. -I however do not recommend exposing this port without any further security measures as I can't guarantee for any security here whatsoever! +The bot comes with a web server plugin developed by [DerDeathraven](https://github.com/DerDeathraven) -Requesting comments is very easy now. Just ping the `/comment` page with the required query parameters shown on the page you just opened and the webserver will respond with a HTTP status code and a message. -Webserver comment requests will always be credited to the first owner set in the config. +Using a RPC style REST API you can easily call various methods. -Example: -`http://localhost:3034/comment?n=5&id=76561198260031749&key=pc90qtmzfk` +all methods follow the same pattern: +`https://localhost:4000/rpc/${Class}.${Method}?${params}` -This will request 5 comments for the steam profile `76561198260031749`. -You can of course also provide group or sharedfile IDs here. \ No newline at end of file +The full API documentation and a TS SDK file can be found on the [plugin page](https://github.com/DerDeathraven/steam-comment-bot-rest-api) From b9c3483d769e36538545c3096962631b1616d9e4 Mon Sep 17 00:00:00 2001 From: JLCD Date: Sun, 2 Jul 2023 14:48:13 +0200 Subject: [PATCH 09/43] feat(docs) updated plugins md --- docs/wiki/creating_plugins.md | 166 +++++++++++++++++++++------------- 1 file changed, 101 insertions(+), 65 deletions(-) diff --git a/docs/wiki/creating_plugins.md b/docs/wiki/creating_plugins.md index bff601e8..a0c54f2c 100644 --- a/docs/wiki/creating_plugins.md +++ b/docs/wiki/creating_plugins.md @@ -1,45 +1,49 @@ # Creating plugins + [⬅️ Go back to wiki home](./) The functionality of this bot can be extended using plugins. -They allow you to intercept events from the bots, run commands, edit or supply data and much much more. +They allow you to intercept events from the bots, run commands, edit or supply data and much much more. This guide will explain you the basics to get started and go through the template plugin! -I'm expecting you already have some experience programming and have worked with JavaScript, as well as NPM packages and Git. +I'm expecting you already have some experience programming and have worked with JavaScript, as well as NPM packages and Git. You do not need to read this quite long article. Feel free to [set up](#getting-started) and just start playing around with parts of the bot using your code editor's IntelliSense. -You should definitely take a look at the developer documentation though, it explains everything every module does and the functions exposed by it. +You should definitely take a look at the developer documentation though, it explains everything every module does and the functions exposed by it.   ## Table Of Contents -- [Getting started](#getting-started) -- [The filestructure](#filestructure) -- [Exposed functions and events](#functions) -- [Logging messages](#logging) -- [Plugin System Interface](#pluginsystem) -- [Controller](#controller) -- [Command System](#commandhandler) -- [Packing and installing your plugin using npm](#npm) -- [Additional information](#additional-info) + +- [Getting started](#getting-started) +- [The filestructure](#filestructure) +- [Exposed functions and events](#functions) +- [Logging messages](#logging) +- [Plugin System Interface](#pluginsystem) +- [Controller](#controller) +- [Command System](#commandhandler) +- [Typescript](#typescript) +- [Packing and installing your plugin using npm](#npm) +- [Additional information](#additional-info)   ## **Getting started** + First, fork my [plugin template repository](https://github.com/3urobeat/steam-comment-bot-template-plugin). -You can do this easily through the GitHub web interface. +You can do this easily through the GitHub web interface. Give your fork a fitting name, but make sure to keep the `steam-comment-bot-` prefix. This is important later. -It probably also makes sense to keep the `-plugin` at the end, to indicate that your fork is a plugin. +It probably also makes sense to keep the `-plugin` at the end, to indicate that your fork is a plugin. Now, clone your fork, for example using the git cli: `git clone https://github.com/your_username/your_fork ./folder/path/to/clone/to` Open the folder you cloned to with your code editor and open the package.json file inside. Change the name to the name you gave your fork. For the bot to recognize your plugin, it must have the `steam-comment-bot-` prefix I mentioned above. -Populate description, author and version as well. The plugin will be packed into an NPM package later. +Populate description, author and version as well. The plugin will be packed into an NPM package later. Open the entry file `plugin.js` and edit the PluginSystem import file path at the top. It should point to your `steam-comment-service-bot` installation. This makes sure your code editor's IntelliSense will work. @@ -51,59 +55,64 @@ If your plugin folder is right beside the bot folder, the default path should al ## **The filestructure** -Each plugin consists of three important files. -- `plugin.js` - The entry file of your plugin. This one will be loaded by the bot and contains all the functions exposed by your plugin. It must contain an exposed constructor and load function. -- `config.json` - The default configuration file of your plugin. This one will be copied into the plugin config folder by the bot the first time your plugin gets loaded. It must contain the parameter "enabled", everything else is up to you. -- `package.json` - The NPM package config file of your plugin. This one will be read by NPM to package and install your plugin. The bot will go through all installed npm packages with the `steam-comment-bot-` name prefix and attempt to load their `plugin.js` file. -You can of course add more files and folders as you like and load them from the `plugin.js` file. +Each plugin consists of three important files. + +- `plugin.js` - The entry file of your plugin. This one will be loaded by the bot and contains all the functions exposed by your plugin. It must contain an exposed constructor and load function. +- `config.json` - The default configuration file of your plugin. This one will be copied into the plugin config folder by the bot the first time your plugin gets loaded. It must contain the parameter "enabled", everything else is up to you. +- `package.json` - The NPM package config file of your plugin. This one will be read by NPM to package and install your plugin. The bot will go through all installed npm packages with the `steam-comment-bot-` name prefix and attempt to load their `plugin.js` file. + +You can of course add more files and folders as you like and load them from the `plugin.js` file.   ## **Exposed functions and events** + Let's take a look at what the template plugin does: -Your plugin file `plugin.js` must expose a constructor and load function, just like the template does. +Your plugin file `plugin.js` must expose a constructor and load function, just like the template does. **Constructor:** The template constructor stores references to the pluginSystem 'sys', the controller (which is the central part of the bot, "controlling" everything), the dataManager 'data' (which imports, checks and stores all config files) and the commandHandler (which loads, stores and runs all commands). This makes using those interesting parts from your plugin easier and is probably a good idea to keep. You **need** the 'sys' reference, otherwise your plugin won't be able to communicate with the bot, making it pretty much useless. -Please also keep the `logger` overwrite. It makes sure that the log hold-back functionality during login is working. +Please also keep the `logger` overwrite. It makes sure that the log hold-back functionality during login is working. **Load function:** The load function is being called when the plugin is loaded. This happens right before the bot starts logging in accounts or right after the '!reload' command was used. It makes sense to load your plugin config file from your plugin config folder, just like the template does. -We are also registering a super cool command here with the names '!hello' and '!cool-alias'. If someone executes it, it will respond with 'Hello World!'. Registering commands and responding to the user is further explained below. +We are also registering a super cool command here with the names '!hello' and '!cool-alias'. If someone executes it, it will respond with 'Hello World!'. Registering commands and responding to the user is further explained below. **Event functions:** The template plugin also exposes a 'ready', 'statusUpdate', 'steamGuardInput' function. -These are functions that will be called by the plugin system when the bot emits those events. +These are functions that will be called by the plugin system when the bot emits those events. The ready event function is called when the bot has finished logging in all accounts. Should the plugin load be caused by '!reload', this function is executed milliseconds after `load()` has been called. The statusUpdate event function is called when any bot account changes their status. Every status a bot can have is documented in the [EStatus enum](../../src/bot/EStatus.js). -The steamGuardInput event function is called when any bot account is currently being logged in, but a Steam Guard Code is requested. The bot has a built in handler that will request code input from the terminal on this event. +The steamGuardInput event function is called when any bot account is currently being logged in, but a Steam Guard Code is requested. The bot has a built in handler that will request code input from the terminal on this event.   ## **Logging messages** + I'm using my own [logging library](https://github.com/3urobeat/output-logger) to log everything to the terminal and the `output.txt` file. It is easy to use, do not be afraid of this wall of text ^^ -Please do not use any `console.log` calls in your plugins (unless maybe for debugging). +Please do not use any `console.log` calls in your plugins (unless maybe for debugging). + +Here is the parameter structure, first to last: -Here is the parameter structure, first to last: -- One of these types: 'debug', 'info', 'warn', 'error'. Debug mesages are only logged if `printDebug` is set to true in `advancedconfig.json` -- The message you want to log. If not of datatype string, the library will attempt to colorize the data, just like console.log does. -- Optional - nodate: true if the message should not have a date -- Optional - remove: true if the next message should overwrite this one -- Optional - animation: An array containing strings. If this is specified, it will display each element of this array after another in the front of the message as an animation. The logger library has some default animations, check them out using your IntelliSense at: `logger.animations` or [here](https://github.com/3urobeat/output-logger/blob/master/lib/data/animations.json) -- Optional - printNow: true to force print this message now. This will skip the log hold back system explained below -- Optional - cutToWidth: true to force cut this message to the current width of the terminal +- One of these types: 'debug', 'info', 'warn', 'error'. Debug mesages are only logged if `printDebug` is set to true in `advancedconfig.json` +- The message you want to log. If not of datatype string, the library will attempt to colorize the data, just like console.log does. +- Optional - nodate: true if the message should not have a date +- Optional - remove: true if the next message should overwrite this one +- Optional - animation: An array containing strings. If this is specified, it will display each element of this array after another in the front of the message as an animation. The logger library has some default animations, check them out using your IntelliSense at: `logger.animations` or [here](https://github.com/3urobeat/output-logger/blob/master/lib/data/animations.json) +- Optional - printNow: true to force print this message now. This will skip the log hold back system explained below +- Optional - cutToWidth: true to force cut this message to the current width of the terminal Check out the JsDoc of the logger function directly: [controller logger.js](../../src/controller/helpers/logger.js) -You can also use this library to read input from the user, display a progress bar, managing animations and much more. Please check out the [output-logger README](https://github.com/3urobeat/output-logger) for more information. +You can also use this library to read input from the user, display a progress bar, managing animations and much more. Please check out the [output-logger README](https://github.com/3urobeat/output-logger) for more information. Do not be confused if your log messages are not showing up instantly while the bot is still logging in. The bot has a logger hold-back functionality which holds back every log message that is not of type 'debug' or 'error' or has `printNow` set to true during login. These messages will be logged as soon as the bot is started, aka the ready event has fired. @@ -113,27 +122,30 @@ The bot has a logger hold-back functionality which holds back every log message ## **Plugin System Interface** + As mentioned above, your constructor gets a reference to the Plugin System as the first parameter. The Plugin System is responsible for loading, checking and calling plugin functions, as well as providing you functions to write to and read from your plugin data folder. -It also stores references to the controller, giving you access to every part of the bot. +It also stores references to the controller, giving you access to every part of the bot. The Plugin System is probably the most important part for you when developing a plugin. -Check it out using your IntelliSense and take a look at the developer documentation (TODO). +Check it out using your IntelliSense and take a look at the developer documentation (TODO).   ## **Controller** + The Controller is the most important part of the application itself. -It is responsible for loading all modules on start, storing references to them, logging in all bot accounts and handling any issues. +It is responsible for loading all modules on start, storing references to them, logging in all bot accounts and handling any issues. You can access it from your plugin through the Plugin System: `sys.controller` -From there, every other module of the bot is accessible. Worth noting: -- Functions to restart/stop the application, resolving steamIDs, getting bot accounts, etc. -- `sys.controller.data` - The DataManager object which contains every loaded datafile (e.g. logininfo, config, quotes, proxies, etc.) -- `sys.controller.bots` - Object which holds references to all Bot objects, mapped to their account names. Access any bot account that is in use right now from there. I recommend using the `getBots()` function instead of accessing this object directly. -- `sys.controller.commandHandler` - The CommandHandler object, read more [below](#commandhandler). +From there, every other module of the bot is accessible. Worth noting: + +- Functions to restart/stop the application, resolving steamIDs, getting bot accounts, etc. +- `sys.controller.data` - The DataManager object which contains every loaded datafile (e.g. logininfo, config, quotes, proxies, etc.) +- `sys.controller.bots` - Object which holds references to all Bot objects, mapped to their account names. Access any bot account that is in use right now from there. I recommend using the `getBots()` function instead of accessing this object directly. +- `sys.controller.commandHandler` - The CommandHandler object, read more [below](#commandhandler). ...and much more. Check it out using your code editor's IntelliSense. @@ -142,28 +154,49 @@ From there, every other module of the bot is accessible. Worth noting: ## **Command System** + The CommandHandler allows you to register and run commands. Commands are the core functionalities that allow you to request comments, retrieve information and manage the bot. -Any command you register will instantly be available to all message handlers. +Any command you register will instantly be available to all message handlers. By default the bot has built-in Steam Chat message handling. You can implement your own message handler as well, allowing you to integrate all registered commands into other platforms. -Take a look at the developer documentation (TODO) for more information about how to write a custom message handler. +Take a look at the developer documentation (TODO) for more information about how to write a custom message handler.   + + +## **Typescript:** + +For the best development environment you can utilize our typing file in TS +just take the [typing file](https://github.com/3urobeat/steam-comment-service-bot/blob/beta-testing/types/types.d.ts) and copy it to your project + +there you can point your ts compiler to the file by adding the following to your tsconfig.json + +```json +{ + "compilerOptions": { + "types": ["path/to/typing-file"] + } +} +``` + +The [web server](https://github.com/DerDeathraven/steam-comment-bot-rest-api) plugin is written in TS and can be used as a example ## **Packing and installing your plugin using npm** + If you have a version that you would like to **pack locally**, follow these steps: -- Open the `package.json` file of your plugin and give it a proper version. NPM packages use [semantic versioning](https://semver.org/). In short, this means: - - The version number is split into three parts: MAJOR.MINOR.PATCH - - Increment MAJOR if you make breaking changes, e.g. user interaction is required to update your package - - Increment MINOR if you add new functionality that is backwards compatible, e.g. no direct user interaction is required to update - - Increment PATCH if you made bugfixes or other small changes which also do not require user interaction - - If you do not have a full release finished yet, e.g. a beta version, start with the version number `0.1.0`. Your first full release `1.0.0` is appropiate when the core functionality has been finished and no major bugs are to be expected -- Open a command line/terminal window in your plugin project folder and run `npm pack`. On success a new `.tgz` archive appeared in your folder. -- Copy the package archive to your steam-comment-service-bot folder, open a new terminal there and run `npm install ./the-archive-name.tgz` + +- Open the `package.json` file of your plugin and give it a proper version. NPM packages use [semantic versioning](https://semver.org/). In short, this means: + - The version number is split into three parts: MAJOR.MINOR.PATCH + - Increment MAJOR if you make breaking changes, e.g. user interaction is required to update your package + - Increment MINOR if you add new functionality that is backwards compatible, e.g. no direct user interaction is required to update + - Increment PATCH if you made bugfixes or other small changes which also do not require user interaction + - If you do not have a full release finished yet, e.g. a beta version, start with the version number `0.1.0`. Your first full release `1.0.0` is appropiate when the core functionality has been finished and no major bugs are to be expected +- Open a command line/terminal window in your plugin project folder and run `npm pack`. On success a new `.tgz` archive appeared in your folder. +- Copy the package archive to your steam-comment-service-bot folder, open a new terminal there and run `npm install ./the-archive-name.tgz` On restart (or by running the command `!reload`) you should see your plugin get loaded! The bot will automatically create a new data folder for your plugin in the `plugins` folder. It will already contain the default config you shipped with your plugin. @@ -171,10 +204,11 @@ The bot will automatically create a new data folder for your plugin in the `plug   If you have a finished version of your plugin that you would like to **publish to NPM**, follow these steps: -- If this is your first time, create an [NPM account](https://www.npmjs.com/signup), open a command line/terminal in your plugin project folder and run `npm login`. (I assume you have npm installed alongside node) -- Once that is done, give your plugin a proper version number in `package.json`. NPM packages use semantic versioning which is explained above. -- Run `npm publish` in the command line/terminal window from step 1. -- If everything goes well, your package should now be accessible to anyone. Check it out by searching for it [on the npm webpage](https://www.npmjs.com/)! + +- If this is your first time, create an [NPM account](https://www.npmjs.com/signup), open a command line/terminal in your plugin project folder and run `npm login`. (I assume you have npm installed alongside node) +- Once that is done, give your plugin a proper version number in `package.json`. NPM packages use semantic versioning which is explained above. +- Run `npm publish` in the command line/terminal window from step 1. +- If everything goes well, your package should now be accessible to anyone. Check it out by searching for it [on the npm webpage](https://www.npmjs.com/)! To install and use your plugin anyone can now run the command `npm install steam-comment-bot-your-plugin-name` in their steam-comment-service-bot folder. On restart (or by running the command `!reload`) you should see your plugin get loaded! @@ -185,22 +219,24 @@ The bot will automatically create a new data folder for your plugin in the `plug ## **Additional information** + **Debug Mode:** It may make sense to enable `printDebug` in the `advancedconfig.json` while you are working on your plugin. This will log way more stuff while the bot is running to maybe help you debug your plugin. -Feel free to include 'debug' log calls in your plugin as well! +Feel free to include 'debug' log calls in your plugin as well!   **More efficient NPM setup for development:** To improve your plugin development experience it is recommended to link your project and the bot using npm. -This will allow you to test changes without needing to pack or publish the plugin. +This will allow you to test changes without needing to pack or publish the plugin. + +To do this, follow these steps: -To do this, follow these steps: -- Open a command line/terminal window in the folder of your plugin project -- Run the command `npm link`. On Linux you might have to precede the command with `sudo` (or doas, or whatever you are using). - This will make the package available locally to all projects -- Open a terminal window in the folder of your bot installation. Run the command `npm link name-of-your-package` +- Open a command line/terminal window in the folder of your plugin project +- Run the command `npm link`. On Linux you might have to precede the command with `sudo` (or doas, or whatever you are using). + This will make the package available locally to all projects +- Open a terminal window in the folder of your bot installation. Run the command `npm link name-of-your-package` On restart (or by running the command `!reload`) you should see your plugin get loaded! If you make changes in your plugin project you now only need to run the `!reload` command to test them. @@ -209,4 +245,4 @@ If you make changes in your plugin project you now only need to run the `!reload **Issues and Pull Requests:** You found a bug or you think something should be changed in the bot itself? -Feel free to [open an issue](https://github.com/3urobeat/steam-comment-service-bot/issues/new/choose) or fork the bot, make changes and [open a pull request](https://github.com/3urobeat/steam-comment-service-bot/compare) yourself! Every contribution is welcome! \ No newline at end of file +Feel free to [open an issue](https://github.com/3urobeat/steam-comment-service-bot/issues/new/choose) or fork the bot, make changes and [open a pull request](https://github.com/3urobeat/steam-comment-service-bot/compare) yourself! Every contribution is welcome! From 507c0cab43b150fa921224756b4b45f8ae68ec5a Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Sun, 2 Jul 2023 12:55:47 +0000 Subject: [PATCH 10/43] Add missing line break --- docs/wiki/creating_plugins.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/wiki/creating_plugins.md b/docs/wiki/creating_plugins.md index a0c54f2c..4929f472 100644 --- a/docs/wiki/creating_plugins.md +++ b/docs/wiki/creating_plugins.md @@ -164,6 +164,7 @@ You can implement your own message handler as well, allowing you to integrate al Take a look at the developer documentation (TODO) for more information about how to write a custom message handler.   + ## **Typescript:** @@ -183,6 +184,8 @@ there you can point your ts compiler to the file by adding the following to your The [web server](https://github.com/DerDeathraven/steam-comment-bot-rest-api) plugin is written in TS and can be used as a example +  + ## **Packing and installing your plugin using npm** From ba94511d35fa4eb49dcbf297833a35b7d2a1bb37 Mon Sep 17 00:00:00 2001 From: JLCD Date: Sun, 2 Jul 2023 14:56:15 +0200 Subject: [PATCH 11/43] fix(plugin) fixed styling --- src/dataManager/dataImport.js | 34 ++++++++++++++-------------- src/pluginSystem/handlePluginData.js | 1 - src/pluginSystem/loadPlugins.js | 1 + 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/dataManager/dataImport.js b/src/dataManager/dataImport.js index 6dcbcbf8..35e03b27 100644 --- a/src/dataManager/dataImport.js +++ b/src/dataManager/dataImport.js @@ -14,9 +14,9 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see . */ -const fs = require("fs"); -const path = require("path"); -const nedb = require("@seald-io/nedb"); +const fs = require("fs"); +const path = require("path"); +const nedb = require("@seald-io/nedb"); const DataManager = require("./dataManager.js"); /** @@ -326,20 +326,20 @@ DataManager.prototype._importFromDisk = function () { // Call all functions from above after another. This must be done async to avoid a check failing that depends on something from a previous function logger("info", "Importing data files and settings...", false, true, logger.animation("loading")); - this.cachefile = await loadCache(); - this.datafile = await loadData(); - this.config = await loadConfig(); - this.advancedconfig = await loadAdvancedConfig(); - this.logininfo = await loadLoginInfo(); - this.proxies = await loadProxies(); - this.quotes = await loadQuotes(); - this.lang = await loadLanguage(); - this.lang = await loadCustomLang(); - this.pluginVersions = this.cachefile.pluginVersions; - - this.lastCommentDB = new nedb({ filename: srcdir + "/data/lastcomment.db", autoload: true }); // Autoload - this.ratingHistoryDB = new nedb({ filename: srcdir + "/data/ratingHistory.db", autoload: true }); - this.tokensDB = new nedb({ filename: srcdir + "/data/tokens.db", autoload: true }); + this.cachefile = await loadCache(); + this.datafile = await loadData(); + this.config = await loadConfig(); + this.advancedconfig = await loadAdvancedConfig(); + this.logininfo = await loadLoginInfo(); + this.proxies = await loadProxies(); + this.quotes = await loadQuotes(); + this.lang = await loadLanguage(); + this.lang = await loadCustomLang(); + this.pluginVersions = this.cachefile.pluginVersions; + + this.lastCommentDB = new nedb({ filename: srcdir + "/data/lastcomment.db", autoload: true }); // Autoload + this.ratingHistoryDB = new nedb({ filename: srcdir + "/data/ratingHistory.db", autoload: true }); + this.tokensDB = new nedb({ filename: srcdir + "/data/tokens.db", autoload: true }); // Check tokens.db every 24 hours for expired tokens to allow users to refresh them beforehand this._startExpiringTokensCheckInterval(); diff --git a/src/pluginSystem/handlePluginData.js b/src/pluginSystem/handlePluginData.js index b8b27f93..0ef8459d 100644 --- a/src/pluginSystem/handlePluginData.js +++ b/src/pluginSystem/handlePluginData.js @@ -17,7 +17,6 @@ const fs = require("fs"); const PluginSystem = require("./pluginSystem.js"); -const { logger } = require("output-logger/lib/logger.js"); /** * Gets the path holding all data of a plugin. If no folder exists yet, one will be created diff --git a/src/pluginSystem/loadPlugins.js b/src/pluginSystem/loadPlugins.js index c9f8bcdf..095eee60 100644 --- a/src/pluginSystem/loadPlugins.js +++ b/src/pluginSystem/loadPlugins.js @@ -25,6 +25,7 @@ const PLUGIN_EVENTS = { steamGuardInput: "steamGuardInput", }; +// Attempt to load all plugins. If a critical check fails loading will be denied function loadPlugin(pluginName) { try { // Load plugin and pluginJson From 9f69e893955c9b33d746583aee931597860b950f Mon Sep 17 00:00:00 2001 From: JLCD Date: Sun, 2 Jul 2023 14:56:27 +0200 Subject: [PATCH 12/43] updated link --- src/pluginSystem/loadPlugins.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pluginSystem/loadPlugins.js b/src/pluginSystem/loadPlugins.js index 095eee60..69fb2eb1 100644 --- a/src/pluginSystem/loadPlugins.js +++ b/src/pluginSystem/loadPlugins.js @@ -7,7 +7,7 @@ * Last Modified: 04.06.2023 19:31:20 * Modified By: 3urobeat * - * Copyright (c) 2023 3urobeat + * Copyright (c) 2023 3urobeat * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. From 8517bab6b5d59f65f2c3be0f73f2901aea54b62b Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Sun, 2 Jul 2023 18:54:40 +0200 Subject: [PATCH 13/43] Formatting --- src/dataManager/dataImport.js | 49 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/dataManager/dataImport.js b/src/dataManager/dataImport.js index 35e03b27..83e8a8ed 100644 --- a/src/dataManager/dataImport.js +++ b/src/dataManager/dataImport.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 02.07.2023 18:51:27 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -14,9 +14,9 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see . */ -const fs = require("fs"); -const path = require("path"); -const nedb = require("@seald-io/nedb"); +const fs = require("fs"); +const path = require("path"); +const nedb = require("@seald-io/nedb"); const DataManager = require("./dataManager.js"); /** @@ -27,8 +27,7 @@ DataManager.prototype._importFromDisk = function () { let _this = this; // Make this accessible within the functions below return new Promise((resolve) => { - (async () => { - // Lets us use await inside a Promise without creating an antipattern + (async () => { // Lets us use await inside a Promise without creating an antipattern function loadCache() { return new Promise((resolve) => { @@ -69,7 +68,7 @@ DataManager.prototype._importFromDisk = function () { // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. if (_this.cachefile.datajson) _this._restoreBackup("data.json", srcdir + "/data/data.json", _this.cachefile.datajson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/src/data/data.json", resolve); - else _this._pullNewFile("data.json", "./src/data/data.json", resolve); + else _this._pullNewFile("data.json", "./src/data/data.json", resolve); } } }); @@ -104,7 +103,7 @@ DataManager.prototype._importFromDisk = function () { setTimeout(() => { // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. if (_this.cachefile.configjson) _this._restoreBackup("config.json", srcdir + "/../config.json", _this.cachefile.configjson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/config.json", resolve); - else _this._pullNewFile("config.json", "./config.json", resolve); + else _this._pullNewFile("config.json", "./config.json", resolve); }, restoreTimeout); } } @@ -123,7 +122,7 @@ DataManager.prototype._importFromDisk = function () { // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. if (_this.cachefile.advancedconfigjson) _this._restoreBackup("advancedconfig.json", srcdir + "/../advancedconfig.json", _this.cachefile.advancedconfigjson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/advancedconfig.json", resolve); - else _this._pullNewFile("advancedconfig.json", "./advancedconfig.json", resolve); + else _this._pullNewFile("advancedconfig.json", "./advancedconfig.json", resolve); } } }); @@ -203,7 +202,7 @@ DataManager.prototype._importFromDisk = function () { fs.writeFile(srcdir + "/../proxies.txt", "", (err) => { if (err) logger("error", "error creating proxies.txt file: " + err); - else logger("info", "Successfully created proxies.txt file.", false, true, logger.animation("loading")); + else logger("info", "Successfully created proxies.txt file.", false, true, logger.animation("loading")); }); } else { // File does seem to exist so now we can try and read it @@ -311,7 +310,7 @@ DataManager.prototype._importFromDisk = function () { if (i == Object.keys(customlang).length - 1) { // Check for last iteration if (customlangkeys > 0) logger("info", `${customlangkeys} customlang key imported!`, false, true, logger.animation("loading")); - else logger("info", "No customlang keys found.", false, true, logger.animation("loading")); + else logger("info", "No customlang keys found.", false, true, logger.animation("loading")); resolve(_this.lang); // Resolve lang object with our new keys } @@ -326,20 +325,20 @@ DataManager.prototype._importFromDisk = function () { // Call all functions from above after another. This must be done async to avoid a check failing that depends on something from a previous function logger("info", "Importing data files and settings...", false, true, logger.animation("loading")); - this.cachefile = await loadCache(); - this.datafile = await loadData(); - this.config = await loadConfig(); - this.advancedconfig = await loadAdvancedConfig(); - this.logininfo = await loadLoginInfo(); - this.proxies = await loadProxies(); - this.quotes = await loadQuotes(); - this.lang = await loadLanguage(); - this.lang = await loadCustomLang(); - this.pluginVersions = this.cachefile.pluginVersions; - - this.lastCommentDB = new nedb({ filename: srcdir + "/data/lastcomment.db", autoload: true }); // Autoload - this.ratingHistoryDB = new nedb({ filename: srcdir + "/data/ratingHistory.db", autoload: true }); - this.tokensDB = new nedb({ filename: srcdir + "/data/tokens.db", autoload: true }); + this.cachefile = await loadCache(); + this.datafile = await loadData(); + this.config = await loadConfig(); + this.advancedconfig = await loadAdvancedConfig(); + this.logininfo = await loadLoginInfo(); + this.proxies = await loadProxies(); + this.quotes = await loadQuotes(); + this.lang = await loadLanguage(); + this.lang = await loadCustomLang(); + this.pluginVersions = this.cachefile.pluginVersions; + + this.lastCommentDB = new nedb({ filename: srcdir + "/data/lastcomment.db", autoload: true }); // Autoload + this.ratingHistoryDB = new nedb({ filename: srcdir + "/data/ratingHistory.db", autoload: true }); + this.tokensDB = new nedb({ filename: srcdir + "/data/tokens.db", autoload: true }); // Check tokens.db every 24 hours for expired tokens to allow users to refresh them beforehand this._startExpiringTokensCheckInterval(); From c2d067a97e050645ac60874daffefb36b9d5f0b3 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Sun, 2 Jul 2023 18:56:16 +0200 Subject: [PATCH 14/43] Update dependencies --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10e0b574..b2efff8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "https": "^1.0.0", "output-logger": "^2.3.7", "request": "^2.88.2", - "steam-comment-bot-rest": "^1.0.3", + "steam-comment-bot-rest": "^1.0.4", "steam-comment-bot-webserver": "file:plugins/steam-comment-bot-webserver-1.0.0.tgz", "steam-session": "^1.2.4", "steam-user": "^4.28.8", @@ -283,9 +283,9 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "node_modules/@types/node": { - "version": "20.3.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.2.tgz", - "integrity": "sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw==" + "version": "20.3.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz", + "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==" }, "node_modules/@types/qs": { "version": "6.9.7", @@ -3321,9 +3321,9 @@ } }, "node_modules/steam-comment-bot-rest": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/steam-comment-bot-rest/-/steam-comment-bot-rest-1.0.3.tgz", - "integrity": "sha512-WEwNNRtQvNwxa0wOzgrEyjVCYU3uH1NUU1QqC8VOaLiPDteHaz9AYZjnczcpT3zI0IsUBq4oGvQmZ7W+blMStQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/steam-comment-bot-rest/-/steam-comment-bot-rest-1.0.4.tgz", + "integrity": "sha512-WkZIsRcN44E4TBgki7DSurvs3xt4N3hZuKZqookst++o8aXrzDLw7L6B8QTyXoVMNakjYQBClGZGQTvlpXSWsg==", "hasInstallScript": true, "dependencies": { "@types/axios": "^0.14.0", diff --git a/package.json b/package.json index 7ba3e418..933d3ced 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "https": "^1.0.0", "output-logger": "^2.3.7", "request": "^2.88.2", - "steam-comment-bot-rest": "^1.0.3", + "steam-comment-bot-rest": "^1.0.4", "steam-comment-bot-webserver": "file:plugins/steam-comment-bot-webserver-1.0.0.tgz", "steam-session": "^1.2.4", "steam-user": "^4.28.8", From 3e19d63d89aaf9ad74dfe6425dcad74943f48438 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Sun, 2 Jul 2023 19:08:36 +0200 Subject: [PATCH 15/43] Simplify reading & writing to pluginVersions --- src/dataManager/dataImport.js | 3 +-- src/dataManager/dataManager.js | 8 ++------ src/dataManager/helpers/refreshCache.js | 3 +-- src/pluginSystem/loadPlugins.js | 12 ++++++++---- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/dataManager/dataImport.js b/src/dataManager/dataImport.js index 83e8a8ed..32a81797 100644 --- a/src/dataManager/dataImport.js +++ b/src/dataManager/dataImport.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 02.07.2023 18:51:27 + * Last Modified: 02.07.2023 19:06:36 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -334,7 +334,6 @@ DataManager.prototype._importFromDisk = function () { this.quotes = await loadQuotes(); this.lang = await loadLanguage(); this.lang = await loadCustomLang(); - this.pluginVersions = this.cachefile.pluginVersions; this.lastCommentDB = new nedb({ filename: srcdir + "/data/lastcomment.db", autoload: true }); // Autoload this.ratingHistoryDB = new nedb({ filename: srcdir + "/data/ratingHistory.db", autoload: true }); diff --git a/src/dataManager/dataManager.js b/src/dataManager/dataManager.js index 9bf6551d..10ce8984 100644 --- a/src/dataManager/dataManager.js +++ b/src/dataManager/dataManager.js @@ -4,7 +4,7 @@ * Created Date: 21.03.2023 22:34:51 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 02.07.2023 19:07:22 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -73,7 +73,7 @@ const DataManager = function (controller) { /** * Stores IDs from config files converted at runtime and backups for all config & data files. - * @type {{ ownerid: Array, botsgroup: string, botsgroupid: string, configgroup: string, configgroup64id: string, ownerlinkid: string, botaccid: Array, configjson: {}, advancedconfigjson: {}, datajson: {} }} + * @type {{ ownerid: Array, botsgroup: string, botsgroupid: string, configgroup: string, configgroup64id: string, ownerlinkid: string, botaccid: Array, pluginVersions: {}, configjson: {}, advancedconfigjson: {}, datajson: {} }} */ this.cachefile = {}; @@ -103,10 +103,6 @@ const DataManager = function (controller) { * @type {Nedb} */ this.tokensDB = {}; - /** - * The last seen plugin versions. - */ - this.pluginVersions = {}; // Dynamically load all helper files const loadHelpersFromFolder = (folder) => { diff --git a/src/dataManager/helpers/refreshCache.js b/src/dataManager/helpers/refreshCache.js index 2acefd92..8afc12f5 100644 --- a/src/dataManager/helpers/refreshCache.js +++ b/src/dataManager/helpers/refreshCache.js @@ -4,7 +4,7 @@ * Created Date: 29.03.2023 17:44:47 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 02.07.2023 19:07:41 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -49,7 +49,6 @@ DataManager.prototype.refreshCache = function () { this.cachefile["configjson"] = this.config; this.cachefile["advancedconfigjson"] = this.advancedconfig; this.cachefile["datajson"] = this.datafile; - this.cachefile["pluginVersions"] = this.pluginVersions; // Write changes to file fs.writeFile(srcdir + "/data/cache.json", JSON.stringify(this.cachefile, null, 4), (err) => { diff --git a/src/pluginSystem/loadPlugins.js b/src/pluginSystem/loadPlugins.js index 69fb2eb1..47f4ca90 100644 --- a/src/pluginSystem/loadPlugins.js +++ b/src/pluginSystem/loadPlugins.js @@ -4,7 +4,7 @@ * Created Date: 04.06.2023 15:37:17 * Author: DerDeathraven * - * Last Modified: 04.06.2023 19:31:20 + * Last Modified: 02.07.2023 19:07:59 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -59,20 +59,23 @@ PluginSystem.prototype._loadPlugins = async function () { for (const plugin of initiatedPlugins) { const { pluginName, pluginInstance, pluginJson } = plugin; + if (!pluginInstance) { logger("warn", `Skipping plugin '${pluginName}'...`, false, false, null, true); // Force print now continue; } + let pluginConfig = {}; - const lastSeenVersion = this.controller.data.pluginVersions; + const lastSeenVersion = this.controller.data.cachefile.pluginVersions; + if (lastSeenVersion[pluginName] && lastSeenVersion[pluginName] !== pluginJson.version) { logger("warn", `Plugin '${pluginName}' is outdated! Updating plugin...`, false, false, null, true); // Force print now pluginConfig = this.aggregatePluginConfig(pluginName); } else { pluginConfig = await this.loadPluginConfig(pluginName).catch((err) => logger("error", `The config of plugin '${pluginName}' is fucked, skipping plugin. ${err}`)); } - // Skip plugin if it is disabled + // Skip plugin if it is disabled if (!pluginConfig || !pluginConfig.enabled) { logger("debug", `Plugin '${pluginName}' is disabled. Skipping plugin...`); continue; @@ -89,6 +92,7 @@ PluginSystem.prototype._loadPlugins = async function () { // eslint-disable-line this.controller.events.on(event, (...args) => pluginInstance[event]?.call(pluginInstance, ...args)); }); - this.controller.data.pluginVersions[pluginName] = pluginJson.version; + + this.controller.data.cachefile.pluginVersions[pluginName] = pluginJson.version; } }; From 329ad48ac86b0beaf4f49dbae7206c5b82a3d0ac Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Sun, 2 Jul 2023 19:13:41 +0200 Subject: [PATCH 16/43] Fix error on pluginVersions update if key does not exist yet --- src/dataManager/dataManager.js | 4 ++-- src/pluginSystem/loadPlugins.js | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/dataManager/dataManager.js b/src/dataManager/dataManager.js index 10ce8984..de4a3f26 100644 --- a/src/dataManager/dataManager.js +++ b/src/dataManager/dataManager.js @@ -4,7 +4,7 @@ * Created Date: 21.03.2023 22:34:51 * Author: 3urobeat * - * Last Modified: 02.07.2023 19:07:22 + * Last Modified: 02.07.2023 19:10:50 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -73,7 +73,7 @@ const DataManager = function (controller) { /** * Stores IDs from config files converted at runtime and backups for all config & data files. - * @type {{ ownerid: Array, botsgroup: string, botsgroupid: string, configgroup: string, configgroup64id: string, ownerlinkid: string, botaccid: Array, pluginVersions: {}, configjson: {}, advancedconfigjson: {}, datajson: {} }} + * @type {{ ownerid: Array, botsgroup: string, botsgroupid: string, configgroup: string, configgroup64id: string, ownerlinkid: string, botaccid: Array, pluginVersions: object., configjson: {}, advancedconfigjson: {}, datajson: {} }} */ this.cachefile = {}; diff --git a/src/pluginSystem/loadPlugins.js b/src/pluginSystem/loadPlugins.js index 47f4ca90..69c8e5a3 100644 --- a/src/pluginSystem/loadPlugins.js +++ b/src/pluginSystem/loadPlugins.js @@ -4,7 +4,7 @@ * Created Date: 04.06.2023 15:37:17 * Author: DerDeathraven * - * Last Modified: 02.07.2023 19:07:59 + * Last Modified: 02.07.2023 19:12:35 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -68,7 +68,7 @@ PluginSystem.prototype._loadPlugins = async function () { let pluginConfig = {}; const lastSeenVersion = this.controller.data.cachefile.pluginVersions; - if (lastSeenVersion[pluginName] && lastSeenVersion[pluginName] !== pluginJson.version) { + if (lastSeenVersion && lastSeenVersion[pluginName] && lastSeenVersion[pluginName] !== pluginJson.version) { logger("warn", `Plugin '${pluginName}' is outdated! Updating plugin...`, false, false, null, true); // Force print now pluginConfig = this.aggregatePluginConfig(pluginName); } else { @@ -93,6 +93,8 @@ PluginSystem.prototype._loadPlugins = async function () { this.controller.events.on(event, (...args) => pluginInstance[event]?.call(pluginInstance, ...args)); }); + // Update last seen version of this plugin name + if (!lastSeenVersion) this.controller.data.cachefile.pluginVersions = {}; this.controller.data.cachefile.pluginVersions[pluginName] = pluginJson.version; } }; From 2f19287a90de881351fa50420f840f78586c2842 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Mon, 3 Jul 2023 15:49:13 +0200 Subject: [PATCH 17/43] Add missing hyperlinks --- docs/wiki/changelogs/CHANGELOG_v2.13.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/wiki/changelogs/CHANGELOG_v2.13.md b/docs/wiki/changelogs/CHANGELOG_v2.13.md index 42b029b3..9c93e3b8 100644 --- a/docs/wiki/changelogs/CHANGELOG_v2.13.md +++ b/docs/wiki/changelogs/CHANGELOG_v2.13.md @@ -35,8 +35,8 @@ If you are using a `customlang.json`, make sure to read the language string chan - Added a library patches system to load my changes until [my PR to the SteamCommunity library gets accepted](https://github.com/DoctorMcKay/node-steamcommunity/pull/306) - Added support for figuring out sharedfile IDs to the handleSteamIdResolving() helper - Added a ratingHistory database to track which bot accounts have voted on or favorized which item -- Added a completely new plugin system, co-author @DerDeathraven #174 - - Added a plugin loader which dynamically loads all installed npm packages with the prefix `steam-comment-bot-` @DerDeathraven #174 +- Added a completely new plugin system, co-author @DerDeathraven [#174](https://github.com/3urobeat/steam-comment-service-bot/pull/174) + - Added a plugin loader which dynamically loads all installed npm packages with the prefix `steam-comment-bot-` @DerDeathraven [#174](https://github.com/3urobeat/steam-comment-service-bot/pull/174) - Added new template plugin which you can [fork here to create your own plugin](https://github.com/3urobeat/steam-comment-bot-template-plugin) - Added plugin functions: `load`, `ready`, `statusUpdate`, `steamGuardInput` - Added plugin data directory and functions to handle data reading & writing: `getPluginDataPath`, `loadPluginData`, `writePluginData`, `loadPluginConfig`, `writePluginConfig` @@ -120,7 +120,7 @@ If you are using a `customlang.json`, make sure to read the language string chan   **Fixes:** -- Fixed the webserver plugin from being completely broken #172 +- Fixed the webserver plugin from being completely broken [#172](https://github.com/3urobeat/steam-comment-service-bot/issues/172) - Fixed return parameters of checkConnection - Fixed webSession looping caused by broken botsgroup check - Fixed accounts.txt import still checking for loginfo.json @@ -140,7 +140,7 @@ If you are using a `customlang.json`, make sure to read the language string chan - Fixed cooldown issues when cooldown is disabled and process got aborted - Fixed a data check error on broken internet connection by checking it beforehand - Fixed handleLoginTimeout causing a DuplicateRequest error on 2FA input -- Fixed output-logger causing crash when running bot with pm2 #48 +- Fixed output-logger causing crash when running bot with pm2 [#48](https://github.com/3urobeat/steam-comment-service-bot/issues/48) - Fixed potential bug where whenAvailableStr in comment command could display wrong information if allAccounts was empty or if more accounts got removed after the activeRequests loop ran 9e6c569 - Fixed/Removed minor unnecessary checks in comment command - Fixed user added while offline message being able to fail because it was sent too early after logging in @@ -151,8 +151,8 @@ If you are using a `customlang.json`, make sure to read the language string chan - Removed support for the old login flow: f5957bb - Removed v2.13 login flow change notification message - Removed `disableCommentCmd` setting from `advancedconfig.json` and replaced it with `restrictAdditionalCommandsToOwners` array -- Removed `enableurltocomment` setting from `advancedconfig.json`. Toggling the webserver plugin is now done in the plugin config in the `plugins` directory #172 -- Removed `urlrequestsecretkey` from `data.json`. This key is now stored in the plugin config in the `plugins` directory. The update will cause a new key to be generated. #172 +- Removed `enableurltocomment` setting from `advancedconfig.json`. Toggling the webserver plugin is now done in the plugin config in the `plugins` directory [#172](https://github.com/3urobeat/steam-comment-service-bot/issues/172) +- Removed `urlrequestsecretkey` from `data.json`. This key is now stored in the plugin config in the `plugins` directory. The update will cause a new key to be generated. [#172](https://github.com/3urobeat/steam-comment-service-bot/issues/172) - Removed most global variables - Removed (nearly) every usage of `var` - Removed lots of unnecessary variables that are now replaced by better systems @@ -165,7 +165,7 @@ If you are using a `customlang.json`, make sure to read the language string chan - Moved various updater, controller & bot helper files to new objects - Moved various log messages to log at more appropriate times - Shortened most comment error descriptions -- Improved eslint styling rules, formatting & code quality and added prettier config @DerDeathraven #171 +- Improved eslint styling rules, formatting & code quality and added prettier config @DerDeathraven [#171](https://github.com/3urobeat/steam-comment-service-bot/pull/171) - Updated dependencies - Tons of fixes for features that have been added in this update and are therefore not listed here - Minor other changes From 0e0d6719d53cd75aee7a62e06af8239ff3536d20 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Mon, 3 Jul 2023 21:40:58 +0200 Subject: [PATCH 18/43] Clean up a few unnecessarily nested promises --- src/commands/helpers/getFavoriteBots.js | 112 +++-- src/commands/helpers/getSharedfileArgs.js | 51 +- src/commands/helpers/getVoteBots.js | 109 ++--- src/dataManager/dataImport.js | 567 +++++++++++----------- src/dataManager/dataManager.js | 4 +- src/dataManager/dataProcessing.js | 209 ++++---- 6 files changed, 514 insertions(+), 538 deletions(-) diff --git a/src/commands/helpers/getFavoriteBots.js b/src/commands/helpers/getFavoriteBots.js index 689371c2..257e181c 100644 --- a/src/commands/helpers/getFavoriteBots.js +++ b/src/commands/helpers/getFavoriteBots.js @@ -4,7 +4,7 @@ * Created Date: 02.06.2023 14:07:27 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 03.07.2023 12:31:17 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -27,78 +27,74 @@ const { timeToString } = require("../../controller/helpers/misc.js"); * @param {string} favType Either "favorite" or "unfavorite", depending on which request this is * @returns {Promise.<{ amount: number, availableAccounts: array, whenAvailable: number, whenAvailableStr: string }>} Promise with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now */ -module.exports.getAvailableBotsForFavorizing = (commandHandler, amount, id, favType) => { - return new Promise((resolve) => { - (async () => { // Lets us use await inside a Promise without creating an antipattern +module.exports.getAvailableBotsForFavorizing = async (commandHandler, amount, id, favType) => { - /* --------- Get all bots which haven't favorized this id yet and aren't currently in another favorite request --------- */ - let whenAvailable; // We will save the until value of the account that the user has to wait for here - let whenAvailableStr; - let allAccsOnline = commandHandler.controller.getBots(null, true); - let allAccounts = [ ... Object.keys(allAccsOnline) ]; // Clone keys array (bot usernames) of bots object + /* --------- Get all bots which haven't favorized this id yet and aren't currently in another favorite request --------- */ + let whenAvailable; // We will save the until value of the account that the user has to wait for here + let whenAvailableStr; + let allAccsOnline = commandHandler.controller.getBots(null, true); + let allAccounts = [ ... Object.keys(allAccsOnline) ]; // Clone keys array (bot usernames) of bots object - // Remove bot accounts from allAccounts which have already favorized this id, or only allow them for type unfavorite - let previousLengthFavorized = allAccounts.length; - let alreadyFavorized = await commandHandler.data.ratingHistoryDB.findAsync({ id: id, type: "favorite" }, {}); + // Remove bot accounts from allAccounts which have already favorized this id, or only allow them for type unfavorite + let previousLengthFavorized = allAccounts.length; + let alreadyFavorized = await commandHandler.data.ratingHistoryDB.findAsync({ id: id, type: "favorite" }, {}); - if (favType == "favorite") { - alreadyFavorized.forEach((e) => { - if (allAccounts.indexOf(e.accountName) != -1) allAccounts.splice(allAccounts.indexOf(e.accountName), 1); // Remove all accounts that already favorized - }); - } else { - allAccounts.forEach((e) => { - if (!alreadyFavorized.some(e => e.accountName)) allAccounts.splice(allAccounts.indexOf(e), 1); // Remove all accounts that have not favorized - }); - } + if (favType == "favorite") { + alreadyFavorized.forEach((e) => { + if (allAccounts.indexOf(e.accountName) != -1) allAccounts.splice(allAccounts.indexOf(e.accountName), 1); // Remove all accounts that already favorized + }); + } else { + allAccounts.forEach((e) => { + if (!alreadyFavorized.some(e => e.accountName)) allAccounts.splice(allAccounts.indexOf(e), 1); // Remove all accounts that have not favorized + }); + } - if (previousLengthFavorized - allAccounts.length > 0) logger("info", `${previousLengthFavorized - allAccounts.length} of ${previousLengthFavorized} bot accounts were removed from available accounts because we know that they have already favorized this item!`); + if (previousLengthFavorized - allAccounts.length > 0) logger("info", `${previousLengthFavorized - allAccounts.length} of ${previousLengthFavorized} bot accounts were removed from available accounts because we know that they have already favorized this item!`); - // Loop over activeRequests and remove all active entries from allAccounts if both are not empty - if (allAccounts.length > 0 && Object.keys(commandHandler.controller.activeRequests).length > 0) { - Object.keys(commandHandler.controller.activeRequests).forEach((e) => { - if (!commandHandler.controller.activeRequests[e].type.includes("favorite")) return; // Ignore entry if not of this type + // Loop over activeRequests and remove all active entries from allAccounts if both are not empty + if (allAccounts.length > 0 && Object.keys(commandHandler.controller.activeRequests).length > 0) { + Object.keys(commandHandler.controller.activeRequests).forEach((e) => { + if (!commandHandler.controller.activeRequests[e].type.includes("favorite")) return; // Ignore entry if not of this type - if (Date.now() < commandHandler.controller.activeRequests[e].until + (commandHandler.data.config.botaccountcooldown * 60000)) { // Check if entry is not finished yet - commandHandler.controller.activeRequests[e].accounts.forEach((f) => { // Loop over every account used in this request - allAccounts.splice(allAccounts.indexOf(f), 1); // Remove that accountindex from the allAccounts array - }); - - // If this removal causes the user to need to wait, update whenAvailable. Don't bother if user provided "all" - if (amount != "all" && allAccounts.length - commandHandler.controller.activeRequests[e].accounts.length < amount) { - whenAvailable = commandHandler.controller.activeRequests[e].until + (commandHandler.data.config.botaccountcooldown * 60000); - whenAvailableStr = timeToString(whenAvailable); - } - } else { - delete commandHandler.controller.activeRequests[e]; // Remove entry from object if it is finished to keep the object clean - } + if (Date.now() < commandHandler.controller.activeRequests[e].until + (commandHandler.data.config.botaccountcooldown * 60000)) { // Check if entry is not finished yet + commandHandler.controller.activeRequests[e].accounts.forEach((f) => { // Loop over every account used in this request + allAccounts.splice(allAccounts.indexOf(f), 1); // Remove that accountindex from the allAccounts array }); + + // If this removal causes the user to need to wait, update whenAvailable. Don't bother if user provided "all" + if (amount != "all" && allAccounts.length - commandHandler.controller.activeRequests[e].accounts.length < amount) { + whenAvailable = commandHandler.controller.activeRequests[e].until + (commandHandler.data.config.botaccountcooldown * 60000); + whenAvailableStr = timeToString(whenAvailable); + } + } else { + delete commandHandler.controller.activeRequests[e]; // Remove entry from object if it is finished to keep the object clean } + }); + } - // Update amount if "all" - if (amount == "all") { - amount = allAccounts.length; - logger("debug", `CommandHandler getFavoriteBots(): User provided max amount keyword "all", updating it to ${allAccounts.length}`); - } + // Update amount if "all" + if (amount == "all") { + amount = allAccounts.length; + logger("debug", `CommandHandler getFavoriteBots(): User provided max amount keyword "all", updating it to ${allAccounts.length}`); + } - // Cut result to only include needed accounts - if (allAccounts.length > amount) allAccounts = allAccounts.slice(0, amount); + // Cut result to only include needed accounts + if (allAccounts.length > amount) allAccounts = allAccounts.slice(0, amount); - // Log result to debug - if (allAccounts.length < amount) logger("debug", `CommandHandler getFavoriteBots(): Found ${allAccounts.length} available bot accounts to un-/favorize ${id} but ${amount} are needed. If accs will become available, the user needs to wait: ${whenAvailableStr || "/"}`); - else logger("debug", `CommandHandler getFavoriteBots(): Found ${allAccounts.length} available bot accounts to un-/favorize ${id}: ${allAccounts}`); + // Log result to debug + if (allAccounts.length < amount) logger("debug", `CommandHandler getFavoriteBots(): Found ${allAccounts.length} available bot accounts to un-/favorize ${id} but ${amount} are needed. If accs will become available, the user needs to wait: ${whenAvailableStr || "/"}`); + else logger("debug", `CommandHandler getFavoriteBots(): Found ${allAccounts.length} available bot accounts to un-/favorize ${id}: ${allAccounts}`); - // Resolve promise with values - resolve({ - "amount": amount, - "availableAccounts": allAccounts, - "whenAvailable": whenAvailable, - "whenAvailableStr": whenAvailableStr - }); - })(); - }); + // Resolve promise with values + return { + "amount": amount, + "availableAccounts": allAccounts, + "whenAvailable": whenAvailable, + "whenAvailableStr": whenAvailableStr + }; }; \ No newline at end of file diff --git a/src/commands/helpers/getSharedfileArgs.js b/src/commands/helpers/getSharedfileArgs.js index a8d88272..ac046ac2 100644 --- a/src/commands/helpers/getSharedfileArgs.js +++ b/src/commands/helpers/getSharedfileArgs.js @@ -4,7 +4,7 @@ * Created Date: 28.05.2023 12:18:49 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 03.07.2023 12:31:10 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -29,40 +29,37 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line */ module.exports.getSharedfileArgs = (commandHandler, args, cmd, resInfo, respond) => { return new Promise((resolve) => { - (async () => { // Lets us use await inside a Promise without creating an antipattern - // Check for missing params - let voteCmdUsage = `'${resInfo.cmdprefix}${cmd} amount/"all" id/link'`; + // Check for missing params + let voteCmdUsage = `'${resInfo.cmdprefix}${cmd} amount/"all" id/link'`; - if (args[0]) args[0] = args[0].toLowerCase(); - if (args[0] == "max") args[0] = "all"; // Convert "all" alias - let amount = args[0] == "all" ? args[0] : Number(args[0]); // If user provides "all" then keep it as is and update it later to how many accounts are available, otherwise convert it to a number + if (args[0]) args[0] = args[0].toLowerCase(); + if (args[0] == "max") args[0] = "all"; // Convert "all" alias + let amount = args[0] == "all" ? args[0] : Number(args[0]); // If user provides "all" then keep it as is and update it later to how many accounts are available, otherwise convert it to a number - if (args.length == 0 || (amount != "all" && isNaN(amount)) || amount == 0) { - respond(commandHandler.data.lang.invalidnumber.replace("cmdusage", voteCmdUsage)); // An empty string will become a 0 - return resolve({}); - } - - - // Process input and check if ID is valid - commandHandler.controller.handleSteamIdResolving(args[1], "sharedfile", (err, id, idType) => { // eslint-disable-line no-unused-vars + if (args.length == 0 || (amount != "all" && isNaN(amount)) || amount == 0) { + respond(commandHandler.data.lang.invalidnumber.replace("cmdusage", voteCmdUsage)); // An empty string will become a 0 + return resolve({}); + } - // Send error if item could not be found - if (err || !id) { - respond(commandHandler.data.lang.invalidsharedfileid.replace("cmdusage", voteCmdUsage)); - return resolve({}); - } + // Process input and check if ID is valid + commandHandler.controller.handleSteamIdResolving(args[1], "sharedfile", (err, id, idType) => { // eslint-disable-line no-unused-vars - // ...otherwise resolve - logger("debug", `CommandHandler getSharedfileArgs() success. amount: ${amount} | id: ${id}`); + // Send error if item could not be found + if (err || !id) { + respond(commandHandler.data.lang.invalidsharedfileid.replace("cmdusage", voteCmdUsage)); + return resolve({}); + } - resolve({ - "amountRaw": amount, - "id": id - }); + // ...otherwise resolve + logger("debug", `CommandHandler getSharedfileArgs() success. amount: ${amount} | id: ${id}`); + resolve({ + "amountRaw": amount, + "id": id }); - })(); + }); + }); }; \ No newline at end of file diff --git a/src/commands/helpers/getVoteBots.js b/src/commands/helpers/getVoteBots.js index 30188094..45c3fdf4 100644 --- a/src/commands/helpers/getVoteBots.js +++ b/src/commands/helpers/getVoteBots.js @@ -4,7 +4,7 @@ * Created Date: 28.05.2023 12:21:02 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 03.07.2023 12:59:52 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -27,78 +27,75 @@ const { timeToString } = require("../../controller/helpers/misc.js"); * @param {string} voteType "upvote" or "downvote", depending on which request this is * @returns {Promise.<{ amount: number, availableAccounts: array, whenAvailable: number, whenAvailableStr: string }>} Promise with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now */ -module.exports.getAvailableBotsForVoting = (commandHandler, amount, id, voteType) => { - return new Promise((resolve) => { - (async () => { // Lets us use await inside a Promise without creating an antipattern +module.exports.getAvailableBotsForVoting = async (commandHandler, amount, id, voteType) => { - /* --------- Get all bots which haven't voted on this id yet and aren't currently in another vote request --------- */ - let whenAvailable; // We will save the until value of the account that the user has to wait for here - let whenAvailableStr; - let allAccsOnline = commandHandler.controller.getBots(null, true); - let allAccounts = [ ... Object.keys(allAccsOnline) ]; // Clone keys array (bot usernames) of bots object + /* --------- Get all bots which haven't voted on this id yet and aren't currently in another vote request --------- */ + let whenAvailable; // We will save the until value of the account that the user has to wait for here + let whenAvailableStr; + let allAccsOnline = commandHandler.controller.getBots(null, true); + let allAccounts = [ ... Object.keys(allAccsOnline) ]; // Clone keys array (bot usernames) of bots object - // Remove limited accounts from allAccounts array as they are unable to vote - let previousLengthLimited = allAccounts.length; - allAccounts = allAccounts.filter(e => allAccsOnline[e].user.limitations && !allAccsOnline[e].user.limitations.limited); + // Remove limited accounts from allAccounts array as they are unable to vote + let previousLengthLimited = allAccounts.length; + allAccounts = allAccounts.filter(e => allAccsOnline[e].user.limitations && !allAccsOnline[e].user.limitations.limited); - if (previousLengthLimited - allAccounts.length > 0) logger("info", `${previousLengthLimited - allAccounts.length} of ${previousLengthLimited} bot accounts were removed from available accounts as they are limited and can't be used for this request!`); + if (previousLengthLimited - allAccounts.length > 0) logger("info", `${previousLengthLimited - allAccounts.length} of ${previousLengthLimited} bot accounts were removed from available accounts as they are limited and can't be used for this request!`); - // Remove bot accounts from allAccounts which have already voted on this id with this voteType - let previousLengthVoted = allAccounts.length; - let alreadyVoted = await commandHandler.data.ratingHistoryDB.findAsync({ id: id, type: voteType }, {}); + // Remove bot accounts from allAccounts which have already voted on this id with this voteType + let previousLengthVoted = allAccounts.length; + let alreadyVoted = await commandHandler.data.ratingHistoryDB.findAsync({ id: id, type: voteType }, {}); - alreadyVoted.forEach((e) => { - if (allAccounts.indexOf(e.accountName) != -1) allAccounts.splice(allAccounts.indexOf(e.accountName), 1); - }); - - if (previousLengthVoted - allAccounts.length > 0) logger("info", `${previousLengthVoted - allAccounts.length} of ${previousLengthVoted} bot accounts were removed from available accounts because we know that they have already voted on this item!`); + alreadyVoted.forEach((e) => { + if (allAccounts.indexOf(e.accountName) != -1) allAccounts.splice(allAccounts.indexOf(e.accountName), 1); + }); + if (previousLengthVoted - allAccounts.length > 0) logger("info", `${previousLengthVoted - allAccounts.length} of ${previousLengthVoted} bot accounts were removed from available accounts because we know that they have already voted on this item!`); - // Loop over activeRequests and remove all active entries from allAccounts if both are not empty - if (allAccounts.length > 0 && Object.keys(commandHandler.controller.activeRequests).length > 0) { - Object.keys(commandHandler.controller.activeRequests).forEach((e) => { - if (!commandHandler.controller.activeRequests[e].type.includes("vote")) return; // Ignore entry if not of this type - if (Date.now() < commandHandler.controller.activeRequests[e].until + (commandHandler.data.config.botaccountcooldown * 60000)) { // Check if entry is not finished yet - commandHandler.controller.activeRequests[e].accounts.forEach((f) => { // Loop over every account used in this request - allAccounts.splice(allAccounts.indexOf(f), 1); // Remove that accountindex from the allAccounts array - }); + // Loop over activeRequests and remove all active entries from allAccounts if both are not empty + if (allAccounts.length > 0 && Object.keys(commandHandler.controller.activeRequests).length > 0) { + Object.keys(commandHandler.controller.activeRequests).forEach((e) => { + if (!commandHandler.controller.activeRequests[e].type.includes("vote")) return; // Ignore entry if not of this type - // If this removal causes the user to need to wait, update whenAvailable. Don't bother if user provided "all" - if (amount != "all" && allAccounts.length - commandHandler.controller.activeRequests[e].accounts.length < amount) { - whenAvailable = commandHandler.controller.activeRequests[e].until + (commandHandler.data.config.botaccountcooldown * 60000); - whenAvailableStr = timeToString(whenAvailable); - } - } else { - delete commandHandler.controller.activeRequests[e]; // Remove entry from object if it is finished to keep the object clean - } + if (Date.now() < commandHandler.controller.activeRequests[e].until + (commandHandler.data.config.botaccountcooldown * 60000)) { // Check if entry is not finished yet + commandHandler.controller.activeRequests[e].accounts.forEach((f) => { // Loop over every account used in this request + allAccounts.splice(allAccounts.indexOf(f), 1); // Remove that accountindex from the allAccounts array }); + + // If this removal causes the user to need to wait, update whenAvailable. Don't bother if user provided "all" + if (amount != "all" && allAccounts.length - commandHandler.controller.activeRequests[e].accounts.length < amount) { + whenAvailable = commandHandler.controller.activeRequests[e].until + (commandHandler.data.config.botaccountcooldown * 60000); + whenAvailableStr = timeToString(whenAvailable); + } + } else { + delete commandHandler.controller.activeRequests[e]; // Remove entry from object if it is finished to keep the object clean } + }); + } - // Update amount if "all" - if (amount == "all") { - amount = allAccounts.length; - logger("debug", `CommandHandler getVoteBots(): User provided max amount keyword "all", updating it to ${allAccounts.length}`); - } + // Update amount if "all" + if (amount == "all") { + amount = allAccounts.length; + logger("debug", `CommandHandler getVoteBots(): User provided max amount keyword "all", updating it to ${allAccounts.length}`); + } - // Cut result to only include needed accounts - if (allAccounts.length > amount) allAccounts = allAccounts.slice(0, amount); + // Cut result to only include needed accounts + if (allAccounts.length > amount) allAccounts = allAccounts.slice(0, amount); - // Log result to debug - if (allAccounts.length < amount) logger("debug", `CommandHandler getVoteBots(): Found ${allAccounts.length} available bot accounts to vote on ${id} but ${amount} are needed. If accs will become available, the user needs to wait: ${whenAvailableStr || "/"}`); - else logger("debug", `CommandHandler getVoteBots(): Found ${allAccounts.length} available bot accounts to vote on ${id}: ${allAccounts}`); + // Log result to debug + if (allAccounts.length < amount) logger("debug", `CommandHandler getVoteBots(): Found ${allAccounts.length} available bot accounts to vote on ${id} but ${amount} are needed. If accs will become available, the user needs to wait: ${whenAvailableStr || "/"}`); + else logger("debug", `CommandHandler getVoteBots(): Found ${allAccounts.length} available bot accounts to vote on ${id}: ${allAccounts}`); + + // Resolve promise with values + return { + "amount": amount, + "availableAccounts": allAccounts, + "whenAvailable": whenAvailable, + "whenAvailableStr": whenAvailableStr + }; - // Resolve promise with values - resolve({ - "amount": amount, - "availableAccounts": allAccounts, - "whenAvailable": whenAvailable, - "whenAvailableStr": whenAvailableStr - }); - })(); - }); }; \ No newline at end of file diff --git a/src/dataManager/dataImport.js b/src/dataManager/dataImport.js index 32a81797..d4ea1646 100644 --- a/src/dataManager/dataImport.js +++ b/src/dataManager/dataImport.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 02.07.2023 19:06:36 + * Last Modified: 03.07.2023 21:32:21 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -23,327 +23,320 @@ const DataManager = require("./dataManager.js"); * Internal: Loads all config & data files from disk and handles potential errors * @returns {Promise.} Resolves promise when all files have been loaded successfully. The function will log an error and terminate the application should a fatal error occur. */ -DataManager.prototype._importFromDisk = function () { +DataManager.prototype._importFromDisk = async function () { let _this = this; // Make this accessible within the functions below - return new Promise((resolve) => { - (async () => { // Lets us use await inside a Promise without creating an antipattern + function loadCache() { + return new Promise((resolve) => { + try { + resolve(require(srcdir + "/data/cache.json")); + } catch (err) { + if (err) { + logger("", "", true, true); + logger("warn", "cache.json seems to have lost it's data/is corrupted. Trying to write/create...", true, true); - function loadCache() { - return new Promise((resolve) => { - try { - resolve(require(srcdir + "/data/cache.json")); - } catch (err) { - if (err) { - logger("", "", true, true); - logger("warn", "cache.json seems to have lost it's data/is corrupted. Trying to write/create...", true, true); - - // Create the underlying folder structure to avoid error when trying to write the downloaded file - fs.mkdirSync(path.dirname("./src/data/cache.json"), { recursive: true }); - - fs.writeFile("./src/data/cache.json", "{}", (err) => { - // Write empty valid json - if (err) { - logger("error", "Error writing {} to cache.json.\nPlease do this manually: Go into 'src' folder, open 'cache.json', write '{}' and save.\nOtherwise the bot will always crash.\nError: " + err + "\n\nAborting...", true); - return _this.controller.stop(); // Abort since writeFile was unable to write and any further execution would crash - } else { - logger("info", "Successfully cleared/created cache.json.\n", true, true); - resolve(require(srcdir + "/data/cache.json")); - } - }); - } - } - }); - } + // Create the underlying folder structure to avoid error when trying to write the downloaded file + fs.mkdirSync(path.dirname("./src/data/cache.json"), { recursive: true }); - function loadData() { - return new Promise((resolve) => { - try { - resolve(require(srcdir + "/data/data.json")); - } catch (err) { + fs.writeFile("./src/data/cache.json", "{}", (err) => { + // Write empty valid json if (err) { - // Corrupted! - logger("", "", true, true); - logger("warn", "'data.json' seems to have lost it's data/is corrupted. Trying to restore from backup...", true); - - // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. - if (_this.cachefile.datajson) _this._restoreBackup("data.json", srcdir + "/data/data.json", _this.cachefile.datajson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/src/data/data.json", resolve); - else _this._pullNewFile("data.json", "./src/data/data.json", resolve); + logger("error", "Error writing {} to cache.json.\nPlease do this manually: Go into 'src' folder, open 'cache.json', write '{}' and save.\nOtherwise the bot will always crash.\nError: " + err + "\n\nAborting...", true); + return _this.controller.stop(); // Abort since writeFile was unable to write and any further execution would crash + } else { + logger("info", "Successfully cleared/created cache.json.\n", true, true); + resolve(require(srcdir + "/data/cache.json")); } - } - }); - } - - function loadConfig() { - return new Promise((resolve) => { - try { - resolve(require(srcdir + "/../config.json")); - } catch (err) { - if (err) { - // Corrupted! - logger("", "", true, true); - logger("warn", "'config.json' seems to have lost it's data/is corrupted. Trying to restore from backup...", true); - - let restoreTimeout = 0; // Allow the following firststart check to delay the restore process so the user has time to read the info message - - // Display an informational message about what happened if datafile firststart is true - if (_this.datafile && _this.datafile.firststart) { - logger("", logger.colors.fgred + "\n--------------------------------------" + logger.colors.reset, true); - logger("", `${logger.colors.fgcyan}Hey!${logger.colors.reset} It seems like this is your first start and you made a formatting mistake in your '${logger.colors.fgcyan}config.json${logger.colors.reset}' file. Because of this I'm sadly ${logger.colors.fgcyan}unable to load${logger.colors.reset} the file.`, true); - logger("", `You can stop the bot now by pressing ${logger.colors.fgcyan}CTRL+C${logger.colors.reset} to fix the issue. Please make sure that you exactly follow the format of the provided 'config.json' when filling in your settings.`, true); - logger("", `Take a look at the default config here and pay attention to every ${logger.colors.fgcyan}"${logger.colors.reset} and ${logger.colors.fgcyan},${logger.colors.reset} as you most likely forgot one of them: ${logger.colors.fgcyan}${logger.colors.underscore}https://github.com/3urobeat/steam-comment-service-bot/blob/master/config.json${logger.colors.reset}`, true); - logger("", `You can also take a look at this blog post to learn more about JSON formatting: ${logger.colors.fgcyan}${logger.colors.underscore}https://stackoverflow.blog/2022/06/02/a-beginners-guide-to-json-the-data-format-for-the-internet/${logger.colors.reset}`, true); - logger("", logger.colors.fgred + "--------------------------------------\n" + logger.colors.reset, true); - logger("", "Restoring the config to default in 15 seconds...", true, false, logger.animation("waiting")); - - restoreTimeout = 15000; // Delay restore process by 10 secs - } - - // Wait restoreTimeout ms if set by firststart check from above - setTimeout(() => { - // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. - if (_this.cachefile.configjson) _this._restoreBackup("config.json", srcdir + "/../config.json", _this.cachefile.configjson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/config.json", resolve); - else _this._pullNewFile("config.json", "./config.json", resolve); - }, restoreTimeout); - } - } - }); + }); + } } - - function loadAdvancedConfig() { - return new Promise((resolve) => { - try { - resolve(require(srcdir + "/../advancedconfig.json")); - } catch (err) { - if (err) { - // Corrupted! - logger("", "", true, true); - logger("warn", "advancedconfig.json seems to have lost it's data/is corrupted. Trying to restore from backup...", true); - - // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. - if (_this.cachefile.advancedconfigjson) _this._restoreBackup("advancedconfig.json", srcdir + "/../advancedconfig.json", _this.cachefile.advancedconfigjson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/advancedconfig.json", resolve); - else _this._pullNewFile("advancedconfig.json", "./advancedconfig.json", resolve); - } - } - }); + }); + } + + function loadData() { + return new Promise((resolve) => { + try { + resolve(require(srcdir + "/data/data.json")); + } catch (err) { + if (err) { + // Corrupted! + logger("", "", true, true); + logger("warn", "'data.json' seems to have lost it's data/is corrupted. Trying to restore from backup...", true); + + // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. + if (_this.cachefile.datajson) _this._restoreBackup("data.json", srcdir + "/data/data.json", _this.cachefile.datajson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/src/data/data.json", resolve); + else _this._pullNewFile("data.json", "./src/data/data.json", resolve); + } } - - function loadLoginInfo() { - return new Promise((resolve) => { - let logininfo = {}; - - // Check accounts.txt first so we can ignore potential syntax errors in logininfo - if (fs.existsSync("./accounts.txt")) { - let data = fs.readFileSync("./accounts.txt", "utf8").split("\n"); - - if (data.length > 0 && data[0].startsWith("//Comment")) data = data.slice(1); // Remove comment from array - - if (data != "") { - logininfo = {}; // Set empty object - data.forEach((e) => { - if (e.length < 2) return; // If the line is empty ignore it to avoid issues like this: https://github.com/3urobeat/steam-comment-service-bot/issues/80 - e = e.split(":"); - e[e.length - 1] = e[e.length - 1].replace("\r", ""); // Remove Windows next line character from last index (which has to be the end of the line) - - // Format logininfo object and use accountName as key to allow the order to change - logininfo[e[0]] = { - accountName: e[0], - password: e[1], - sharedSecret: e[2], - steamGuardCode: null, - machineName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-user - deviceFriendlyName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-session - }; - }); - - logger("info", `Found ${Object.keys(logininfo).length} accounts in accounts.txt, not checking for logininfo.json...`, false, true, logger.animation("loading")); - - return resolve(logininfo); - } + }); + } + + function loadConfig() { + return new Promise((resolve) => { + try { + resolve(require(srcdir + "/../config.json")); + } catch (err) { + if (err) { + // Corrupted! + logger("", "", true, true); + logger("warn", "'config.json' seems to have lost it's data/is corrupted. Trying to restore from backup...", true); + + let restoreTimeout = 0; // Allow the following firststart check to delay the restore process so the user has time to read the info message + + // Display an informational message about what happened if datafile firststart is true + if (_this.datafile && _this.datafile.firststart) { + logger("", logger.colors.fgred + "\n--------------------------------------" + logger.colors.reset, true); + logger("", `${logger.colors.fgcyan}Hey!${logger.colors.reset} It seems like this is your first start and you made a formatting mistake in your '${logger.colors.fgcyan}config.json${logger.colors.reset}' file. Because of this I'm sadly ${logger.colors.fgcyan}unable to load${logger.colors.reset} the file.`, true); + logger("", `You can stop the bot now by pressing ${logger.colors.fgcyan}CTRL+C${logger.colors.reset} to fix the issue. Please make sure that you exactly follow the format of the provided 'config.json' when filling in your settings.`, true); + logger("", `Take a look at the default config here and pay attention to every ${logger.colors.fgcyan}"${logger.colors.reset} and ${logger.colors.fgcyan},${logger.colors.reset} as you most likely forgot one of them: ${logger.colors.fgcyan}${logger.colors.underscore}https://github.com/3urobeat/steam-comment-service-bot/blob/master/config.json${logger.colors.reset}`, true); + logger("", `You can also take a look at this blog post to learn more about JSON formatting: ${logger.colors.fgcyan}${logger.colors.underscore}https://stackoverflow.blog/2022/06/02/a-beginners-guide-to-json-the-data-format-for-the-internet/${logger.colors.reset}`, true); + logger("", logger.colors.fgred + "--------------------------------------\n" + logger.colors.reset, true); + logger("", "Restoring the config to default in 15 seconds...", true, false, logger.animation("waiting")); + + restoreTimeout = 15000; // Delay restore process by 10 secs } - // Check logininfo for Syntax errors and display custom error message - try { - // Only check if file exists (it is not shipped by default anymore since 2.12.1). If it doesn't an empty obj will be returned, leading to empty logininfo err msg in checkData() - if (fs.existsSync("./logininfo.json")) { - logininfo = require(srcdir + "/../logininfo.json"); - - // Reformat to use new logininfo object structure and use accountName as key instead of bot0 etc to allow the order to change - Object.keys(logininfo).forEach((k) => { - logininfo[logininfo[k][0]] = { - accountName: logininfo[k][0], - password: logininfo[k][1], - sharedSecret: logininfo[k][2], - steamGuardCode: null, - machineName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-user - deviceFriendlyName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-session - }; - - delete logininfo[k]; // Remove old entry - }); - } + // Wait restoreTimeout ms if set by firststart check from above + setTimeout(() => { + // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. + if (_this.cachefile.configjson) _this._restoreBackup("config.json", srcdir + "/../config.json", _this.cachefile.configjson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/config.json", resolve); + else _this._pullNewFile("config.json", "./config.json", resolve); + }, restoreTimeout); + } + } + }); + } + + function loadAdvancedConfig() { + return new Promise((resolve) => { + try { + resolve(require(srcdir + "/../advancedconfig.json")); + } catch (err) { + if (err) { + // Corrupted! + logger("", "", true, true); + logger("warn", "advancedconfig.json seems to have lost it's data/is corrupted. Trying to restore from backup...", true); + + // Check if cache.json has a backup of config.json and try to restore it. If not then pull the file directly from GitHub. + if (_this.cachefile.advancedconfigjson) _this._restoreBackup("advancedconfig.json", srcdir + "/../advancedconfig.json", _this.cachefile.advancedconfigjson, "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/advancedconfig.json", resolve); + else _this._pullNewFile("advancedconfig.json", "./advancedconfig.json", resolve); + } + } + }); + } + + function loadLoginInfo() { + return new Promise((resolve) => { + let logininfo = {}; + + // Check accounts.txt first so we can ignore potential syntax errors in logininfo + if (fs.existsSync("./accounts.txt")) { + let data = fs.readFileSync("./accounts.txt", "utf8").split("\n"); + + if (data.length > 0 && data[0].startsWith("//Comment")) data = data.slice(1); // Remove comment from array + + if (data != "") { + logininfo = {}; // Set empty object + data.forEach((e) => { + if (e.length < 2) return; // If the line is empty ignore it to avoid issues like this: https://github.com/3urobeat/steam-comment-service-bot/issues/80 + e = e.split(":"); + e[e.length - 1] = e[e.length - 1].replace("\r", ""); // Remove Windows next line character from last index (which has to be the end of the line) + + // Format logininfo object and use accountName as key to allow the order to change + logininfo[e[0]] = { + accountName: e[0], + password: e[1], + sharedSecret: e[2], + steamGuardCode: null, + machineName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-user + deviceFriendlyName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-session + }; + }); - logger("info", `Found ${Object.keys(logininfo).length} accounts in logininfo.json...`, false, true, logger.animation("loading")); + logger("info", `Found ${Object.keys(logininfo).length} accounts in accounts.txt, not checking for logininfo.json...`, false, true, logger.animation("loading")); - resolve(logininfo); - } catch (err) { - logger("error", "It seems like you made a mistake in your logininfo.json. Please check if your Syntax looks exactly like in the example/template and try again.\n " + err, true); - return _this.controller.stop(); - } - }); + return resolve(logininfo); + } } - function loadProxies() { - return new Promise((resolve) => { - let proxies = []; // When the file is just created there can't be proxies in it (this bot doesn't support magic) + // Check logininfo for Syntax errors and display custom error message + try { + // Only check if file exists (it is not shipped by default anymore since 2.12.1). If it doesn't an empty obj will be returned, leading to empty logininfo err msg in checkData() + if (fs.existsSync("./logininfo.json")) { + logininfo = require(srcdir + "/../logininfo.json"); + + // Reformat to use new logininfo object structure and use accountName as key instead of bot0 etc to allow the order to change + Object.keys(logininfo).forEach((k) => { + logininfo[logininfo[k][0]] = { + accountName: logininfo[k][0], + password: logininfo[k][1], + sharedSecret: logininfo[k][2], + steamGuardCode: null, + machineName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-user + deviceFriendlyName: `${_this.datafile.mestr}'s Comment Bot`, // For steam-session + }; + + delete logininfo[k]; // Remove old entry + }); + } - if (!fs.existsSync("./proxies.txt")) { - logger("info", "Creating proxies.txt file as it doesn't exist yet...", false, true, logger.animation("loading")); + logger("info", `Found ${Object.keys(logininfo).length} accounts in logininfo.json...`, false, true, logger.animation("loading")); - fs.writeFile(srcdir + "/../proxies.txt", "", (err) => { - if (err) logger("error", "error creating proxies.txt file: " + err); - else logger("info", "Successfully created proxies.txt file.", false, true, logger.animation("loading")); - }); - } else { - // File does seem to exist so now we can try and read it - proxies = fs.readFileSync("./proxies.txt", "utf8").split("\n"); - proxies = proxies.filter((str) => str != ""); // Remove empty lines + resolve(logininfo); + } catch (err) { + logger("error", "It seems like you made a mistake in your logininfo.json. Please check if your Syntax looks exactly like in the example/template and try again.\n " + err, true); + return _this.controller.stop(); + } + }); + } - if (proxies.length > 0 && proxies[0].startsWith("//Comment")) proxies = proxies.slice(1); // Remove comment from array + function loadProxies() { + return new Promise((resolve) => { + let proxies = []; // When the file is just created there can't be proxies in it (this bot doesn't support magic) - if (_this.advancedconfig.useLocalIP) proxies.unshift(null); // Add no proxy (local ip) if useLocalIP is true + if (!fs.existsSync("./proxies.txt")) { + logger("info", "Creating proxies.txt file as it doesn't exist yet...", false, true, logger.animation("loading")); - // Check if no proxies were found (can only be the case when useLocalIP is false) - if (proxies.length == 0) { - logger("", "", true); - logger("error", "useLocalIP is turned off in advancedconfig.json but I couldn't find any proxies in proxies.txt!\n Aborting as I don't have at least one IP to log in with!", true); - return _this.controller.stop(); - } - } - - resolve(proxies); + fs.writeFile(srcdir + "/../proxies.txt", "", (err) => { + if (err) logger("error", "error creating proxies.txt file: " + err); + else logger("info", "Successfully created proxies.txt file.", false, true, logger.animation("loading")); }); - } + } else { + // File does seem to exist so now we can try and read it + proxies = fs.readFileSync("./proxies.txt", "utf8").split("\n"); + proxies = proxies.filter((str) => str != ""); // Remove empty lines - function loadQuotes() { - return new Promise((resolve) => { - let quotes = []; - - // Pull new file and call loadQuotes again, wait for it to resolve, and then resolve this promise. This is slightly hacky but relatively clean - if (!fs.existsSync(srcdir + "/../quotes.txt")) { - return _this._pullNewFile( - "quotes.txt", - "./quotes.txt", - async () => { - resolve(await loadQuotes()); - }, - true - ); - } + if (proxies.length > 0 && proxies[0].startsWith("//Comment")) proxies = proxies.slice(1); // Remove comment from array - quotes = fs.readFileSync(srcdir + "/../quotes.txt", "utf8").split("\n"); // Get all quotes from the quotes.txt file into an array - quotes = quotes.filter((str) => str != ""); // Remove empty quotes + if (_this.advancedconfig.useLocalIP) proxies.unshift(null); // Add no proxy (local ip) if useLocalIP is true - quotes.forEach((e, i) => { - // Multi line strings that contain \n will get split to \\n -> remove second \ so that node-steamcommunity understands the quote when commenting - if (e.length > 999) { - logger("warn", `The quote.txt line ${i} is longer than the limit of 999 characters. This quote will be ignored for now.`, true, false, logger.animation("loading")); - quotes.splice(i, 1); // Remove this item from the array - return; - } + // Check if no proxies were found (can only be the case when useLocalIP is false) + if (proxies.length == 0) { + logger("", "", true); + logger("error", "useLocalIP is turned off in advancedconfig.json but I couldn't find any proxies in proxies.txt!\n Aborting as I don't have at least one IP to log in with!", true); + return _this.controller.stop(); + } + } - quotes[i] = e.replace(/\\n/g, "\n").replace("\\n", "\n"); - }); + resolve(proxies); + }); + } + + function loadQuotes() { + return new Promise((resolve) => { + let quotes = []; + + // Pull new file and call loadQuotes again, wait for it to resolve, and then resolve this promise. This is slightly hacky but relatively clean + if (!fs.existsSync(srcdir + "/../quotes.txt")) { + return _this._pullNewFile( + "quotes.txt", + "./quotes.txt", + async () => { + resolve(await loadQuotes()); + }, + true + ); + } - if (quotes.length == 0) { - // Check if quotes.txt is empty to avoid errors further down when trying to comment - logger("error", `${logger.colors.fgred}You haven't put any comment quotes into the quotes.txt file! Aborting...`, true); - return _this.controller.stop(); - } else { - logger("info", `Successfully loaded ${quotes.length} quotes from quotes.txt...`, false, true, logger.animation("loading")); - } + quotes = fs.readFileSync(srcdir + "/../quotes.txt", "utf8").split("\n"); // Get all quotes from the quotes.txt file into an array + quotes = quotes.filter((str) => str != ""); // Remove empty quotes + + quotes.forEach((e, i) => { + // Multi line strings that contain \n will get split to \\n -> remove second \ so that node-steamcommunity understands the quote when commenting + if (e.length > 999) { + logger("warn", `The quote.txt line ${i} is longer than the limit of 999 characters. This quote will be ignored for now.`, true, false, logger.animation("loading")); + quotes.splice(i, 1); // Remove this item from the array + return; + } + + quotes[i] = e.replace(/\\n/g, "\n").replace("\\n", "\n"); + }); + + if (quotes.length == 0) { + // Check if quotes.txt is empty to avoid errors further down when trying to comment + logger("error", `${logger.colors.fgred}You haven't put any comment quotes into the quotes.txt file! Aborting...`, true); + return _this.controller.stop(); + } else { + logger("info", `Successfully loaded ${quotes.length} quotes from quotes.txt...`, false, true, logger.animation("loading")); + } - resolve(quotes); - }); + resolve(quotes); + }); + } + + function loadLanguage() { + return new Promise((resolve) => { + try { + resolve(require(srcdir + "/data/lang/defaultlang.json")); + } catch (err) { + if (err) { + // Corrupted! + logger("", "", true, true); + + // Pull the file directly from GitHub. + _this._pullNewFile("defaultlang.json", "./src/data/lang/defaultlang.json", resolve); + } } + }); + } + + function loadCustomLang() { + return new Promise((resolve) => { + // Check before trying to import if the user even created the file + if (fs.existsSync(srcdir + "/../customlang.json")) { + let customlang; + let customlangkeys = 0; + + // Try importing customlang.json + try { + customlang = require(srcdir + "/../customlang.json"); + } catch (err) { + logger("error", "It seems like you made a mistake (probably Syntax) in your customlang.json! I will not use any custom message.\nError: " + err); + + resolve(_this.lang); // Resolve with default lang object + } + + // Overwrite values in lang object with values from customlang + Object.keys(customlang).forEach((e, i) => { + if (e != "" && e != "note") { + _this.lang[e] = customlang[e]; // Overwrite each defaultlang key with a corresponding customlang key if one is set + + customlangkeys++; + } - function loadLanguage() { - return new Promise((resolve) => { - try { - resolve(require(srcdir + "/data/lang/defaultlang.json")); - } catch (err) { - if (err) { - // Corrupted! - logger("", "", true, true); + if (i == Object.keys(customlang).length - 1) { + // Check for last iteration + if (customlangkeys > 0) logger("info", `${customlangkeys} customlang key imported!`, false, true, logger.animation("loading")); + else logger("info", "No customlang keys found.", false, true, logger.animation("loading")); - // Pull the file directly from GitHub. - _this._pullNewFile("defaultlang.json", "./src/data/lang/defaultlang.json", resolve); - } + resolve(_this.lang); // Resolve lang object with our new keys } }); + } else { + logger("info", "No customlang.json file found...", false, true, logger.animation("loading")); + resolve(_this.lang); // Resolve with default lang object } + }); + } - function loadCustomLang() { - return new Promise((resolve) => { - // Check before trying to import if the user even created the file - if (fs.existsSync(srcdir + "/../customlang.json")) { - let customlang; - let customlangkeys = 0; + // Call all functions from above after another. This must be done async to avoid a check failing that depends on something from a previous function. We sadly cannot use Promise.all() because of this. + logger("info", "Importing data files and settings...", false, true, logger.animation("loading")); - // Try importing customlang.json - try { - customlang = require(srcdir + "/../customlang.json"); - } catch (err) { - logger("error", "It seems like you made a mistake (probably Syntax) in your customlang.json! I will not use any custom message.\nError: " + err); + this.cachefile = await loadCache(); + this.datafile = await loadData(); + this.config = await loadConfig(); + this.advancedconfig = await loadAdvancedConfig(); + this.logininfo = await loadLoginInfo(); + this.proxies = await loadProxies(); + this.quotes = await loadQuotes(); + this.lang = await loadLanguage(); + this.lang = await loadCustomLang(); - resolve(_this.lang); // Resolve with default lang object - } + this.lastCommentDB = new nedb({ filename: srcdir + "/data/lastcomment.db", autoload: true }); // Autoload + this.ratingHistoryDB = new nedb({ filename: srcdir + "/data/ratingHistory.db", autoload: true }); + this.tokensDB = new nedb({ filename: srcdir + "/data/tokens.db", autoload: true }); - // Overwrite values in lang object with values from customlang - Object.keys(customlang).forEach((e, i) => { - if (e != "" && e != "note") { - _this.lang[e] = customlang[e]; // Overwrite each defaultlang key with a corresponding customlang key if one is set - - customlangkeys++; - } - - if (i == Object.keys(customlang).length - 1) { - // Check for last iteration - if (customlangkeys > 0) logger("info", `${customlangkeys} customlang key imported!`, false, true, logger.animation("loading")); - else logger("info", "No customlang keys found.", false, true, logger.animation("loading")); - - resolve(_this.lang); // Resolve lang object with our new keys - } - }); - } else { - logger("info", "No customlang.json file found...", false, true, logger.animation("loading")); - resolve(_this.lang); // Resolve with default lang object - } - }); - } + // Check tokens.db every 24 hours for expired tokens to allow users to refresh them beforehand + this._startExpiringTokensCheckInterval(); - // Call all functions from above after another. This must be done async to avoid a check failing that depends on something from a previous function - logger("info", "Importing data files and settings...", false, true, logger.animation("loading")); - - this.cachefile = await loadCache(); - this.datafile = await loadData(); - this.config = await loadConfig(); - this.advancedconfig = await loadAdvancedConfig(); - this.logininfo = await loadLoginInfo(); - this.proxies = await loadProxies(); - this.quotes = await loadQuotes(); - this.lang = await loadLanguage(); - this.lang = await loadCustomLang(); - - this.lastCommentDB = new nedb({ filename: srcdir + "/data/lastcomment.db", autoload: true }); // Autoload - this.ratingHistoryDB = new nedb({ filename: srcdir + "/data/ratingHistory.db", autoload: true }); - this.tokensDB = new nedb({ filename: srcdir + "/data/tokens.db", autoload: true }); - - // Check tokens.db every 24 hours for expired tokens to allow users to refresh them beforehand - this._startExpiringTokensCheckInterval(); - - // Resolve our promise to let caller know the dataImport is finished - resolve(); - })(); - }); }; diff --git a/src/dataManager/dataManager.js b/src/dataManager/dataManager.js index de4a3f26..3ca22156 100644 --- a/src/dataManager/dataManager.js +++ b/src/dataManager/dataManager.js @@ -4,7 +4,7 @@ * Created Date: 21.03.2023 22:34:51 * Author: 3urobeat * - * Last Modified: 02.07.2023 19:10:50 + * Last Modified: 03.07.2023 15:50:15 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -137,7 +137,7 @@ DataManager.prototype.processData = async function () {}; * Internal: Loads all config & data files from disk and handles potential errors * @returns {Promise.} Resolves promise when all files have been loaded successfully. The function will log an error and terminate the application should a fatal error occur. */ -DataManager.prototype._importFromDisk = function () {}; +DataManager.prototype._importFromDisk = async function () {}; /** * Gets a random quote diff --git a/src/dataManager/dataProcessing.js b/src/dataManager/dataProcessing.js index 27925f0c..68259fc1 100644 --- a/src/dataManager/dataProcessing.js +++ b/src/dataManager/dataProcessing.js @@ -4,7 +4,7 @@ * Created Date: 27.03.2023 21:34:45 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 03.07.2023 15:52:15 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -25,149 +25,142 @@ const DataManager = require("./dataManager"); /** * Converts owners and groups imported from config.json to steam ids and updates cachefile. (Call this after dataImport and before dataCheck) */ -DataManager.prototype.processData = function() { +DataManager.prototype.processData = async function() { let _this = this; - return new Promise((resolve) => { - (async () => { // Lets us use await insidea Promise without creating an antipattern + function yourgroup() { + return new Promise((resolve) => { - function yourgroup() { - return new Promise((resolve) => { + if (_this.config.yourgroup.length == 0) { // Check if yourgroup is empty + logger("debug", "DataManager processData(): yourgroup is not set, clearing cachefile entry"); // Log to output for debugging - if (_this.config.yourgroup.length == 0) { // Check if yourgroup is empty - logger("debug", "DataManager processData(): yourgroup is not set, clearing cachefile entry"); // Log to output for debugging + // Reset cachefile values + _this.cachefile.configgroup = ""; + _this.cachefile.configgroup64id = ""; - // Reset cachefile values - _this.cachefile.configgroup = ""; - _this.cachefile.configgroup64id = ""; + return resolve(); + } - return resolve(); - } + // Check if URL was processed previously and skip conversion + if (_this.cachefile.configgroup == _this.config.yourgroup) { + logger("debug", "DataManager processData(): ID of yourgroup is stored in cache.json, skipping..."); + return resolve(); + } + + logger("info", "groupID64 of yourgroup is not in cache.json. Requesting information from Steam...", false, true, logger.animation("loading")); - // Check if URL was processed previously and skip conversion - if (_this.cachefile.configgroup == _this.config.yourgroup) { - logger("debug", "DataManager processData(): ID of yourgroup is stored in cache.json, skipping..."); + steamIdResolver.groupUrlToGroupID64(_this.config.yourgroup, (err, res) => { + if (err == "The specified group could not be found.") { // If the group couldn't be found display specific message + logger("error", "Your yourgroup in config doesn't seem to be valid!\n Error: " + _this.config.yourgroup + " contains no xml or groupID64 data", true); + return resolve(); + } else { + if (err) { + logger("error", "Error getting yourgroup information from Steam: " + err); // If a different error then display a generic message with the error return resolve(); } + } - logger("info", "groupID64 of yourgroup is not in cache.json. Requesting information from Steam...", false, true, logger.animation("loading")); + logger("info", `Successfully retrieved yourgroup information. groupID64: ${res}`, false, true, logger.animation("loading")); - steamIdResolver.groupUrlToGroupID64(_this.config.yourgroup, (err, res) => { - if (err == "The specified group could not be found.") { // If the group couldn't be found display specific message - logger("error", "Your yourgroup in config doesn't seem to be valid!\n Error: " + _this.config.yourgroup + " contains no xml or groupID64 data", true); - return resolve(); - } else { - if (err) { - logger("error", "Error getting yourgroup information from Steam: " + err); // If a different error then display a generic message with the error - return resolve(); - } - } + _this.cachefile.configgroup = _this.config.yourgroup; + _this.cachefile.configgroup64id = res; + resolve(); + }); - logger("info", `Successfully retrieved yourgroup information. groupID64: ${res}`, false, true, logger.animation("loading")); + }); + } - _this.cachefile.configgroup = _this.config.yourgroup; - _this.cachefile.configgroup64id = res; - resolve(); - }); + function botsgroup() { + return new Promise((resolve) => { - }); - } + if (_this.config.botsgroup.length == 0) { // Check if botsgroup is empty + logger("debug", "DataManager processData(): botsgroup is not set, clearing cachefile entry"); // Log to output for debugging - function botsgroup() { - return new Promise((resolve) => { + // Reset cachefile values + _this.cachefile.botsgroup = ""; + _this.cachefile.botsgroupid = ""; - if (_this.config.botsgroup.length == 0) { // Check if botsgroup is empty - logger("debug", "DataManager processData(): botsgroup is not set, clearing cachefile entry"); // Log to output for debugging + return resolve(); + } - // Reset cachefile values - _this.cachefile.botsgroup = ""; - _this.cachefile.botsgroupid = ""; + // Check if URL was processed previously and skip conversion + if (_this.cachefile.botsgroup == _this.config.botsgroup) { + logger("debug", "DataManager processData(): ID of botsgroup is stored in cache.json, skipping..."); + return resolve(); + } - return resolve(); - } + logger("info", "groupID64 of botsgroup is not in cache.json. Requesting information from Steam...", false, true, logger.animation("loading")); - // Check if URL was processed previously and skip conversion - if (_this.cachefile.botsgroup == _this.config.botsgroup) { - logger("debug", "DataManager processData(): ID of botsgroup is stored in cache.json, skipping..."); + steamIdResolver.groupUrlToGroupID64(_this.config.botsgroup, (err, res) => { + if (err == "The specified group could not be found.") { // If the group couldn't be found display specific message + logger("warn", "Your botsgroup in config doesn't seem to be valid!\n " + _this.config.botsgroup + " contains no xml or groupID64 data"); + return resolve(); + } else { + if (err) { + logger("error", "Error getting botsgroup information from Steam: " + err); // If a different error then display a generic message with the error return resolve(); } + } - logger("info", "groupID64 of botsgroup is not in cache.json. Requesting information from Steam...", false, true, logger.animation("loading")); + logger("info", `Successfully retrieved botsgroup information. groupID64: ${res}`, false, true, logger.animation("loading")); - steamIdResolver.groupUrlToGroupID64(_this.config.botsgroup, (err, res) => { - if (err == "The specified group could not be found.") { // If the group couldn't be found display specific message - logger("warn", "Your botsgroup in config doesn't seem to be valid!\n " + _this.config.botsgroup + " contains no xml or groupID64 data"); - return resolve(); - } else { - if (err) { - logger("error", "Error getting botsgroup information from Steam: " + err); // If a different error then display a generic message with the error - return resolve(); - } - } - - logger("info", `Successfully retrieved botsgroup information. groupID64: ${res}`, false, true, logger.animation("loading")); + _this.cachefile.botsgroup = _this.config.botsgroup; + _this.cachefile.botsgroupid = res; + resolve(); + }); - _this.cachefile.botsgroup = _this.config.botsgroup; - _this.cachefile.botsgroupid = res; - resolve(); - }); + }); + } - }); - } + function owners() { + return new Promise((resolve) => { - function owners() { - return new Promise((resolve) => { + let tempArr = []; + logger("debug", `DataManager processData(): Converting ${_this.config.ownerid.length} owner(s)...`); - let tempArr = []; - logger("debug", `DataManager processData(): Converting ${_this.config.ownerid.length} owner(s)...`); + // Check for last iteration, update cache and resolve Promise + function finishedResponse(i) { + if (i + 1 == _this.config.ownerid.length) { + logger("debug", "DataManager processData(): Finished converting all ownerids. Array:"); + logger("debug", tempArr); - // Check for last iteration, update cache and resolve Promise - function finishedResponse(i) { - if (i + 1 == _this.config.ownerid.length) { - logger("debug", "DataManager processData(): Finished converting all ownerids. Array:"); - logger("debug", tempArr); + _this.cachefile["ownerid"] = tempArr; // Refresh cache + resolve(); + } + } - _this.cachefile["ownerid"] = tempArr; // Refresh cache - resolve(); - } - } + // Instantly bail out if the array is empty. DataCheck will abort the bot later on + if (_this.config.ownerid.length == 0) finishedResponse(-1); - // Instantly bail out if the array is empty. DataCheck will abort the bot later on - if (_this.config.ownerid.length == 0) finishedResponse(-1); - - // Either convert to steamID64 or directly push e - _this.config.ownerid.forEach((e, i) => { - if (isNaN(e) || !new SteamID(String(e)).isValid()) { - steamIdResolver.customUrlToSteamID64(String(e), (err, id) => { - if (err) { - logger("warn", `ownerid ${e} in your config does not seem to be valid! Error: ${err}`); - tempArr[i] = null; - } else { - logger("debug", `DataManager processData(): Converted ${e} to ${id}`); - tempArr[i] = id; - } - - finishedResponse(i); - }); + // Either convert to steamID64 or directly push e + _this.config.ownerid.forEach((e, i) => { + if (isNaN(e) || !new SteamID(String(e)).isValid()) { + steamIdResolver.customUrlToSteamID64(String(e), (err, id) => { + if (err) { + logger("warn", `ownerid ${e} in your config does not seem to be valid! Error: ${err}`); + tempArr[i] = null; } else { - tempArr[i] = e; - finishedResponse(i); + logger("debug", `DataManager processData(): Converted ${e} to ${id}`); + tempArr[i] = id; } - }); - - }); - } + finishedResponse(i); + }); + } else { + tempArr[i] = e; + finishedResponse(i); + } + }); - // Process all three, then update cache.json - await Promise.all([yourgroup(), botsgroup(), owners()]); + }); + } - fs.writeFile(srcdir + "/data/cache.json", JSON.stringify(this.cachefile, null, 4), err => { - if (err) logger("error", `DataManager processData(): Error updating cache.json: ${err}`); - resolve(); - }); + // Process all three, then update cache.json + await Promise.all([yourgroup(), botsgroup(), owners()]); - })(); + fs.writeFile(srcdir + "/data/cache.json", JSON.stringify(this.cachefile, null, 4), err => { + if (err) logger("error", `DataManager processData(): Error updating cache.json: ${err}`); }); + }; \ No newline at end of file From 8ebdb9a04df743d6653ea30a97827b50ea5ddf06 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Mon, 3 Jul 2023 23:35:40 +0200 Subject: [PATCH 19/43] Update various descriptions --- docs/wiki/commands_doc.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/wiki/commands_doc.md b/docs/wiki/commands_doc.md index db12c98c..084ff5c8 100644 --- a/docs/wiki/commands_doc.md +++ b/docs/wiki/commands_doc.md @@ -12,30 +12,31 @@ This is the full documentation of all commands. Most commands have aliases but s | !downvote | `amount ID` | Downvotes a sharedfile with all bot accounts that haven't yet voted on that item. Requires unlimited accounts! (Owner only.) | | !favorite | `amount ID` | Favorizes a sharedfile with all bot accounts that haven't yet favorized that item. | | !unfavorite | `amount ID` | Unfavorizes a sharedfile with all bot accounts that have favorized that item. (Owners only.) | -| !ping | No arguments | Returns a `'Pong!'` and ping to Steam's servers. Can be used to check if the bot is responsive | +| !ping | No arguments | Returns ping in ms to Steam's servers. Can be used to check if the bot is responsive | | !info | No arguments | Returns useful information and statistics about the bot and you. | | !owner | No arguments | Returns a link to the owner's profile set in the config.json. | | !group | No arguments | Sends an invite or responds with the group link set as yourgroup in the config. | -| !abort | `profileid` | Abort your own comment process. Owners can also provide a profile id to abort a comment process for that profile. | +| !abort | `ID` | Abort your own comment process or one on another ID you have started. Owners can also abort requests started by other users. | | !resetcooldown | `profileid` or `global` | Clear your, the profileid's or the comment cooldown of all bot accounts (global). Alias: !rc (Owner only.) | | !settings | `config key` `new value` | Change a value in the config. (Owner only.) | -| !failed | `profileid` | See the exact errors of your last comment request. Owners can also provide a profile id to show errors for that profile. | -| !sessions | No arguments | Displays all active comment processes. (Owner only.) | -| !mysessions | No arguments | Displays all active comment processes for your profile. | -| !about | No arguments | Returns the link to this repository, my steam profile and a donation link.
The message also contains a disclaimer as well as a link to the owner's profile set in the config.json. | -| !addfriend | `profileid` | Adds the profileid with all bot accounts. **This only works with unlimited accounts!** (Owner only.) | -| !unfriend | `profileid` | Unfriends the associated user from all logged in accounts if he is still on their friendlist. (Owner only.) Providing no argument will let all bots unfriend you. (Available to normal users) | +| !failed | `ID` | See the exact errors of the last comment request on your profile or provide an ID to see the errors of the last request you started. Owners can also view errors for requests started by other users. | +| !sessions | No arguments | Displays all active requests. (Owner only.) | +| !mysessions | No arguments | Displays all active requests for your profile. | +| !about | No arguments | Displays information about this project. The message also contains a disclaimer as well as a link to the owner's profile set in the config.json. | +| !addfriend | `profileid` | Adds the profileid with all bot accounts. Requires unlimited accounts! (Owner only.) | +| !unfriend | `profileid` | Unfriends a user from all logged in accounts. (Owner only.) Providing no argument will let all bots unfriend you. (Available to normal users) | | !unfriendall | `"abort"` | Unfriends everyone with all bot accounts. (Owner only.) | -| !leavegroup | `groupid64` or `group url` | Leave this group with all bot accounts. (Owner only.) | +| !joingroup | `groupid64` or `group url` | Joins a Steam Group with all bot accounts. (Owner only.) | +| !leavegroup | `groupid64` or `group url` | Leaves a group with all bot accounts. (Owner only.) | | !leaveallgroups | `"abort"`      | Leaves all groups with all bot accounts. (Owner only.) | -| !block | `profileid`      | Blocks the user on Steam. (Owner only.) | -| !unblock | `profileid`      | Unblocks the user on Steam. Note: The user still seems to be ignored for a few days by Steam. (Owner only.) | +| !block | `profileid`      | Blocks a user with all bot accounts on Steam. (Owner only.) | +| !unblock | `profileid`      | Unblocks a user with all bot accounts on Steam. Note: The user can still get ignored by Steam for a while. (Owner only.) | | !reload | No arguments | Reloads all commands and plugins without needing to restart. Please only use it for testing/development. Alias: !rl (Owner only.) | | !restart | No arguments | Restarts the bot and checks for available updates. Alias: !rs (Owner only.) | | !stop | No arguments | Stops the bot. (Owner only.) | -| !update | `true` | Checks for an available update and installs it if automatic updates are enabled and no comment sessions are active. 'true' forces an update. Blocks new comment requests if it currently waits for one to be completed. | +| !update | `true` | Checks for an available update and installs it if automatic updates are enabled and no requests are active. 'true' forces an update. Blocks new requests if it currently waits for one to be completed. (Owner only.) | | !log | No arguments | Shows the last 15 lines of the log. (Owner only.) | -| !eval | `javascript code` | Disabled by default, needs to be toggled on with `enableevalcmd` in config.json.

**Warning!** This will run any javascript code that was provided. It is strongly advised to leave this feature off unless you know exactly what this means! If you have multiple owners configured they also can run code on **your** machine!

(Owner only.) | +| !eval | `javascript code` | Disabled by default, needs to be toggled on with `enableevalcmd` in config.json.

**Warning!** This will run any javascript code that was provided. It is strongly advised to leave this feature off unless you know exactly what this means! If you have multiple owners configured they can also run code on **your** machine!

(Owner only.) |

To get more information about responses in form of an error that one of these commands could return, visit the `Errors & FAQ` page in this wiki. From 6086d262fefa4c3c1ba148f861e679921d53815a Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Mon, 3 Jul 2023 23:36:16 +0200 Subject: [PATCH 20/43] Update types --- types/types.d.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/types/types.d.ts b/types/types.d.ts index 9577b7b0..13beb343 100644 --- a/types/types.d.ts +++ b/types/types.d.ts @@ -849,6 +849,11 @@ declare class PluginSystem { * @returns Resolves with your plugin config processed from JSON to an object. If the config failed to load, the promise will be rejected with an error. */ loadPluginConfig(pluginName: string): Promise; + /** + * Integrates changes made to the config to the users config + * @returns the config + */ + aggregatePluginConfig(pluginName: string): Record; /** * Writes your plugin config changes to the filesystem. The object data will be processed to JSON. * @param pluginName - Name of your plugin @@ -928,6 +933,11 @@ declare class PluginSystem { * @returns Resolves on success, rejects otherwise with an error */ writePluginConfig(pluginName: string, pluginConfig: any): Promise; + /** + * Integrates changes made to the config to the users config + * @returns the config + */ + aggregatePluginConfig(pluginName: string): Record; } /** From c58292ea21c7963ff4ae8ea072923f6cfe592446 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Tue, 4 Jul 2023 13:30:38 +0200 Subject: [PATCH 21/43] Add descriptions from wiki to all commands --- docs/wiki/commands_doc.md | 6 +++--- src/commands/core/block.js | 6 +++--- src/commands/core/comment.js | 4 ++-- src/commands/core/favorite.js | 6 +++--- src/commands/core/friend.js | 8 ++++---- src/commands/core/general.js | 18 +++++++++--------- src/commands/core/group.js | 8 ++++---- src/commands/core/requests.js | 12 ++++++------ src/commands/core/settings.js | 4 ++-- src/commands/core/system.js | 14 +++++++------- src/commands/core/vote.js | 6 +++--- 11 files changed, 46 insertions(+), 46 deletions(-) diff --git a/docs/wiki/commands_doc.md b/docs/wiki/commands_doc.md index 084ff5c8..15663875 100644 --- a/docs/wiki/commands_doc.md +++ b/docs/wiki/commands_doc.md @@ -16,12 +16,12 @@ This is the full documentation of all commands. Most commands have aliases but s | !info | No arguments | Returns useful information and statistics about the bot and you. | | !owner | No arguments | Returns a link to the owner's profile set in the config.json. | | !group | No arguments | Sends an invite or responds with the group link set as yourgroup in the config. | -| !abort | `ID` | Abort your own comment process or one on another ID you have started. Owners can also abort requests started by other users. | +| !abort | `ID` | Abort your own comment process or one on another ID you have started. Owners can also abort requests started by other users. | | !resetcooldown | `profileid` or `global` | Clear your, the profileid's or the comment cooldown of all bot accounts (global). Alias: !rc (Owner only.) | | !settings | `config key` `new value` | Change a value in the config. (Owner only.) | -| !failed | `ID` | See the exact errors of the last comment request on your profile or provide an ID to see the errors of the last request you started. Owners can also view errors for requests started by other users. | +| !failed | `ID` | See the exact errors of the last comment request on your profile or provide an ID to see the errors of the last request you started. Owners can also view errors for requests started by other users. | | !sessions | No arguments | Displays all active requests. (Owner only.) | -| !mysessions | No arguments | Displays all active requests for your profile. | +| !mysessions | No arguments | Displays all active requests that you have started. | | !about | No arguments | Displays information about this project. The message also contains a disclaimer as well as a link to the owner's profile set in the config.json. | | !addfriend | `profileid` | Adds the profileid with all bot accounts. Requires unlimited accounts! (Owner only.) | | !unfriend | `profileid` | Unfriends a user from all logged in accounts. (Owner only.) Providing no argument will let all bots unfriend you. (Available to normal users) | diff --git a/src/commands/core/block.js b/src/commands/core/block.js index 6061e76e..d360109d 100644 --- a/src/commands/core/block.js +++ b/src/commands/core/block.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 13:20:48 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -22,7 +22,7 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.block = { names: ["block"], - description: "", + description: "Blocks a user with all bot accounts on Steam", ownersOnly: true, /** @@ -58,7 +58,7 @@ module.exports.block = { module.exports.unblock = { names: ["unblock"], - description: "", + description: "Unblocks a user with all bot accounts on Steam. Note: The user can still get ignored by Steam for a while", ownersOnly: true, /** diff --git a/src/commands/core/comment.js b/src/commands/core/comment.js index 95bbf8f9..49d611a4 100644 --- a/src/commands/core/comment.js +++ b/src/commands/core/comment.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:49 + * Last Modified: 04.07.2023 13:21:20 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -26,7 +26,7 @@ const { logCommentError, handleIterationSkip } = require("../helpers/handleComme module.exports.comment = { names: ["comment", "gcomment", "groupcomment"], - description: "", + description: "Request comments from all available bot accounts for a profile, group or sharedfile", ownersOnly: false, /** diff --git a/src/commands/core/favorite.js b/src/commands/core/favorite.js index 899601f4..84114ee0 100644 --- a/src/commands/core/favorite.js +++ b/src/commands/core/favorite.js @@ -4,7 +4,7 @@ * Created Date: 02.06.2023 13:23:01 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:49 + * Last Modified: 04.07.2023 13:22:27 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -24,7 +24,7 @@ const { handleFavoriteIterationSkip, logFavoriteError } = require("../helpers/ha module.exports.favorite = { names: ["favorite", "fav"], - description: "Favorites a sharedfile", + description: "Favorizes a sharedfile with all bot accounts that haven't yet favorized that item", ownersOnly: false, /** @@ -191,7 +191,7 @@ module.exports.favorite = { module.exports.unfavorite = { names: ["unfavorite", "unfav"], - description: "Unfavorites a sharedfile", + description: "Unfavorizes a sharedfile with all bot accounts that have favorized that item", ownersOnly: true, /** diff --git a/src/commands/core/friend.js b/src/commands/core/friend.js index 3be5b164..c6b37cb8 100644 --- a/src/commands/core/friend.js +++ b/src/commands/core/friend.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 13:23:11 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -22,7 +22,7 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.addFriend = { names: ["addfriend"], - description: "", + description: "Adds the ID with all bot accounts. Requires unlimited accounts!", ownersOnly: true, /** @@ -82,7 +82,7 @@ module.exports.addFriend = { module.exports.unfriend = { names: ["unfriend"], - description: "", + description: "Unfriends a user from all logged in accounts. (Owner only) Providing no argument will let all bots unfriend you. (Available to normal users)", ownersOnly: false, /** @@ -135,7 +135,7 @@ module.exports.unfriend = { module.exports.unfriendall = { names: ["unfriendall"], - description: "", + description: "Unfriends everyone with all bot accounts", ownersOnly: true, /** diff --git a/src/commands/core/general.js b/src/commands/core/general.js index 12a13775..ffca9162 100644 --- a/src/commands/core/general.js +++ b/src/commands/core/general.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 13:24:44 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -25,7 +25,7 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.help = { names: ["h", "help", "commands"], - description: "", + description: "Returns a list of commands available to you and a link to the commands documentation wiki page", ownersOnly: false, /** @@ -75,7 +75,7 @@ module.exports.help = { module.exports.info = { names: ["info"], - description: "", + description: "Returns useful information and statistics about the bot and you", ownersOnly: false, /** @@ -118,7 +118,7 @@ module.exports.info = { module.exports.ping = { names: ["ping", "pong"], - description: "Pings SteamCommunity and measures the time it took.", + description: "Returns ping in ms to Steam's servers. Can be used to check if the bot is responsive", ownersOnly: false, /** @@ -145,7 +145,7 @@ module.exports.ping = { module.exports.about = { names: ["about"], - description: "", + description: "Displays information about this project. The message also contains a disclaimer as well as a link to the owner's profile set in the config.json", ownersOnly: false, /** @@ -167,7 +167,7 @@ module.exports.about = { module.exports.owner = { names: ["owner"], - description: "", + description: "Returns a link to the owner's profile set in the config.json", ownersOnly: false, /** @@ -193,7 +193,7 @@ module.exports.owner = { // Test Command for debugging module.exports.test = { names: ["test"], - description: "", + description: "Test Command for debugging", ownersOnly: true, /** @@ -208,7 +208,7 @@ module.exports.test = { run: async (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // eslint-disable-line - // Do not remove, these are handleSteamIdResolving test cases. Might be useful to include later in steamid-resolving lib test suite + /* // Do not remove, these are handleSteamIdResolving test cases. Might be useful to include later in steamid-resolving lib test suite let handleSteamIdResolving = commandHandler.controller.handleSteamIdResolving; // With type param @@ -229,6 +229,6 @@ module.exports.test = { // We already provide the correct id handleSteamIdResolving("76561198260031749", null, console.log); - handleSteamIdResolving("103582791464712227", null, console.log); + handleSteamIdResolving("103582791464712227", null, console.log); */ } }; diff --git a/src/commands/core/group.js b/src/commands/core/group.js index da38b241..ed2d892b 100644 --- a/src/commands/core/group.js +++ b/src/commands/core/group.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 13:25:30 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -22,7 +22,7 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.group = { names: ["group"], - description: "", + description: "Sends an invite or responds with the group link set as yourgroup in the config", ownersOnly: false, /** @@ -93,7 +93,7 @@ module.exports.joinGroup = { module.exports.leaveGroup = { names: ["leavegroup"], - description: "", + description: "Leaves a group with all bot accounts", ownersOnly: true, /** @@ -130,7 +130,7 @@ module.exports.leaveGroup = { module.exports.leaveAllGroups = { names: ["leaveallgroups"], - description: "", + description: "Leaves all groups with all bot accounts", ownersOnly: true, /** diff --git a/src/commands/core/requests.js b/src/commands/core/requests.js index 35285247..163092c2 100644 --- a/src/commands/core/requests.js +++ b/src/commands/core/requests.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 13:26:53 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -21,7 +21,7 @@ const { failedCommentsObjToString } = require("../helpers/handleCommentSkips.js" module.exports.abort = { names: ["abort"], - description: "", + description: "Abort your own comment process or one on another ID you have started. Owners can also abort requests started by other users", ownersOnly: false, /** @@ -62,7 +62,7 @@ module.exports.abort = { module.exports.resetCooldown = { names: ["resetcooldown", "rc"], - description: "", + description: "Clear your, the ID's or the comment cooldown of all bot accounts (global)", ownersOnly: true, /** @@ -106,7 +106,7 @@ module.exports.resetCooldown = { module.exports.failed = { names: ["failed"], - description: "", + description: "See the exact errors of the last comment request on your profile or provide an ID to see the errors of the last request you started. Owners can also view errors for requests started by other users", ownersOnly: false, /** @@ -152,7 +152,7 @@ module.exports.failed = { module.exports.sessions = { names: ["sessions"], - description: "", + description: "Displays all active requests", ownersOnly: true, /** @@ -196,7 +196,7 @@ module.exports.sessions = { module.exports.mySessions = { names: ["mysessions"], - description: "", + description: "Displays all active requests for your profile", ownersOnly: false, /** diff --git a/src/commands/core/settings.js b/src/commands/core/settings.js index b40db996..52734bce 100644 --- a/src/commands/core/settings.js +++ b/src/commands/core/settings.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 13:27:31 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -22,7 +22,7 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.settings = { names: ["set", "settings", "config"], - description: "", + description: "Change a value in the config", ownersOnly: true, /** diff --git a/src/commands/core/system.js b/src/commands/core/system.js index 8674dd95..bdf26758 100644 --- a/src/commands/core/system.js +++ b/src/commands/core/system.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 13:29:00 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -22,7 +22,7 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.restart = { names: ["restart", "rs"], - description: "", + description: "Restarts the bot and checks for available updates", ownersOnly: true, /** @@ -44,7 +44,7 @@ module.exports.restart = { module.exports.stop = { names: ["stop"], - description: "", + description: "Stops the bot", ownersOnly: true, /** @@ -66,7 +66,7 @@ module.exports.stop = { module.exports.reload = { names: ["reload", "rl"], - description: "Reloads all commands and plugins without needing to restart. Please only use it for testing, this isn't clean.", + description: "Reloads all commands and plugins without needing to restart. Please only use it for testing/development", ownersOnly: true, /** @@ -95,7 +95,7 @@ module.exports.reload = { module.exports.update = { names: ["update"], - description: "", + description: "Checks for an available update and installs it if automatic updates are enabled and no requests are active. 'true' forces an update. Blocks new requests if it currently waits for one to be completed", ownersOnly: true, /** @@ -125,7 +125,7 @@ module.exports.update = { module.exports.output = { names: ["output", "log"], - description: "", + description: "Shows the last 15 lines of the log", ownersOnly: true, /** @@ -150,7 +150,7 @@ module.exports.output = { module.exports.eval = { names: ["eval"], - description: "", + description: "Disabled by default, needs to be toggled on with `enableevalcmd` in config.json. **Warning!** This will run any javascript code that was provided. It is strongly advised to leave this feature off unless you know exactly what this means! If you have multiple owners configured they can also run code on **your** machine!", ownersOnly: true, /** diff --git a/src/commands/core/vote.js b/src/commands/core/vote.js index f297870d..443450b4 100644 --- a/src/commands/core/vote.js +++ b/src/commands/core/vote.js @@ -4,7 +4,7 @@ * Created Date: 28.05.2023 12:02:24 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 13:29:30 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -24,7 +24,7 @@ const { handleVoteIterationSkip, logVoteError } = require("../helpers/handleShar module.exports.upvote = { names: ["upvote"], - description: "Upvotes a sharedfile", + description: "Upvotes a sharedfile with all bot accounts that haven't yet voted on that item. Requires unlimited accounts!", ownersOnly: false, /** @@ -196,7 +196,7 @@ module.exports.upvote = { module.exports.downvote = { names: ["downvote"], - description: "Downvotes a sharedfile", + description: "Downvotes a sharedfile with all bot accounts that haven't yet voted on that item. Requires unlimited accounts!", ownersOnly: true, // I would like to prevent users from abusing this feature to dislike other peoples creations /** From 8836b441818757a8d6a5af5f34285d397cd22478 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Tue, 4 Jul 2023 16:33:15 +0200 Subject: [PATCH 22/43] Experimental fix for SteamCommunity lib failing to parse Posted --- src/bot/bot.js | 3 +- src/libraryPatches/CSteamSharedFile.js | 223 +++++++++++++++++++++++++ 2 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 src/libraryPatches/CSteamSharedFile.js diff --git a/src/bot/bot.js b/src/bot/bot.js index 3390af26..0a645a57 100644 --- a/src/bot/bot.js +++ b/src/bot/bot.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 15:45:22 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -104,6 +104,7 @@ const Bot = function(controller, index) { this.community = new SteamCommunity({ request: request.defaults({ "proxy": this.loginData.proxy }) }); // Pass proxy to community library as well // Load my library patches + require("../libraryPatches/CSteamSharedFile.js"); require("../libraryPatches/profile.js"); require("../libraryPatches/sharedfiles.js"); require("../libraryPatches/helpers.js"); diff --git a/src/libraryPatches/CSteamSharedFile.js b/src/libraryPatches/CSteamSharedFile.js new file mode 100644 index 00000000..f75bdbe2 --- /dev/null +++ b/src/libraryPatches/CSteamSharedFile.js @@ -0,0 +1,223 @@ +const Cheerio = require('cheerio'); +const SteamID = require('steamid'); + +const SteamCommunity = require('steamcommunity'); +const Helpers = require('../../node_modules/steamcommunity/components/helpers.js'); + +const ESharedFileType = require('../../node_modules/steamcommunity/resources/ESharedFileType.js'); + + +/** + * Scrape a sharedfile's DOM to get all available information + * @param {string} sharedFileId - ID of the sharedfile + * @param {function} callback - First argument is null/Error, second is object containing all available information + */ +SteamCommunity.prototype.getSteamSharedFile = function(sharedFileId, callback) { + // Construct object holding all the data we can scrape + let sharedfile = { + id: sharedFileId, + type: null, + appID: null, + owner: null, + fileSize: null, + postDate: null, + resolution: null, + uniqueVisitorsCount: null, + favoritesCount: null, + upvoteCount: null, + guideNumRatings: null, + isUpvoted: null, + isDownvoted: null + }; + + // Get DOM of sharedfile + this.httpRequestGet(`https://steamcommunity.com/sharedfiles/filedetails/?id=${sharedFileId}&l=english`, (err, res, body) => { // Request page in english so that the Posted scraping below works + try { + + /* --------------------- Preprocess output --------------------- */ + + // Load output into cheerio to make parsing easier + let $ = Cheerio.load(body); + + // Dynamically map detailsStatsContainerLeft to detailsStatsContainerRight in an object to make readout easier. It holds size, post date and resolution. + let detailsStatsObj = {}; + let detailsLeft = $(".detailsStatsContainerLeft").children(); + let detailsRight = $(".detailsStatsContainerRight").children(); + + Object.keys(detailsLeft).forEach((e) => { // Dynamically get all details. Don't hardcore so that this also works for guides. + if (isNaN(e)) { + return; // Ignore invalid entries + } + + detailsStatsObj[detailsLeft[e].children[0].data.trim()] = detailsRight[e].children[0].data; + }); + + // Dynamically map stats_table descriptions to values. This holds Unique Visitors and Current Favorites + let statsTableObj = {}; + let statsTable = $(".stats_table").children(); + + Object.keys(statsTable).forEach((e) => { + if (isNaN(e)) { + return; // Ignore invalid entries + } + + // Value description is at index 3, value data at index 1 + statsTableObj[statsTable[e].children[3].children[0].data] = statsTable[e].children[1].children[0].data.replace(/,/g, ""); // Remove commas from 1k+ values + }); + + + /* --------------------- Find and map values --------------------- */ + + // Find appID in share button onclick event + sharedfile.appID = Number($("#ShareItemBtn").attr()["onclick"].replace(`ShowSharePublishedFilePopup( '${sharedFileId}', '`, "").replace("' );", "")); + + + // Find fileSize if not guide + sharedfile.fileSize = detailsStatsObj["File Size"] || null; // TODO: Convert to bytes? It seems like to always be MB but no guarantee + + + // Find postDate and convert to timestamp + let posted = detailsStatsObj["Posted"] || null; // Set to null if "posted" could not be found as Steam translates dates and parsing it below will return a wrong result + + if (posted) { + sharedfile.postDate = Helpers.decodeSteamTime(posted.trim()); // Only parse if posted is defined to avoid errors + } + + + // Find resolution if artwork or screenshot + sharedfile.resolution = detailsStatsObj["Size"] || null; + + + // Find uniqueVisitorsCount. We can't use ' || null' here as Number("0") casts to false + if (statsTableObj["Unique Visitors"]) { + sharedfile.uniqueVisitorsCount = Number(statsTableObj["Unique Visitors"]); + } + + + // Find favoritesCount. We can't use ' || null' here as Number("0") casts to false + if (statsTableObj["Current Favorites"]) { + sharedfile.favoritesCount = Number(statsTableObj["Current Favorites"]); + } + + + // Find upvoteCount. We can't use ' || null' here as Number("0") casts to false + let upvoteCount = $("#VotesUpCountContainer > #VotesUpCount").text(); + + if (upvoteCount) { + sharedfile.upvoteCount = Number(upvoteCount); + } + + + // Find numRatings if this is a guide as they use a different voting system + let numRatings = $(".ratingSection > .numRatings").text().replace(" ratings", ""); + + sharedfile.guideNumRatings = Number(numRatings) || null; // Set to null if not a guide or if the guide does not have enough ratings to show a value + + + // Determine if this account has already voted on this sharedfile + sharedfile.isUpvoted = String($(".workshopItemControlCtn > #VoteUpBtn")[0].attribs["class"]).includes("toggled"); // Check if upvote btn class contains "toggled" + sharedfile.isDownvoted = String($(".workshopItemControlCtn > #VoteDownBtn")[0].attribs["class"]).includes("toggled"); // Check if downvote btn class contains "toggled" + + + // Determine type by looking at the second breadcrumb. Find the first separator as it has a unique name and go to the next element which holds our value of interest + let breadcrumb = $(".breadcrumbs > .breadcrumb_separator").next().get(0).children[0].data || ""; + + if (breadcrumb.includes("Screenshot")) { + sharedfile.type = ESharedFileType.Screenshot; + } + + if (breadcrumb.includes("Artwork")) { + sharedfile.type = ESharedFileType.Artwork; + } + + if (breadcrumb.includes("Guide")) { + sharedfile.type = ESharedFileType.Guide; + } + + + // Find owner profile link, convert to steamID64 using SteamIdResolver lib and create a SteamID object + let ownerHref = $(".friendBlockLinkOverlay").attr()["href"]; + + Helpers.resolveVanityURL(ownerHref, (err, data) => { // This request takes <1 sec + if (err) { + callback(err); + return; + } + + sharedfile.owner = new SteamID(data.steamID); + + // Make callback when ID was resolved as otherwise owner will always be null + callback(null, new CSteamSharedFile(this, sharedfile)); + }); + + } catch (err) { + callback(err, null); + } + }, "steamcommunity"); +}; + +/** + * Constructor - Creates a new SharedFile object + * @class + * @param {SteamCommunity} community + * @param {{ id: string, type: ESharedFileType, appID: number, owner: SteamID|null, fileSize: string|null, postDate: number, resolution: string|null, uniqueVisitorsCount: number, favoritesCount: number, upvoteCount: number|null, guideNumRatings: Number|null, isUpvoted: boolean, isDownvoted: boolean }} data + */ +function CSteamSharedFile(community, data) { + /** + * @type {SteamCommunity} + */ + this._community = community; + + // Clone all the data we received + Object.assign(this, data); +} + +/** + * Deletes a comment from this sharedfile's comment section + * @param {String} cid - ID of the comment to delete + * @param {function} callback - Takes only an Error object/null as the first argument + */ +CSteamSharedFile.prototype.deleteComment = function(cid, callback) { + this._community.deleteSharedFileComment(this.owner, this.id, cid, callback); +}; + +/** + * Favorites this sharedfile + * @param {function} callback - Takes only an Error object/null as the first argument + */ +CSteamSharedFile.prototype.favorite = function(callback) { + this._community.favoriteSharedFile(this.id, this.appID, callback); +}; + +/** + * Posts a comment to this sharedfile + * @param {String} message - Content of the comment to post + * @param {function} callback - Takes only an Error object/null as the first argument + */ +CSteamSharedFile.prototype.comment = function(message, callback) { + this._community.postSharedFileComment(this.owner, this.id, message, callback); +}; + +/** + * Subscribes to this sharedfile's comment section. Note: Checkbox on webpage does not update + * @param {function} callback - Takes only an Error object/null as the first argument + */ +CSteamSharedFile.prototype.subscribe = function(callback) { + this._community.subscribeSharedFileComments(this.owner, this.id, callback); +}; + +/** + * Unfavorites this sharedfile + * @param {function} callback - Takes only an Error object/null as the first argument + */ +CSteamSharedFile.prototype.unfavorite = function(callback) { + this._community.unfavoriteSharedFile(this.id, this.appID, callback); +}; + +/** + * Unsubscribes from this sharedfile's comment section. Note: Checkbox on webpage does not update + * @param {function} callback - Takes only an Error object/null as the first argument + */ +CSteamSharedFile.prototype.unsubscribe = function(callback) { + this._community.unsubscribeSharedFileComments(this.owner, this.id, callback); +}; From 6c356c199e9a909cefdfb481f528784383c6ddec Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:26:08 +0200 Subject: [PATCH 23/43] Misc wiki formatting improvements --- docs/wiki/advancedconfig_doc.md | 5 ++++- docs/wiki/commands_doc.md | 4 ++++ docs/wiki/config_doc.md | 5 ++++- docs/wiki/creating_plugins.md | 3 ++- docs/wiki/customlang_doc.md | 2 ++ docs/wiki/data_doc.md | 4 ++++ docs/wiki/errors_doc.md | 16 ++++++++++++---- docs/wiki/integrating_into_your_app.md | 5 +++-- docs/wiki/steam_limitations.md | 1 + docs/wiki/version_changelogs.md | 2 ++ 10 files changed, 38 insertions(+), 9 deletions(-) diff --git a/docs/wiki/advancedconfig_doc.md b/docs/wiki/advancedconfig_doc.md index d0081b18..708d6f7e 100644 --- a/docs/wiki/advancedconfig_doc.md +++ b/docs/wiki/advancedconfig_doc.md @@ -1,11 +1,14 @@ # Advanced Config Documentation [⬅️ Go back to wiki home](./) +  + This is the full documentation to customize your `advancedconfig.json`. **Note:** These settings are meant for advanced users. Everything important is located in the `config.json` file and you probably don't need to change anything here. - +  + | Key | Usage | Description | | ------------- | ---------------- | ------------ | | \_disclaimer\_ | String | No functionality. Just a comment pointing to the normal config. | diff --git a/docs/wiki/commands_doc.md b/docs/wiki/commands_doc.md index 15663875..7ff6aae2 100644 --- a/docs/wiki/commands_doc.md +++ b/docs/wiki/commands_doc.md @@ -1,9 +1,13 @@ # Commands documentation [⬅️ Go back to wiki home](./) +  + This is the full documentation of all commands. Most commands have aliases but some might be missing in this list. [Try them out!](https://steamcommunity.com/id/3urobeatscommentbot/) +  + | Command | Usage/Arguments | Description | | ------------- | ---------------- | ------------ | | !help | No arguments | Returns a list of commands available to you and a link to this page. | diff --git a/docs/wiki/config_doc.md b/docs/wiki/config_doc.md index 0dd7eaf8..7bb8c6a7 100644 --- a/docs/wiki/config_doc.md +++ b/docs/wiki/config_doc.md @@ -1,10 +1,13 @@ # Config Documentation [⬅️ Go back to wiki home](./) +  + This is the full documentation to customize your `config.json`. **Note:** You don't need to change any values except the owner and ownerid values. Everything else is configured to work out of the box but there might be better settings for your specific situation. Recommendation: Try the default values and customize them if you get errors/problems. - + +  | Key | Usage | Description | | ------------- | ---------------- | ------------ | diff --git a/docs/wiki/creating_plugins.md b/docs/wiki/creating_plugins.md index 4929f472..c2b71a25 100644 --- a/docs/wiki/creating_plugins.md +++ b/docs/wiki/creating_plugins.md @@ -1,7 +1,8 @@ # Creating plugins - [⬅️ Go back to wiki home](./) +  + The functionality of this bot can be extended using plugins. They allow you to intercept events from the bots, run commands, edit or supply data and much much more. diff --git a/docs/wiki/customlang_doc.md b/docs/wiki/customlang_doc.md index c6b1d85e..8ed82b01 100644 --- a/docs/wiki/customlang_doc.md +++ b/docs/wiki/customlang_doc.md @@ -1,6 +1,8 @@ # How to customize chat messages sent by the bot [⬅️ Go back to wiki home](./) +  + This page will instruct you on how to modify the messages the bot will send to a user. This includes nearly all messages and isn't difficult! diff --git a/docs/wiki/data_doc.md b/docs/wiki/data_doc.md index 36291a06..b9928f4c 100644 --- a/docs/wiki/data_doc.md +++ b/docs/wiki/data_doc.md @@ -1,9 +1,13 @@ # Data Documentation [⬅️ Go back to wiki home](./) +  + This is the full documentation of the `data.json` file. This file must **not** be edited! It stores various persistent data about what version the bot is running, which file to start, etc. +  + | Key | Description | | ------------- | ------------ | | version | Defines the installed version. This number will be used by the updater to determine if an update is available. | diff --git a/docs/wiki/errors_doc.md b/docs/wiki/errors_doc.md index d51e9317..92df7133 100644 --- a/docs/wiki/errors_doc.md +++ b/docs/wiki/errors_doc.md @@ -9,10 +9,14 @@ Please remember that the steam errors list is incomplete and the descriptions ar
Bot errors are errors that are being directly returned from my bot, not from steam. I created this documentation so that my bot doesn't suffer the same fate as the steam errors. -- [Errors, FAQ \& Common problems](#errors-faq--common-problems) - - [Bot Errors:](#bot-errors) - - [Steam Errors:](#steam-errors) - - [FAQ/Common problems](#faqcommon-problems) +  + +**Table of Contents:** +- [Bot Errors:](#bot-errors) +- [Steam Errors:](#steam-errors) +- [FAQ/Common problems](#faqcommon-problems) + +  ## Bot Errors: | Error message | Description | @@ -20,6 +24,8 @@ Bot errors are errors that are being directly returned from my bot, not from ste Coming soon... +  + ## Steam Errors: Please don't take all error descriptions for granted. Steam sometimes seems to throw random errors that might not actually have an impact or have completely different reasons.

@@ -49,6 +55,8 @@ You can find all HTTP status codes here: [Wikipedia](https://en.wikipedia.org/wi | ----- | ----- | `Error: AccessDenied` | This can happen if your session got invalidated for some reason. This can often be solved by deleting the `tokens.db` file, located at `src/data/` inside the bot folder, or by only removing the one line of the affected account inside the `tokens.db` file. +  + ## FAQ/Common problems **Q: I got a problem/bug that isn't listed here.** diff --git a/docs/wiki/integrating_into_your_app.md b/docs/wiki/integrating_into_your_app.md index 5b63614b..d9b3d724 100644 --- a/docs/wiki/integrating_into_your_app.md +++ b/docs/wiki/integrating_into_your_app.md @@ -1,12 +1,13 @@ # Integrating into your own application - [⬅️ Go back to wiki home](./) +  + The bot comes with a web server plugin developed by [DerDeathraven](https://github.com/DerDeathraven) Using a RPC style REST API you can easily call various methods. -all methods follow the same pattern: +All methods follow the same pattern: `https://localhost:4000/rpc/${Class}.${Method}?${params}` The full API documentation and a TS SDK file can be found on the [plugin page](https://github.com/DerDeathraven/steam-comment-bot-rest-api) diff --git a/docs/wiki/steam_limitations.md b/docs/wiki/steam_limitations.md index 27e97c86..390f44d7 100644 --- a/docs/wiki/steam_limitations.md +++ b/docs/wiki/steam_limitations.md @@ -3,6 +3,7 @@ Steam sadly has some strict restrictions for commenting. You can read all of them here: [Steam Support](https://help.steampowered.com/en/faqs/view/71D3-35C2-AD96-AA3A) +  If you use *limited accounts* (spent <$5 on the Store) the user will need to send all of these bot accounts a friend request before requesting a comment! diff --git a/docs/wiki/version_changelogs.md b/docs/wiki/version_changelogs.md index eecc4f20..9991baec 100644 --- a/docs/wiki/version_changelogs.md +++ b/docs/wiki/version_changelogs.md @@ -1,6 +1,8 @@ # Version Changelogs [⬅️ Go back to wiki home](./) +  + This is a list of links to the changelogs of all versions. Each changelog contains a date, all changes made and a link to the commit. From 7eebd748598a2289b4757625dba91a8be703f963 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:26:34 +0200 Subject: [PATCH 24/43] Rewrite Steam Limitations page to include new request types --- docs/wiki/steam_limitations.md | 37 +++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/docs/wiki/steam_limitations.md b/docs/wiki/steam_limitations.md index 390f44d7..16fdb093 100644 --- a/docs/wiki/steam_limitations.md +++ b/docs/wiki/steam_limitations.md @@ -1,11 +1,38 @@ # Steam Limitations [⬅️ Go back to wiki home](./) -Steam sadly has some strict restrictions for commenting. -You can read all of them here: [Steam Support](https://help.steampowered.com/en/faqs/view/71D3-35C2-AD96-AA3A)   -If you use *limited accounts* (spent <$5 on the Store) the user will need to send all of these bot accounts a friend request before requesting a comment! +Steam has some strict restrictions for commenting. +This page attempts to explain what you can and cannot do with limited & unlimited accounts. +Steam also has their own page [which you can view here](https://help.steampowered.com/en/faqs/view/71D3-35C2-AD96-AA3A). -Please be also advised that in order to comment on a profile the accounts need to have at least **email steam guard** activated. -There are generators out there that can directly generate accounts with steam guard, however it does not take long to do yourself if you'd like to avoid shady generators. \ No newline at end of file +  + +**Steam Guard:** +Most interactions in the community need you to have Steam Guard enabled, especially for commenting. +Please make sure that all your bot accounts have at least E-Mail Steam Guard enabled. + +  + +**What is a limited account?** +Limited accounts are Steam accounts which have spent less than $5 USD on the Steam Store. +They have stricter limitations and ratelimits to reduce the amount of spam and scams in the SteamCommunity. + +  + +If your account is **limited**, you can: +- ...comment on profiles of friends +- ...comment on sharedfiles (screenshots, artworks & guides) +- ...favorize and unfavorize sharedfiles + +If your account is **unlimited**, you can do all of the above and additionally: +- ...comment on non-friend profiles +- ...comment in groups +- ...upvote and downvote sharedfiles +- ...add other users as friends + +  + +This list is not exhaustive, it just lists features supported by this bot. +For more information, please check out the Steam Support article linked at the top of this page. \ No newline at end of file From 72055d1d1a9b2c1545ca1e181e4c65fb1a8c5860 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:43:09 +0200 Subject: [PATCH 25/43] Rewrite the Integrating into your app wiki page --- docs/wiki/adding_proxies.md | 2 ++ docs/wiki/integrating_into_your_app.md | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/wiki/adding_proxies.md b/docs/wiki/adding_proxies.md index f5595e6b..38264f97 100644 --- a/docs/wiki/adding_proxies.md +++ b/docs/wiki/adding_proxies.md @@ -1,6 +1,8 @@ # Adding proxies [⬅️ Go back to wiki home](./) +  + If you are using 10+ accounts I encourage you to use proxies. It drastically reduces the amount of requests on one IP by equally spreading all accounts onto different IPs, allowing you to comment more and faster, reducing the chance of an IP ban. diff --git a/docs/wiki/integrating_into_your_app.md b/docs/wiki/integrating_into_your_app.md index d9b3d724..9dd048b4 100644 --- a/docs/wiki/integrating_into_your_app.md +++ b/docs/wiki/integrating_into_your_app.md @@ -3,11 +3,22 @@   -The bot comes with a web server plugin developed by [DerDeathraven](https://github.com/DerDeathraven) +This project provides you two ways to integrate it into your own application. +You can either write a **native plugin** or use the official **REST API** to communicate with another application. -Using a RPC style REST API you can easily call various methods. +  + +**Native plugin:** +A native plugin allows you to call functions provided by the bot, as well as reading & writing data directly. +This is the best way to add features to the bot directly. Check out the [creating plugins page](./creating_plugins.md) for a detailed walkthrough. + +  + +**REST API:** +The REST API is an official web server plugin developed by [DerDeathraven](https://github.com/DerDeathraven). It is shipped with this project by default. +It uses this RPC style pattern `https://localhost:4000/rpc/${Class}.${Method}?${params}` to easily call various methods. -All methods follow the same pattern: -`https://localhost:4000/rpc/${Class}.${Method}?${params}` +This is the best way to get data from the bot and run commands from another, completely detached application. +For an example, check out the official [Web UI project](https://github.com/DerDeathraven/steam-comment-service-bot-frontend) which is also made by [DerDeathraven](https://github.com/DerDeathraven)! -The full API documentation and a TS SDK file can be found on the [plugin page](https://github.com/DerDeathraven/steam-comment-bot-rest-api) +The full API documentation and a TS SDK file can be found on the [plugin project page](https://github.com/DerDeathraven/steam-comment-bot-rest-api). From ec8b3a07bc6ecaf6b172e6640a99c648a3795913 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:12:18 +0200 Subject: [PATCH 26/43] Enforce lowercase primitive types in JsDocs --- src/bot/bot.js | 28 +++++----- src/bot/helpers/checkMsgBlock.js | 8 +-- src/bot/helpers/steamChatInteraction.js | 14 ++--- src/commands/commandHandler.js | 24 ++++----- src/commands/core/block.js | 14 ++--- src/commands/core/comment.js | 14 ++--- src/commands/core/favorite.js | 6 +-- src/commands/core/friend.js | 20 +++---- src/commands/core/general.js | 38 ++++++------- src/commands/core/group.js | 26 ++++----- src/commands/core/requests.js | 32 +++++------ src/commands/core/settings.js | 8 +-- src/commands/core/system.js | 38 ++++++------- src/commands/core/vote.js | 10 ++-- src/commands/helpers/getCommentArgs.js | 12 ++--- src/commands/helpers/getCommentBots.js | 10 ++-- src/commands/helpers/getFavoriteBots.js | 4 +- src/commands/helpers/getSharedfileArgs.js | 10 ++-- src/commands/helpers/handleCommentSkips.js | 16 +++--- .../helpers/handleSharedfileErrors.js | 16 +++--- src/controller/controller.js | 54 +++++++++---------- src/controller/helpers/getBots.js | 6 +-- .../helpers/handleSteamIdResolving.js | 6 +-- src/controller/helpers/logger.js | 14 ++--- src/controller/helpers/misc.js | 30 +++++------ src/controller/helpers/npminteraction.js | 4 +- src/controller/login.js | 4 +- src/dataManager/dataManager.js | 40 +++++++------- src/dataManager/helpers/getQuote.js | 4 +- src/dataManager/helpers/handleCooldowns.js | 8 +-- .../helpers/handleExpiringTokens.js | 4 +- src/dataManager/helpers/misc.js | 6 +-- src/dataManager/helpers/repairFile.js | 18 +++---- src/libraryPatches/CSteamSharedFile.js | 4 +- src/libraryPatches/helpers.js | 4 +- src/libraryPatches/sharedfiles.js | 4 +- src/pluginSystem/pluginSystem.js | 10 ++-- src/sessions/helpers/handle2FA.js | 6 +-- src/sessions/helpers/tokenStorageHandler.js | 4 +- src/sessions/sessionHandler.js | 10 ++-- src/starter.js | 10 ++-- src/updater/helpers/checkForUpdate.js | 8 +-- src/updater/helpers/customUpdateRules.js | 8 +-- src/updater/helpers/prepareUpdate.js | 4 +- src/updater/updater.js | 6 +-- types/types.d.ts | 44 ++++++++++++++- 46 files changed, 354 insertions(+), 314 deletions(-) diff --git a/src/bot/bot.js b/src/bot/bot.js index 0a645a57..31e319e5 100644 --- a/src/bot/bot.js +++ b/src/bot/bot.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 15:45:22 + * Last Modified: 04.07.2023 17:58:09 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,7 +28,7 @@ const SessionHandler = require("../sessions/sessionHandler.js"); * Constructor - Initializes an object which represents a user steam account * @class * @param {Controller} controller Reference to the controller object - * @param {Number} index The index of this account in the logininfo object + * @param {number} index The index of this account in the logininfo object */ const Bot = function(controller, index) { @@ -46,7 +46,7 @@ const Bot = function(controller, index) { /** * Login index of this bot account - * @type {Number} + * @type {number} */ this.index = index; @@ -58,7 +58,7 @@ const Bot = function(controller, index) { /** * SteamID64's to ignore in the friendMessage event handler. This is used by readChatMessage() to prevent duplicate responses. - * @type {Array.} + * @type {array.} */ this.friendMessageBlock = []; @@ -176,9 +176,9 @@ module.exports = Bot; /** * Checks if user is blocked, has an active cooldown for spamming or isn't a friend - * @param {Object} steamID64 The steamID64 of the message sender - * @param {String} message The message string provided by steam-user friendMessage event - * @returns {Boolean} `true` if friendMessage event shouldn't be handled, `false` if user is allowed to be handled + * @param {object} steamID64 The steamID64 of the message sender + * @param {string} message The message string provided by steam-user friendMessage event + * @returns {boolean} `true` if friendMessage event shouldn't be handled, `false` if user is allowed to be handled */ Bot.prototype.checkMsgBlock = function(steamID64, message) {}; // eslint-disable-line @@ -194,18 +194,18 @@ Bot.prototype.handleMissingGameLicenses = function() {}; /** * Our commandHandler respondModule implementation - Sends a message to a Steam user - * @param {Object} _this The Bot object context - * @param {Object} resInfo Object containing information passed to command by friendMessage event - * @param {String} txt The text to send - * @param {Boolean} retry Internal: true if this message called itself again to send failure message - * @param {Number} part Internal: Index of which part to send for messages larger than 750 chars + * @param {object} _this The Bot object context + * @param {object} resInfo Object containing information passed to command by friendMessage event + * @param {string} txt The text to send + * @param {boolean} retry Internal: true if this message called itself again to send failure message + * @param {number} part Internal: Index of which part to send for messages larger than 750 chars */ Bot.prototype.sendChatMessage = function(_this, resInfo, txt, retry, part = 0) {}; // eslint-disable-line /** * Waits for a Steam Chat message from this user to this account and resolves their message content. The "normal" friendMessage event handler will be blocked for this user. - * @param {String} steamID64 The steamID64 of the user to read a message from - * @param {Number} timeout Time in ms after which the Promise will be resolved if user does not respond. Pass 0 to disable (not recommended) + * @param {string} steamID64 The steamID64 of the user to read a message from + * @param {number} timeout Time in ms after which the Promise will be resolved if user does not respond. Pass 0 to disable (not recommended) * @returns {Promise.} Resolved with `String` on response or `null` on timeout. */ Bot.prototype.readChatMessage = function(steamID64, timeout) {}; // eslint-disable-line \ No newline at end of file diff --git a/src/bot/helpers/checkMsgBlock.js b/src/bot/helpers/checkMsgBlock.js index 42d38fce..195900cb 100644 --- a/src/bot/helpers/checkMsgBlock.js +++ b/src/bot/helpers/checkMsgBlock.js @@ -4,7 +4,7 @@ * Created Date: 20.03.2023 12:46:47 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:55:45 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -22,9 +22,9 @@ const lastmessage = {}; // Tracks the last cmd usage of a normal command to appl /** * Checks if user is blocked, has an active cooldown for spamming or isn't a friend - * @param {Object} steamID64 The steamID64 of the message sender - * @param {String} message The message string provided by steam-user friendMessage event - * @returns {Boolean} `true` if friendMessage event shouldn't be handled, `false` if user is allowed to be handled + * @param {object} steamID64 The steamID64 of the message sender + * @param {string} message The message string provided by steam-user friendMessage event + * @returns {boolean} `true` if friendMessage event shouldn't be handled, `false` if user is allowed to be handled */ Bot.prototype.checkMsgBlock = function(steamID64, message) { diff --git a/src/bot/helpers/steamChatInteraction.js b/src/bot/helpers/steamChatInteraction.js index 130b01ee..7b052a80 100644 --- a/src/bot/helpers/steamChatInteraction.js +++ b/src/bot/helpers/steamChatInteraction.js @@ -4,7 +4,7 @@ * Created Date: 01.04.2023 21:09:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:51:07 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -29,10 +29,10 @@ const { cutStringsIntelligently } = require("../../controller/helpers/misc.js"); /** * Our commandHandler respondModule implementation - Sends a message to a Steam user * @param {Bot} _this The Bot object context - * @param {Object} resInfo Object containing information passed to command by friendMessage event. Supported by this handler: prefix, charLimit, cutChars - * @param {String} txt The text to send - * @param {Number} retry Internal: Counter of retries for this part if sending failed - * @param {Number} part Internal: Index of which part to send for messages larger than charLimit chars + * @param {object} resInfo Object containing information passed to command by friendMessage event. Supported by this handler: prefix, charLimit, cutChars + * @param {string} txt The text to send + * @param {number} retry Internal: Counter of retries for this part if sending failed + * @param {number} part Internal: Index of which part to send for messages larger than charLimit chars */ Bot.prototype.sendChatMessage = function(_this, resInfo, txt, retry = 0, part = 0) { if (!resInfo) return logger("warn", "sendChatMessage() was called without a resInfo object! Ignoring call..."); @@ -110,8 +110,8 @@ Bot.prototype.sendChatMessage = function(_this, resInfo, txt, retry = 0, part = /** * Waits for a Steam Chat message from this user to this account and resolves their message content. The "normal" friendMessage event handler will be blocked for this user. - * @param {String} steamID64 The steamID64 of the user to read a message from - * @param {Number} timeout Time in ms after which the Promise will be resolved if user does not respond. Pass 0 to disable (not recommended) + * @param {string} steamID64 The steamID64 of the user to read a message from + * @param {number} timeout Time in ms after which the Promise will be resolved if user does not respond. Pass 0 to disable (not recommended) * @returns {Promise.} Resolved with `String` on response or `null` on timeout. */ Bot.prototype.readChatMessage = function(steamID64, timeout) { diff --git a/src/commands/commandHandler.js b/src/commands/commandHandler.js index 11e72c15..61cf6769 100644 --- a/src/commands/commandHandler.js +++ b/src/commands/commandHandler.js @@ -4,7 +4,7 @@ * Created Date: 01.04.2023 21:54:21 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 18:04:59 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -74,11 +74,11 @@ CommandHandler.prototype._importCoreCommands = function() { /** * Registers a new command during runtime - * @param {Object} command The command object to register - * @param {[String]} command.names All names that should trigger this command - * @param {String} command.description Description of what this command does - * @param {Boolean} command.ownersOnly Set to true to only allow owners to use this command. - * @param {function(CommandHandler, Array, String, function(object, object, string), Object, Object)} command.run Function that will be executed when the command runs. Arguments: commandHandler, args, steamID64, respondModule, context, resInfo + * @param {object} command The command object to register + * @param {[string]} command.names All names that should trigger this command + * @param {string} command.description Description of what this command does + * @param {boolean} command.ownersOnly Set to true to only allow owners to use this command. + * @param {function(CommandHandler, Array, string, function(object, object, string), object, object)} command.run Function that will be executed when the command runs. Arguments: commandHandler, args, steamID64, respondModule, context, resInfo * @returns true if the command was successfully registered, false otherwise */ CommandHandler.prototype.registerCommand = function(command) { @@ -116,7 +116,7 @@ CommandHandler.prototype.registerCommand = function(command) { /** * The name of the command to unregister during runtime - * @param {String} commandName Name of the command to unregister + * @param {string} commandName Name of the command to unregister * @returns true if the command was successfully unregistered, false otherwise */ CommandHandler.prototype.unregisterCommand = function(commandName) { @@ -142,12 +142,12 @@ CommandHandler.prototype.unregisterCommand = function(commandName) { /** * Finds a loaded command by name and runs it - * @param {String} name The name of the command - * @param {Array} args Array of arguments that will be passed to the command - * @param {Number} steamID64 SteamID64 of the requesting user which is used to check for ownerOnly and will be passed to the command + * @param {string} name The name of the command + * @param {array} args Array of arguments that will be passed to the command + * @param {number} steamID64 SteamID64 of the requesting user which is used to check for ownerOnly and will be passed to the command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). Please also include a "cmdprefix" key & value pair if your command handler uses a prefix other than "!". + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). Please also include a "cmdprefix" key & value pair if your command handler uses a prefix other than "!". * @returns `true` if command was found, `false` if not */ CommandHandler.prototype.runCommand = function(name, args, steamID64, respondModule, context, resInfo) { diff --git a/src/commands/core/block.js b/src/commands/core/block.js index d360109d..760c568e 100644 --- a/src/commands/core/block.js +++ b/src/commands/core/block.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 13:20:48 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,11 +28,11 @@ module.exports.block = { /** * The block command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -64,11 +64,11 @@ module.exports.unblock = { /** * The unblock command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call diff --git a/src/commands/core/comment.js b/src/commands/core/comment.js index 49d611a4..4b8e2095 100644 --- a/src/commands/core/comment.js +++ b/src/commands/core/comment.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 13:21:20 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -32,11 +32,11 @@ module.exports.comment = { /** * The comment command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: async (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -193,11 +193,11 @@ module.exports.comment = { /** * Internal: Do the actual commenting, activeRequests entry with all relevant information was processed by the comment command function above. * @param {CommandHandler} commandHandler The commandHandler object - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). * @param {function(string)} respond Shortened respondModule call * @param {function} postComment The correct postComment function for this idType. Context from the correct bot account is being applied later. - * @param {Object} commentArgs All arguments this postComment function needs, without callback. It will be applied and a callback added as last param. Include a key called "quote" to dynamically replace it with a random quote. - * @param {String} receiverSteamID64 steamID64 of the profile to receive the comments + * @param {object} commentArgs All arguments this postComment function needs, without callback. It will be applied and a callback added as last param. Include a key called "quote" to dynamically replace it with a random quote. + * @param {string} receiverSteamID64 steamID64 of the profile to receive the comments */ function comment(commandHandler, resInfo, respond, postComment, commentArgs, receiverSteamID64) { let activeReqEntry = commandHandler.controller.activeRequests[receiverSteamID64]; // Make using the obj shorter diff --git a/src/commands/core/favorite.js b/src/commands/core/favorite.js index 84114ee0..ee3a52d8 100644 --- a/src/commands/core/favorite.js +++ b/src/commands/core/favorite.js @@ -4,7 +4,7 @@ * Created Date: 02.06.2023 13:23:01 * Author: 3urobeat * - * Last Modified: 04.07.2023 13:22:27 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -30,7 +30,7 @@ module.exports.favorite = { /** * The favorite command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. @@ -197,7 +197,7 @@ module.exports.unfavorite = { /** * The unfavorite command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. diff --git a/src/commands/core/friend.js b/src/commands/core/friend.js index c6b37cb8..9474d3aa 100644 --- a/src/commands/core/friend.js +++ b/src/commands/core/friend.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 13:23:11 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,11 +28,11 @@ module.exports.addFriend = { /** * The addFriend command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -88,11 +88,11 @@ module.exports.unfriend = { /** * The unfriend command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -141,11 +141,11 @@ module.exports.unfriendall = { /** * The unfriendall command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call diff --git a/src/commands/core/general.js b/src/commands/core/general.js index ffca9162..f30fd41e 100644 --- a/src/commands/core/general.js +++ b/src/commands/core/general.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 13:24:44 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -31,11 +31,11 @@ module.exports.help = { /** * The help command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -81,11 +81,11 @@ module.exports.info = { /** * The info command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -124,11 +124,11 @@ module.exports.ping = { /** * The ping command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -151,11 +151,11 @@ module.exports.about = { /** * The about command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -173,11 +173,11 @@ module.exports.owner = { /** * The owner command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -199,11 +199,11 @@ module.exports.test = { /** * The test command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: async (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // eslint-disable-line diff --git a/src/commands/core/group.js b/src/commands/core/group.js index ed2d892b..679e6867 100644 --- a/src/commands/core/group.js +++ b/src/commands/core/group.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 13:25:30 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,11 +28,11 @@ module.exports.group = { /** * The group command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -62,11 +62,11 @@ module.exports.joinGroup = { /** * The joinGroup command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -99,11 +99,11 @@ module.exports.leaveGroup = { /** * The leaveGroup command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -136,11 +136,11 @@ module.exports.leaveAllGroups = { /** * The leaveAllGroups command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call diff --git a/src/commands/core/requests.js b/src/commands/core/requests.js index 163092c2..e2777423 100644 --- a/src/commands/core/requests.js +++ b/src/commands/core/requests.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 13:26:53 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -27,11 +27,11 @@ module.exports.abort = { /** * The abort command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -68,11 +68,11 @@ module.exports.resetCooldown = { /** * The resetcooldown command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -112,11 +112,11 @@ module.exports.failed = { /** * The failed command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -158,11 +158,11 @@ module.exports.sessions = { /** * The sessions command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call @@ -202,11 +202,11 @@ module.exports.mySessions = { /** * The mysessions command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call diff --git a/src/commands/core/settings.js b/src/commands/core/settings.js index 52734bce..c0a395f8 100644 --- a/src/commands/core/settings.js +++ b/src/commands/core/settings.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 13:27:31 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,11 +28,11 @@ module.exports.settings = { /** * The settings command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call diff --git a/src/commands/core/system.js b/src/commands/core/system.js index bdf26758..e9ca7d22 100644 --- a/src/commands/core/system.js +++ b/src/commands/core/system.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 13:29:00 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,11 +28,11 @@ module.exports.restart = { /** * The restart command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { respondModule(context, { prefix: "/me", ...resInfo }, commandHandler.data.lang.restartcmdrestarting); // Pass new resInfo object which contains prefix and everything the original resInfo obj contained @@ -50,11 +50,11 @@ module.exports.stop = { /** * The stop command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { respondModule(context, { prefix: "/me", ...resInfo }, commandHandler.data.lang.stopcmdstopping); // Pass new resInfo object which contains prefix and everything the original resInfo obj contained @@ -72,11 +72,11 @@ module.exports.reload = { /** * The reload command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { @@ -101,11 +101,11 @@ module.exports.update = { /** * The update command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((modResInfo, txt) => respondModule(context, modResInfo, txt)); // Shorten each call. Updater takes resInfo as param and can modify it, so we need to pass the modified resInfo object here @@ -131,11 +131,11 @@ module.exports.output = { /** * The output command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { fs.readFile("./output.txt", function (err, data) { @@ -156,11 +156,11 @@ module.exports.eval = { /** * The eval command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call diff --git a/src/commands/core/vote.js b/src/commands/core/vote.js index 443450b4..d1974e41 100644 --- a/src/commands/core/vote.js +++ b/src/commands/core/vote.js @@ -4,7 +4,7 @@ * Created Date: 28.05.2023 12:02:24 * Author: 3urobeat * - * Last Modified: 04.07.2023 13:29:30 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -30,7 +30,7 @@ module.exports.upvote = { /** * The upvote command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. @@ -202,11 +202,11 @@ module.exports.downvote = { /** * The upvote command * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args Array of arguments that will be passed to the command + * @param {array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. - * @param {Object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ run: async (commandHandler, args, steamID64, respondModule, context, resInfo) => { let respond = ((txt) => respondModule(context, resInfo, txt)); // Shorten each call diff --git a/src/commands/helpers/getCommentArgs.js b/src/commands/helpers/getCommentArgs.js index 0ab9b001..cfe638d1 100644 --- a/src/commands/helpers/getCommentArgs.js +++ b/src/commands/helpers/getCommentArgs.js @@ -4,7 +4,7 @@ * Created Date: 28.02.2022 11:55:06 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 18:08:02 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -21,11 +21,11 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line /** * Retrieves arguments from a comment request. If request is invalid (for example too many comments requested) an error message will be sent * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args The command arguments - * @param {String} requesterSteamID64 The steamID64 of the requesting user - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). - * @param {Function} respond The function to send messages to the requesting user - * @returns {Promise.<{ maxRequestAmount: number, commentcmdUsage: string, numberOfComments: number, profileID: string, idType: string, quotesArr: array }>} + * @param {array} args The command arguments + * @param {string} requesterSteamID64 The steamID64 of the requesting user + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {function} respond The function to send messages to the requesting user + * @returns {Promise.<{ maxRequestAmount: number, commentcmdUsage: string, numberOfComments: number, profileID: string, idType: string, quotesArr: array. }>} */ module.exports.getCommentArgs = (commandHandler, args, requesterSteamID64, resInfo, respond) => { return new Promise((resolve) => { diff --git a/src/commands/helpers/getCommentBots.js b/src/commands/helpers/getCommentBots.js index a8183336..71c90b24 100644 --- a/src/commands/helpers/getCommentBots.js +++ b/src/commands/helpers/getCommentBots.js @@ -4,7 +4,7 @@ * Created Date: 09.04.2023 12:49:53 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:55:45 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -22,10 +22,10 @@ const { timeToString } = require("../../controller/helpers/misc.js"); /** * Finds all needed and currently available bot accounts for a comment request. * @param {CommandHandler} commandHandler The commandHandler object - * @param {Number} numberOfComments Number of requested comments - * @param {Boolean} canBeLimited If the accounts are allowed to be limited - * @param {String} idType Type of the request. This can either be "profile", "group" or "sharedfile". This is used to determine if limited accs need to be added first. - * @param {String} receiverSteamID Optional: steamID64 of the receiving user. If set, accounts that are friend with the user will be prioritized and accsToAdd will be calculated. + * @param {number} numberOfComments Number of requested comments + * @param {boolean} canBeLimited If the accounts are allowed to be limited + * @param {string} idType Type of the request. This can either be "profile", "group" or "sharedfile". This is used to determine if limited accs need to be added first. + * @param {string} receiverSteamID Optional: steamID64 of the receiving user. If set, accounts that are friend with the user will be prioritized and accsToAdd will be calculated. * @returns {{ accsNeeded: number, availableAccounts: array., accsToAdd: array., whenAvailable: number, whenAvailableStr: string }} `availableAccounts` contains all account names from bot object, `accsToAdd` account names which are limited and not friend, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now */ module.exports.getAvailableBotsForCommenting = function(commandHandler, numberOfComments, canBeLimited, idType, receiverSteamID = null) { diff --git a/src/commands/helpers/getFavoriteBots.js b/src/commands/helpers/getFavoriteBots.js index 257e181c..1cc25487 100644 --- a/src/commands/helpers/getFavoriteBots.js +++ b/src/commands/helpers/getFavoriteBots.js @@ -4,7 +4,7 @@ * Created Date: 02.06.2023 14:07:27 * Author: 3urobeat * - * Last Modified: 03.07.2023 12:31:17 + * Last Modified: 04.07.2023 18:07:56 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -25,7 +25,7 @@ const { timeToString } = require("../../controller/helpers/misc.js"); * @param {number|"all"} amount Amount of favs requested or "all" to get the max available amount * @param {string} id The sharedfile id to favorize * @param {string} favType Either "favorite" or "unfavorite", depending on which request this is - * @returns {Promise.<{ amount: number, availableAccounts: array, whenAvailable: number, whenAvailableStr: string }>} Promise with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now + * @returns {Promise.<{ amount: number, availableAccounts: array., whenAvailable: number, whenAvailableStr: string }>} Promise with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now */ module.exports.getAvailableBotsForFavorizing = async (commandHandler, amount, id, favType) => { diff --git a/src/commands/helpers/getSharedfileArgs.js b/src/commands/helpers/getSharedfileArgs.js index ac046ac2..e53c747a 100644 --- a/src/commands/helpers/getSharedfileArgs.js +++ b/src/commands/helpers/getSharedfileArgs.js @@ -4,7 +4,7 @@ * Created Date: 28.05.2023 12:18:49 * Author: 3urobeat * - * Last Modified: 03.07.2023 12:31:10 + * Last Modified: 04.07.2023 18:01:36 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -21,10 +21,10 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line /** * Retrieves arguments from a vote request. If request is invalid, an error message will be sent * @param {CommandHandler} commandHandler The commandHandler object - * @param {Array} args The command arguments - * @param {String} cmd Either "upvote", "downvote", "favorite" or "unfavorite", depending on which command is calling this function - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). - * @param {Function} respond The function to send messages to the requesting user + * @param {array} args The command arguments + * @param {string} cmd Either "upvote", "downvote", "favorite" or "unfavorite", depending on which command is calling this function + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {function} respond The function to send messages to the requesting user * @returns {Promise.<{ amount: number|string, id: string }>} If the user provided a specific amount, amount will be a number. If user provided "all" or "max", it will be returned as an unmodified string for getVoteBots.js to handle */ module.exports.getSharedfileArgs = (commandHandler, args, cmd, resInfo, respond) => { diff --git a/src/commands/helpers/handleCommentSkips.js b/src/commands/helpers/handleCommentSkips.js index c8c8c617..5bd61a7d 100644 --- a/src/commands/helpers/handleCommentSkips.js +++ b/src/commands/helpers/handleCommentSkips.js @@ -4,7 +4,7 @@ * Created Date: 28.02.2022 12:22:48 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:55:45 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -25,8 +25,8 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line * @param {CommandHandler} commandHandler The commandHandler object * @param {{ next: function, break: function, index: function }} loop Object returned by misc.js syncLoop() helper * @param {Bot} bot Bot object of the account posting this comment - * @param {String} receiverSteamID64 steamID64 of the receiving user/group - * @returns {Boolean} true if iteration should continue, false if iteration should be skipped using return + * @param {string} receiverSteamID64 steamID64 of the receiving user/group + * @returns {boolean} true if iteration should continue, false if iteration should be skipped using return */ module.exports.handleIterationSkip = (commandHandler, loop, bot, receiverSteamID64) => { let activeReqEntry = commandHandler.controller.activeRequests[receiverSteamID64]; // Make using the obj shorter @@ -99,10 +99,10 @@ module.exports.handleIterationSkip = (commandHandler, loop, bot, receiverSteamID /** * Adds a description to comment errors and applies additional cooldowns for certain errors - * @param {String} error The error string returned by steamcommunity + * @param {string} error The error string returned by steamcommunity * @param {CommandHandler} commandHandler The commandHandler object * @param {Bot} bot Bot object of the account posting this comment - * @param {String} receiverSteamID64 steamID64 of the receiving user/group + * @param {string} receiverSteamID64 steamID64 of the receiving user/group */ module.exports.logCommentError = (error, commandHandler, bot, receiverSteamID64) => { let activeReqEntry = commandHandler.controller.activeRequests[receiverSteamID64]; // Make using the obj shorter @@ -176,7 +176,7 @@ module.exports.logCommentError = (error, commandHandler, bot, receiverSteamID64) /** * Helper function to sort failed object by comment number so that it is easier to read - * @param {Object} failedObj Current state of failed object + * @param {object} failedObj Current state of failed object */ function sortFailedCommentsObject(failedObj) { let sortedvals = Object.keys(failedObj).sort((a, b) => { @@ -192,8 +192,8 @@ function sortFailedCommentsObject(failedObj) { /** * Groups same error messages together, counts amount, lists affected bots and converts it to a String. - * @param {Object} obj failedcomments object that should be converted - * @returns {String} String that looks like this: `amount`x - `indices`\n`error message` + * @param {object} obj failedcomments object that should be converted + * @returns {string} String that looks like this: `amount`x - `indices`\n`error message` */ module.exports.failedCommentsObjToString = (obj) => { // Count amount of each string diff --git a/src/commands/helpers/handleSharedfileErrors.js b/src/commands/helpers/handleSharedfileErrors.js index 17e260d1..b1361723 100644 --- a/src/commands/helpers/handleSharedfileErrors.js +++ b/src/commands/helpers/handleSharedfileErrors.js @@ -4,7 +4,7 @@ * Created Date: 31.05.2023 16:57:21 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:50:12 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -23,7 +23,7 @@ const Bot = require("../../bot/bot.js"); // eslint-disable-line * @param {CommandHandler} commandHandler The commandHandler object * @param {{ next: function, break: function, index: function }} loop Object returned by misc.js syncLoop() helper * @param {Bot} bot Bot object of the account making this request - * @param {String} id ID of the sharedfile that receives the votes + * @param {string} id ID of the sharedfile that receives the votes * @returns true if iteration should continue, false if iteration should be skipped using return */ module.exports.handleVoteIterationSkip = function(commandHandler, loop, bot, id) { @@ -57,7 +57,7 @@ module.exports.handleVoteIterationSkip = function(commandHandler, loop, bot, id) * @param {CommandHandler} commandHandler The commandHandler object * @param {{ next: function, break: function, index: function }} loop Object returned by misc.js syncLoop() helper * @param {Bot} bot Bot object of the account making this request - * @param {String} id ID of the sharedfile that receives the votes + * @param {string} id ID of the sharedfile that receives the votes * @returns true if iteration should continue, false if iteration should be skipped using return */ module.exports.handleFavoriteIterationSkip = function(commandHandler, loop, bot, id) { @@ -88,10 +88,10 @@ module.exports.handleFavoriteIterationSkip = function(commandHandler, loop, bot, /** * Logs vote errors - * @param {String} error The error string returned by steam-community + * @param {string} error The error string returned by steam-community * @param {CommandHandler} commandHandler The commandHandler object * @param {Bot} bot Bot object of the account making this request - * @param {String} id ID of the sharedfile that receives the votes + * @param {string} id ID of the sharedfile that receives the votes */ module.exports.logVoteError = (error, commandHandler, bot, id) => { let activeReqEntry = commandHandler.controller.activeRequests[id]; // Make using the obj shorter @@ -114,10 +114,10 @@ module.exports.logVoteError = (error, commandHandler, bot, id) => { /** * Logs favorite errors - * @param {String} error The error string returned by steam-community + * @param {string} error The error string returned by steam-community * @param {CommandHandler} commandHandler The commandHandler object * @param {Bot} bot Bot object of the account making this request - * @param {String} id ID of the sharedfile that receives the favorites + * @param {string} id ID of the sharedfile that receives the favorites */ module.exports.logFavoriteError = (error, commandHandler, bot, id) => { let activeReqEntry = commandHandler.controller.activeRequests[id]; // Make using the obj shorter @@ -140,7 +140,7 @@ module.exports.logFavoriteError = (error, commandHandler, bot, id) => { /** * Helper function to sort failed object by number so that it is easier to read - * @param {Object} failedObj Current state of failed object + * @param {object} failedObj Current state of failed object */ function sortFailedCommentsObject(failedObj) { let sortedvals = Object.keys(failedObj).sort((a, b) => { diff --git a/src/controller/controller.js b/src/controller/controller.js index 5bf52830..18e9bc1c 100644 --- a/src/controller/controller.js +++ b/src/controller/controller.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 18:02:14 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -34,30 +34,30 @@ const Controller = function() { this.misc = { /** * Implementation of a synchronous for loop in JS (Used as reference: https://whitfin.io/handling-synchronous-asynchronous-loops-javascriptnode-js/) - * @param {Number} iterations The amount of iterations - * @param {Function} func The function to run each iteration (Params: loop, index) - * @param {Function} exit This function will be called when the loop is finished + * @param {number} iterations The amount of iterations + * @param {function} func The function to run each iteration (Params: loop, index) + * @param {function} exit This function will be called when the loop is finished */ syncLoop: (iterations, func, exit) => {}, // eslint-disable-line /** * Rounds a number with x decimals - * @param {Number} value Number to round - * @param {Number} decimals Amount of decimals - * @returns {Number} Rounded number + * @param {number} value Number to round + * @param {number} decimals Amount of decimals + * @returns {number} Rounded number */ round: (value, decimals) => {}, // eslint-disable-line /** * Converts a timestamp to a human-readable until from now format. Does not care about past/future. - * @returns {String} "x seconds/minutes/hours/days" + * @returns {string} "x seconds/minutes/hours/days" */ timeToString: () => {}, // eslint-disable-line /** * Pings an URL to check if the service and this internet connection is working - * @param {String} url The URL of the service to check - * @param {Boolean} throwTimeout If true, the function will throw a timeout error if Steam can't be reached after 20 seconds + * @param {string} url The URL of the service to check + * @param {boolean} throwTimeout If true, the function will throw a timeout error if Steam can't be reached after 20 seconds * @returns {Promise.<{ statusMessage: string, statusCode: number|null }>} Resolves on response code 2xx and rejects on any other response code. Both are called with parameter `response` (Object) which has a `statusMessage` (String) and `statusCode` (Number) key. `statusCode` is `null` if request failed. */ checkConnection: (url, throwTimeout) => {}, // eslint-disable-line @@ -65,11 +65,11 @@ const Controller = function() { /** * Helper function which attempts to cut Strings intelligently and returns all parts. It will attempt to not cut words & links in half. * It is used by the steamChatInteraction helper but can be used in plugins as well. - * @param {String} txt The string to cut - * @param {Number} limit Maximum length for each part. The function will attempt to cut txt into parts that don't exceed this amount. - * @param {Array} cutChars Optional: Custom chars to search after for cutting string in parts. Default: [" ", "\n", "\r"] - * @param {Number} threshold Optional: Maximum amount that limit can be reduced to find the last space or line break. If no match is found within this limit a word will be cut. Default: 15% of total length - * @returns {Array} Returns all parts of the string in an array + * @param {string} txt The string to cut + * @param {number} limit Maximum length for each part. The function will attempt to cut txt into parts that don't exceed this amount. + * @param {array} cutChars Optional: Custom chars to search after for cutting string in parts. Default: [" ", "\n", "\r"] + * @param {number} threshold Optional: Maximum amount that limit can be reduced to find the last space or line break. If no match is found within this limit a word will be cut. Default: 15% of total length + * @returns {array} Returns all parts of the string in an array */ cutStringsIntelligently: (txt, limit, cutChars, threshold) => {} // eslint-disable-line }; @@ -250,7 +250,7 @@ Controller.prototype._preLogin = async function() { /** * Stores references to all bot account objects mapped to their accountName - * @type {Object.} + * @type {object.} */ this.bots = {}; @@ -352,7 +352,7 @@ if (parseInt(process.argv[3]) + 2500 > Date.now()) { // Check if this process ju /** * Restarts the whole application - * @param {String} data Stringified restartdata object that will be kept through restarts + * @param {string} data Stringified restartdata object that will be kept through restarts */ Controller.prototype.restart = function(data) { process.send(`restart(${data})`); }; @@ -364,7 +364,7 @@ Controller.prototype.stop = function() { process.send("stop()"); }; /** * Attempts to log in all bot accounts which are currently offline one after another. * Creates a new bot object for every new account and reuses existing one if possible - * @param {Boolean} firstLogin Is set to true by controller if this is the first login to display more information + * @param {boolean} firstLogin Is set to true by controller if this is the first login to display more information */ Controller.prototype.login = function(firstLogin) {}; // eslint-disable-line @@ -408,8 +408,8 @@ Controller.prototype._lastcommentUnfriendCheck = function() {} // eslint-disable /** * Retrieves all matching bot accounts and returns them. * @param {(EStatus|EStatus[]|string)} [statusFilter=EStatus.ONLINE] Optional: EStatus or Array of EStatus's including account statuses to filter. Pass '*' to get all accounts. If omitted, only accs with status 'EStatus.ONLINE' will be returned. - * @param {Boolean} mapToObject Optional: If true, an object will be returned where every bot object is mapped to their accountName. - * @returns {Array|Object} An array or object if `mapToObject == true` containing all matching bot accounts. + * @param {boolean} mapToObject Optional: If true, an object will be returned where every bot object is mapped to their accountName. + * @returns {array|object} An array or object if `mapToObject == true` containing all matching bot accounts. */ Controller.prototype.getBots = function(statusFilter = EStatus.ONLINE, mapToObject = false) {}; // eslint-disable-line @@ -421,19 +421,19 @@ Controller.prototype._handleErrors = function() {} // eslint-disable-line /** * Handles converting URLs to steamIDs, determining their type if unknown and checking if it matches your expectation - * @param {String} str The profileID argument provided by the user - * @param {String} expectedIdType The type of SteamID expected ("profile", "group" or "sharedfile") or `null` if type should be assumed. + * @param {string} str The profileID argument provided by the user + * @param {string} expectedIdType The type of SteamID expected ("profile", "group" or "sharedfile") or `null` if type should be assumed. * @param {function} [callback] Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion */ Controller.prototype.handleSteamIdResolving = (str, expectedIdType, callback) => {} // eslint-disable-line /** * Logs text to the terminal and appends it to the output.txt file. - * @param {String} type String that determines the type of the log message. Can be info, warn, error, debug or an empty string to not use the field. - * @param {String} str The text to log into the terminal - * @param {Boolean} nodate Setting to true will hide date and time in the message - * @param {Boolean} remove Setting to true will remove this message with the next one - * @param {Boolean} printNow Ignores the readyafterlogs check and force prints the message now + * @param {string} type String that determines the type of the log message. Can be info, warn, error, debug or an empty string to not use the field. + * @param {string} str The text to log into the terminal + * @param {boolean} nodate Setting to true will hide date and time in the message + * @param {boolean} remove Setting to true will remove this message with the next one + * @param {boolean} printNow Ignores the readyafterlogs check and force prints the message now */ Controller.prototype.logger = function(type, str, nodate, remove, animation, printNow) {}; // eslint-disable-line diff --git a/src/controller/helpers/getBots.js b/src/controller/helpers/getBots.js index 26bed5da..e8e7eaf1 100644 --- a/src/controller/helpers/getBots.js +++ b/src/controller/helpers/getBots.js @@ -4,7 +4,7 @@ * Created Date: 02.05.2023 13:46:21 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 18:02:29 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -22,8 +22,8 @@ const EStatus = require("../../bot/EStatus.js"); /** * Retrieves all matching bot accounts and returns them. * @param {(EStatus|EStatus[]|string)} [statusFilter=EStatus.ONLINE] Optional: EStatus or Array of EStatus's including account statuses to filter. Pass '*' to get all accounts. If omitted, only accs with status 'EStatus.ONLINE' will be returned. - * @param {Boolean} mapToObject Optional: If true, an object will be returned where every bot object is mapped to their accountName. - * @returns {Array|Object} An array or object if `mapToObject == true` containing all matching bot accounts. + * @param {boolean} mapToObject Optional: If true, an object will be returned where every bot object is mapped to their accountName. + * @returns {array|object} An array or object if `mapToObject == true` containing all matching bot accounts. */ Controller.prototype.getBots = function(statusFilter, mapToObject) { if (!statusFilter) statusFilter = EStatus.ONLINE; diff --git a/src/controller/helpers/handleSteamIdResolving.js b/src/controller/helpers/handleSteamIdResolving.js index bd508076..feb56d44 100644 --- a/src/controller/helpers/handleSteamIdResolving.js +++ b/src/controller/helpers/handleSteamIdResolving.js @@ -4,7 +4,7 @@ * Created Date: 09.03.2022 12:58:17 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:49:45 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -26,8 +26,8 @@ const Controller = require("../controller.js"); /** * Handles converting URLs to steamIDs, determining their type if unknown and checking if it matches your expectation - * @param {String} str The profileID argument provided by the user - * @param {String} expectedIdType The type of SteamID expected ("profile", "group" or "sharedfile") or `null` if type should be assumed. + * @param {string} str The profileID argument provided by the user + * @param {string} expectedIdType The type of SteamID expected ("profile", "group" or "sharedfile") or `null` if type should be assumed. * @param {function} [callback] Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion */ Controller.prototype.handleSteamIdResolving = (str, expectedIdType, callback) => { diff --git a/src/controller/helpers/logger.js b/src/controller/helpers/logger.js index 323977d4..17439802 100644 --- a/src/controller/helpers/logger.js +++ b/src/controller/helpers/logger.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:55:45 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -37,13 +37,13 @@ let botIsReady = false; // Modfied output-logger function to hold back certain messages until ready event fired /** * Logs text to the terminal and appends it to the output.txt file. - * @param {String} type String that determines the type of the log message. Can be info, warn, error, debug or an empty string to not use the field. - * @param {String} str The text to log into the terminal - * @param {Boolean} nodate Setting to true will hide date and time in the message - * @param {Boolean} remove Setting to true will remove this message with the next one + * @param {string} type String that determines the type of the log message. Can be info, warn, error, debug or an empty string to not use the field. + * @param {string} str The text to log into the terminal + * @param {boolean} nodate Setting to true will hide date and time in the message + * @param {boolean} remove Setting to true will remove this message with the next one * @param {array.} animation Array containing animation frames as elements - * @param {Boolean} printNow Ignores the readyafterlogs check and force prints the message now - * @param {Boolean} cutToWidth Cuts the string to the width of the terminal + * @param {boolean} printNow Ignores the readyafterlogs check and force prints the message now + * @param {boolean} cutToWidth Cuts the string to the width of the terminal */ Controller.prototype.logger = function(type, str, nodate, remove, animation, printNow, cutToWidth) { diff --git a/src/controller/helpers/misc.js b/src/controller/helpers/misc.js index 11d1436a..b2f9183d 100644 --- a/src/controller/helpers/misc.js +++ b/src/controller/helpers/misc.js @@ -4,7 +4,7 @@ * Created Date: 25.03.2023 14:02:56 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 18:01:36 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -20,9 +20,9 @@ const https = require("https"); /** * Implementation of a synchronous for loop in JS (Used as reference: https://whitfin.io/handling-synchronous-asynchronous-loops-javascriptnode-js/) - * @param {Number} iterations The amount of iterations - * @param {Function} func The function to run each iteration (Params: loop, index) - * @param {Function} exit This function will be called when the loop is finished + * @param {number} iterations The amount of iterations + * @param {function} func The function to run each iteration (Params: loop, index) + * @param {function} exit This function will be called when the loop is finished */ module.exports.syncLoop = (iterations, func, exit) => { let currentIndex = 0; @@ -55,9 +55,9 @@ module.exports.syncLoop = (iterations, func, exit) => { /** * Rounds a number with x decimals - * @param {Number} value Number to round - * @param {Number} decimals Amount of decimals - * @returns {Number} Rounded number + * @param {number} value Number to round + * @param {number} decimals Amount of decimals + * @returns {number} Rounded number */ module.exports.round = (value, decimals) => { return Number(Math.round(value+"e"+decimals)+"e-"+decimals); @@ -66,7 +66,7 @@ module.exports.round = (value, decimals) => { /** * Converts a timestamp to a human-readable until from now format. Does not care about past/future. - * @returns {String} "x seconds/minutes/hours/days" + * @returns {string} "x seconds/minutes/hours/days" */ module.exports.timeToString = (timestamp) => { let until = Math.abs((Date.now() - timestamp) / 1000); @@ -90,8 +90,8 @@ module.exports.timeToString = (timestamp) => { /** * Pings an URL to check if the service and this internet connection is working - * @param {String} url The URL of the service to check - * @param {Boolean} throwTimeout If true, the function will throw a timeout error if Steam can't be reached after 20 seconds + * @param {string} url The URL of the service to check + * @param {boolean} throwTimeout If true, the function will throw a timeout error if Steam can't be reached after 20 seconds * @returns {Promise.<{ statusMessage: string, statusCode: number|null }>} Resolves on response code 2xx and rejects on any other response code. Both are called with parameter `response` (Object) which has a `statusMessage` (String) and `statusCode` (Number) key. `statusCode` is `null` if request failed. */ module.exports.checkConnection = (url, throwTimeout) => { @@ -124,11 +124,11 @@ module.exports.checkConnection = (url, throwTimeout) => { /** * Helper function which attempts to cut Strings intelligently and returns all parts. It will attempt to not cut words & links in half. * It is used by the steamChatInteraction helper but can be used in plugins as well. - * @param {String} txt The string to cut - * @param {Number} limit Maximum length for each part. The function will attempt to cut txt into parts that don't exceed this amount. - * @param {Array} cutChars Optional: Custom chars to search after for cutting string in parts. Default: [" ", "\n", "\r"] - * @param {Number} threshold Optional: Maximum amount that limit can be reduced to find the last space or line break. If no match is found within this limit a word will be cut. Default: 15% of total length - * @returns {Array} Returns all parts of the string in an array + * @param {string} txt The string to cut + * @param {number} limit Maximum length for each part. The function will attempt to cut txt into parts that don't exceed this amount. + * @param {array} cutChars Optional: Custom chars to search after for cutting string in parts. Default: [" ", "\n", "\r"] + * @param {number} threshold Optional: Maximum amount that limit can be reduced to find the last space or line break. If no match is found within this limit a word will be cut. Default: 15% of total length + * @returns {array} Returns all parts of the string in an array */ module.exports.cutStringsIntelligently = (txt, limit, cutChars, threshold) => { if (!cutChars) cutChars = [" ", "\n", "\r"]; // Set cutChars to space, newline or Windows newline if undefined diff --git a/src/controller/helpers/npminteraction.js b/src/controller/helpers/npminteraction.js index ea1b3aec..d157a776 100644 --- a/src/controller/helpers/npminteraction.js +++ b/src/controller/helpers/npminteraction.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:49:45 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -60,7 +60,7 @@ module.exports.update = (callback) => { /** * Updates all installed packages to versions listed in package.json - * @param {String} path Custom path to read package.json from and install packages to + * @param {string} path Custom path to read package.json from and install packages to * @param {function} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ module.exports.updateFromPath = (path, callback) => { diff --git a/src/controller/login.js b/src/controller/login.js index a7eb6b37..3d805d36 100644 --- a/src/controller/login.js +++ b/src/controller/login.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:55:45 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -26,7 +26,7 @@ const misc = require("./helpers/misc.js"); /** * Attempts to log in all bot accounts which are currently offline one after another. * Creates a new bot object for every new account and reuses existing one if possible - * @param {Boolean} firstLogin Is set to true by controller if this is the first login to display more information + * @param {boolean} firstLogin Is set to true by controller if this is the first login to display more information */ Controller.prototype.login = function(firstLogin) { diff --git a/src/dataManager/dataManager.js b/src/dataManager/dataManager.js index 3ca22156..d5d33e46 100644 --- a/src/dataManager/dataManager.js +++ b/src/dataManager/dataManager.js @@ -4,7 +4,7 @@ * Created Date: 21.03.2023 22:34:51 * Author: 3urobeat * - * Last Modified: 03.07.2023 15:50:15 + * Last Modified: 04.07.2023 18:08:40 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -42,44 +42,44 @@ const DataManager = function (controller) { /** * Stores all `config.json` settings. - * @type {Object.} + * @type {object.} */ this.config = {}; /** * Stores all `advancedconfig.json` settings. - * @type {Object.} + * @type {object.} */ this.advancedconfig = {}; /** * Stores all language strings used for responding to a user. * All default strings have already been replaced with corresponding matches from `customlang.json`. - * @type {Object.} + * @type {object.} */ this.lang = {}; /** * Stores all quotes used for commenting provided via the `quotes.txt` file. - * @type {Array} + * @type {array.} */ this.quotes = []; /** * Stores all proxies provided via the `proxies.txt` file. - * @type {Array} + * @type {array.} */ this.proxies = []; /** * Stores IDs from config files converted at runtime and backups for all config & data files. - * @type {{ ownerid: Array, botsgroup: string, botsgroupid: string, configgroup: string, configgroup64id: string, ownerlinkid: string, botaccid: Array, pluginVersions: object., configjson: {}, advancedconfigjson: {}, datajson: {} }} + * @type {{ ownerid: array., botsgroup: string, botsgroupid: string, configgroup: string, configgroup64id: string, ownerlinkid: string, botaccid: array., pluginVersions: object., configjson: {}, advancedconfigjson: {}, datajson: {} }} */ this.cachefile = {}; /** * Stores the login information for every bot account provided via the `logininfo.json` or `accounts.txt` files. - * @type {Object.} + * @type {object.} */ this.logininfo = {}; @@ -141,22 +141,22 @@ DataManager.prototype._importFromDisk = async function () {}; /** * Gets a random quote - * @param {Array} quotesArr Optional: Custom array of quotes to choose from. If not provided the default quotes set which was imported from the disk will be used. + * @param {array} quotesArr Optional: Custom array of quotes to choose from. If not provided the default quotes set which was imported from the disk will be used. * @returns {Promise.} Resolves with `quote` (String) */ DataManager.prototype.getQuote = function (quotesArr = null) {}; // eslint-disable-line /** * Checks if a user ID is currently on cooldown and formats human readable lastRequestStr and untilStr strings. - * @param {String} id ID of the user to look up + * @param {string} id ID of the user to look up * @returns {Promise.<{ lastRequest: number, until: number, lastRequestStr: string, untilStr: string }|null>} Resolves with object containing `lastRequest` (Unix timestamp of the last interaction received), `until` (Unix timestamp of cooldown end), `lastRequestStr` (How long ago as String), `untilStr` (Wait until as String). If id wasn't found, `null` will be returned. */ DataManager.prototype.getUserCooldown = function (id) {}; // eslint-disable-line /** * Updates or inserts timestamp of a user - * @param {String} id ID of the user to update - * @param {Number} timestamp Unix timestamp of the last interaction the user received + * @param {string} id ID of the user to update + * @param {number} timestamp Unix timestamp of the last interaction the user received */ DataManager.prototype.setUserCooldown = function (id, timestamp) {}; // eslint-disable-line @@ -167,20 +167,20 @@ DataManager.prototype._startExpiringTokensCheckInterval = () => {}; /** * Internal: Asks user if he/she wants to refresh the tokens of all expiring accounts when no active request was found and relogs them - * @param {Object} expiring Object of botobject entries to ask user for + * @param {object} expiring Object of botobject entries to ask user for */ DataManager.prototype._askForGetNewToken = function (expiring) {}; // eslint-disable-line /** * Retrieves the last processed request of anyone or a specific steamID64 from the lastcomment database - * @param {String} steamID64 Search for a specific user + * @param {string} steamID64 Search for a specific user * @returns {Promise.} Called with the greatest timestamp (Number) found */ DataManager.prototype.getLastCommentRequest = function (steamID64 = null) {}; // eslint-disable-line /** * Decodes a JsonWebToken - https://stackoverflow.com/a/38552302 - * @param {String} token The token to decode + * @param {string} token The token to decode * @returns JWT object on success, `null` on failure */ DataManager.prototype.decodeJWT = function (token) {}; // eslint-disable-line @@ -192,11 +192,11 @@ DataManager.prototype.refreshCache = function () {}; /** * Internal: Helper function to try and restore backup of corrupted file from cache.json - * @param {String} name Name of the file - * @param {String} filepath Absolute path of the file on the disk - * @param {Object} cacheentry Backup-Object of the file in cache.json - * @param {String} onlinelink Link to the raw file in the GitHub repository - * @param {Function} resolve Function to resolve the caller's promise + * @param {string} name Name of the file + * @param {string} filepath Absolute path of the file on the disk + * @param {object} cacheentry Backup-Object of the file in cache.json + * @param {string} onlinelink Link to the raw file in the GitHub repository + * @param {function} resolve Function to resolve the caller's promise */ DataManager.prototype._restoreBackup = function (name, filepath, cacheentry, onlinelink, resolve) {}; // eslint-disable-line diff --git a/src/dataManager/helpers/getQuote.js b/src/dataManager/helpers/getQuote.js index b6ef2a07..bc928bd3 100644 --- a/src/dataManager/helpers/getQuote.js +++ b/src/dataManager/helpers/getQuote.js @@ -4,7 +4,7 @@ * Created Date: 02.03.2022 16:21:11 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:55:32 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -25,7 +25,7 @@ let lastQuotes = []; // Tracks recently used quotes to avoid duplicates /** * Gets a random quote - * @param {Array} quotesArr Optional: Custom array of quotes to choose from. If not provided the default quotes set which was imported from the disk will be used. + * @param {array} quotesArr Optional: Custom array of quotes to choose from. If not provided the default quotes set which was imported from the disk will be used. * @returns {Promise.} Resolves with `quote` (String) */ DataManager.prototype.getQuote = function(quotesArr = null) { diff --git a/src/dataManager/helpers/handleCooldowns.js b/src/dataManager/helpers/handleCooldowns.js index 39ff76fd..46278db2 100644 --- a/src/dataManager/helpers/handleCooldowns.js +++ b/src/dataManager/helpers/handleCooldowns.js @@ -4,7 +4,7 @@ * Created Date: 13.04.2023 17:58:23 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:51:07 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -20,7 +20,7 @@ const DataManager = require("../dataManager"); /** * Checks if a user ID is currently on cooldown and formats human readable lastRequestStr and untilStr strings. - * @param {String} id ID of the user to look up + * @param {string} id ID of the user to look up * @returns {Promise.<{ lastRequest: number, until: number, lastRequestStr: string, untilStr: string }|null>} Resolves with object containing `lastRequest` (Unix timestamp of the last interaction received), `until` (Unix timestamp of cooldown end), `lastRequestStr` (How long ago as String), `untilStr` (Wait until as String). If id wasn't found, `null` will be returned. */ DataManager.prototype.getUserCooldown = function(id) { @@ -89,8 +89,8 @@ DataManager.prototype.getUserCooldown = function(id) { /** * Updates or inserts timestamp of a user - * @param {String} id ID of the user to update - * @param {Number} timestamp Unix timestamp of the last interaction the user received + * @param {string} id ID of the user to update + * @param {number} timestamp Unix timestamp of the last interaction the user received */ DataManager.prototype.setUserCooldown = function(id, timestamp) { logger("debug", `DataManager setUserCooldown(): Updating lastcomment db entry for ${id} to ${timestamp}.`); diff --git a/src/dataManager/helpers/handleExpiringTokens.js b/src/dataManager/helpers/handleExpiringTokens.js index 8cab1884..3f894a51 100644 --- a/src/dataManager/helpers/handleExpiringTokens.js +++ b/src/dataManager/helpers/handleExpiringTokens.js @@ -4,7 +4,7 @@ * Created Date: 14.10.2022 14:58:25 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:50:12 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -96,7 +96,7 @@ DataManager.prototype._startExpiringTokensCheckInterval = function() { /** * Internal: Asks user if he/she wants to refresh the tokens of all expiring accounts when no active request was found and relogs them - * @param {Object} expiring Object of botobject entries to ask user for + * @param {object} expiring Object of botobject entries to ask user for */ DataManager.prototype._askForGetNewToken = function(expiring) { let EStatus = require("../../bot/EStatus.js"); // Import not at top scope as this can be undefined because this helper file gets loaded before updater ran diff --git a/src/dataManager/helpers/misc.js b/src/dataManager/helpers/misc.js index a4e5b9d2..5b7b40b9 100644 --- a/src/dataManager/helpers/misc.js +++ b/src/dataManager/helpers/misc.js @@ -4,7 +4,7 @@ * Created Date: 24.03.2023 18:58:55 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:49:45 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -20,7 +20,7 @@ const DataManager = require("../dataManager.js"); /** * Retrieves the last processed request of anyone or a specific steamID64 from the lastcomment database - * @param {String} steamID64 Search for a specific user + * @param {string} steamID64 Search for a specific user * @returns {Promise.} Called with the greatest timestamp (Number) found */ DataManager.prototype.getLastCommentRequest = function(steamID64 = null) { @@ -47,7 +47,7 @@ DataManager.prototype.getLastCommentRequest = function(steamID64 = null) { /** * Decodes a JsonWebToken - https://stackoverflow.com/a/38552302 - * @param {String} token The token to decode + * @param {string} token The token to decode * @returns JWT object on success, `null` on failure */ DataManager.prototype.decodeJWT = function(token) { diff --git a/src/dataManager/helpers/repairFile.js b/src/dataManager/helpers/repairFile.js index 091d5acc..dae3ae8d 100644 --- a/src/dataManager/helpers/repairFile.js +++ b/src/dataManager/helpers/repairFile.js @@ -4,7 +4,7 @@ * Created Date: 22.03.2023 12:35:01 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 18:01:36 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -22,11 +22,11 @@ const DataManager = require("../dataManager.js"); /** * Internal: Helper function to try and restore backup of corrupted file from cache.json - * @param {String} name Name of the file - * @param {String} filepath Absolute path of the file on the disk - * @param {Object} cacheentry Backup-Object of the file in cache.json - * @param {String} onlinelink Link to the raw file in the GitHub repository - * @param {Function} resolve Function to resolve the caller's promise + * @param {string} name Name of the file + * @param {string} filepath Absolute path of the file on the disk + * @param {object} cacheentry Backup-Object of the file in cache.json + * @param {string} onlinelink Link to the raw file in the GitHub repository + * @param {function} resolve Function to resolve the caller's promise */ DataManager.prototype._restoreBackup = function(name, filepath, cacheentry, onlinelink, resolve) { @@ -74,10 +74,10 @@ DataManager.prototype._restoreBackup = function(name, filepath, cacheentry, onli /** * Internal: Helper function to pull new file from GitHub - * @param {String} name Name of the file - * @param {String} filepath Full path, starting from project root with './' + * @param {string} name Name of the file + * @param {string} filepath Full path, starting from project root with './' * @param {function} resolve Your promise to resolve when file was pulled - * @param {Boolean} noRequire Optional: Set to true if resolve() should not be called with require(file) as param + * @param {boolean} noRequire Optional: Set to true if resolve() should not be called with require(file) as param */ DataManager.prototype._pullNewFile = async function(name, filepath, resolve, noRequire) { logger("warn", "Backup seems to be broken/not available! Pulling file from GitHub...", true); diff --git a/src/libraryPatches/CSteamSharedFile.js b/src/libraryPatches/CSteamSharedFile.js index f75bdbe2..109e4a88 100644 --- a/src/libraryPatches/CSteamSharedFile.js +++ b/src/libraryPatches/CSteamSharedFile.js @@ -174,7 +174,7 @@ function CSteamSharedFile(community, data) { /** * Deletes a comment from this sharedfile's comment section - * @param {String} cid - ID of the comment to delete + * @param {string} cid - ID of the comment to delete * @param {function} callback - Takes only an Error object/null as the first argument */ CSteamSharedFile.prototype.deleteComment = function(cid, callback) { @@ -191,7 +191,7 @@ CSteamSharedFile.prototype.favorite = function(callback) { /** * Posts a comment to this sharedfile - * @param {String} message - Content of the comment to post + * @param {string} message - Content of the comment to post * @param {function} callback - Takes only an Error object/null as the first argument */ CSteamSharedFile.prototype.comment = function(message, callback) { diff --git a/src/libraryPatches/helpers.js b/src/libraryPatches/helpers.js index 5bbc6345..e2b39a46 100644 --- a/src/libraryPatches/helpers.js +++ b/src/libraryPatches/helpers.js @@ -5,8 +5,8 @@ const xml2js = require('xml2js'); /** * Resolves a Steam profile URL to get steamID64 and vanityURL - * @param {String} url - Full steamcommunity profile URL or only the vanity part. - * @param {Object} callback - First argument is null/Error, second is object containing vanityURL (String) and steamID (String) + * @param {string} url - Full steamcommunity profile URL or only the vanity part. + * @param {object} callback - First argument is null/Error, second is object containing vanityURL (String) and steamID (String) */ helpers.resolveVanityURL = function(url, callback) { // Precede url param if only the vanity was provided diff --git a/src/libraryPatches/sharedfiles.js b/src/libraryPatches/sharedfiles.js index 735dfd63..b4f63107 100644 --- a/src/libraryPatches/sharedfiles.js +++ b/src/libraryPatches/sharedfiles.js @@ -2,7 +2,7 @@ const SteamCommunity = require('steamcommunity'); /** * Downvotes a sharedfile - * @param {String} sid - ID of the sharedfile + * @param {string} sid - ID of the sharedfile * @param {function} callback - Takes only an Error object/null as the first argument */ SteamCommunity.prototype.voteDownSharedFile = function(sid, callback) { @@ -23,7 +23,7 @@ SteamCommunity.prototype.voteDownSharedFile = function(sid, callback) { /** * Upvotes a sharedfile - * @param {String} sid - ID of the sharedfile + * @param {string} sid - ID of the sharedfile * @param {function} callback - Takes only an Error object/null as the first argument */ SteamCommunity.prototype.voteUpSharedFile = function(sid, callback) { diff --git a/src/pluginSystem/pluginSystem.js b/src/pluginSystem/pluginSystem.js index 84636657..d813dd42 100644 --- a/src/pluginSystem/pluginSystem.js +++ b/src/pluginSystem/pluginSystem.js @@ -4,7 +4,7 @@ * Created Date: 19.03.2023 13:34:27 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 18:03:48 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -42,7 +42,7 @@ const PluginSystem = function (controller) { /** * References to all plugin objects - * @type {Object.} + * @type {object.} */ this.pluginList = {}; @@ -99,9 +99,9 @@ PluginSystem.prototype._loadPlugins = function () {}; /** * Internal: Checks a plugin, displays relevant warnings and decides whether the plugin is allowed to be loaded - * @param {String} folderName Name of the plugin folder. This is used to reference the plugin when thisPluginConf is undefined - * @param {Object} thisPlugin Plugin file object returned by require() - * @param {Object} thisPluginConf package.json object of this plugin + * @param {string} folderName Name of the plugin folder. This is used to reference the plugin when thisPluginConf is undefined + * @param {object} thisPlugin Plugin file object returned by require() + * @param {object} thisPluginConf package.json object of this plugin * @returns {Promise.} Resolved with `true` (can be loaded) or `false` (must not be loaded) on completion */ PluginSystem.prototype._checkPlugin = function (folderName, thisPlugin, thisPluginConf) {}; // eslint-disable-line diff --git a/src/sessions/helpers/handle2FA.js b/src/sessions/helpers/handle2FA.js index a3fda3b4..29a9b85a 100644 --- a/src/sessions/helpers/handle2FA.js +++ b/src/sessions/helpers/handle2FA.js @@ -4,7 +4,7 @@ * Created Date: 09.10.2022 12:59:31 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:50:12 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -22,7 +22,7 @@ const SessionHandler = require("../sessionHandler.js"); /** * Internal: Handles submitting 2FA code - * @param {Object} res Response object from startWithCredentials() promise + * @param {object} res Response object from startWithCredentials() promise */ SessionHandler.prototype._handle2FA = function(res) { @@ -132,7 +132,7 @@ SessionHandler.prototype._get2FAUserInput = function() { /** * Internal: Helper function to make accepting and re-requesting invalid steam guard codes easier - * @param {String} code Input from user + * @param {string} code Input from user */ SessionHandler.prototype._acceptSteamGuardCode = function(code) { diff --git a/src/sessions/helpers/tokenStorageHandler.js b/src/sessions/helpers/tokenStorageHandler.js index 4042e00f..f9a3ba13 100644 --- a/src/sessions/helpers/tokenStorageHandler.js +++ b/src/sessions/helpers/tokenStorageHandler.js @@ -4,7 +4,7 @@ * Created Date: 10.10.2022 12:53:20 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:49:45 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -58,7 +58,7 @@ SessionHandler.prototype._getTokenFromStorage = function(callback) { /** * Internal - Saves a new token for this account to tokens.db - * @param {String} token The refreshToken to store + * @param {string} token The refreshToken to store */ SessionHandler.prototype._saveTokenToStorage = function(token) { logger("debug", `[${this.bot.logPrefix}] _saveTokenToStorage(): Updating tokens.db entry for accountName '${this.logOnOptions.accountName}'...`); diff --git a/src/sessions/sessionHandler.js b/src/sessions/sessionHandler.js index ce0f1c37..a7c9dcf3 100644 --- a/src/sessions/sessionHandler.js +++ b/src/sessions/sessionHandler.js @@ -4,7 +4,7 @@ * Created Date: 09.10.2022 12:47:27 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:50:12 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -81,7 +81,7 @@ SessionHandler.prototype.getToken = function() { // I'm not allowed to use arrow /** * Internal - Handles resolving the getToken() promise and skipping the account if necessary - * @param {String} token The token to resolve with or null when account should be skipped + * @param {string} token The token to resolve with or null when account should be skipped */ SessionHandler.prototype._resolvePromise = function(token) { @@ -143,7 +143,7 @@ SessionHandler.prototype._attachEvents = function() {}; /** * Internal: Handles submitting 2FA code - * @param {Object} res Response object from startWithCredentials() promise + * @param {object} res Response object from startWithCredentials() promise */ SessionHandler.prototype._handle2FA = function(res) {}; // eslint-disable-line @@ -154,7 +154,7 @@ SessionHandler.prototype._get2FAUserInput = function() {}; /** * Internal: Helper function to make accepting and re-requesting invalid steam guard codes easier - * @param {String} code Input from user + * @param {string} code Input from user */ SessionHandler.prototype._acceptSteamGuardCode = function(code) {}; // eslint-disable-line @@ -172,7 +172,7 @@ SessionHandler.prototype._getTokenFromStorage = function(callback) {}; // eslint /** * Internal - Saves a new token for this account to tokens.db - * @param {String} token The refreshToken to store + * @param {string} token The refreshToken to store */ SessionHandler.prototype._saveTokenToStorage = function(token) {}; // eslint-disable-line diff --git a/src/starter.js b/src/starter.js index 3a183030..0918214f 100644 --- a/src/starter.js +++ b/src/starter.js @@ -4,7 +4,7 @@ * Created Date: 10.07.2021 10:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:55:45 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -220,10 +220,10 @@ function attachChildListeners() { /** * Checks if the needed file exists and gets it if it doesn't - * @param {String} file The file path (from project root) to check and get + * @param {string} file The file path (from project root) to check and get * @param {function} logger Your current logger function - * @param {Boolean} norequire If set to true the function will return the path instead of importing it - * @param {Boolean} force If set to true the function will skip checking if the file exists and overwrite it. + * @param {boolean} norequire If set to true the function will return the path instead of importing it + * @param {boolean} force If set to true the function will skip checking if the file exists and overwrite it. * @returns {Promise.} Resolves when file was successfully loaded */ module.exports.checkAndGetFile = (file, logger, norequire = false, force = false) => { @@ -349,7 +349,7 @@ module.exports.run = () => { /** * Restart the application - * @param {Object} args The argument object that will be passed to `controller.restartargs()` + * @param {object} args The argument object that will be passed to `controller.restartargs()` */ module.exports.restart = async (args) => { attachParentListeners(() => { diff --git a/src/updater/helpers/checkForUpdate.js b/src/updater/helpers/checkForUpdate.js index 39b5d60f..2cf9b681 100644 --- a/src/updater/helpers/checkForUpdate.js +++ b/src/updater/helpers/checkForUpdate.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:55:45 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -20,9 +20,9 @@ const https = require("https"); /** * Checks for an available update from the GitHub repo - * @param {Object} datafile The current `data.json` file from the DataManager - * @param {String} branch Which branch you want to check. Defaults to the current branch set in `data.json` - * @param {Boolean} forceUpdate If true an update will be forced, even if disableAutoUpdate is true or the newest version is already installed + * @param {object} datafile The current `data.json` file from the DataManager + * @param {string} branch Which branch you want to check. Defaults to the current branch set in `data.json` + * @param {boolean} forceUpdate If true an update will be forced, even if disableAutoUpdate is true or the newest version is already installed * @param {function} [callback] Called with `updateFound` (Boolean) and `data` (Object) on completion. `updatefound` will be false if the check should fail. `data` includes the full data.json file found online. */ module.exports.check = (datafile, branch, forceUpdate, callback) => { diff --git a/src/updater/helpers/customUpdateRules.js b/src/updater/helpers/customUpdateRules.js index f5c0de90..f7921f22 100644 --- a/src/updater/helpers/customUpdateRules.js +++ b/src/updater/helpers/customUpdateRules.js @@ -4,7 +4,7 @@ * Created Date: 22.02.2022 17:39:21 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:50:12 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -21,9 +21,9 @@ const fs = require("fs"); /** * Applies custom update rules for a few files (gets called by downloadUpdate.js) * @param {any} compatibilityfeaturedone Legacy param, is unused - * @param {Object} oldconfig The old config from before the update - * @param {Object} oldadvancedconfig The old advancedconfig from before the update - * @param {Object} olddatafile The old datafile from before the update + * @param {object} oldconfig The old config from before the update + * @param {object} oldadvancedconfig The old advancedconfig from before the update + * @param {object} olddatafile The old datafile from before the update * @param {function} callback Legacy param, is unused * @returns {Promise.} Resolves when we can proceed */ diff --git a/src/updater/helpers/prepareUpdate.js b/src/updater/helpers/prepareUpdate.js index 780fa5b7..a8e5858d 100644 --- a/src/updater/helpers/prepareUpdate.js +++ b/src/updater/helpers/prepareUpdate.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:50:12 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -22,7 +22,7 @@ const Controller = require("../../controller/controller.js"); // eslint-disable- * Wait for active requests and log off all bot accounts * @param {Controller} controller Reference to the controller object * @param {function(Object, string)} respondModule If defined, this function will be called with the result of the check. This allows to integrate checking for updates into commands or plugins. Passes resInfo and txt as parameters. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). * @returns {Promise.} Resolves when we can proceed */ module.exports.run = (controller, respondModule, resInfo) => { diff --git a/src/updater/updater.js b/src/updater/updater.js index c77a9f48..650fc90f 100644 --- a/src/updater/updater.js +++ b/src/updater/updater.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 17:55:45 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -47,9 +47,9 @@ module.exports = Updater; /** * Checks for any available update and installs it. - * @param {Boolean} forceUpdate If true an update will be forced, even if disableAutoUpdate is true or the newest version is already installed + * @param {boolean} forceUpdate If true an update will be forced, even if disableAutoUpdate is true or the newest version is already installed * @param {function(Object, string)} respondModule If defined, this function will be called with the result of the check. This allows to integrate checking for updates into commands or plugins. Passes resInfo and txt as parameters. - * @param {Object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). + * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). * @returns {Promise.} Promise that will be resolved with false when no update was found or with true when the update check or download was completed. Expect a restart when true was returned. */ Updater.prototype.run = function(forceUpdate, respondModule, resInfo) { diff --git a/types/types.d.ts b/types/types.d.ts index 13beb343..5522e1af 100644 --- a/types/types.d.ts +++ b/types/types.d.ts @@ -632,11 +632,11 @@ declare class DataManager { /** * Stores all quotes used for commenting provided via the `quotes.txt` file. */ - quotes: String[]; + quotes: string[]; /** * Stores all proxies provided via the `proxies.txt` file. */ - proxies: String[]; + proxies: string[]; /** * Stores IDs from config files converted at runtime and backups for all config & data files. */ @@ -794,6 +794,46 @@ declare class DataManager { _pullNewFile(): void; } +/** + * Constructor - Creates a new SharedFile object + */ +declare class CSteamSharedFile { + constructor(community: SteamCommunity, data: any); + _community: SteamCommunity; + /** + * Deletes a comment from this sharedfile's comment section + * @param cid - ID of the comment to delete + * @param callback - Takes only an Error object/null as the first argument + */ + deleteComment(cid: string, callback: (...params: any[]) => any): void; + /** + * Favorites this sharedfile + * @param callback - Takes only an Error object/null as the first argument + */ + favorite(callback: (...params: any[]) => any): void; + /** + * Posts a comment to this sharedfile + * @param message - Content of the comment to post + * @param callback - Takes only an Error object/null as the first argument + */ + comment(message: string, callback: (...params: any[]) => any): void; + /** + * Subscribes to this sharedfile's comment section. Note: Checkbox on webpage does not update + * @param callback - Takes only an Error object/null as the first argument + */ + subscribe(callback: (...params: any[]) => any): void; + /** + * Unfavorites this sharedfile + * @param callback - Takes only an Error object/null as the first argument + */ + unfavorite(callback: (...params: any[]) => any): void; + /** + * Unsubscribes from this sharedfile's comment section. Note: Checkbox on webpage does not update + * @param callback - Takes only an Error object/null as the first argument + */ + unsubscribe(callback: (...params: any[]) => any): void; +} + /** * @property load - Called on Plugin load * @property unload - Called on Plugin unload From 54d3d45d5cb737d5ac9ecdd014b3085f662bf75c Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Tue, 4 Jul 2023 20:29:25 +0200 Subject: [PATCH 27/43] Add jsdoc eslint rules and enforce them --- .eslintrc.json | 21 +- package-lock.json | 1234 ++++++++++++++++- package.json | 2 + src/bot/bot.js | 4 +- src/commands/commandHandler.js | 14 +- src/commands/core/block.js | 10 +- src/commands/core/comment.js | 10 +- src/commands/core/favorite.js | 10 +- src/commands/core/friend.js | 14 +- src/commands/core/general.js | 26 +- src/commands/core/group.js | 18 +- src/commands/core/requests.js | 22 +- src/commands/core/settings.js | 6 +- src/commands/core/system.js | 26 +- src/commands/core/vote.js | 10 +- src/commands/helpers/getCommentArgs.js | 8 +- src/commands/helpers/getCommentBots.js | 4 +- src/commands/helpers/getFavoriteBots.js | 4 +- src/commands/helpers/getSharedfileArgs.js | 6 +- src/commands/helpers/getVoteBots.js | 4 +- src/commands/helpers/handleCommentSkips.js | 4 +- .../helpers/handleSharedfileErrors.js | 10 +- src/controller/controller.js | 29 +- src/controller/events/statusUpdate.js | 4 +- src/controller/events/steamGuardInput.js | 4 +- src/controller/helpers/friendlist.js | 4 +- src/controller/helpers/getBots.js | 4 +- .../helpers/handleSteamIdResolving.js | 4 +- src/controller/helpers/logger.js | 5 +- src/controller/helpers/misc.js | 13 +- src/controller/helpers/npminteraction.js | 10 +- src/dataManager/dataImport.js | 6 +- src/dataManager/dataManager.js | 26 +- src/dataManager/dataProcessing.js | 4 +- src/dataManager/helpers/getQuote.js | 4 +- .../helpers/handleExpiringTokens.js | 4 +- src/dataManager/helpers/misc.js | 4 +- src/dataManager/helpers/repairFile.js | 6 +- src/pluginSystem/loadPlugins.js | 12 +- src/pluginSystem/pluginSystem.js | 14 +- src/sessions/helpers/tokenStorageHandler.js | 4 +- src/sessions/sessionHandler.js | 4 +- src/starter.js | 23 +- src/updater/helpers/checkForUpdate.js | 4 +- src/updater/helpers/createBackup.js | 9 +- src/updater/helpers/customUpdateRules.js | 4 +- src/updater/helpers/prepareUpdate.js | 7 +- src/updater/helpers/restoreBackup.js | 9 +- src/updater/updater.js | 12 +- start.js | 7 +- types/types.d.ts | 147 +- 51 files changed, 1589 insertions(+), 265 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 58c59461..76548097 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -18,6 +18,9 @@ "parserOptions": { "ecmaVersion": 11 }, + "plugins": [ + "jsdoc" + ], "rules": { "no-var": "error", "no-redeclare": "off", @@ -37,7 +40,23 @@ "semi-spacing": "error", "semi-style": ["error", "last"], "quotes": ["error", "double", { "avoidEscape": true }], - "spaced-comment": "warn" + "spaced-comment": "warn", + + // JsDoc - https://github.com/gajus/eslint-plugin-jsdoc + "jsdoc/check-alignment": "warn", + "jsdoc/check-indentation": "warn", + "jsdoc/check-types": "warn", + "jsdoc/informative-docs": "warn", + "jsdoc/require-asterisk-prefix": "warn", + "jsdoc/require-description": "warn", + "jsdoc/require-jsdoc": "warn", + "jsdoc/require-param": "warn", + "jsdoc/require-param-name": "warn", + "jsdoc/valid-types": "warn", + //"jsdoc/require-returns": "warn", // Always requires @return, even when function does not return something + "jsdoc/require-returns-type": "warn", + //"jsdoc/require-returns-check": "warn", // Unnecessary when require-returns above is disabled + "jsdoc/require-returns-description": "warn" }, "ignorePatterns": ["src/libraryPatches/*"] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b2efff8b..ff1ab750 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,9 +24,20 @@ "steamid-resolver": "^1.3.3" }, "devDependencies": { + "eslint": "^8.44.0", + "eslint-plugin-jsdoc": "^46.4.3", "tsd-jsdoc": "^2.5.0" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@babel/parser": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", @@ -77,6 +88,190 @@ "resolved": "https://registry.npmjs.org/@doctormckay/steam-crypto/-/steam-crypto-1.2.0.tgz", "integrity": "sha512-lsxgLw640gEdZBOXpVIcYWcYD+V+QbtEsMPzRvjmjz2XXKc7QeEMyHL07yOFRmay+cUwO4ObKTJO0dSInEuq5g==" }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.39.4", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz", + "integrity": "sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg==", + "dev": true, + "dependencies": { + "comment-parser": "1.3.1", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -383,6 +578,27 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", + "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/adm-zip": { "version": "0.5.10", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", @@ -438,6 +654,30 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/appdirectory": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/appdirectory/-/appdirectory-0.1.0.tgz", @@ -463,12 +703,20 @@ "node": ">=4" } }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "peer": true + "dev": true }, "node_modules/array-flatten": { "version": "1.1.1", @@ -551,6 +799,12 @@ "node": ">= 6" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -663,6 +917,16 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -713,6 +977,18 @@ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bytebuffer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", @@ -782,6 +1058,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -800,6 +1085,22 @@ "node": ">= 10" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/cheerio": { "version": "0.22.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", @@ -896,6 +1197,24 @@ "mimic-response": "^1.0.0" } }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -912,6 +1231,21 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, + "node_modules/comment-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", + "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -961,6 +1295,20 @@ "node": ">= 0.10" } }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/css-select": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", @@ -1206,6 +1554,12 @@ "node": ">=0.10.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1231,6 +1585,18 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -1421,6 +1787,257 @@ "node": ">=8" } }, + "node_modules/eslint": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz", + "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.6.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-jsdoc": { + "version": "46.4.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.3.tgz", + "integrity": "sha512-Prc7ol+vCIghPeECpwZq5+P+VZfoi87suywvbYCiCnkI1kTmVSdcOC2M8mioglWxBbd28wbb1OVjg/8OzGzatA==", + "dev": true, + "dependencies": { + "@es-joy/jsdoccomment": "~0.39.4", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.3.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.1", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/espree": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz", + "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -1567,6 +2184,12 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "node_modules/fast-xml-parser": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", @@ -1588,6 +2211,15 @@ "fxparser": "src/cli/cli.js" } }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -1596,6 +2228,18 @@ "pend": "~1.2.0" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-manager": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/file-manager/-/file-manager-2.0.1.tgz", @@ -1661,6 +2305,41 @@ "node": ">= 0.8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, "node_modules/follow-redirects": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", @@ -1744,6 +2423,12 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -1782,6 +2467,53 @@ "assert-plus": "^1.0.0" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -1841,6 +2573,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -1873,6 +2611,15 @@ "node": ">= 0.4.0" } }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", @@ -2015,6 +2762,15 @@ } ] }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/image-size": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.8.3.tgz", @@ -2034,6 +2790,41 @@ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -2079,6 +2870,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -2090,6 +2896,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", @@ -2104,6 +2919,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-natural-number": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", @@ -2117,6 +2944,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -2169,6 +3005,12 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -2186,6 +3028,18 @@ "node": ">= 4" } }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/js2xmlparser": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", @@ -2231,6 +3085,15 @@ "node": ">=12.0.0" } }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -2246,6 +3109,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -2291,6 +3160,19 @@ "node": ">=4.0.0" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lie": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", @@ -2317,6 +3199,21 @@ "lie": "3.1.1" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -2395,6 +3292,18 @@ "node": ">=0.10.0" } }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/lzma": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/lzma/-/lzma-2.3.2.tgz", @@ -2532,6 +3441,18 @@ "node": ">=4" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -2550,6 +3471,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -2630,6 +3557,23 @@ "wrappy": "1" } }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/output-logger": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/output-logger/-/output-logger-2.3.7.tgz", @@ -2674,6 +3618,36 @@ "node": ">=4" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", @@ -2685,6 +3659,18 @@ "node": ">=4" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2693,6 +3679,33 @@ "node": ">= 0.8" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -2746,6 +3759,15 @@ "node": ">=0.10.0" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -2850,6 +3872,26 @@ "inherits": "~2.0.3" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -2937,6 +3979,15 @@ "lodash": "^4.17.21" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -2945,6 +3996,54 @@ "lowercase-keys": "^1.0.0" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3041,6 +4140,27 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -3222,6 +4342,28 @@ "node": ">=0.10.0" } }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, "node_modules/sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", @@ -3558,6 +4700,18 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-dirs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", @@ -3571,7 +4725,6 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "peer": true, "engines": { "node": ">=8" }, @@ -3603,6 +4756,18 @@ "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", @@ -3627,6 +4792,12 @@ "node": ">= 0.8.0" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -3730,6 +4901,30 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -3903,6 +5098,21 @@ "node": ">=6.0.0" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/which-typed-array": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", @@ -3982,6 +5192,12 @@ "node": ">=0.4" } }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -3990,6 +5206,18 @@ "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 933d3ced..859f38f4 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "homepage": "https://github.com/3urobeat", "repository": "https://github.com/3urobeat/steam-comment-service-bot", "devDependencies": { + "eslint": "^8.44.0", + "eslint-plugin-jsdoc": "^46.4.3", "tsd-jsdoc": "^2.5.0" }, "types": "./types/types.d.ts" diff --git a/src/bot/bot.js b/src/bot/bot.js index 31e319e5..dbc7aa6f 100644 --- a/src/bot/bot.js +++ b/src/bot/bot.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:58:09 + * Last Modified: 04.07.2023 19:05:34 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -58,7 +58,7 @@ const Bot = function(controller, index) { /** * SteamID64's to ignore in the friendMessage event handler. This is used by readChatMessage() to prevent duplicate responses. - * @type {array.} + * @type {string[]} */ this.friendMessageBlock = []; diff --git a/src/commands/commandHandler.js b/src/commands/commandHandler.js index 61cf6769..cc9c1344 100644 --- a/src/commands/commandHandler.js +++ b/src/commands/commandHandler.js @@ -4,7 +4,7 @@ * Created Date: 01.04.2023 21:54:21 * Author: 3urobeat * - * Last Modified: 04.07.2023 18:04:59 + * Last Modified: 04.07.2023 19:26:29 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -78,8 +78,8 @@ CommandHandler.prototype._importCoreCommands = function() { * @param {[string]} command.names All names that should trigger this command * @param {string} command.description Description of what this command does * @param {boolean} command.ownersOnly Set to true to only allow owners to use this command. - * @param {function(CommandHandler, Array, string, function(object, object, string), object, object)} command.run Function that will be executed when the command runs. Arguments: commandHandler, args, steamID64, respondModule, context, resInfo - * @returns true if the command was successfully registered, false otherwise + * @param {function(CommandHandler, Array, string, function(object, object, string): void, object, object): void} command.run Function that will be executed when the command runs. Arguments: commandHandler, args, steamID64, respondModule, context, resInfo + * @returns {boolean} true if the command was successfully registered, false otherwise */ CommandHandler.prototype.registerCommand = function(command) { @@ -117,7 +117,7 @@ CommandHandler.prototype.registerCommand = function(command) { /** * The name of the command to unregister during runtime * @param {string} commandName Name of the command to unregister - * @returns true if the command was successfully unregistered, false otherwise + * @returns {boolean} `true` if the command was successfully unregistered, `false` otherwise */ CommandHandler.prototype.unregisterCommand = function(commandName) { @@ -143,12 +143,12 @@ CommandHandler.prototype.unregisterCommand = function(commandName) { /** * Finds a loaded command by name and runs it * @param {string} name The name of the command - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {number} steamID64 SteamID64 of the requesting user which is used to check for ownerOnly and will be passed to the command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). Please also include a "cmdprefix" key & value pair if your command handler uses a prefix other than "!". - * @returns `true` if command was found, `false` if not + * @returns {boolean} `true` if command was found, `false` if not */ CommandHandler.prototype.runCommand = function(name, args, steamID64, respondModule, context, resInfo) { diff --git a/src/commands/core/block.js b/src/commands/core/block.js index 760c568e..6efa0831 100644 --- a/src/commands/core/block.js +++ b/src/commands/core/block.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:25:54 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,9 +28,9 @@ module.exports.block = { /** * The block command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -64,9 +64,9 @@ module.exports.unblock = { /** * The unblock command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ diff --git a/src/commands/core/comment.js b/src/commands/core/comment.js index 4b8e2095..833027fa 100644 --- a/src/commands/core/comment.js +++ b/src/commands/core/comment.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:32:52 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -32,9 +32,9 @@ module.exports.comment = { /** * The comment command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -194,8 +194,8 @@ module.exports.comment = { * Internal: Do the actual commenting, activeRequests entry with all relevant information was processed by the comment command function above. * @param {CommandHandler} commandHandler The commandHandler object * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). - * @param {function(string)} respond Shortened respondModule call - * @param {function} postComment The correct postComment function for this idType. Context from the correct bot account is being applied later. + * @param {function(string): void} respond The shortened respondModule call + * @param {Function} postComment The correct postComment function for this idType. Context from the correct bot account is being applied later. * @param {object} commentArgs All arguments this postComment function needs, without callback. It will be applied and a callback added as last param. Include a key called "quote" to dynamically replace it with a random quote. * @param {string} receiverSteamID64 steamID64 of the profile to receive the comments */ diff --git a/src/commands/core/favorite.js b/src/commands/core/favorite.js index ee3a52d8..4de00ccd 100644 --- a/src/commands/core/favorite.js +++ b/src/commands/core/favorite.js @@ -4,7 +4,7 @@ * Created Date: 02.06.2023 13:23:01 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:27:09 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -30,9 +30,9 @@ module.exports.favorite = { /** * The favorite command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -197,9 +197,9 @@ module.exports.unfavorite = { /** * The unfavorite command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ diff --git a/src/commands/core/friend.js b/src/commands/core/friend.js index 9474d3aa..1971c0fc 100644 --- a/src/commands/core/friend.js +++ b/src/commands/core/friend.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:27:09 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,9 +28,9 @@ module.exports.addFriend = { /** * The addFriend command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -88,9 +88,9 @@ module.exports.unfriend = { /** * The unfriend command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -141,9 +141,9 @@ module.exports.unfriendall = { /** * The unfriendall command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ diff --git a/src/commands/core/general.js b/src/commands/core/general.js index f30fd41e..28e6235d 100644 --- a/src/commands/core/general.js +++ b/src/commands/core/general.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:27:09 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -31,9 +31,9 @@ module.exports.help = { /** * The help command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -81,9 +81,9 @@ module.exports.info = { /** * The info command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -124,9 +124,9 @@ module.exports.ping = { /** * The ping command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -151,9 +151,9 @@ module.exports.about = { /** * The about command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -173,9 +173,9 @@ module.exports.owner = { /** * The owner command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -199,9 +199,9 @@ module.exports.test = { /** * The test command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ diff --git a/src/commands/core/group.js b/src/commands/core/group.js index 679e6867..6c439ad3 100644 --- a/src/commands/core/group.js +++ b/src/commands/core/group.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:27:09 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,9 +28,9 @@ module.exports.group = { /** * The group command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -62,9 +62,9 @@ module.exports.joinGroup = { /** * The joinGroup command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -99,9 +99,9 @@ module.exports.leaveGroup = { /** * The leaveGroup command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -136,9 +136,9 @@ module.exports.leaveAllGroups = { /** * The leaveAllGroups command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ diff --git a/src/commands/core/requests.js b/src/commands/core/requests.js index e2777423..e67a15d8 100644 --- a/src/commands/core/requests.js +++ b/src/commands/core/requests.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:27:09 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -27,9 +27,9 @@ module.exports.abort = { /** * The abort command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -68,9 +68,9 @@ module.exports.resetCooldown = { /** * The resetcooldown command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -112,9 +112,9 @@ module.exports.failed = { /** * The failed command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -158,9 +158,9 @@ module.exports.sessions = { /** * The sessions command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -202,9 +202,9 @@ module.exports.mySessions = { /** * The mysessions command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ diff --git a/src/commands/core/settings.js b/src/commands/core/settings.js index c0a395f8..04b0aff4 100644 --- a/src/commands/core/settings.js +++ b/src/commands/core/settings.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:27:09 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,9 +28,9 @@ module.exports.settings = { /** * The settings command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ diff --git a/src/commands/core/system.js b/src/commands/core/system.js index e9ca7d22..f4780abc 100644 --- a/src/commands/core/system.js +++ b/src/commands/core/system.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:27:09 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,9 +28,9 @@ module.exports.restart = { /** * The restart command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -50,9 +50,9 @@ module.exports.stop = { /** * The stop command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -72,9 +72,9 @@ module.exports.reload = { /** * The reload command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -101,9 +101,9 @@ module.exports.update = { /** * The update command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -131,9 +131,9 @@ module.exports.output = { /** * The output command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -156,9 +156,9 @@ module.exports.eval = { /** * The eval command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ diff --git a/src/commands/core/vote.js b/src/commands/core/vote.js index d1974e41..f4b2709e 100644 --- a/src/commands/core/vote.js +++ b/src/commands/core/vote.js @@ -4,7 +4,7 @@ * Created Date: 28.05.2023 12:02:24 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:27:09 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -30,9 +30,9 @@ module.exports.upvote = { /** * The upvote command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ @@ -202,9 +202,9 @@ module.exports.downvote = { /** * The upvote command * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args Array of arguments that will be passed to the command + * @param {Array} args Array of arguments that will be passed to the command * @param {string} steamID64 Steam ID of the user that executed this command - * @param {function(object, object, string)} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. + * @param {function(object, object, string): void} respondModule Function that will be called to respond to the user's request. Passes context, resInfo and txt as parameters. * @param {object} context The context (this.) of the object calling this command. Will be passed to respondModule() as first parameter. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). */ diff --git a/src/commands/helpers/getCommentArgs.js b/src/commands/helpers/getCommentArgs.js index cfe638d1..36c9c435 100644 --- a/src/commands/helpers/getCommentArgs.js +++ b/src/commands/helpers/getCommentArgs.js @@ -4,7 +4,7 @@ * Created Date: 28.02.2022 11:55:06 * Author: 3urobeat * - * Last Modified: 04.07.2023 18:08:02 + * Last Modified: 04.07.2023 19:30:48 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -21,11 +21,11 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line /** * Retrieves arguments from a comment request. If request is invalid (for example too many comments requested) an error message will be sent * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args The command arguments + * @param {Array} args The command arguments * @param {string} requesterSteamID64 The steamID64 of the requesting user * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). - * @param {function} respond The function to send messages to the requesting user - * @returns {Promise.<{ maxRequestAmount: number, commentcmdUsage: string, numberOfComments: number, profileID: string, idType: string, quotesArr: array. }>} + * @param {function(string): void} respond The shortened respondModule call + * @returns {Promise.<{ maxRequestAmount: number, commentcmdUsage: string, numberOfComments: number, profileID: string, idType: string, quotesArr: Array. }>} Resolves promise with object containing all relevant data when done */ module.exports.getCommentArgs = (commandHandler, args, requesterSteamID64, resInfo, respond) => { return new Promise((resolve) => { diff --git a/src/commands/helpers/getCommentBots.js b/src/commands/helpers/getCommentBots.js index 71c90b24..f0bc3bc4 100644 --- a/src/commands/helpers/getCommentBots.js +++ b/src/commands/helpers/getCommentBots.js @@ -4,7 +4,7 @@ * Created Date: 09.04.2023 12:49:53 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:45 + * Last Modified: 04.07.2023 19:30:59 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -26,7 +26,7 @@ const { timeToString } = require("../../controller/helpers/misc.js"); * @param {boolean} canBeLimited If the accounts are allowed to be limited * @param {string} idType Type of the request. This can either be "profile", "group" or "sharedfile". This is used to determine if limited accs need to be added first. * @param {string} receiverSteamID Optional: steamID64 of the receiving user. If set, accounts that are friend with the user will be prioritized and accsToAdd will be calculated. - * @returns {{ accsNeeded: number, availableAccounts: array., accsToAdd: array., whenAvailable: number, whenAvailableStr: string }} `availableAccounts` contains all account names from bot object, `accsToAdd` account names which are limited and not friend, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now + * @returns {{ accsNeeded: number, availableAccounts: Array., accsToAdd: Array., whenAvailable: number, whenAvailableStr: string }} `availableAccounts` contains all account names from bot object, `accsToAdd` account names which are limited and not friend, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now */ module.exports.getAvailableBotsForCommenting = function(commandHandler, numberOfComments, canBeLimited, idType, receiverSteamID = null) { diff --git a/src/commands/helpers/getFavoriteBots.js b/src/commands/helpers/getFavoriteBots.js index 1cc25487..d2d7c9c7 100644 --- a/src/commands/helpers/getFavoriteBots.js +++ b/src/commands/helpers/getFavoriteBots.js @@ -4,7 +4,7 @@ * Created Date: 02.06.2023 14:07:27 * Author: 3urobeat * - * Last Modified: 04.07.2023 18:07:56 + * Last Modified: 04.07.2023 19:31:26 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -25,7 +25,7 @@ const { timeToString } = require("../../controller/helpers/misc.js"); * @param {number|"all"} amount Amount of favs requested or "all" to get the max available amount * @param {string} id The sharedfile id to favorize * @param {string} favType Either "favorite" or "unfavorite", depending on which request this is - * @returns {Promise.<{ amount: number, availableAccounts: array., whenAvailable: number, whenAvailableStr: string }>} Promise with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now + * @returns {Promise.<{ amount: number, availableAccounts: Array., whenAvailable: number, whenAvailableStr: string }>} Resolves with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now */ module.exports.getAvailableBotsForFavorizing = async (commandHandler, amount, id, favType) => { diff --git a/src/commands/helpers/getSharedfileArgs.js b/src/commands/helpers/getSharedfileArgs.js index e53c747a..038fe00e 100644 --- a/src/commands/helpers/getSharedfileArgs.js +++ b/src/commands/helpers/getSharedfileArgs.js @@ -4,7 +4,7 @@ * Created Date: 28.05.2023 12:18:49 * Author: 3urobeat * - * Last Modified: 04.07.2023 18:01:36 + * Last Modified: 04.07.2023 19:31:41 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -21,10 +21,10 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line /** * Retrieves arguments from a vote request. If request is invalid, an error message will be sent * @param {CommandHandler} commandHandler The commandHandler object - * @param {array} args The command arguments + * @param {Array} args The command arguments * @param {string} cmd Either "upvote", "downvote", "favorite" or "unfavorite", depending on which command is calling this function * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). - * @param {function} respond The function to send messages to the requesting user + * @param {function(string): void} respond The shortened respondModule call * @returns {Promise.<{ amount: number|string, id: string }>} If the user provided a specific amount, amount will be a number. If user provided "all" or "max", it will be returned as an unmodified string for getVoteBots.js to handle */ module.exports.getSharedfileArgs = (commandHandler, args, cmd, resInfo, respond) => { diff --git a/src/commands/helpers/getVoteBots.js b/src/commands/helpers/getVoteBots.js index 45c3fdf4..d2a40e74 100644 --- a/src/commands/helpers/getVoteBots.js +++ b/src/commands/helpers/getVoteBots.js @@ -4,7 +4,7 @@ * Created Date: 28.05.2023 12:21:02 * Author: 3urobeat * - * Last Modified: 03.07.2023 12:59:52 + * Last Modified: 04.07.2023 19:31:54 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -25,7 +25,7 @@ const { timeToString } = require("../../controller/helpers/misc.js"); * @param {number|"all"} amount Amount of votes requested or "all" to get the max available amount * @param {string} id The sharedfile id to vote on * @param {string} voteType "upvote" or "downvote", depending on which request this is - * @returns {Promise.<{ amount: number, availableAccounts: array, whenAvailable: number, whenAvailableStr: string }>} Promise with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now + * @returns {Promise.<{ amount: number, availableAccounts: Array., whenAvailable: number, whenAvailableStr: string }>} Resolves with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now */ module.exports.getAvailableBotsForVoting = async (commandHandler, amount, id, voteType) => { diff --git a/src/commands/helpers/handleCommentSkips.js b/src/commands/helpers/handleCommentSkips.js index 5bd61a7d..cf995eab 100644 --- a/src/commands/helpers/handleCommentSkips.js +++ b/src/commands/helpers/handleCommentSkips.js @@ -4,7 +4,7 @@ * Created Date: 28.02.2022 12:22:48 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:45 + * Last Modified: 04.07.2023 19:33:05 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -23,7 +23,7 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line * Checks if the following comment process iteration should be skipped * Aborts comment process on critical error. * @param {CommandHandler} commandHandler The commandHandler object - * @param {{ next: function, break: function, index: function }} loop Object returned by misc.js syncLoop() helper + * @param {{ next: function(): void, break: function(): void, index: function(): number }} loop Object returned by misc.js syncLoop() helper * @param {Bot} bot Bot object of the account posting this comment * @param {string} receiverSteamID64 steamID64 of the receiving user/group * @returns {boolean} true if iteration should continue, false if iteration should be skipped using return diff --git a/src/commands/helpers/handleSharedfileErrors.js b/src/commands/helpers/handleSharedfileErrors.js index b1361723..8190b00c 100644 --- a/src/commands/helpers/handleSharedfileErrors.js +++ b/src/commands/helpers/handleSharedfileErrors.js @@ -4,7 +4,7 @@ * Created Date: 31.05.2023 16:57:21 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:50:12 + * Last Modified: 04.07.2023 19:51:58 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -21,10 +21,10 @@ const Bot = require("../../bot/bot.js"); // eslint-disable-line /** * Checks if the following vote process iteration should be skipped * @param {CommandHandler} commandHandler The commandHandler object - * @param {{ next: function, break: function, index: function }} loop Object returned by misc.js syncLoop() helper + * @param {{ next: function(): void, break: function(): void, index: function(): number }} loop Object returned by misc.js syncLoop() helper * @param {Bot} bot Bot object of the account making this request * @param {string} id ID of the sharedfile that receives the votes - * @returns true if iteration should continue, false if iteration should be skipped using return + * @returns {boolean} `true` if iteration should continue, `false` if iteration should be skipped using return */ module.exports.handleVoteIterationSkip = function(commandHandler, loop, bot, id) { let activeReqEntry = commandHandler.controller.activeRequests[id]; // Make using the obj shorter @@ -55,10 +55,10 @@ module.exports.handleVoteIterationSkip = function(commandHandler, loop, bot, id) /** * Checks if the following favorite process iteration should be skipped * @param {CommandHandler} commandHandler The commandHandler object - * @param {{ next: function, break: function, index: function }} loop Object returned by misc.js syncLoop() helper + * @param {{ next: function(): void, break: function(): void, index: function(): number }} loop Object returned by misc.js syncLoop() helper * @param {Bot} bot Bot object of the account making this request * @param {string} id ID of the sharedfile that receives the votes - * @returns true if iteration should continue, false if iteration should be skipped using return + * @returns {boolean} `true` if iteration should continue, `false` if iteration should be skipped using return */ module.exports.handleFavoriteIterationSkip = function(commandHandler, loop, bot, id) { let activeReqEntry = commandHandler.controller.activeRequests[id]; // Make using the obj shorter diff --git a/src/controller/controller.js b/src/controller/controller.js index 18e9bc1c..317e40ae 100644 --- a/src/controller/controller.js +++ b/src/controller/controller.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 18:02:14 + * Last Modified: 04.07.2023 19:54:44 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -35,8 +35,8 @@ const Controller = function() { /** * Implementation of a synchronous for loop in JS (Used as reference: https://whitfin.io/handling-synchronous-asynchronous-loops-javascriptnode-js/) * @param {number} iterations The amount of iterations - * @param {function} func The function to run each iteration (Params: loop, index) - * @param {function} exit This function will be called when the loop is finished + * @param {function(): void} func The function to run each iteration (Params: loop, index) + * @param {function(): void} exit This function will be called when the loop is finished */ syncLoop: (iterations, func, exit) => {}, // eslint-disable-line @@ -49,7 +49,8 @@ const Controller = function() { round: (value, decimals) => {}, // eslint-disable-line /** - * Converts a timestamp to a human-readable until from now format. Does not care about past/future. + * Converts a timestamp to a human-readable "until from now" format. Does not care about past/future. + * @param {number} timestamp UNIX timestamp to convert * @returns {string} "x seconds/minutes/hours/days" */ timeToString: () => {}, // eslint-disable-line @@ -67,9 +68,9 @@ const Controller = function() { * It is used by the steamChatInteraction helper but can be used in plugins as well. * @param {string} txt The string to cut * @param {number} limit Maximum length for each part. The function will attempt to cut txt into parts that don't exceed this amount. - * @param {array} cutChars Optional: Custom chars to search after for cutting string in parts. Default: [" ", "\n", "\r"] + * @param {Array} cutChars Optional: Custom chars to search after for cutting string in parts. Default: [" ", "\n", "\r"] * @param {number} threshold Optional: Maximum amount that limit can be reduced to find the last space or line break. If no match is found within this limit a word will be cut. Default: 15% of total length - * @returns {array} Returns all parts of the string in an array + * @returns {Array} Returns all parts of the string in an array */ cutStringsIntelligently: (txt, limit, cutChars, threshold) => {} // eslint-disable-line }; @@ -250,7 +251,7 @@ Controller.prototype._preLogin = async function() { /** * Stores references to all bot account objects mapped to their accountName - * @type {object.} + * @type {{[key: string]: Bot}} */ this.bots = {}; @@ -306,6 +307,7 @@ module.exports = Controller; /** * Process data that should be kept over restarts + * @param {string} data Stringified data received by previous process */ function restartdata(data) { data = JSON.parse(data); // Convert the stringified object back to an object @@ -376,14 +378,14 @@ Controller.prototype._readyEvent = function() {}; /** * Runs internal statusUpdate event code and emits statusUpdate event for plugins * @param {Bot} bot Bot instance - * @param {Bot.EStatus} newStatus The new status + * @param {Bot.EStatus} newStatus The new status of this bot */ Controller.prototype._statusUpdateEvent = function(bot, newStatus) {}; // eslint-disable-line /** * Emits steamGuardInput event for bot & plugins * @param {Bot} bot Bot instance of the affected account - * @param {function(string)} submitCode Function to submit a code. Pass an empty string to skip the account. + * @param {function(string): void} submitCode Function to submit a code. Pass an empty string to skip the account. */ Controller.prototype._steamGuardInputEvent = function(bot, submitCode) {}; // eslint-disable-line @@ -396,7 +398,7 @@ Controller.prototype.checkLastcommentDB = function(bot) {}; // eslint-disable-li /** * Checks the remaining space on the friendlist of a bot account, sends a warning message if it is less than 10 and force unfriends oldest lastcomment db user to always keep room for 1 friend. * @param {Bot} bot Bot object of the account to check - * @param {function} [callback] Called with `remaining` (Number) on completion + * @param {function(number|null): void} [callback] Called with `remaining` (Number) on success or `null` on failure */ Controller.prototype.friendListCapacityCheck = function(bot, callback) {}; // eslint-disable-line @@ -409,7 +411,7 @@ Controller.prototype._lastcommentUnfriendCheck = function() {} // eslint-disable * Retrieves all matching bot accounts and returns them. * @param {(EStatus|EStatus[]|string)} [statusFilter=EStatus.ONLINE] Optional: EStatus or Array of EStatus's including account statuses to filter. Pass '*' to get all accounts. If omitted, only accs with status 'EStatus.ONLINE' will be returned. * @param {boolean} mapToObject Optional: If true, an object will be returned where every bot object is mapped to their accountName. - * @returns {array|object} An array or object if `mapToObject == true` containing all matching bot accounts. + * @returns {Array|object} An array or object if `mapToObject == true` containing all matching bot accounts. */ Controller.prototype.getBots = function(statusFilter = EStatus.ONLINE, mapToObject = false) {}; // eslint-disable-line @@ -423,7 +425,7 @@ Controller.prototype._handleErrors = function() {} // eslint-disable-line * Handles converting URLs to steamIDs, determining their type if unknown and checking if it matches your expectation * @param {string} str The profileID argument provided by the user * @param {string} expectedIdType The type of SteamID expected ("profile", "group" or "sharedfile") or `null` if type should be assumed. - * @param {function} [callback] Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion + * @param {function(string|null, string|null, string|null): void} [callback] Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion */ Controller.prototype.handleSteamIdResolving = (str, expectedIdType, callback) => {} // eslint-disable-line @@ -433,12 +435,15 @@ Controller.prototype.handleSteamIdResolving = (str, expectedIdType, callback) => * @param {string} str The text to log into the terminal * @param {boolean} nodate Setting to true will hide date and time in the message * @param {boolean} remove Setting to true will remove this message with the next one + * @param {Array.} animation Array containing animation frames as elements * @param {boolean} printNow Ignores the readyafterlogs check and force prints the message now + * @param {boolean} cutToWidth Cuts the string to the width of the terminal */ Controller.prototype.logger = function(type, str, nodate, remove, animation, printNow) {}; // eslint-disable-line /** * Internal: Call this function after loading advancedconfig.json to set previously inaccessible options + * @param {object} advancedconfig The advancedconfig object imported by the DataManager */ Controller.prototype._loggerOptionsUpdateAfterConfigLoad = function(advancedconfig) {}; // eslint-disable-line diff --git a/src/controller/events/statusUpdate.js b/src/controller/events/statusUpdate.js index e4a0ca33..f2b80bde 100644 --- a/src/controller/events/statusUpdate.js +++ b/src/controller/events/statusUpdate.js @@ -4,7 +4,7 @@ * Created Date: 30.03.2023 21:05:13 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 19:36:26 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -22,7 +22,7 @@ const Controller = require("../controller"); /** * Runs internal statusUpdate event code and emits statusUpdate event for plugins * @param {Bot} bot Bot instance - * @param {Bot.EStatus} newStatus The new status + * @param {Bot.EStatus} newStatus The new status of this bot */ Controller.prototype._statusUpdateEvent = function(bot, newStatus) { let oldStatus = bot.status; diff --git a/src/controller/events/steamGuardInput.js b/src/controller/events/steamGuardInput.js index de8c1d6b..f747a7d4 100644 --- a/src/controller/events/steamGuardInput.js +++ b/src/controller/events/steamGuardInput.js @@ -4,7 +4,7 @@ * Created Date: 04.06.2023 12:00:48 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 19:36:34 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -22,7 +22,7 @@ const Controller = require("../controller"); /** * Emits steamGuardInput event for bot & plugins * @param {Bot} bot Bot instance of the affected account - * @param {function(string)} submitCode Function to submit a code. Pass an empty string to skip the account. + * @param {function(string): void} submitCode Function to submit a code. Pass an empty string to skip the account. */ Controller.prototype._steamGuardInputEvent = function(bot, submitCode) { diff --git a/src/controller/helpers/friendlist.js b/src/controller/helpers/friendlist.js index facf9775..dc542b4b 100644 --- a/src/controller/helpers/friendlist.js +++ b/src/controller/helpers/friendlist.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 19:37:53 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -52,7 +52,7 @@ Controller.prototype.checkLastcommentDB = function(bot) { /** * Checks the remaining space on the friendlist of a bot account, sends a warning message if it is less than 10 and force unfriends oldest lastcomment db user to always keep room for 1 friend. * @param {Bot} bot Bot object of the account to check - * @param {function} [callback] Called with `remaining` (Number) on completion + * @param {function(number|null): void} [callback] Called with `remaining` (Number) on success or `null` on failure */ Controller.prototype.friendListCapacityCheck = function(bot, callback) { try { diff --git a/src/controller/helpers/getBots.js b/src/controller/helpers/getBots.js index e8e7eaf1..ef8d2463 100644 --- a/src/controller/helpers/getBots.js +++ b/src/controller/helpers/getBots.js @@ -4,7 +4,7 @@ * Created Date: 02.05.2023 13:46:21 * Author: 3urobeat * - * Last Modified: 04.07.2023 18:02:29 + * Last Modified: 04.07.2023 19:38:06 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -23,7 +23,7 @@ const EStatus = require("../../bot/EStatus.js"); * Retrieves all matching bot accounts and returns them. * @param {(EStatus|EStatus[]|string)} [statusFilter=EStatus.ONLINE] Optional: EStatus or Array of EStatus's including account statuses to filter. Pass '*' to get all accounts. If omitted, only accs with status 'EStatus.ONLINE' will be returned. * @param {boolean} mapToObject Optional: If true, an object will be returned where every bot object is mapped to their accountName. - * @returns {array|object} An array or object if `mapToObject == true` containing all matching bot accounts. + * @returns {Array|object} An array or object if `mapToObject == true` containing all matching bot accounts. */ Controller.prototype.getBots = function(statusFilter, mapToObject) { if (!statusFilter) statusFilter = EStatus.ONLINE; diff --git a/src/controller/helpers/handleSteamIdResolving.js b/src/controller/helpers/handleSteamIdResolving.js index feb56d44..76bc843f 100644 --- a/src/controller/helpers/handleSteamIdResolving.js +++ b/src/controller/helpers/handleSteamIdResolving.js @@ -4,7 +4,7 @@ * Created Date: 09.03.2022 12:58:17 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:49:45 + * Last Modified: 04.07.2023 19:38:26 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -28,7 +28,7 @@ const Controller = require("../controller.js"); * Handles converting URLs to steamIDs, determining their type if unknown and checking if it matches your expectation * @param {string} str The profileID argument provided by the user * @param {string} expectedIdType The type of SteamID expected ("profile", "group" or "sharedfile") or `null` if type should be assumed. - * @param {function} [callback] Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion + * @param {function(string|null, string|null, string|null): void} [callback] Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion */ Controller.prototype.handleSteamIdResolving = (str, expectedIdType, callback) => { diff --git a/src/controller/helpers/logger.js b/src/controller/helpers/logger.js index 17439802..7a003ae2 100644 --- a/src/controller/helpers/logger.js +++ b/src/controller/helpers/logger.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:45 + * Last Modified: 04.07.2023 19:39:07 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -41,7 +41,7 @@ let botIsReady = false; * @param {string} str The text to log into the terminal * @param {boolean} nodate Setting to true will hide date and time in the message * @param {boolean} remove Setting to true will remove this message with the next one - * @param {array.} animation Array containing animation frames as elements + * @param {Array.} animation Array containing animation frames as elements * @param {boolean} printNow Ignores the readyafterlogs check and force prints the message now * @param {boolean} cutToWidth Cuts the string to the width of the terminal */ @@ -75,6 +75,7 @@ global.logger = Controller.prototype.logger; /** * Internal: Call this function after loading advancedconfig.json to set previously inaccessible options + * @param {object} advancedconfig The advancedconfig object imported by the DataManager */ Controller.prototype._loggerOptionsUpdateAfterConfigLoad = function(advancedconfig) { logger.options({ diff --git a/src/controller/helpers/misc.js b/src/controller/helpers/misc.js index b2f9183d..d246b501 100644 --- a/src/controller/helpers/misc.js +++ b/src/controller/helpers/misc.js @@ -4,7 +4,7 @@ * Created Date: 25.03.2023 14:02:56 * Author: 3urobeat * - * Last Modified: 04.07.2023 18:01:36 + * Last Modified: 04.07.2023 19:40:22 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -21,8 +21,8 @@ const https = require("https"); /** * Implementation of a synchronous for loop in JS (Used as reference: https://whitfin.io/handling-synchronous-asynchronous-loops-javascriptnode-js/) * @param {number} iterations The amount of iterations - * @param {function} func The function to run each iteration (Params: loop, index) - * @param {function} exit This function will be called when the loop is finished + * @param {function(): void} func The function to run each iteration (Params: loop, index) + * @param {function(): void} exit This function will be called when the loop is finished */ module.exports.syncLoop = (iterations, func, exit) => { let currentIndex = 0; @@ -65,7 +65,8 @@ module.exports.round = (value, decimals) => { /** - * Converts a timestamp to a human-readable until from now format. Does not care about past/future. + * Converts a timestamp to a human-readable "until from now" format. Does not care about past/future. + * @param {number} timestamp UNIX timestamp to convert * @returns {string} "x seconds/minutes/hours/days" */ module.exports.timeToString = (timestamp) => { @@ -126,9 +127,9 @@ module.exports.checkConnection = (url, throwTimeout) => { * It is used by the steamChatInteraction helper but can be used in plugins as well. * @param {string} txt The string to cut * @param {number} limit Maximum length for each part. The function will attempt to cut txt into parts that don't exceed this amount. - * @param {array} cutChars Optional: Custom chars to search after for cutting string in parts. Default: [" ", "\n", "\r"] + * @param {Array} cutChars Optional: Custom chars to search after for cutting string in parts. Default: [" ", "\n", "\r"] * @param {number} threshold Optional: Maximum amount that limit can be reduced to find the last space or line break. If no match is found within this limit a word will be cut. Default: 15% of total length - * @returns {array} Returns all parts of the string in an array + * @returns {Array} Returns all parts of the string in an array */ module.exports.cutStringsIntelligently = (txt, limit, cutChars, threshold) => { if (!cutChars) cutChars = [" ", "\n", "\r"]; // Set cutChars to space, newline or Windows newline if undefined diff --git a/src/controller/helpers/npminteraction.js b/src/controller/helpers/npminteraction.js index d157a776..6a32cde1 100644 --- a/src/controller/helpers/npminteraction.js +++ b/src/controller/helpers/npminteraction.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:49:45 + * Last Modified: 04.07.2023 19:42:16 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -21,8 +21,8 @@ const { exec } = require("child_process"); // Wanted to do it with the npm packa /** * Attempts to reinstall all modules - * @param {function} logger The currently used logger function (real or fake, the caller decides) - * @param {function} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion + * @param {function(string, string): void} logger The currently used logger function (real or fake, the caller decides) + * @param {function(string|null, string|null): void} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ module.exports.reinstallAll = (logger, callback) => { if (!fs.existsSync(srcdir + "/../node_modules")) { @@ -51,7 +51,7 @@ module.exports.reinstallAll = (logger, callback) => { /** * Updates all installed packages to versions listed in package.json from the project root directory. - * @param {function} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion + * @param {function(string|null, string|null): void} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ module.exports.update = (callback) => { module.exports.updateFromPath(srcdir + "/..", callback); @@ -61,7 +61,7 @@ module.exports.update = (callback) => { /** * Updates all installed packages to versions listed in package.json * @param {string} path Custom path to read package.json from and install packages to - * @param {function} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion + * @param {function(string|null, string|null): void} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ module.exports.updateFromPath = (path, callback) => { logger("debug", `npminteraction update(): Running 'npm install' in '${path}'...`); diff --git a/src/dataManager/dataImport.js b/src/dataManager/dataImport.js index d4ea1646..0217700d 100644 --- a/src/dataManager/dataImport.js +++ b/src/dataManager/dataImport.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 03.07.2023 21:32:21 + * Last Modified: 04.07.2023 19:44:01 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -14,11 +14,13 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see . */ + const fs = require("fs"); const path = require("path"); const nedb = require("@seald-io/nedb"); const DataManager = require("./dataManager.js"); + /** * Internal: Loads all config & data files from disk and handles potential errors * @returns {Promise.} Resolves promise when all files have been loaded successfully. The function will log an error and terminate the application should a fatal error occur. @@ -26,6 +28,7 @@ const DataManager = require("./dataManager.js"); DataManager.prototype._importFromDisk = async function () { let _this = this; // Make this accessible within the functions below + /* eslint-disable jsdoc/require-jsdoc */ function loadCache() { return new Promise((resolve) => { try { @@ -318,6 +321,7 @@ DataManager.prototype._importFromDisk = async function () { } }); } + /* eslint-enable jsdoc/require-jsdoc */ // Call all functions from above after another. This must be done async to avoid a check failing that depends on something from a previous function. We sadly cannot use Promise.all() because of this. logger("info", "Importing data files and settings...", false, true, logger.animation("loading")); diff --git a/src/dataManager/dataManager.js b/src/dataManager/dataManager.js index d5d33e46..0a8b7c3d 100644 --- a/src/dataManager/dataManager.js +++ b/src/dataManager/dataManager.js @@ -4,7 +4,7 @@ * Created Date: 21.03.2023 22:34:51 * Author: 3urobeat * - * Last Modified: 04.07.2023 18:08:40 + * Last Modified: 04.07.2023 19:59:31 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -42,44 +42,44 @@ const DataManager = function (controller) { /** * Stores all `config.json` settings. - * @type {object.} + * @type {{[key: string]: any}} */ this.config = {}; /** * Stores all `advancedconfig.json` settings. - * @type {object.} + * @type {{[key: string]: any}} */ this.advancedconfig = {}; /** * Stores all language strings used for responding to a user. * All default strings have already been replaced with corresponding matches from `customlang.json`. - * @type {object.} + * @type {{[key: string]: string}} */ this.lang = {}; /** * Stores all quotes used for commenting provided via the `quotes.txt` file. - * @type {array.} + * @type {Array.} */ this.quotes = []; /** * Stores all proxies provided via the `proxies.txt` file. - * @type {array.} + * @type {Array.} */ this.proxies = []; /** * Stores IDs from config files converted at runtime and backups for all config & data files. - * @type {{ ownerid: array., botsgroup: string, botsgroupid: string, configgroup: string, configgroup64id: string, ownerlinkid: string, botaccid: array., pluginVersions: object., configjson: {}, advancedconfigjson: {}, datajson: {} }} + * @type {{ ownerid: Array., botsgroup: string, botsgroupid: string, configgroup: string, configgroup64id: string, ownerlinkid: string, botaccid: Array., pluginVersions: {[key: string]: string}, configjson: {}, advancedconfigjson: {}, datajson: {} }} */ this.cachefile = {}; /** * Stores the login information for every bot account provided via the `logininfo.json` or `accounts.txt` files. - * @type {object.} + * @type {{[key: string]: { accountName: string, password: string, sharedSecret: string, steamGuardCode: null, machineName: string, deviceFriendlyName: string }}} */ this.logininfo = {}; @@ -141,7 +141,7 @@ DataManager.prototype._importFromDisk = async function () {}; /** * Gets a random quote - * @param {array} quotesArr Optional: Custom array of quotes to choose from. If not provided the default quotes set which was imported from the disk will be used. + * @param {Array} quotesArr Optional: Custom array of quotes to choose from. If not provided the default quotes set which was imported from the disk will be used. * @returns {Promise.} Resolves with `quote` (String) */ DataManager.prototype.getQuote = function (quotesArr = null) {}; // eslint-disable-line @@ -181,7 +181,7 @@ DataManager.prototype.getLastCommentRequest = function (steamID64 = null) {}; // /** * Decodes a JsonWebToken - https://stackoverflow.com/a/38552302 * @param {string} token The token to decode - * @returns JWT object on success, `null` on failure + * @returns {object|null} JWT object on success, `null` on failure */ DataManager.prototype.decodeJWT = function (token) {}; // eslint-disable-line @@ -196,12 +196,16 @@ DataManager.prototype.refreshCache = function () {}; * @param {string} filepath Absolute path of the file on the disk * @param {object} cacheentry Backup-Object of the file in cache.json * @param {string} onlinelink Link to the raw file in the GitHub repository - * @param {function} resolve Function to resolve the caller's promise + * @param {function(any): void} resolve Function to resolve the caller's promise */ DataManager.prototype._restoreBackup = function (name, filepath, cacheentry, onlinelink, resolve) {}; // eslint-disable-line /** * Internal: Helper function to pull new file from GitHub + * @param {string} name Name of the file + * @param {string} filepath Full path, starting from project root with './' + * @param {function(any): void} resolve Your promise to resolve when file was pulled + * @param {boolean} noRequire Optional: Set to true if resolve() should not be called with require(file) as param */ DataManager.prototype._pullNewFile = async function (name, filepath, resolve) {}; // eslint-disable-line diff --git a/src/dataManager/dataProcessing.js b/src/dataManager/dataProcessing.js index 68259fc1..e14c3d1d 100644 --- a/src/dataManager/dataProcessing.js +++ b/src/dataManager/dataProcessing.js @@ -4,7 +4,7 @@ * Created Date: 27.03.2023 21:34:45 * Author: 3urobeat * - * Last Modified: 03.07.2023 15:52:15 + * Last Modified: 04.07.2023 19:59:57 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -28,6 +28,7 @@ const DataManager = require("./dataManager"); DataManager.prototype.processData = async function() { let _this = this; + /* eslint-disable jsdoc/require-jsdoc */ function yourgroup() { return new Promise((resolve) => { @@ -154,6 +155,7 @@ DataManager.prototype.processData = async function() { }); } + /* eslint-enable jsdoc/require-jsdoc */ // Process all three, then update cache.json diff --git a/src/dataManager/helpers/getQuote.js b/src/dataManager/helpers/getQuote.js index bc928bd3..f108194a 100644 --- a/src/dataManager/helpers/getQuote.js +++ b/src/dataManager/helpers/getQuote.js @@ -4,7 +4,7 @@ * Created Date: 02.03.2022 16:21:11 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:32 + * Last Modified: 04.07.2023 19:27:09 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -25,7 +25,7 @@ let lastQuotes = []; // Tracks recently used quotes to avoid duplicates /** * Gets a random quote - * @param {array} quotesArr Optional: Custom array of quotes to choose from. If not provided the default quotes set which was imported from the disk will be used. + * @param {Array} quotesArr Optional: Custom array of quotes to choose from. If not provided the default quotes set which was imported from the disk will be used. * @returns {Promise.} Resolves with `quote` (String) */ DataManager.prototype.getQuote = function(quotesArr = null) { diff --git a/src/dataManager/helpers/handleExpiringTokens.js b/src/dataManager/helpers/handleExpiringTokens.js index 3f894a51..7b56108d 100644 --- a/src/dataManager/helpers/handleExpiringTokens.js +++ b/src/dataManager/helpers/handleExpiringTokens.js @@ -4,7 +4,7 @@ * Created Date: 14.10.2022 14:58:25 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:50:12 + * Last Modified: 04.07.2023 20:00:28 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -24,6 +24,7 @@ const DataManager = require("../dataManager.js"); DataManager.prototype._startExpiringTokensCheckInterval = function() { let _this = this; + /* eslint-disable-next-line jsdoc/require-jsdoc */ function scanDatabase() { logger("debug", "DataManager detectExpiringTokens(): Scanning tokens.db for expiring tokens..."); @@ -102,6 +103,7 @@ DataManager.prototype._askForGetNewToken = function(expiring) { let EStatus = require("../../bot/EStatus.js"); // Import not at top scope as this can be undefined because this helper file gets loaded before updater ran let _this = this; + /* eslint-disable-next-line jsdoc/require-jsdoc */ function askForRelog() { // TODO: Add support for asking in steam chat // Ask for all accounts once diff --git a/src/dataManager/helpers/misc.js b/src/dataManager/helpers/misc.js index 5b7b40b9..632b1dd6 100644 --- a/src/dataManager/helpers/misc.js +++ b/src/dataManager/helpers/misc.js @@ -4,7 +4,7 @@ * Created Date: 24.03.2023 18:58:55 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:49:45 + * Last Modified: 04.07.2023 19:58:05 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -48,7 +48,7 @@ DataManager.prototype.getLastCommentRequest = function(steamID64 = null) { /** * Decodes a JsonWebToken - https://stackoverflow.com/a/38552302 * @param {string} token The token to decode - * @returns JWT object on success, `null` on failure + * @returns {object|null} JWT object on success, `null` on failure */ DataManager.prototype.decodeJWT = function(token) { let payload = token.split(".")[1]; // Remove header and signature as we only care about the payload diff --git a/src/dataManager/helpers/repairFile.js b/src/dataManager/helpers/repairFile.js index dae3ae8d..e32ef9ba 100644 --- a/src/dataManager/helpers/repairFile.js +++ b/src/dataManager/helpers/repairFile.js @@ -4,7 +4,7 @@ * Created Date: 22.03.2023 12:35:01 * Author: 3urobeat * - * Last Modified: 04.07.2023 18:01:36 + * Last Modified: 04.07.2023 19:59:23 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -26,7 +26,7 @@ const DataManager = require("../dataManager.js"); * @param {string} filepath Absolute path of the file on the disk * @param {object} cacheentry Backup-Object of the file in cache.json * @param {string} onlinelink Link to the raw file in the GitHub repository - * @param {function} resolve Function to resolve the caller's promise + * @param {function(any): void} resolve Function to resolve the caller's promise */ DataManager.prototype._restoreBackup = function(name, filepath, cacheentry, onlinelink, resolve) { @@ -76,7 +76,7 @@ DataManager.prototype._restoreBackup = function(name, filepath, cacheentry, onli * Internal: Helper function to pull new file from GitHub * @param {string} name Name of the file * @param {string} filepath Full path, starting from project root with './' - * @param {function} resolve Your promise to resolve when file was pulled + * @param {function(any): void} resolve Your promise to resolve when file was pulled * @param {boolean} noRequire Optional: Set to true if resolve() should not be called with require(file) as param */ DataManager.prototype._pullNewFile = async function(name, filepath, resolve, noRequire) { diff --git a/src/pluginSystem/loadPlugins.js b/src/pluginSystem/loadPlugins.js index 69c8e5a3..1e73d6d4 100644 --- a/src/pluginSystem/loadPlugins.js +++ b/src/pluginSystem/loadPlugins.js @@ -4,7 +4,7 @@ * Created Date: 04.06.2023 15:37:17 * Author: DerDeathraven * - * Last Modified: 02.07.2023 19:12:35 + * Last Modified: 04.07.2023 19:02:01 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see . */ + const PluginSystem = require("./pluginSystem.js"); const PLUGIN_REGEX = /^steam-comment-bot-/; @@ -25,7 +26,12 @@ const PLUGIN_EVENTS = { steamGuardInput: "steamGuardInput", }; -// Attempt to load all plugins. If a critical check fails loading will be denied + +/** + * Attempt to load all plugins. If a critical check fails loading will be denied + * @param {string} pluginName Name of the plugin package + * @returns {{ pluginName: string, pluginInstance: object, pluginJson: object }} Creates a plugin instance and returns it along with more information + */ function loadPlugin(pluginName) { try { // Load plugin and pluginJson @@ -88,7 +94,7 @@ PluginSystem.prototype._loadPlugins = async function () { pluginInstance.load(); // Call the exposed event functions if they exist - Object.entries(PLUGIN_EVENTS).forEach(([eventName, event]) => { + Object.entries(PLUGIN_EVENTS).forEach(([eventName, event]) => { // eslint-disable-line no-unused-vars // eslint-disable-line this.controller.events.on(event, (...args) => pluginInstance[event]?.call(pluginInstance, ...args)); }); diff --git a/src/pluginSystem/pluginSystem.js b/src/pluginSystem/pluginSystem.js index d813dd42..46b64fd9 100644 --- a/src/pluginSystem/pluginSystem.js +++ b/src/pluginSystem/pluginSystem.js @@ -4,7 +4,7 @@ * Created Date: 19.03.2023 13:34:27 * Author: 3urobeat * - * Last Modified: 04.07.2023 18:03:48 + * Last Modified: 04.07.2023 20:05:42 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -21,11 +21,11 @@ const Bot = require("../../src/bot/bot.js"); // eslint-disable-line /** * @typedef Plugin Documentation of the Plugin structure for IntelliSense support * @type {object} - * @property {function} load Called on Plugin load - * @property {function} unload Called on Plugin unload - * @property {function} ready Controller ready event - * @property {function(Bot, Bot.EStatus, Bot.EStatus)} statusUpdate Controller statusUpdate event - * @property {function(Bot, function(string))} steamGuardInput Controller steamGuardInput event + * @property {function(): void} load Called on Plugin load + * @property {function(): void} unload Called on Plugin unload + * @property {function(): void} ready Controller ready event + * @property {function(Bot, Bot.EStatus, Bot.EStatus): void} statusUpdate Controller statusUpdate event + * @property {function(Bot, function(string): void): void} steamGuardInput Controller steamGuardInput event */ /** @@ -42,7 +42,7 @@ const PluginSystem = function (controller) { /** * References to all plugin objects - * @type {object.} + * @type {{[key: string]: Plugin}} */ this.pluginList = {}; diff --git a/src/sessions/helpers/tokenStorageHandler.js b/src/sessions/helpers/tokenStorageHandler.js index f9a3ba13..be79d2e4 100644 --- a/src/sessions/helpers/tokenStorageHandler.js +++ b/src/sessions/helpers/tokenStorageHandler.js @@ -4,7 +4,7 @@ * Created Date: 10.10.2022 12:53:20 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:49:45 + * Last Modified: 04.07.2023 20:06:35 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -20,7 +20,7 @@ const SessionHandler = require("../sessionHandler.js"); /** * Internal - Attempts to get a token for this account from tokens.db and checks if it's valid - * @param {function} [callback] Called with `refreshToken` (String) on success or `null` on failure + * @param {function(string|null): void} [callback] Called with `refreshToken` (String) on success or `null` on failure */ SessionHandler.prototype._getTokenFromStorage = function(callback) { diff --git a/src/sessions/sessionHandler.js b/src/sessions/sessionHandler.js index a7c9dcf3..a3908bd3 100644 --- a/src/sessions/sessionHandler.js +++ b/src/sessions/sessionHandler.js @@ -4,7 +4,7 @@ * Created Date: 09.10.2022 12:47:27 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:50:12 + * Last Modified: 04.07.2023 20:06:48 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -166,7 +166,7 @@ SessionHandler.prototype._handleCredentialsLoginError = function(err) {}; // esl /** * Internal - Attempts to get a token for this account from tokens.db and checks if it's valid - * @param {function} [callback] Called with `refreshToken` (String) on success or `null` on failure + * @param {function(string|null): void} [callback] Called with `refreshToken` (String) on success or `null` on failure */ SessionHandler.prototype._getTokenFromStorage = function(callback) {}; // eslint-disable-line diff --git a/src/starter.js b/src/starter.js index 0918214f..b2f37f73 100644 --- a/src/starter.js +++ b/src/starter.js @@ -4,7 +4,7 @@ * Created Date: 10.07.2021 10:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:45 + * Last Modified: 04.07.2023 20:10:00 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -44,7 +44,10 @@ const execArgs = [ "--max-old-space-size=2048", "--optimize-for-size" ]; /* -------- Now, provide functions for attaching/detaching event listeners to the parent and child process -------- */ -// Provide function to only once attach listeners to parent process +/** + * Provide function to only once attach listeners to parent process + * @param {function(): void} callback Called on completion + */ function attachParentListeners(callback) { let logafterrestart = []; @@ -150,7 +153,10 @@ function attachParentListeners(callback) { callback(); } -// Provide function to detach parent process event listeners + +/** + * Provide function to detach parent process event listeners + */ function detachParentListeners() { logger("info", "Detaching parent's event listeners...", false, true); @@ -161,7 +167,10 @@ function detachParentListeners() { if (parentExitEvent) process.removeListener("exit", parentExitEvent); } -// Provide function to attach listeners to make communicating with child possible + +/** + * Provide function to attach listeners to make communicating with child possible + */ function attachChildListeners() { forkedprocess.on("message", (msg) => { logger("debug", "Received message from child: " + msg); @@ -221,7 +230,7 @@ function attachChildListeners() { /** * Checks if the needed file exists and gets it if it doesn't * @param {string} file The file path (from project root) to check and get - * @param {function} logger Your current logger function + * @param {function(string, string): void} logger Your current logger function * @param {boolean} norequire If set to true the function will return the path instead of importing it * @param {boolean} force If set to true the function will skip checking if the file exists and overwrite it. * @returns {Promise.} Resolves when file was successfully loaded @@ -234,7 +243,9 @@ module.exports.checkAndGetFile = (file, logger, norequire = false, force = false return; } - // Function that will download a new file, test it and resolve/reject promise + /** + * Function that will download a new file, test it and resolve/reject promise + */ function getNewFile() { // Determine branch let branch = "master"; // Default to master diff --git a/src/updater/helpers/checkForUpdate.js b/src/updater/helpers/checkForUpdate.js index 2cf9b681..ca926a4b 100644 --- a/src/updater/helpers/checkForUpdate.js +++ b/src/updater/helpers/checkForUpdate.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:45 + * Last Modified: 04.07.2023 20:10:27 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -23,7 +23,7 @@ const https = require("https"); * @param {object} datafile The current `data.json` file from the DataManager * @param {string} branch Which branch you want to check. Defaults to the current branch set in `data.json` * @param {boolean} forceUpdate If true an update will be forced, even if disableAutoUpdate is true or the newest version is already installed - * @param {function} [callback] Called with `updateFound` (Boolean) and `data` (Object) on completion. `updatefound` will be false if the check should fail. `data` includes the full data.json file found online. + * @param {function(boolean, object): void} [callback] Called with `updateFound` (Boolean) and `data` (Object) on completion. `updatefound` will be false if the check should fail. `data` includes the full data.json file found online. */ module.exports.check = (datafile, branch, forceUpdate, callback) => { if (!branch) branch = datafile.branch; // Set current branch as default value diff --git a/src/updater/helpers/createBackup.js b/src/updater/helpers/createBackup.js index 080f2577..63619951 100644 --- a/src/updater/helpers/createBackup.js +++ b/src/updater/helpers/createBackup.js @@ -4,7 +4,7 @@ * Created Date: 26.02.2022 16:54:03 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 20:12:39 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -31,7 +31,12 @@ module.exports.run = () => { // Specify which files and folders we can ignore const dontCopy = [".git", ".github", "node_modules", "backup"]; - // This but slightly modified - Thanks: https://stackoverflow.com/a/26038979/12934162 + /** + * Copy everything in a folder including its subpaths - Thanks (modified): https://stackoverflow.com/a/26038979/12934162 + * @param {string} src From path + * @param {string} dest To path + * @param {boolean} firstCall Set to `true` on first call, will be set to `false` on recursive call + */ function copyFolderRecursiveSync(src, dest, firstCall) { let files = []; diff --git a/src/updater/helpers/customUpdateRules.js b/src/updater/helpers/customUpdateRules.js index f7921f22..549fa797 100644 --- a/src/updater/helpers/customUpdateRules.js +++ b/src/updater/helpers/customUpdateRules.js @@ -4,7 +4,7 @@ * Created Date: 22.02.2022 17:39:21 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:50:12 + * Last Modified: 04.07.2023 20:13:24 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -24,7 +24,7 @@ const fs = require("fs"); * @param {object} oldconfig The old config from before the update * @param {object} oldadvancedconfig The old advancedconfig from before the update * @param {object} olddatafile The old datafile from before the update - * @param {function} callback Legacy param, is unused + * @param {function(): void} [callback] Legacy param, is unused * @returns {Promise.} Resolves when we can proceed */ module.exports.customUpdateRules = (compatibilityfeaturedone, oldconfig, oldadvancedconfig, olddatafile, callback) => { // eslint-disable-line diff --git a/src/updater/helpers/prepareUpdate.js b/src/updater/helpers/prepareUpdate.js index a8e5858d..f6b46344 100644 --- a/src/updater/helpers/prepareUpdate.js +++ b/src/updater/helpers/prepareUpdate.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:50:12 + * Last Modified: 04.07.2023 20:16:06 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -21,7 +21,7 @@ const Controller = require("../../controller/controller.js"); // eslint-disable- /** * Wait for active requests and log off all bot accounts * @param {Controller} controller Reference to the controller object - * @param {function(Object, string)} respondModule If defined, this function will be called with the result of the check. This allows to integrate checking for updates into commands or plugins. Passes resInfo and txt as parameters. + * @param {function(object, string): void} respondModule If defined, this function will be called with the result of the check. This allows to integrate checking for updates into commands or plugins. Passes resInfo and txt as parameters. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). * @returns {Promise.} Resolves when we can proceed */ @@ -34,7 +34,7 @@ module.exports.run = (controller, respondModule, resInfo) => { logger("info", "Bot is logged in. Checking for active requests...", false, true, logger.animation("loading")); - /* eslint-disable no-inner-declarations */ + /* eslint-disable no-inner-declarations, jsdoc/require-jsdoc */ function initiateUpdate() { // Make initiating the update a function to simplify the activerequest check below controller.info.relogAfterDisconnect = false; // Prevents disconnect event (which will be called by logOff) to relog accounts @@ -76,6 +76,7 @@ module.exports.run = (controller, respondModule, resInfo) => { } }); } + /* eslint-enable no-inner-declarations, jsdoc/require-jsdoc */ // Check for active request process. If obj not empty then first sort out all invalid/expired entries. diff --git a/src/updater/helpers/restoreBackup.js b/src/updater/helpers/restoreBackup.js index 6c9a1d7c..4f8d9803 100644 --- a/src/updater/helpers/restoreBackup.js +++ b/src/updater/helpers/restoreBackup.js @@ -4,7 +4,7 @@ * Created Date: 26.02.2022 20:16:44 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 20:16:28 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -32,7 +32,12 @@ module.exports.run = () => { // Specify which files and folders we can ignore const dontCopy = ["backup"]; - // This but slightly modified - Thanks: https://stackoverflow.com/a/26038979/12934162 + /** + * Copy everything in a folder including its subpaths - Thanks (modified): https://stackoverflow.com/a/26038979/12934162 + * @param {string} src From path + * @param {string} dest To path + * @param {boolean} firstCall Set to `true` on first call, will be set to `false` on recursive call + */ function copyFolderRecursiveSync(src, dest, firstCall) { // eslint-disable-line no-inner-declarations let files = []; diff --git a/src/updater/updater.js b/src/updater/updater.js index 650fc90f..6839ae38 100644 --- a/src/updater/updater.js +++ b/src/updater/updater.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 17:55:45 + * Last Modified: 04.07.2023 20:17:07 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -48,14 +48,16 @@ module.exports = Updater; /** * Checks for any available update and installs it. * @param {boolean} forceUpdate If true an update will be forced, even if disableAutoUpdate is true or the newest version is already installed - * @param {function(Object, string)} respondModule If defined, this function will be called with the result of the check. This allows to integrate checking for updates into commands or plugins. Passes resInfo and txt as parameters. + * @param {function(object, string): void} respondModule If defined, this function will be called with the result of the check. This allows to integrate checking for updates into commands or plugins. Passes resInfo and txt as parameters. * @param {object} resInfo Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). * @returns {Promise.} Promise that will be resolved with false when no update was found or with true when the update check or download was completed. Expect a restart when true was returned. */ Updater.prototype.run = function(forceUpdate, respondModule, resInfo) { let _this = this; - // Shorthander to abort when a part of the updater is missing and couldn't be repaired + /** + * Shorthander to abort when a part of the updater is missing and couldn't be repaired + */ function stopOnFatalError() { logger("error", "Fatal Error: Failed to load updater! Please reinstall the bot manually. Aborting..."); _this.stop(); @@ -103,7 +105,9 @@ Updater.prototype.run = function(forceUpdate, respondModule, resInfo) { } - // Make initiating the update a function to simplify the permission check below + /** + * Make initiating the update a function to simplify the permission check below + */ async function initiateUpdate() { _this.controller.info.activeLogin = true; // Block new requests by setting active login to true diff --git a/start.js b/start.js index 7d0dd98c..aed97212 100644 --- a/start.js +++ b/start.js @@ -4,7 +4,7 @@ * Created Date: 15.01.2020 10:38:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 04.07.2023 19:46:02 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -21,6 +21,11 @@ // It is designed to be modular and to start and restart the whole application. // To be able to change the file it is supposed to start on the fly it pulls the necessary file path from the data.json file + +/** + * Attempts to load the data.json file. + * @returns {object|{ filetostart: string, filetostarturl: string }} Returns an data.json object on success or an object with default values for `filetostart` and `filetostarturl` on failure. + */ function getExtdata() { try { // Just try to require, if it should fail then the actual restoring process will be handled later return require("./src/data/data.json"); diff --git a/types/types.d.ts b/types/types.d.ts index 5522e1af..53cceab7 100644 --- a/types/types.d.ts +++ b/types/types.d.ts @@ -159,13 +159,13 @@ declare class CommandHandler { description: string; ownersOnly: boolean; run: (...params: any[]) => any; - }): any; + }): boolean; /** * The name of the command to unregister during runtime * @param commandName - Name of the command to unregister - * @returns true if the command was successfully unregistered, false otherwise + * @returns `true` if the command was successfully unregistered, `false` otherwise */ - unregisterCommand(commandName: string): any; + unregisterCommand(commandName: string): boolean; /** * Finds a loaded command by name and runs it * @param name - The name of the command @@ -176,7 +176,7 @@ declare class CommandHandler { * @param resInfo - Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). Please also include a "cmdprefix" key & value pair if your command handler uses a prefix other than "!". * @returns `true` if command was found, `false` if not */ - runCommand(name: string, args: any[], steamID64: number, respondModule: (...params: any[]) => any, context: any, resInfo: any): any; + runCommand(name: string, args: any[], steamID64: number, respondModule: (...params: any[]) => any, context: any, resInfo: any): boolean; /** * Reloads all core commands. Does NOT reload commands registered at runtime. Please consider reloading the pluginSystem as well. */ @@ -187,7 +187,7 @@ declare class CommandHandler { * Internal: Do the actual commenting, activeRequests entry with all relevant information was processed by the comment command function above. * @param commandHandler - The commandHandler object * @param resInfo - Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). - * @param respond - Shortened respondModule call + * @param respond - The shortened respondModule call * @param postComment - The correct postComment function for this idType. Context from the correct bot account is being applied later. * @param commentArgs - All arguments this postComment function needs, without callback. It will be applied and a callback added as last param. Include a key called "quote" to dynamically replace it with a random quote. * @param receiverSteamID64 - steamID64 of the profile to receive the comments @@ -200,7 +200,8 @@ declare function comment(commandHandler: CommandHandler, resInfo: any, respond: * @param args - The command arguments * @param requesterSteamID64 - The steamID64 of the requesting user * @param resInfo - Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). - * @param respond - The function to send messages to the requesting user + * @param respond - The shortened respondModule call + * @returns Resolves promise with object containing all relevant data when done */ declare function getCommentArgs(commandHandler: CommandHandler, args: any[], requesterSteamID64: string, resInfo: any, respond: (...params: any[]) => any): Promise<{ maxRequestAmount: number; commentcmdUsage: string; numberOfComments: number; profileID: string; idType: string; quotesArr: string[]; }>; @@ -221,7 +222,7 @@ declare function getAvailableBotsForCommenting(commandHandler: CommandHandler, n * @param amount - Amount of favs requested or "all" to get the max available amount * @param id - The sharedfile id to favorize * @param favType - Either "favorite" or "unfavorite", depending on which request this is - * @returns Promise with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now + * @returns Resolves with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now */ declare function getAvailableBotsForFavorizing(commandHandler: CommandHandler, amount: number | "all", id: string, favType: string): Promise<{ amount: number; availableAccounts: string[]; whenAvailable: number; whenAvailableStr: string; }>; @@ -231,7 +232,7 @@ declare function getAvailableBotsForFavorizing(commandHandler: CommandHandler, a * @param args - The command arguments * @param cmd - Either "upvote", "downvote", "favorite" or "unfavorite", depending on which command is calling this function * @param resInfo - Object containing additional information your respondModule might need to process the response (for example the userID who executed the command). - * @param respond - The function to send messages to the requesting user + * @param respond - The shortened respondModule call * @returns If the user provided a specific amount, amount will be a number. If user provided "all" or "max", it will be returned as an unmodified string for getVoteBots.js to handle */ declare function getSharedfileArgs(commandHandler: CommandHandler, args: any[], cmd: string, resInfo: any, respond: (...params: any[]) => any): Promise<{ amount: number | string; id: string; }>; @@ -242,7 +243,7 @@ declare function getSharedfileArgs(commandHandler: CommandHandler, args: any[], * @param amount - Amount of votes requested or "all" to get the max available amount * @param id - The sharedfile id to vote on * @param voteType - "upvote" or "downvote", depending on which request this is - * @returns Promise with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now + * @returns Resolves with obj: `availableAccounts` contains all account names from bot object, `whenAvailable` is a timestamp representing how long to wait until accsNeeded accounts will be available and `whenAvailableStr` is formatted human-readable as time from now */ declare function getAvailableBotsForVoting(commandHandler: CommandHandler, amount: number | "all", id: string, voteType: string): Promise<{ amount: number; availableAccounts: string[]; whenAvailable: number; whenAvailableStr: string; }>; @@ -285,9 +286,9 @@ declare function failedCommentsObjToString(obj: any): string; * @param loop - Object returned by misc.js syncLoop() helper * @param bot - Bot object of the account making this request * @param id - ID of the sharedfile that receives the votes - * @returns true if iteration should continue, false if iteration should be skipped using return + * @returns `true` if iteration should continue, `false` if iteration should be skipped using return */ -declare function handleVoteIterationSkip(commandHandler: CommandHandler, loop: any, bot: Bot, id: string): any; +declare function handleVoteIterationSkip(commandHandler: CommandHandler, loop: any, bot: Bot, id: string): boolean; /** * Checks if the following favorite process iteration should be skipped @@ -295,9 +296,9 @@ declare function handleVoteIterationSkip(commandHandler: CommandHandler, loop: a * @param loop - Object returned by misc.js syncLoop() helper * @param bot - Bot object of the account making this request * @param id - ID of the sharedfile that receives the votes - * @returns true if iteration should continue, false if iteration should be skipped using return + * @returns `true` if iteration should continue, `false` if iteration should be skipped using return */ -declare function handleFavoriteIterationSkip(commandHandler: CommandHandler, loop: any, bot: Bot, id: string): any; +declare function handleFavoriteIterationSkip(commandHandler: CommandHandler, loop: any, bot: Bot, id: string): boolean; /** * Logs vote errors @@ -347,9 +348,7 @@ declare class Controller { /** * Stores references to all bot account objects mapped to their accountName */ - bots: { - [key: string]: Bot; - }; + bots: any; /** * The main bot account */ @@ -384,7 +383,7 @@ declare class Controller { /** * Runs internal statusUpdate event code and emits statusUpdate event for plugins * @param bot - Bot instance - * @param newStatus - The new status + * @param newStatus - The new status of this bot */ _statusUpdateEvent(bot: Bot, newStatus: Bot.EStatus): void; /** @@ -401,9 +400,8 @@ declare class Controller { /** * Checks the remaining space on the friendlist of a bot account, sends a warning message if it is less than 10 and force unfriends oldest lastcomment db user to always keep room for 1 friend. * @param bot - Bot object of the account to check - * @param [callback] - Called with `remaining` (Number) on completion */ - friendListCapacityCheck(bot: Bot, callback?: (...params: any[]) => any): void; + friendListCapacityCheck(bot: Bot, callback: any): void; /** * Check for friends who haven't requested comments in config.unfriendtime days and unfriend them */ @@ -424,22 +422,24 @@ declare class Controller { * Handles converting URLs to steamIDs, determining their type if unknown and checking if it matches your expectation * @param str - The profileID argument provided by the user * @param expectedIdType - The type of SteamID expected ("profile", "group" or "sharedfile") or `null` if type should be assumed. - * @param [callback] - Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion */ - handleSteamIdResolving(str: string, expectedIdType: string, callback?: (...params: any[]) => any): void; + handleSteamIdResolving(str: string, expectedIdType: string, callback: any): void; /** * Logs text to the terminal and appends it to the output.txt file. * @param type - String that determines the type of the log message. Can be info, warn, error, debug or an empty string to not use the field. * @param str - The text to log into the terminal * @param nodate - Setting to true will hide date and time in the message * @param remove - Setting to true will remove this message with the next one + * @param animation - Array containing animation frames as elements * @param printNow - Ignores the readyafterlogs check and force prints the message now + * @param cutToWidth - Cuts the string to the width of the terminal */ - logger(type: string, str: string, nodate: boolean, remove: boolean, printNow: boolean): void; + logger(type: string, str: string, nodate: boolean, remove: boolean, animation: string[], printNow: boolean, cutToWidth: boolean): void; /** * Internal: Call this function after loading advancedconfig.json to set previously inaccessible options + * @param advancedconfig - The advancedconfig object imported by the DataManager */ - _loggerOptionsUpdateAfterConfigLoad(): void; + _loggerOptionsUpdateAfterConfigLoad(advancedconfig: any): void; /** * Internal: Logs all held back messages from logAfterReady array */ @@ -451,7 +451,7 @@ declare class Controller { /** * Runs internal statusUpdate event code and emits statusUpdate event for plugins * @param bot - Bot instance - * @param newStatus - The new status + * @param newStatus - The new status of this bot */ _statusUpdateEvent(bot: Bot, newStatus: Bot.EStatus): void; /** @@ -468,9 +468,8 @@ declare class Controller { /** * Checks the remaining space on the friendlist of a bot account, sends a warning message if it is less than 10 and force unfriends oldest lastcomment db user to always keep room for 1 friend. * @param bot - Bot object of the account to check - * @param [callback] - Called with `remaining` (Number) on completion */ - friendListCapacityCheck(bot: Bot, callback?: (...params: any[]) => any): void; + friendListCapacityCheck(bot: Bot, callback: any): void; /** * Check for friends who haven't requested comments in config.unfriendtime days and unfriend them */ @@ -491,22 +490,24 @@ declare class Controller { * Handles converting URLs to steamIDs, determining their type if unknown and checking if it matches your expectation * @param str - The profileID argument provided by the user * @param expectedIdType - The type of SteamID expected ("profile", "group" or "sharedfile") or `null` if type should be assumed. - * @param [callback] - Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion */ - handleSteamIdResolving(str: string, expectedIdType: string, callback?: (...params: any[]) => any): void; + handleSteamIdResolving(str: string, expectedIdType: string, callback: any): void; /** * Logs text to the terminal and appends it to the output.txt file. * @param type - String that determines the type of the log message. Can be info, warn, error, debug or an empty string to not use the field. * @param str - The text to log into the terminal * @param nodate - Setting to true will hide date and time in the message * @param remove - Setting to true will remove this message with the next one + * @param animation - Array containing animation frames as elements * @param printNow - Ignores the readyafterlogs check and force prints the message now + * @param cutToWidth - Cuts the string to the width of the terminal */ - logger(type: string, str: string, nodate: boolean, remove: boolean, printNow: boolean): void; + logger(type: string, str: string, nodate: boolean, remove: boolean, animation: string[], printNow: boolean, cutToWidth: boolean): void; /** * Internal: Call this function after loading advancedconfig.json to set previously inaccessible options + * @param advancedconfig - The advancedconfig object imported by the DataManager */ - _loggerOptionsUpdateAfterConfigLoad(): void; + _loggerOptionsUpdateAfterConfigLoad(advancedconfig: any): void; /** * Internal: Logs all held back messages from logAfterReady array */ @@ -521,8 +522,9 @@ declare class Controller { /** * Process data that should be kept over restarts + * @param data - Stringified data received by previous process */ -declare function restartdata(): void; +declare function restartdata(data: string): void; /** * Implementation of a synchronous for loop in JS (Used as reference: https://whitfin.io/handling-synchronous-asynchronous-loops-javascriptnode-js/) @@ -541,10 +543,11 @@ declare function syncLoop(iterations: number, func: (...params: any[]) => any, e declare function round(value: number, decimals: number): number; /** - * Converts a timestamp to a human-readable until from now format. Does not care about past/future. + * Converts a timestamp to a human-readable "until from now" format. Does not care about past/future. + * @param timestamp - UNIX timestamp to convert * @returns "x seconds/minutes/hours/days" */ -declare function timeToString(): string; +declare function timeToString(timestamp: number): string; /** * Pings an URL to check if the service and this internet connection is working @@ -568,22 +571,19 @@ declare function cutStringsIntelligently(txt: string, limit: number, cutChars: a /** * Attempts to reinstall all modules * @param logger - The currently used logger function (real or fake, the caller decides) - * @param [callback] - Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ -declare function reinstallAll(logger: (...params: any[]) => any, callback?: (...params: any[]) => any): void; +declare function reinstallAll(logger: (...params: any[]) => any, callback: any): void; /** * Updates all installed packages to versions listed in package.json from the project root directory. - * @param [callback] - Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ -declare function update(callback?: (...params: any[]) => any): void; +declare function update(callback: any): void; /** * Updates all installed packages to versions listed in package.json * @param path - Custom path to read package.json from and install packages to - * @param [callback] - Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ -declare function updateFromPath(path: string, callback?: (...params: any[]) => any): void; +declare function updateFromPath(path: string, callback: any): void; /** * Constructor - The dataManager system imports, checks, handles errors and provides a file updating service for all configuration files @@ -613,22 +613,16 @@ declare class DataManager { /** * Stores all `config.json` settings. */ - config: { - [key: string]: any; - }; + config: any; /** * Stores all `advancedconfig.json` settings. */ - advancedconfig: { - [key: string]: any; - }; + advancedconfig: any; /** * Stores all language strings used for responding to a user. * All default strings have already been replaced with corresponding matches from `customlang.json`. */ - lang: { - [key: string]: string; - }; + lang: any; /** * Stores all quotes used for commenting provided via the `quotes.txt` file. */ @@ -644,9 +638,7 @@ declare class DataManager { /** * Stores the login information for every bot account provided via the `logininfo.json` or `accounts.txt` files. */ - logininfo: { - [key: string]: { accountName: string; password: string; sharedSecret: string; steamGuardCode: null; machineName: string; deviceFriendlyName: string; }; - }; + logininfo: any; /** * Database which stores the timestamp of the last request of every user. This is used to enforce `config.unfriendTime`. * Document structure: { id: String, time: Number } @@ -714,7 +706,7 @@ declare class DataManager { * @param token - The token to decode * @returns JWT object on success, `null` on failure */ - decodeJWT(token: string): any; + decodeJWT(token: string): any | null; /** * Refreshes Backups in cache.json with new data */ @@ -730,8 +722,12 @@ declare class DataManager { _restoreBackup(name: string, filepath: string, cacheentry: any, onlinelink: string, resolve: (...params: any[]) => any): void; /** * Internal: Helper function to pull new file from GitHub + * @param name - Name of the file + * @param filepath - Full path, starting from project root with './' + * @param resolve - Your promise to resolve when file was pulled + * @param noRequire - Optional: Set to true if resolve() should not be called with require(file) as param */ - _pullNewFile(): void; + _pullNewFile(name: string, filepath: string, resolve: (...params: any[]) => any, noRequire: boolean): void; /** * Converts owners and groups imported from config.json to steam ids and updates cachefile. (Call this after dataImport and before dataCheck) */ @@ -774,7 +770,7 @@ declare class DataManager { * @param token - The token to decode * @returns JWT object on success, `null` on failure */ - decodeJWT(token: string): any; + decodeJWT(token: string): any | null; /** * Refreshes Backups in cache.json with new data */ @@ -790,8 +786,12 @@ declare class DataManager { _restoreBackup(name: string, filepath: string, cacheentry: any, onlinelink: string, resolve: (...params: any[]) => any): void; /** * Internal: Helper function to pull new file from GitHub + * @param name - Name of the file + * @param filepath - Full path, starting from project root with './' + * @param resolve - Your promise to resolve when file was pulled + * @param noRequire - Optional: Set to true if resolve() should not be called with require(file) as param */ - _pullNewFile(): void; + _pullNewFile(name: string, filepath: string, resolve: (...params: any[]) => any, noRequire: boolean): void; } /** @@ -834,6 +834,13 @@ declare class CSteamSharedFile { unsubscribe(callback: (...params: any[]) => any): void; } +/** + * Attempt to load all plugins. If a critical check fails loading will be denied + * @param pluginName - Name of the plugin package + * @returns Creates a plugin instance and returns it along with more information + */ +declare function loadPlugin(pluginName: string): any; + /** * @property load - Called on Plugin load * @property unload - Called on Plugin unload @@ -912,9 +919,7 @@ declare class PluginSystem { /** * References to all plugin objects */ - pluginList: { - [key: string]: Plugin; - }; + pluginList: any; commandHandler: CommandHandler; /** * Reloads all plugins and calls ready event after ~2.5 seconds. @@ -1011,9 +1016,8 @@ declare class SessionHandler { _handleCredentialsLoginError(err: any): void; /** * Internal - Attempts to get a token for this account from tokens.db and checks if it's valid - * @param [callback] - Called with `refreshToken` (String) on success or `null` on failure */ - _getTokenFromStorage(callback?: (...params: any[]) => any): void; + _getTokenFromStorage(callback: any): void; /** * Internal - Saves a new token for this account to tokens.db * @param token - The refreshToken to store @@ -1062,9 +1066,8 @@ declare class SessionHandler { _handleCredentialsLoginError(err: any): void; /** * Internal - Attempts to get a token for this account from tokens.db and checks if it's valid - * @param [callback] - Called with `refreshToken` (String) on success or `null` on failure */ - _getTokenFromStorage(callback?: (...params: any[]) => any): void; + _getTokenFromStorage(callback: any): void; /** * Internal - Saves a new token for this account to tokens.db * @param token - The refreshToken to store @@ -1076,6 +1079,22 @@ declare class SessionHandler { invalidateTokenInStorage(): void; } +/** + * Provide function to only once attach listeners to parent process + * @param callback - Called on completion + */ +declare function attachParentListeners(callback: (...params: any[]) => any): void; + +/** + * Provide function to detach parent process event listeners + */ +declare function detachParentListeners(): void; + +/** + * Provide function to attach listeners to make communicating with child possible + */ +declare function attachChildListeners(): void; + /** * Checks if the needed file exists and gets it if it doesn't * @param file - The file path (from project root) to check and get @@ -1124,10 +1143,10 @@ declare function run(): void; * @param oldconfig - The old config from before the update * @param oldadvancedconfig - The old advancedconfig from before the update * @param olddatafile - The old datafile from before the update - * @param callback - Legacy param, is unused + * @param [callback] - Legacy param, is unused * @returns Resolves when we can proceed */ -declare function customUpdateRules(compatibilityfeaturedone: any, oldconfig: any, oldadvancedconfig: any, olddatafile: any, callback: (...params: any[]) => any): Promise; +declare function customUpdateRules(compatibilityfeaturedone: any, oldconfig: any, oldadvancedconfig: any, olddatafile: any, callback?: (...params: any[]) => any): Promise; /** * Downloads all files from the repository and installs them From 7c5a02afbfb832006d59d6dae209a32c61e9dc0f Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Tue, 4 Jul 2023 23:06:46 +0200 Subject: [PATCH 28/43] Add dataExport.js with functions to write all data files to disk --- src/dataManager/dataExport.js | 184 +++++++++++++++++++++++++++++++++ src/dataManager/dataManager.js | 46 ++++++++- types/types.d.ts | 68 +++++++++++- 3 files changed, 293 insertions(+), 5 deletions(-) create mode 100644 src/dataManager/dataExport.js diff --git a/src/dataManager/dataExport.js b/src/dataManager/dataExport.js new file mode 100644 index 00000000..91cb8b80 --- /dev/null +++ b/src/dataManager/dataExport.js @@ -0,0 +1,184 @@ +/* + * File: dataExport.js + * Project: steam-comment-service-bot + * Created Date: 04.07.2023 21:29:42 + * Author: 3urobeat + * + * Last Modified: 04.07.2023 23:04:19 + * Modified By: 3urobeat + * + * Copyright (c) 2023 3urobeat + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with this program. If not, see . + */ + + +const fs = require("fs"); + +const DataManager = require("./dataManager.js"); + + +/** + * Writes (all) files imported by DataManager back to the disk + */ +DataManager.prototype.writeAllFilesToDisk = function() { + this.writeCachefileToDisk(); + this.writeDatafileToDisk(); + this.writeConfigToDisk(); + this.writeAdvancedconfigToDisk(); + this.writeLogininfoToDisk(); + this.writeProxiesToDisk(); + this.writeQuotesToDisk(); +}; + + +/** + * Writes cachefile to cache.json on disk + */ +DataManager.prototype.writeCachefileToDisk = function() { + logger("debug", "DataManager dataExport: Writing to cache.json..."); + + fs.writeFile("./src/data/cache.json", JSON.stringify(this.cachefile, null, 4), (err) => { + if (err) logger("error", "DataManager: Error writing cachefile to cache.json: " + err); + }); +}; + + +/** + * Writes datafile to data.json on disk + */ +DataManager.prototype.writeDatafileToDisk = function() { + logger("debug", "DataManager dataExport: Writing to data.json..."); + + fs.writeFile("./src/data/data.json", JSON.stringify(this.datafile, null, 4), (err) => { + if (err) logger("error", "DataManager: Error writing datafile to data.json: " + err); + }); +}; + + +/** + * Writes config to config.json on disk + */ +DataManager.prototype.writeConfigToDisk = function() { + logger("debug", "DataManager dataExport: Writing to config.json..."); + + // Get arrays on one line + let stringifiedconfig = JSON.stringify(this.config, function(k, v) { // Credit: https://stackoverflow.com/a/46217335/12934162 + if (v instanceof Array) return JSON.stringify(v); + return v; + }, 4) + .replace(/"\[/g, "[") + .replace(/\]"/g, "]") + .replace(/\\"/g, '"') + .replace(/""/g, '""'); + + fs.writeFile(srcdir + "/../config.json", stringifiedconfig, (err) => { + if (err) logger("error", "DataManager: Error writing config to config.json: " + err); + }); +}; + + +/** + * Writes advancedconfig to advancedconfig.json on disk + */ +DataManager.prototype.writeAdvancedconfigToDisk = function() { + logger("debug", "DataManager dataExport: Writing to advancedconfig.json..."); + + // Get arrays on one line + let stringifiedadvancedconfig = JSON.stringify(this.advancedconfig, function(k, v) { // Credit: https://stackoverflow.com/a/46217335/12934162 + if (v instanceof Array) return JSON.stringify(v); + return v; + }, 4) + .replace(/"\[/g, "[") + .replace(/\]"/g, "]") + .replace(/\\"/g, '"') + .replace(/""/g, '""'); + + fs.writeFile(srcdir + "/../advancedconfig.json", stringifiedadvancedconfig, (err) => { + if (err) logger("error", "DataManager: Error writing advancedconfig to advancedconfig.json: " + err); + }); +}; + + +/** + * Writes logininfo to logininfo.json and accounts.txt on disk, depending on which of the files exist + */ +DataManager.prototype.writeLogininfoToDisk = function() { + + if (fs.existsSync(srcdir + "/../logininfo.json")) { + logger("debug", "DataManager dataExport: Writing to logininfo.json..."); + + let logininfojson = {}; + + // Re-Construct logininfo object. Iterate over bots instead of logininfo to retain a changed bots hierarchy + for (let e of this.controller.getBots("*")) { + logininfojson[`bot${e.index}`] = [ e.loginData.logOnOptions.accountName, e.loginData.logOnOptions.password, e.loginData.logOnOptions.sharedSecret ]; + } + + // Get arrays on one line + let stringifiedlogininfo = JSON.stringify(logininfojson, function(k, v) { // Credit: https://stackoverflow.com/a/46217335/12934162 + if (v instanceof Array) return JSON.stringify(v); + return v; + }, 4) + .replace(/"\[/g, "[") + .replace(/\]"/g, "]") + .replace(/\\"/g, '"') + .replace(/""/g, '""'); + + fs.writeFile(srcdir + "/../logininfo.json", stringifiedlogininfo, (err) => { + if (err) logger("error", "DataManager: Error writing logininfo to logininfo.json: " + err); + }); + } + + if (fs.existsSync(srcdir + "/../accounts.txt")) { + logger("debug", "DataManager dataExport: Writing to accounts.txt..."); + + let accountstxt = [ "//Comment: This file is used to provide your bot accounts in the form of username:password. Read the instructions here: https://github.com/3urobeat/steam-comment-service-bot#accounts" ]; // Re-add comment + + // Re-construct accounts.txt string. Iterate over bots instead of logininfo to retain a changed bots hierarchy + for (let e of this.controller.getBots("*")) { + if (e.loginData.logOnOptions.sharedSecret) accountstxt.push(`${e.loginData.logOnOptions.accountName}:${e.loginData.logOnOptions.password}:${e.loginData.logOnOptions.sharedSecret}`); + else accountstxt.push(`${e.loginData.logOnOptions.accountName}:${e.loginData.logOnOptions.password}`); + } + + fs.writeFile(srcdir + "/../accounts.txt", accountstxt.join("\n"), (err) => { + if (err) logger("error", "DataManager: Error writing accounts to accounts.txt: " + err); + }); + } + +}; + + +/** + * Writes proxies to proxies.txt on disk + */ +DataManager.prototype.writeProxiesToDisk = function() { + logger("debug", "DataManager dataExport: Writing to proxies.txt..."); + + let comment = "//Comment: This file is used to provide proxies to spread your accounts over multiple IPs. Read the instructions here: https://github.com/3urobeat/steam-comment-service-bot/wiki/Adding-proxies"; + + fs.writeFile(srcdir + "/../proxies.txt", comment + this.proxies.join("\n"), (err) => { + if (err) logger("error", "DataManager: Error writing proxies to proxies.txt: " + err); + }); +}; + + +/** + * Writes quotes to quotes.txt on disk + */ +DataManager.prototype.writeQuotesToDisk = function() { + logger("debug", "DataManager dataExport: Writing to quotes.txt..."); + let quotesArr = []; + + // Replace every \n with \\n so that writeFile won't parse them to actual newlines + this.quotes.forEach(e => quotesArr.push(e.replace(/\n/g, "\\n"))); + + fs.writeFile(srcdir + "/../quotes.txt", quotesArr.join("\n"), (err) => { + if (err) logger("error", "DataManager: Error writing quotes to quotes.txt: " + err); + }); +}; + + +// No function to write language \ No newline at end of file diff --git a/src/dataManager/dataManager.js b/src/dataManager/dataManager.js index 0a8b7c3d..a9125d4e 100644 --- a/src/dataManager/dataManager.js +++ b/src/dataManager/dataManager.js @@ -4,7 +4,7 @@ * Created Date: 21.03.2023 22:34:51 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:59:31 + * Last Modified: 04.07.2023 22:26:01 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -129,9 +129,44 @@ const DataManager = function (controller) { DataManager.prototype.checkData = function () {}; /** - * Converts owners and groups imported from config.json to steam ids and updates cachefile. (Call this after dataImport and before dataCheck) + * Writes (all) files imported by DataManager back to the disk + */ +DataManager.prototype.writeAllFilesToDisk = function() {}; + +/** + * Writes cachefile to cache.json on disk + */ +DataManager.prototype.writeCachefileToDisk = function() {}; + +/** + * Writes datafile to data.json on disk + */ +DataManager.prototype.writeDatafileToDisk = function() {}; + +/** + * Writes config to config.json on disk + */ +DataManager.prototype.writeConfigToDisk = function() {}; + +/** + * Writes advancedconfig to advancedconfig.json on disk */ -DataManager.prototype.processData = async function () {}; +DataManager.prototype.writeAdvancedconfigToDisk = function() {}; + +/** + * Writes logininfo to logininfo.json and accounts.txt on disk, depending on which of the files exist + */ +DataManager.prototype.writeLogininfoToDisk = function() {}; + +/** + * Writes proxies to proxies.txt on disk + */ +DataManager.prototype.writeProxiesToDisk = function() {}; + +/** + * Writes quotes to quotes.txt on disk + */ +DataManager.prototype.writeQuotesToDisk = function() {}; /** * Internal: Loads all config & data files from disk and handles potential errors @@ -139,6 +174,11 @@ DataManager.prototype.processData = async function () {}; */ DataManager.prototype._importFromDisk = async function () {}; +/** + * Converts owners and groups imported from config.json to steam ids and updates cachefile. (Call this after dataImport and before dataCheck) + */ +DataManager.prototype.processData = async function() {}; + /** * Gets a random quote * @param {Array} quotesArr Optional: Custom array of quotes to choose from. If not provided the default quotes set which was imported from the disk will be used. diff --git a/types/types.d.ts b/types/types.d.ts index 53cceab7..c52c2ecb 100644 --- a/types/types.d.ts +++ b/types/types.d.ts @@ -596,6 +596,38 @@ declare class DataManager { * @returns Resolves promise when all checks have finished. If promise is rejected you should terminate the application or reset the changes. Reject is called with a String specifying the failed check. */ checkData(): Promise; + /** + * Writes (all) files imported by DataManager back to the disk + */ + writeAllFilesToDisk(): void; + /** + * Writes cachefile to cache.json on disk + */ + writeCachefileToDisk(): void; + /** + * Writes datafile to data.json on disk + */ + writeDatafileToDisk(): void; + /** + * Writes config to config.json on disk + */ + writeConfigToDisk(): void; + /** + * Writes advancedconfig to advancedconfig.json on disk + */ + writeAdvancedconfigToDisk(): void; + /** + * Writes logininfo to logininfo.json and accounts.txt on disk, depending on which of the files exist + */ + writeLogininfoToDisk(): void; + /** + * Writes proxies to proxies.txt on disk + */ + writeProxiesToDisk(): void; + /** + * Writes quotes to quotes.txt on disk + */ + writeQuotesToDisk(): void; /** * Internal: Loads all config & data files from disk and handles potential errors * @returns Resolves promise when all files have been loaded successfully. The function will log an error and terminate the application should a fatal error occur. @@ -660,14 +692,46 @@ declare class DataManager { */ checkData(): Promise; /** - * Converts owners and groups imported from config.json to steam ids and updates cachefile. (Call this after dataImport and before dataCheck) + * Writes (all) files imported by DataManager back to the disk */ - processData(): void; + writeAllFilesToDisk(): void; + /** + * Writes cachefile to cache.json on disk + */ + writeCachefileToDisk(): void; + /** + * Writes datafile to data.json on disk + */ + writeDatafileToDisk(): void; + /** + * Writes config to config.json on disk + */ + writeConfigToDisk(): void; + /** + * Writes advancedconfig to advancedconfig.json on disk + */ + writeAdvancedconfigToDisk(): void; + /** + * Writes logininfo to logininfo.json and accounts.txt on disk, depending on which of the files exist + */ + writeLogininfoToDisk(): void; + /** + * Writes proxies to proxies.txt on disk + */ + writeProxiesToDisk(): void; + /** + * Writes quotes to quotes.txt on disk + */ + writeQuotesToDisk(): void; /** * Internal: Loads all config & data files from disk and handles potential errors * @returns Resolves promise when all files have been loaded successfully. The function will log an error and terminate the application should a fatal error occur. */ _importFromDisk(): Promise; + /** + * Converts owners and groups imported from config.json to steam ids and updates cachefile. (Call this after dataImport and before dataCheck) + */ + processData(): void; /** * Gets a random quote * @param quotesArr - Optional: Custom array of quotes to choose from. If not provided the default quotes set which was imported from the disk will be used. From e249832ea4ad1ab879a1461594d1e4f8009d6981 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Wed, 5 Jul 2023 10:43:52 +0200 Subject: [PATCH 29/43] Revert one change from 9adafde --- src/pluginSystem/loadPlugins.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pluginSystem/loadPlugins.js b/src/pluginSystem/loadPlugins.js index 1e73d6d4..7f982308 100644 --- a/src/pluginSystem/loadPlugins.js +++ b/src/pluginSystem/loadPlugins.js @@ -4,7 +4,7 @@ * Created Date: 04.06.2023 15:37:17 * Author: DerDeathraven * - * Last Modified: 04.07.2023 19:02:01 + * Last Modified: 05.07.2023 10:31:36 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -52,6 +52,7 @@ function loadPlugin(pluginName) { return { pluginName, pluginInstance, pluginJson }; } catch (e) { logger("error", `Plugin '${pluginName}' could not be instantiated: ${e.stack}`); + return { pluginName, pluginInstance: null, pluginJson: null }; } } From ea115cc91d627bcdaa8350e0c9eb03f495da86b6 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Wed, 5 Jul 2023 10:49:11 +0200 Subject: [PATCH 30/43] Misc --- src/controller/helpers/handleErrors.js | 4 ++-- src/controller/helpers/npminteraction.js | 8 ++++---- src/dataManager/dataImport.js | 11 ++--------- src/starter.js | 4 ++-- src/updater/helpers/customUpdateRules.js | 6 +++--- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/controller/helpers/handleErrors.js b/src/controller/helpers/handleErrors.js index d91b9da8..e1274d04 100644 --- a/src/controller/helpers/handleErrors.js +++ b/src/controller/helpers/handleErrors.js @@ -4,7 +4,7 @@ * Created Date: 21.03.2023 22:53:37 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 05.07.2023 10:48:43 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -40,7 +40,7 @@ Controller.prototype._handleErrors = function() { require("./npminteraction.js").reinstallAll(logger, (err, stdout) => { //eslint-disable-line if (err) { - logger("error", "I was unable to reinstall all modules. Please try running 'npm install' manually. Error: " + err); + logger("error", "I was unable to reinstall all modules. Please try running 'npm install --production' manually. Error: " + err); return this.stop(); } else { // Logger("info", `NPM Log:\n${stdout}`, true) //entire log (not using it rn to avoid possible confusion with vulnerabilities message) diff --git a/src/controller/helpers/npminteraction.js b/src/controller/helpers/npminteraction.js index 6a32cde1..f7a60824 100644 --- a/src/controller/helpers/npminteraction.js +++ b/src/controller/helpers/npminteraction.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:42:16 + * Last Modified: 05.07.2023 10:48:17 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -36,12 +36,12 @@ module.exports.reinstallAll = (logger, callback) => { fs.rm(srcdir + "/../node_modules", { recursive: true }, (err) => { if (err) return callback(err, null); - logger("info", "Running 'npm install'..."); + logger("info", "Running 'npm install --production'..."); exec("npm install --production", { cwd: srcdir + "/.." }, (err, stdout) => { if (err) return callback(err, null); - logger("info", "Successfully ran 'npm install'"); + logger("info", "Successfully ran 'npm install --production'"); callback(null, stdout); }); @@ -64,7 +64,7 @@ module.exports.update = (callback) => { * @param {function(string|null, string|null): void} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ module.exports.updateFromPath = (path, callback) => { - logger("debug", `npminteraction update(): Running 'npm install' in '${path}'...`); + logger("debug", `npminteraction update(): Running 'npm install --production' in '${path}'...`); exec("npm install --production", { cwd: path }, (err, stdout) => { if (err) return callback(err, null); diff --git a/src/dataManager/dataImport.js b/src/dataManager/dataImport.js index 0217700d..e6f3515a 100644 --- a/src/dataManager/dataImport.js +++ b/src/dataManager/dataImport.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:44:01 + * Last Modified: 04.07.2023 22:47:47 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -231,14 +231,7 @@ DataManager.prototype._importFromDisk = async function () { // Pull new file and call loadQuotes again, wait for it to resolve, and then resolve this promise. This is slightly hacky but relatively clean if (!fs.existsSync(srcdir + "/../quotes.txt")) { - return _this._pullNewFile( - "quotes.txt", - "./quotes.txt", - async () => { - resolve(await loadQuotes()); - }, - true - ); + return _this._pullNewFile("quotes.txt", "./quotes.txt", async () => { resolve(await loadQuotes()); }, true); } quotes = fs.readFileSync(srcdir + "/../quotes.txt", "utf8").split("\n"); // Get all quotes from the quotes.txt file into an array diff --git a/src/starter.js b/src/starter.js index b2f37f73..441b1beb 100644 --- a/src/starter.js +++ b/src/starter.js @@ -4,7 +4,7 @@ * Created Date: 10.07.2021 10:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 20:10:00 + * Last Modified: 05.07.2023 10:48:48 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -78,7 +78,7 @@ function attachParentListeners(callback) { require("./controller/helpers/npminteraction.js").reinstallAll(logger, (err, stdout) => { // eslint-disable-line if (err) { - logger("error", "I was unable to reinstall all modules. Please try running 'npm install' manually. Error: " + err); + logger("error", "I was unable to reinstall all modules. Please try running 'npm install --production' manually. Error: " + err); process.exit(1); } else { // Logger("info", `NPM Log:\n${stdout}`, true) //entire log (not using it rn to avoid possible confusion with vulnerabilities message) diff --git a/src/updater/helpers/customUpdateRules.js b/src/updater/helpers/customUpdateRules.js index 549fa797..2b5d192f 100644 --- a/src/updater/helpers/customUpdateRules.js +++ b/src/updater/helpers/customUpdateRules.js @@ -4,7 +4,7 @@ * Created Date: 22.02.2022 17:39:21 * Author: 3urobeat * - * Last Modified: 04.07.2023 20:13:24 + * Last Modified: 04.07.2023 21:57:28 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -95,8 +95,8 @@ module.exports.customUpdateRules = (compatibilityfeaturedone, oldconfig, oldadva let newextdata = require(srcdir + "/data/data.json"); // Transfer a few specific values to the new datafile if they exist to avoid errors - if (olddatafile.timesloggedin) newextdata.timesloggedin = olddatafile.timesloggedin; - if (olddatafile.totallogintime) newextdata.totallogintime = olddatafile.totallogintime; + if (olddatafile.timesloggedin) newextdata.timesloggedin = olddatafile.timesloggedin; + if (olddatafile.totallogintime) newextdata.totallogintime = olddatafile.totallogintime; // Write changes to file fs.writeFile(srcdir + "/data/data.json", JSON.stringify(newextdata, null, 4), (err) => { // Write the changed file From 0b7a4d50bd00bf160d1387bad08d6e53dad14362 Mon Sep 17 00:00:00 2001 From: JLCD Date: Wed, 5 Jul 2023 14:40:00 +0200 Subject: [PATCH 31/43] fix(pluginSystem) fixed plugin caching --- src/pluginSystem/pluginSystem.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/pluginSystem/pluginSystem.js b/src/pluginSystem/pluginSystem.js index 46b64fd9..85778268 100644 --- a/src/pluginSystem/pluginSystem.js +++ b/src/pluginSystem/pluginSystem.js @@ -65,20 +65,16 @@ module.exports = PluginSystem; PluginSystem.prototype.reloadPlugins = function () { // Delete all plugin objects. (I'm not sure if this is necessary or if clearing the pluginList obj will garbage collect them) Object.keys(this.pluginList).forEach((e) => { + console.log(e); if (this.pluginList[e].unload) { this.pluginList[e].unload(); } else { logger("warn", `PluginSystem reloadPlugins: Plugin ${e} does not have an unload function, reloading might not work properly!`); } - + delete require.cache[require.resolve(e)]; delete this.pluginList[e]; }); - // Delete cache so requiring plugins again will load new changes - Object.keys(require.cache).forEach((key) => { - if (key.includes("node_modules/steam-comment-bot-") || key.includes("/plugins/")) delete require.cache[key]; - }); - this.pluginList = {}; setTimeout(() => this._loadPlugins(), 500); From 048004d0192306d2977b42e29100015acfd03ba9 Mon Sep 17 00:00:00 2001 From: JLCD Date: Wed, 5 Jul 2023 14:41:32 +0200 Subject: [PATCH 32/43] removed console.log --- src/pluginSystem/pluginSystem.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pluginSystem/pluginSystem.js b/src/pluginSystem/pluginSystem.js index 85778268..ec46c641 100644 --- a/src/pluginSystem/pluginSystem.js +++ b/src/pluginSystem/pluginSystem.js @@ -65,7 +65,6 @@ module.exports = PluginSystem; PluginSystem.prototype.reloadPlugins = function () { // Delete all plugin objects. (I'm not sure if this is necessary or if clearing the pluginList obj will garbage collect them) Object.keys(this.pluginList).forEach((e) => { - console.log(e); if (this.pluginList[e].unload) { this.pluginList[e].unload(); } else { From 90ced78195e26ee0ab717b28c4f9388e3430df7b Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Wed, 5 Jul 2023 17:43:06 +0200 Subject: [PATCH 33/43] Add missing step to npm link explanation --- docs/wiki/creating_plugins.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/wiki/creating_plugins.md b/docs/wiki/creating_plugins.md index c2b71a25..9b07ff4b 100644 --- a/docs/wiki/creating_plugins.md +++ b/docs/wiki/creating_plugins.md @@ -241,6 +241,9 @@ To do this, follow these steps: - Run the command `npm link`. On Linux you might have to precede the command with `sudo` (or doas, or whatever you are using). This will make the package available locally to all projects - Open a terminal window in the folder of your bot installation. Run the command `npm link name-of-your-package` +- Open the package.json in the folder of your bot installation and add your plugin as a dependency with a random version. This is important so that the plugin loader will find your package. + Example: `"name-of-your-package": "^0.0.0"` + Don't forget to add a comma at the end of the previous line so that your JSON object is valid. On restart (or by running the command `!reload`) you should see your plugin get loaded! If you make changes in your plugin project you now only need to run the `!reload` command to test them. From ce96986b2be8116522d4a82fd83ed9098635b458 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Wed, 5 Jul 2023 17:49:56 +0200 Subject: [PATCH 34/43] Revert deletion of loop with /plugins/ path check --- src/pluginSystem/pluginSystem.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pluginSystem/pluginSystem.js b/src/pluginSystem/pluginSystem.js index ec46c641..e632abef 100644 --- a/src/pluginSystem/pluginSystem.js +++ b/src/pluginSystem/pluginSystem.js @@ -4,7 +4,7 @@ * Created Date: 19.03.2023 13:34:27 * Author: 3urobeat * - * Last Modified: 04.07.2023 20:05:42 + * Last Modified: 05.07.2023 17:49:09 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -70,10 +70,16 @@ PluginSystem.prototype.reloadPlugins = function () { } else { logger("warn", `PluginSystem reloadPlugins: Plugin ${e} does not have an unload function, reloading might not work properly!`); } + delete require.cache[require.resolve(e)]; delete this.pluginList[e]; }); + // Delete cache so requiring plugins again will load new changes + Object.keys(require.cache).forEach((key) => { + if (key.includes("/plugins/")) delete require.cache[key]; + }); + this.pluginList = {}; setTimeout(() => this._loadPlugins(), 500); From 02a05f92d92119583f85fa9594cb2286544ed62a Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Thu, 6 Jul 2023 22:29:25 +0200 Subject: [PATCH 35/43] Await _importCoreCommands() to fix plugins reading an empty commands array --- src/commands/commandHandler.js | 52 +++++++++++++++++++++------------- src/controller/controller.js | 4 +-- types/types.d.ts | 3 +- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/commands/commandHandler.js b/src/commands/commandHandler.js index cc9c1344..330f7971 100644 --- a/src/commands/commandHandler.js +++ b/src/commands/commandHandler.js @@ -4,7 +4,7 @@ * Created Date: 01.04.2023 21:54:21 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:26:29 + * Last Modified: 06.07.2023 22:27:39 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -37,38 +37,50 @@ const CommandHandler = function(controller) { /** * Internal: Imports core commands on startup + * @returns {Promise.} Resolved when all commands have been imported */ CommandHandler.prototype._importCoreCommands = function() { + return new Promise((resolve) => { - logger("info", "CommandHandler: Loading all core commands...", false, true, logger.animation("loading")); + logger("info", "CommandHandler: Loading all core commands...", false, true, logger.animation("loading")); - fs.readdir("./src/commands/core", (err, files) => { + fs.readdir("./src/commands/core", (err, files) => { - // Stop now on error or if nothing was found - if (err) return logger("error", "Error while reading core dir: " + err, true); - if (files.length == 0) return logger("info", "No commands in ./core found!", false, true, logger.animation("loading")); + // Stop now on error or if nothing was found + if (err) { + logger("error", "Error while reading core dir: " + err, true); + return resolve(); + } + if (files.length == 0) { + logger("info", "No commands in ./core found!", false, true, logger.animation("loading")); + return resolve(); + } - // Iterate over all files in this dir - files.forEach((e, i) => { - let thisFile; + // Iterate over all files in this dir + files.forEach((e, i) => { + let thisFile; - // Try to load plugin - try { - // Load the plugin file - thisFile = require(`./core/${e}`); + // Try to load plugin + try { + // Load the plugin file + thisFile = require(`./core/${e}`); - // Push all exported commands in this file into the command list - Object.values(thisFile).every(val => this.commands.push(val)); + // Push all exported commands in this file into the command list + Object.values(thisFile).every(val => this.commands.push(val)); - } catch (err) { + } catch (err) { - logger("error", `Error loading core command '${e}'! ${err.stack}`, true); - } + logger("error", `Error loading core command '${e}'! ${err.stack}`, true); + } - if (i + 1 == files.length) logger("info", `CommandHandler: Successfully loaded ${this.commands.length} core commands!`, false, true, logger.animation("loading")); + if (i + 1 == files.length) { + logger("info", `CommandHandler: Successfully loaded ${this.commands.length} core commands!`, false, true, logger.animation("loading")); + resolve(); + } + }); }); - }); + }); }; diff --git a/src/controller/controller.js b/src/controller/controller.js index 317e40ae..97e4b088 100644 --- a/src/controller/controller.js +++ b/src/controller/controller.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:54:44 + * Last Modified: 06.07.2023 22:28:04 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -280,7 +280,7 @@ Controller.prototype._preLogin = async function() { * @type {CommandHandler} */ this.commandHandler = new CommandHandler(this); - this.commandHandler._importCoreCommands(); + await this.commandHandler._importCoreCommands(); // Load pluginSystem diff --git a/types/types.d.ts b/types/types.d.ts index c52c2ecb..35844f20 100644 --- a/types/types.d.ts +++ b/types/types.d.ts @@ -145,8 +145,9 @@ declare class CommandHandler { constructor(controller: Controller); /** * Internal: Imports core commands on startup + * @returns Resolved when all commands have been imported */ - _importCoreCommands(): void; + _importCoreCommands(): Promise; /** * Registers a new command during runtime * @param command - The command object to register From d76ea8917c9a06e1956a91ab161f5020a3077efb Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Fri, 7 Jul 2023 11:37:06 +0200 Subject: [PATCH 36/43] Add args documentation to all commands --- src/commands/core/block.js | 18 +++++++++++++++++- src/commands/core/comment.js | 22 +++++++++++++++++++++- src/commands/core/favorite.js | 30 +++++++++++++++++++++++++++++- src/commands/core/friend.js | 26 +++++++++++++++++++++++++- src/commands/core/general.js | 11 ++++++++--- src/commands/core/group.js | 27 ++++++++++++++++++++++++++- src/commands/core/requests.js | 30 ++++++++++++++++++++++++++++-- src/commands/core/settings.js | 16 +++++++++++++++- src/commands/core/system.js | 22 +++++++++++++++++++++- src/commands/core/vote.js | 30 +++++++++++++++++++++++++++++- 10 files changed, 219 insertions(+), 13 deletions(-) diff --git a/src/commands/core/block.js b/src/commands/core/block.js index 6efa0831..820f5a5c 100644 --- a/src/commands/core/block.js +++ b/src/commands/core/block.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:25:54 + * Last Modified: 07.07.2023 11:22:55 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -23,6 +23,14 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.block = { names: ["block"], description: "Blocks a user with all bot accounts on Steam", + args: [ + { + name: "ID", + description: "The link, steamID64 or vanity of the profile to block", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** @@ -59,6 +67,14 @@ module.exports.block = { module.exports.unblock = { names: ["unblock"], description: "Unblocks a user with all bot accounts on Steam. Note: The user can still get ignored by Steam for a while", + args: [ + { + name: "ID", + description: "The link, steamID64 or vanity of the profile to unblock", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** diff --git a/src/commands/core/comment.js b/src/commands/core/comment.js index 833027fa..df0364f7 100644 --- a/src/commands/core/comment.js +++ b/src/commands/core/comment.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:32:52 + * Last Modified: 07.07.2023 11:06:42 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -27,6 +27,26 @@ const { logCommentError, handleIterationSkip } = require("../helpers/handleComme module.exports.comment = { names: ["comment", "gcomment", "groupcomment"], description: "Request comments from all available bot accounts for a profile, group or sharedfile", + args: [ + { + name: "amount", + description: "The amount of comments to request", + type: "string", + ownersOnly: false + }, + { + name: "ID", + description: "The link, steamID64 or vanity of the profile, group or sharedfile to comment on", + type: "string", + ownersOnly: true + }, + { + name: "custom quotes", + description: "Array of strings to use as quotes in this comment request instead of the default quotes.txt set", + type: "string", + ownersOnly: true + } + ], ownersOnly: false, /** diff --git a/src/commands/core/favorite.js b/src/commands/core/favorite.js index 4de00ccd..f53208b3 100644 --- a/src/commands/core/favorite.js +++ b/src/commands/core/favorite.js @@ -4,7 +4,7 @@ * Created Date: 02.06.2023 13:23:01 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:27:09 + * Last Modified: 07.07.2023 11:22:47 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -25,6 +25,20 @@ const { handleFavoriteIterationSkip, logFavoriteError } = require("../helpers/ha module.exports.favorite = { names: ["favorite", "fav"], description: "Favorizes a sharedfile with all bot accounts that haven't yet favorized that item", + args: [ + { + name: "amount", + description: "The amount of favorites to request", + type: "string", + ownersOnly: false + }, + { + name: "ID", + description: "The link or sharedfile ID to vote on", + type: "string", + ownersOnly: false + } + ], ownersOnly: false, /** @@ -192,6 +206,20 @@ module.exports.favorite = { module.exports.unfavorite = { names: ["unfavorite", "unfav"], description: "Unfavorizes a sharedfile with all bot accounts that have favorized that item", + args: [ + { + name: "amount", + description: "The amount of favorites to request", + type: "string", + ownersOnly: true + }, + { + name: "ID", + description: "The link or sharedfile ID to vote on", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** diff --git a/src/commands/core/friend.js b/src/commands/core/friend.js index 1971c0fc..bc534588 100644 --- a/src/commands/core/friend.js +++ b/src/commands/core/friend.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:27:09 + * Last Modified: 07.07.2023 11:23:51 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -23,6 +23,14 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.addFriend = { names: ["addfriend"], description: "Adds the ID with all bot accounts. Requires unlimited accounts!", + args: [ + { + name: "ID", + description: "The link, steamID64 or vanity of the profile to add", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** @@ -83,6 +91,14 @@ module.exports.addFriend = { module.exports.unfriend = { names: ["unfriend"], description: "Unfriends a user from all logged in accounts. (Owner only) Providing no argument will let all bots unfriend you. (Available to normal users)", + args: [ + { + name: "ID", + description: "The link, steamID64 or vanity of the profile to unfriend", + type: "string", + ownersOnly: false + } + ], ownersOnly: false, /** @@ -136,6 +152,14 @@ module.exports.unfriend = { module.exports.unfriendall = { names: ["unfriendall"], description: "Unfriends everyone with all bot accounts", + args: [ + { + name: '"abort"', + description: "Aborts a unfriendall request if it did not start yet", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** diff --git a/src/commands/core/general.js b/src/commands/core/general.js index 28e6235d..f730b959 100644 --- a/src/commands/core/general.js +++ b/src/commands/core/general.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:27:09 + * Last Modified: 07.07.2023 11:25:17 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -17,8 +17,7 @@ // General commands - -const https = require("https"); +const https = require("https"); const CommandHandler = require("../commandHandler.js"); // eslint-disable-line @@ -26,6 +25,7 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.help = { names: ["h", "help", "commands"], description: "Returns a list of commands available to you and a link to the commands documentation wiki page", + args: [], ownersOnly: false, /** @@ -76,6 +76,7 @@ module.exports.help = { module.exports.info = { names: ["info"], description: "Returns useful information and statistics about the bot and you", + args: [], ownersOnly: false, /** @@ -119,6 +120,7 @@ module.exports.info = { module.exports.ping = { names: ["ping", "pong"], description: "Returns ping in ms to Steam's servers. Can be used to check if the bot is responsive", + args: [], ownersOnly: false, /** @@ -146,6 +148,7 @@ module.exports.ping = { module.exports.about = { names: ["about"], description: "Displays information about this project. The message also contains a disclaimer as well as a link to the owner's profile set in the config.json", + args: [], ownersOnly: false, /** @@ -168,6 +171,7 @@ module.exports.about = { module.exports.owner = { names: ["owner"], description: "Returns a link to the owner's profile set in the config.json", + args: [], ownersOnly: false, /** @@ -194,6 +198,7 @@ module.exports.owner = { module.exports.test = { names: ["test"], description: "Test Command for debugging", + args: [], ownersOnly: true, /** diff --git a/src/commands/core/group.js b/src/commands/core/group.js index 6c439ad3..16531ac5 100644 --- a/src/commands/core/group.js +++ b/src/commands/core/group.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:27:09 + * Last Modified: 07.07.2023 11:27:13 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -23,6 +23,7 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.group = { names: ["group"], description: "Sends an invite or responds with the group link set as yourgroup in the config", + args: [], ownersOnly: false, /** @@ -57,6 +58,14 @@ module.exports.group = { module.exports.joinGroup = { names: ["joingroup"], description: "Joins a Steam Group with all bot accounts", + args: [ + { + name: "ID", + description: "The link or groupID64 of the group to join", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** @@ -94,6 +103,14 @@ module.exports.joinGroup = { module.exports.leaveGroup = { names: ["leavegroup"], description: "Leaves a group with all bot accounts", + args: [ + { + name: "ID", + description: "The link or groupID64 of the group to leave", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** @@ -131,6 +148,14 @@ module.exports.leaveGroup = { module.exports.leaveAllGroups = { names: ["leaveallgroups"], description: "Leaves all groups with all bot accounts", + args: [ + { + name: '"abort"', + description: "Aborts a leaveallgroups request if it did not start yet", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** diff --git a/src/commands/core/requests.js b/src/commands/core/requests.js index e67a15d8..f50d4b35 100644 --- a/src/commands/core/requests.js +++ b/src/commands/core/requests.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:27:09 + * Last Modified: 07.07.2023 11:30:25 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -22,6 +22,14 @@ const { failedCommentsObjToString } = require("../helpers/handleCommentSkips.js" module.exports.abort = { names: ["abort"], description: "Abort your own comment process or one on another ID you have started. Owners can also abort requests started by other users", + args: [ + { + name: "ID", + description: "The link, steamID64 or vanity of the profile, group or sharedfile to abort the request of", + type: "string", + ownersOnly: false // Providing an ID for a request of another user is ownerOnly + }, + ], ownersOnly: false, /** @@ -63,6 +71,14 @@ module.exports.abort = { module.exports.resetCooldown = { names: ["resetcooldown", "rc"], description: "Clear your, the ID's or the comment cooldown of all bot accounts (global)", + args: [ + { + name: 'ID or "global"', + description: "The link, steamID64 or vanity of the profile to clear the cooldown of or the word global to clear the cooldown of all bot accounts", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** @@ -107,6 +123,14 @@ module.exports.resetCooldown = { module.exports.failed = { names: ["failed"], description: "See the exact errors of the last comment request on your profile or provide an ID to see the errors of the last request you started. Owners can also view errors for requests started by other users", + args: [ + { + name: "ID", + description: "The link, steamID64 or vanity of the profile, group or sharedfile to view the errors of", + type: "string", + ownersOnly: false // Providing an ID for a request of another user is ownerOnly + } + ], ownersOnly: false, /** @@ -153,6 +177,7 @@ module.exports.failed = { module.exports.sessions = { names: ["sessions"], description: "Displays all active requests", + args: [], ownersOnly: true, /** @@ -196,7 +221,8 @@ module.exports.sessions = { module.exports.mySessions = { names: ["mysessions"], - description: "Displays all active requests for your profile", + description: "Displays all active requests that you have started", + args: [], ownersOnly: false, /** diff --git a/src/commands/core/settings.js b/src/commands/core/settings.js index 04b0aff4..b5577880 100644 --- a/src/commands/core/settings.js +++ b/src/commands/core/settings.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:27:09 + * Last Modified: 07.07.2023 11:30:54 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -23,6 +23,20 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.settings = { names: ["set", "settings", "config"], description: "Change a value in the config", + args: [ + { + name: "config key", + description: "Name of the config key to update", + type: "string", + ownersOnly: true + }, + { + name: "new value", + description: "New value of the config key", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** diff --git a/src/commands/core/system.js b/src/commands/core/system.js index f4780abc..02d721f8 100644 --- a/src/commands/core/system.js +++ b/src/commands/core/system.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:27:09 + * Last Modified: 07.07.2023 11:32:54 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -23,6 +23,7 @@ const CommandHandler = require("../commandHandler.js"); // eslint-disable-line module.exports.restart = { names: ["restart", "rs"], description: "Restarts the bot and checks for available updates", + args: [], ownersOnly: true, /** @@ -45,6 +46,7 @@ module.exports.restart = { module.exports.stop = { names: ["stop"], description: "Stops the bot", + args: [], ownersOnly: true, /** @@ -67,6 +69,7 @@ module.exports.stop = { module.exports.reload = { names: ["reload", "rl"], description: "Reloads all commands and plugins without needing to restart. Please only use it for testing/development", + args: [], ownersOnly: true, /** @@ -96,6 +99,14 @@ module.exports.reload = { module.exports.update = { names: ["update"], description: "Checks for an available update and installs it if automatic updates are enabled and no requests are active. 'true' forces an update. Blocks new requests if it currently waits for one to be completed", + args: [ + { + name: '"true"', + description: "Forces an update", + type: "string", + ownersOnly: true + }, + ], ownersOnly: true, /** @@ -126,6 +137,7 @@ module.exports.update = { module.exports.output = { names: ["output", "log"], description: "Shows the last 15 lines of the log", + args: [], ownersOnly: true, /** @@ -151,6 +163,14 @@ module.exports.output = { module.exports.eval = { names: ["eval"], description: "Disabled by default, needs to be toggled on with `enableevalcmd` in config.json. **Warning!** This will run any javascript code that was provided. It is strongly advised to leave this feature off unless you know exactly what this means! If you have multiple owners configured they can also run code on **your** machine!", + args: [ + { + name: "javascript code", + description: "The code to run", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, /** diff --git a/src/commands/core/vote.js b/src/commands/core/vote.js index f4b2709e..f3ecc694 100644 --- a/src/commands/core/vote.js +++ b/src/commands/core/vote.js @@ -4,7 +4,7 @@ * Created Date: 28.05.2023 12:02:24 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:27:09 + * Last Modified: 07.07.2023 11:34:01 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -25,6 +25,20 @@ const { handleVoteIterationSkip, logVoteError } = require("../helpers/handleShar module.exports.upvote = { names: ["upvote"], description: "Upvotes a sharedfile with all bot accounts that haven't yet voted on that item. Requires unlimited accounts!", + args: [ + { + name: "amount", + description: "The amount of upvotes to request", + type: "string", + ownersOnly: false + }, + { + name: "ID", + description: "The link or sharedfile ID to vote on", + type: "string", + ownersOnly: false + } + ], ownersOnly: false, /** @@ -197,6 +211,20 @@ module.exports.upvote = { module.exports.downvote = { names: ["downvote"], description: "Downvotes a sharedfile with all bot accounts that haven't yet voted on that item. Requires unlimited accounts!", + args: [ + { + name: "amount", + description: "The amount of downvotes to request", + type: "string", + ownersOnly: true + }, + { + name: "ID", + description: "The link or sharedfile ID to vote on", + type: "string", + ownersOnly: true + } + ], ownersOnly: true, // I would like to prevent users from abusing this feature to dislike other peoples creations /** From 341918bef12c713d98d779c519b63a234c197145 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Fri, 7 Jul 2023 12:17:44 +0200 Subject: [PATCH 37/43] Provide Command typedef --- src/commands/commandHandler.js | 23 ++++++++++++++++------- types/types.d.ts | 26 ++++++++++++++++++-------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/commands/commandHandler.js b/src/commands/commandHandler.js index 330f7971..4a87ba9c 100644 --- a/src/commands/commandHandler.js +++ b/src/commands/commandHandler.js @@ -4,7 +4,7 @@ * Created Date: 01.04.2023 21:54:21 * Author: 3urobeat * - * Last Modified: 06.07.2023 22:27:39 + * Last Modified: 07.07.2023 12:15:05 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -19,6 +19,15 @@ const fs = require("fs"); const Controller = require("../controller/controller.js"); // eslint-disable-line +/** + * @typedef Command Documentation of the Command structure + * @type {object} + * @property {[string]} names All names that should trigger this command + * @property {string} description Description of what this command does + * @property {Array.<{ name: string, description: string, type: string, ownersOnly: boolean }>} args Array of objects containing information about each parameter supported by this command + * @property {boolean} ownersOnly Set to true to only allow owners to use this command. + * @property {function(CommandHandler, Array, string, function(object, object, string): void, object, object): void} run Function that will be executed when the command runs. Arguments: commandHandler, args, steamID64, respondModule, context, resInfo + */ /** * Constructor - Initializes the commandHandler which allows you to integrate core commands into your plugin or add new commands from your plugin. @@ -30,7 +39,11 @@ const CommandHandler = function(controller) { this.controller = controller; this.data = controller.data; - this.commands = []; // Array of objects, where each object represents a command + /** + * Array of objects, where each object represents a registered command + * @type {Array.} + */ + this.commands = []; }; @@ -86,11 +99,7 @@ CommandHandler.prototype._importCoreCommands = function() { /** * Registers a new command during runtime - * @param {object} command The command object to register - * @param {[string]} command.names All names that should trigger this command - * @param {string} command.description Description of what this command does - * @param {boolean} command.ownersOnly Set to true to only allow owners to use this command. - * @param {function(CommandHandler, Array, string, function(object, object, string): void, object, object): void} command.run Function that will be executed when the command runs. Arguments: commandHandler, args, steamID64, respondModule, context, resInfo + * @param {Command} command The command object to register * @returns {boolean} true if the command was successfully registered, false otherwise */ CommandHandler.prototype.registerCommand = function(command) { diff --git a/types/types.d.ts b/types/types.d.ts index 35844f20..3f0940ed 100644 --- a/types/types.d.ts +++ b/types/types.d.ts @@ -137,12 +137,29 @@ declare namespace Bot { } } +/** + * @property description - Description of what this command does + * @property args - Array of objects containing information about each parameter supported by this command + * @property ownersOnly - Set to true to only allow owners to use this command. + * @property run - Function that will be executed when the command runs. Arguments: commandHandler, args, steamID64, respondModule, context, resInfo + */ +declare type Command = { + description: string; + args: { name: string; description: string; type: string; ownersOnly: boolean; }[]; + ownersOnly: boolean; + run: (...params: any[]) => any; +}; + /** * Constructor - Initializes the commandHandler which allows you to integrate core commands into your plugin or add new commands from your plugin. * @param controller - Reference to the current controller object */ declare class CommandHandler { constructor(controller: Controller); + /** + * Array of objects, where each object represents a registered command + */ + commands: Command[]; /** * Internal: Imports core commands on startup * @returns Resolved when all commands have been imported @@ -151,16 +168,9 @@ declare class CommandHandler { /** * Registers a new command during runtime * @param command - The command object to register - * @param command.description - Description of what this command does - * @param command.ownersOnly - Set to true to only allow owners to use this command. - * @param command.run - Function that will be executed when the command runs. Arguments: commandHandler, args, steamID64, respondModule, context, resInfo * @returns true if the command was successfully registered, false otherwise */ - registerCommand(command: { - description: string; - ownersOnly: boolean; - run: (...params: any[]) => any; - }): boolean; + registerCommand(command: Command): boolean; /** * The name of the command to unregister during runtime * @param commandName - Name of the command to unregister From 46a15a4d6f0e71cba912a4f31bdf35cab902d054 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Fri, 7 Jul 2023 12:45:46 +0200 Subject: [PATCH 38/43] Fix !reload not clearing cache of plugin subpaths --- src/pluginSystem/pluginSystem.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/pluginSystem/pluginSystem.js b/src/pluginSystem/pluginSystem.js index e632abef..f613ef3f 100644 --- a/src/pluginSystem/pluginSystem.js +++ b/src/pluginSystem/pluginSystem.js @@ -4,7 +4,7 @@ * Created Date: 19.03.2023 13:34:27 * Author: 3urobeat * - * Last Modified: 05.07.2023 17:49:09 + * Last Modified: 07.07.2023 12:43:16 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -63,7 +63,7 @@ module.exports = PluginSystem; * Reloads all plugins and calls ready event after ~2.5 seconds. */ PluginSystem.prototype.reloadPlugins = function () { - // Delete all plugin objects. (I'm not sure if this is necessary or if clearing the pluginList obj will garbage collect them) + // Delete all plugin objects and their subfiles Object.keys(this.pluginList).forEach((e) => { if (this.pluginList[e].unload) { this.pluginList[e].unload(); @@ -71,13 +71,18 @@ PluginSystem.prototype.reloadPlugins = function () { logger("warn", `PluginSystem reloadPlugins: Plugin ${e} does not have an unload function, reloading might not work properly!`); } + // Delete the original path of the plugin, otherwise plugins linked via 'npm link' won't be reloaded correctly delete require.cache[require.resolve(e)]; - delete this.pluginList[e]; - }); - // Delete cache so requiring plugins again will load new changes - Object.keys(require.cache).forEach((key) => { - if (key.includes("/plugins/")) delete require.cache[key]; + // Make sure to delete subfiles of this plugin + Object.keys(require.cache).forEach((key) => { + if (key.includes(e) || key.includes("/plugins/")) { + delete require.cache[require.resolve(key)]; + } + }); + + // Delete entry from pluginList object + delete this.pluginList[e]; }); this.pluginList = {}; From be9adcc48165a5fdb8dcb7bdc2a7c5a9150dce04 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Fri, 7 Jul 2023 15:31:13 +0200 Subject: [PATCH 39/43] Throw errors for missing parameters in plugin data handling functions --- src/pluginSystem/handlePluginData.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/pluginSystem/handlePluginData.js b/src/pluginSystem/handlePluginData.js index 0ef8459d..d2a80742 100644 --- a/src/pluginSystem/handlePluginData.js +++ b/src/pluginSystem/handlePluginData.js @@ -4,7 +4,7 @@ * Created Date: 04.06.2023 17:52:51 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 07.07.2023 15:25:16 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -24,6 +24,8 @@ const PluginSystem = require("./pluginSystem.js"); * @returns {string} Path to the folder containing your plugin data */ PluginSystem.prototype.getPluginDataPath = function (pluginName) { + if (!pluginName) throw new Error("Plugin name parameter is missing!"); + let path = `${srcdir}/../plugins/${pluginName}/`; if (!fs.existsSync(path)) fs.mkdirSync(path); @@ -39,6 +41,9 @@ PluginSystem.prototype.getPluginDataPath = function (pluginName) { */ PluginSystem.prototype.loadPluginData = function (pluginName, filename) { return new Promise((resolve, reject) => { + // Check for missing parameters + if (!pluginName || !filename) return reject(new Error("Plugin name or file name parameter is missing!")); + // Get path let path = this.getPluginDataPath(pluginName); @@ -62,6 +67,9 @@ PluginSystem.prototype.loadPluginData = function (pluginName, filename) { */ PluginSystem.prototype.writePluginData = function (pluginName, filename, data) { return new Promise((resolve, reject) => { + // Check for missing parameters + if (!pluginName || !filename || !data) return reject(new Error("Plugin name, file name or data parameter is missing!")); + // Get path let path = this.getPluginDataPath(pluginName); @@ -84,6 +92,9 @@ PluginSystem.prototype.writePluginData = function (pluginName, filename, data) { */ PluginSystem.prototype.deletePluginData = function (pluginName, filename) { return new Promise((resolve, reject) => { + // Check for missing parameters + if (!pluginName || !filename) return reject(new Error("Plugin name or file name parameter is missing!")); + // Get path let path = this.getPluginDataPath(pluginName); @@ -109,6 +120,9 @@ PluginSystem.prototype.deletePluginData = function (pluginName, filename) { */ PluginSystem.prototype.loadPluginConfig = function (pluginName) { return new Promise((resolve, reject) => { + // Check for missing parameters + if (!pluginName) return reject(new Error("Plugin name parameter is missing!")); + // Get path let path = this.getPluginDataPath(pluginName); @@ -133,6 +147,8 @@ PluginSystem.prototype.loadPluginConfig = function (pluginName) { } }); }; + + /** * Integrates changes made to the config to the users config * @param {string} pluginName @@ -151,6 +167,7 @@ PluginSystem.prototype.aggregatePluginConfig = function (pluginName) { return aggregatedConfig; }; + /** * Writes your plugin config changes to the filesystem. The object data will be processed to JSON. * @param {string} pluginName Name of your plugin @@ -159,6 +176,9 @@ PluginSystem.prototype.aggregatePluginConfig = function (pluginName) { */ PluginSystem.prototype.writePluginConfig = function (pluginName, pluginConfig) { return new Promise((resolve, reject) => { + // Check for missing parameters + if (!pluginName || !pluginConfig) return reject(new Error("Plugin name or plugin config parameter is missing!")); + // Get path let path = this.getPluginDataPath(pluginName); From e3c0e5e858bdc971a536af6897b6c1b245649102 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Fri, 7 Jul 2023 16:02:38 +0200 Subject: [PATCH 40/43] Add isOptional param to all command args --- src/commands/core/block.js | 4 +++- src/commands/core/comment.js | 5 ++++- src/commands/core/favorite.js | 6 +++++- src/commands/core/friend.js | 5 ++++- src/commands/core/group.js | 5 ++++- src/commands/core/requests.js | 5 ++++- src/commands/core/settings.js | 4 +++- src/commands/core/system.js | 4 +++- src/commands/core/vote.js | 6 +++++- 9 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/commands/core/block.js b/src/commands/core/block.js index 820f5a5c..be315c5d 100644 --- a/src/commands/core/block.js +++ b/src/commands/core/block.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 07.07.2023 11:22:55 + * Last Modified: 07.07.2023 15:51:40 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,6 +28,7 @@ module.exports.block = { name: "ID", description: "The link, steamID64 or vanity of the profile to block", type: "string", + isOptional: false, ownersOnly: true } ], @@ -72,6 +73,7 @@ module.exports.unblock = { name: "ID", description: "The link, steamID64 or vanity of the profile to unblock", type: "string", + isOptional: false, ownersOnly: true } ], diff --git a/src/commands/core/comment.js b/src/commands/core/comment.js index df0364f7..edde4058 100644 --- a/src/commands/core/comment.js +++ b/src/commands/core/comment.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 07.07.2023 11:06:42 + * Last Modified: 07.07.2023 15:51:55 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -32,18 +32,21 @@ module.exports.comment = { name: "amount", description: "The amount of comments to request", type: "string", + isOptional: false, ownersOnly: false }, { name: "ID", description: "The link, steamID64 or vanity of the profile, group or sharedfile to comment on", type: "string", + isOptional: true, ownersOnly: true }, { name: "custom quotes", description: "Array of strings to use as quotes in this comment request instead of the default quotes.txt set", type: "string", + isOptional: true, ownersOnly: true } ], diff --git a/src/commands/core/favorite.js b/src/commands/core/favorite.js index f53208b3..b5640242 100644 --- a/src/commands/core/favorite.js +++ b/src/commands/core/favorite.js @@ -4,7 +4,7 @@ * Created Date: 02.06.2023 13:23:01 * Author: 3urobeat * - * Last Modified: 07.07.2023 11:22:47 + * Last Modified: 07.07.2023 15:53:13 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -30,12 +30,14 @@ module.exports.favorite = { name: "amount", description: "The amount of favorites to request", type: "string", + isOptional: false, ownersOnly: false }, { name: "ID", description: "The link or sharedfile ID to vote on", type: "string", + isOptional: false, ownersOnly: false } ], @@ -211,12 +213,14 @@ module.exports.unfavorite = { name: "amount", description: "The amount of favorites to request", type: "string", + isOptional: false, ownersOnly: true }, { name: "ID", description: "The link or sharedfile ID to vote on", type: "string", + isOptional: false, ownersOnly: true } ], diff --git a/src/commands/core/friend.js b/src/commands/core/friend.js index bc534588..f4dc85df 100644 --- a/src/commands/core/friend.js +++ b/src/commands/core/friend.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 07.07.2023 11:23:51 + * Last Modified: 07.07.2023 15:57:36 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,6 +28,7 @@ module.exports.addFriend = { name: "ID", description: "The link, steamID64 or vanity of the profile to add", type: "string", + isOptional: false, ownersOnly: true } ], @@ -96,6 +97,7 @@ module.exports.unfriend = { name: "ID", description: "The link, steamID64 or vanity of the profile to unfriend", type: "string", + isOptional: true, // If not provided all bots will unfriend the requesting user ownersOnly: false } ], @@ -157,6 +159,7 @@ module.exports.unfriendall = { name: '"abort"', description: "Aborts a unfriendall request if it did not start yet", type: "string", + isOptional: true, ownersOnly: true } ], diff --git a/src/commands/core/group.js b/src/commands/core/group.js index 16531ac5..61da6386 100644 --- a/src/commands/core/group.js +++ b/src/commands/core/group.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 07.07.2023 11:27:13 + * Last Modified: 07.07.2023 16:01:25 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -63,6 +63,7 @@ module.exports.joinGroup = { name: "ID", description: "The link or groupID64 of the group to join", type: "string", + isOptional: false, ownersOnly: true } ], @@ -108,6 +109,7 @@ module.exports.leaveGroup = { name: "ID", description: "The link or groupID64 of the group to leave", type: "string", + isOptional: false, ownersOnly: true } ], @@ -153,6 +155,7 @@ module.exports.leaveAllGroups = { name: '"abort"', description: "Aborts a leaveallgroups request if it did not start yet", type: "string", + isOptional: true, ownersOnly: true } ], diff --git a/src/commands/core/requests.js b/src/commands/core/requests.js index f50d4b35..e8ccd349 100644 --- a/src/commands/core/requests.js +++ b/src/commands/core/requests.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 07.07.2023 11:30:25 + * Last Modified: 07.07.2023 15:58:36 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -27,6 +27,7 @@ module.exports.abort = { name: "ID", description: "The link, steamID64 or vanity of the profile, group or sharedfile to abort the request of", type: "string", + isOptional: true, ownersOnly: false // Providing an ID for a request of another user is ownerOnly }, ], @@ -76,6 +77,7 @@ module.exports.resetCooldown = { name: 'ID or "global"', description: "The link, steamID64 or vanity of the profile to clear the cooldown of or the word global to clear the cooldown of all bot accounts", type: "string", + isOptional: true, ownersOnly: true } ], @@ -128,6 +130,7 @@ module.exports.failed = { name: "ID", description: "The link, steamID64 or vanity of the profile, group or sharedfile to view the errors of", type: "string", + isOptional: true, ownersOnly: false // Providing an ID for a request of another user is ownerOnly } ], diff --git a/src/commands/core/settings.js b/src/commands/core/settings.js index b5577880..229acd66 100644 --- a/src/commands/core/settings.js +++ b/src/commands/core/settings.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 07.07.2023 11:30:54 + * Last Modified: 07.07.2023 15:59:10 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -28,12 +28,14 @@ module.exports.settings = { name: "config key", description: "Name of the config key to update", type: "string", + isOptional: false, ownersOnly: true }, { name: "new value", description: "New value of the config key", type: "string", + isOptional: false, ownersOnly: true } ], diff --git a/src/commands/core/system.js b/src/commands/core/system.js index 02d721f8..30d9ed5a 100644 --- a/src/commands/core/system.js +++ b/src/commands/core/system.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 07.07.2023 11:32:54 + * Last Modified: 07.07.2023 15:59:30 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -104,6 +104,7 @@ module.exports.update = { name: '"true"', description: "Forces an update", type: "string", + isOptional: true, ownersOnly: true }, ], @@ -168,6 +169,7 @@ module.exports.eval = { name: "javascript code", description: "The code to run", type: "string", + isOptional: false, ownersOnly: true } ], diff --git a/src/commands/core/vote.js b/src/commands/core/vote.js index f3ecc694..eac39433 100644 --- a/src/commands/core/vote.js +++ b/src/commands/core/vote.js @@ -4,7 +4,7 @@ * Created Date: 28.05.2023 12:02:24 * Author: 3urobeat * - * Last Modified: 07.07.2023 11:34:01 + * Last Modified: 07.07.2023 15:59:45 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -30,12 +30,14 @@ module.exports.upvote = { name: "amount", description: "The amount of upvotes to request", type: "string", + isOptional: false, ownersOnly: false }, { name: "ID", description: "The link or sharedfile ID to vote on", type: "string", + isOptional: false, ownersOnly: false } ], @@ -216,12 +218,14 @@ module.exports.downvote = { name: "amount", description: "The amount of downvotes to request", type: "string", + isOptional: false, ownersOnly: true }, { name: "ID", description: "The link or sharedfile ID to vote on", type: "string", + isOptional: false, ownersOnly: true } ], From 4a8d8f051f3937757be2fc2c0c3bed5f0c0b42d6 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Fri, 7 Jul 2023 16:02:56 +0200 Subject: [PATCH 41/43] Provide CommandArg typedef --- src/commands/commandHandler.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/commands/commandHandler.js b/src/commands/commandHandler.js index 4a87ba9c..a7c05eea 100644 --- a/src/commands/commandHandler.js +++ b/src/commands/commandHandler.js @@ -4,7 +4,7 @@ * Created Date: 01.04.2023 21:54:21 * Author: 3urobeat * - * Last Modified: 07.07.2023 12:15:05 + * Last Modified: 07.07.2023 15:52:46 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -24,11 +24,22 @@ const Controller = require("../controller/controller.js"); // eslint-disable-lin * @type {object} * @property {[string]} names All names that should trigger this command * @property {string} description Description of what this command does - * @property {Array.<{ name: string, description: string, type: string, ownersOnly: boolean }>} args Array of objects containing information about each parameter supported by this command + * @property {Array.} args Array of objects containing information about each parameter supported by this command * @property {boolean} ownersOnly Set to true to only allow owners to use this command. * @property {function(CommandHandler, Array, string, function(object, object, string): void, object, object): void} run Function that will be executed when the command runs. Arguments: commandHandler, args, steamID64, respondModule, context, resInfo */ +/** + * @typedef CommandArg Documentation of the Command argument structure + * @type {object} + * @property {string} name Name of this argument. Use common phrases like "ID" or "amount" if possible. If a specific word is expected, put the word inside quotation marks. + * @property {string} description Description of this argument + * @property {string} type Expected datatype of this argument. If read from a chat it will usually be "string" + * @property {boolean} isOptional True if this argument is optional, false if it must be provided. Make sure to check for missing arguments and return an error if false. + * @property {boolean} ownersOnly True if this argument is only allowed to be provided by owners set in the config. If the command itself is `ownersOnly`, set this property to `true` as well. + */ + + /** * Constructor - Initializes the commandHandler which allows you to integrate core commands into your plugin or add new commands from your plugin. * @class From aa41b5abe717af76929d7f5a9557c49aa3a6da96 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Sat, 8 Jul 2023 00:39:24 +0200 Subject: [PATCH 42/43] Throw proper Errors in dataCheck, update steam-user and misc JsDoc fixes --- package-lock.json | 441 ++++++------------ package.json | 2 +- src/controller/controller.js | 6 +- src/controller/helpers/friendlist.js | 4 +- .../helpers/handleSteamIdResolving.js | 4 +- src/controller/helpers/npminteraction.js | 8 +- src/dataManager/dataCheck.js | 10 +- src/sessions/helpers/tokenStorageHandler.js | 4 +- src/sessions/sessionHandler.js | 4 +- src/updater/helpers/checkForUpdate.js | 4 +- src/updater/helpers/customUpdateRules.js | 4 +- types/types.d.ts | 25 +- 12 files changed, 177 insertions(+), 339 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff1ab750..a0535f71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "steam-comment-bot-rest": "^1.0.4", "steam-comment-bot-webserver": "file:plugins/steam-comment-bot-webserver-1.0.0.tgz", "steam-session": "^1.2.4", - "steam-user": "^4.28.8", + "steam-user": "^4.28.9", "steamcommunity": "^3.46.1", "steamid": "^2.0.0", "steamid-resolver": "^1.3.3" @@ -39,9 +39,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", - "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==", + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", + "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", "dev": true, "peer": true, "bin": { @@ -73,9 +73,9 @@ } }, "node_modules/@doctormckay/stdlib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@doctormckay/stdlib/-/stdlib-2.6.0.tgz", - "integrity": "sha512-8g1600orAg+5dZJWy/CgZw7lC6a/1gOUXEGT8owUz6ep8xoQoxxq6elZcDMpopjOAFGPB8yarll/IR+ZOiGuYg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@doctormckay/stdlib/-/stdlib-2.7.0.tgz", + "integrity": "sha512-mNHFwj/U5kBxsh00vuqILEw95keMAsbxIIewkSZ9ORUoOxMIaA4WWlbqx3BFjU7aF+0/QLuA4ey9y4MFw4cj0w==", "dependencies": { "psl": "^1.9.0" }, @@ -149,29 +149,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/@eslint/js": { "version": "8.44.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", @@ -195,29 +172,6 @@ "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -478,9 +432,9 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "node_modules/@types/node": { - "version": "20.3.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz", - "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==" + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.0.tgz", + "integrity": "sha512-jfT7iTf/4kOQ9S7CHV9BIyRaQqHu67mOjsIQBC3BKZvzvUB6zLxEwJ6sBE3ozcvP8kF6Uk5PXN0Q+c0dfhGX0g==" }, "node_modules/@types/qs": { "version": "6.9.7", @@ -579,9 +533,9 @@ } }, "node_modules/acorn": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", - "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -618,27 +572,6 @@ "node": ">= 6.0.0" } }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -678,12 +611,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/appdirectory": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/appdirectory/-/appdirectory-0.1.0.tgz", - "integrity": "sha512-DJ5DV8vZXBbusyiyPlH28xppwS8eAMRuuyMo88xeEcf4bV64lbLtbxRxqixZuJBXsZzLtXFmA13GwVjJc7vdQw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info." - }, "node_modules/archive-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", @@ -898,6 +825,19 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/body-parser/node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -1376,11 +1316,19 @@ } }, "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "2.0.0" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/decode-uri-component": { @@ -1740,27 +1688,6 @@ "node": ">= 0.6" } }, - "node_modules/engine.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/engine.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -1778,13 +1705,15 @@ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "peer": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { @@ -1866,56 +1795,6 @@ "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/eslint-plugin-jsdoc/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-jsdoc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/eslint-plugin-jsdoc/node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-scope": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", @@ -1944,41 +1823,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/espree": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz", @@ -2110,6 +1954,19 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/express/node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -2252,9 +2109,9 @@ } }, "node_modules/file-manager/node_modules/@doctormckay/stdlib": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@doctormckay/stdlib/-/stdlib-1.15.2.tgz", - "integrity": "sha512-PRb0kXvHbAzYZT3wIaXTBg1JxiPGZJ54KNg8z5uXkuQ07PWqA1gbXmb15NrMd6EnDa4evC/ErHXVvb9EgySR2w==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@doctormckay/stdlib/-/stdlib-1.16.0.tgz", + "integrity": "sha512-mObNOnuEgEb+hZKkd6mY2PoB+9gLfuYkmv8ggN/R3JFjaRIWDOR1QlBV3psQZs7TqGpe3ZFB6bgddQGE02psOA==", "engines": { "node": ">=6.0.0" } @@ -2305,6 +2162,19 @@ "node": ">= 0.8" } }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3094,6 +2964,16 @@ "node": ">=12.0.0" } }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -3324,6 +3204,14 @@ "node": ">=6" } }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", @@ -3467,9 +3355,9 @@ } }, "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -4086,11 +3974,18 @@ } }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/send": { @@ -4116,6 +4011,19 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4220,48 +4128,6 @@ "node": ">=10.0.0" } }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/socket.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/socks": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", @@ -4288,27 +4154,6 @@ "node": ">= 10" } }, - "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socks-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", @@ -4412,9 +4257,9 @@ } }, "node_modules/steam-appticket/node_modules/@doctormckay/stdlib": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@doctormckay/stdlib/-/stdlib-1.15.2.tgz", - "integrity": "sha512-PRb0kXvHbAzYZT3wIaXTBg1JxiPGZJ54KNg8z5uXkuQ07PWqA1gbXmb15NrMd6EnDa4evC/ErHXVvb9EgySR2w==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@doctormckay/stdlib/-/stdlib-1.16.0.tgz", + "integrity": "sha512-mObNOnuEgEb+hZKkd6mY2PoB+9gLfuYkmv8ggN/R3JFjaRIWDOR1QlBV3psQZs7TqGpe3ZFB6bgddQGE02psOA==", "engines": { "node": ">=6.0.0" } @@ -4509,27 +4354,6 @@ "node": ">=12.22.0" } }, - "node_modules/steam-session/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/steam-session/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/steam-totp": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/steam-totp/-/steam-totp-2.1.2.tgz", @@ -4539,15 +4363,14 @@ } }, "node_modules/steam-user": { - "version": "4.28.8", - "resolved": "https://registry.npmjs.org/steam-user/-/steam-user-4.28.8.tgz", - "integrity": "sha512-DQAoLxpKFFVL3jKb8eMXZ4ne+j/CF4ppjwyTMQY3cvJ/SPGZ4UMKKm2x8V9is+YBE2Gif10ehQLXU9dBdvJwVg==", + "version": "4.28.9", + "resolved": "https://registry.npmjs.org/steam-user/-/steam-user-4.28.9.tgz", + "integrity": "sha512-95M5ALWtVMPWKQKD9xW/bI9a9GVcf3bQcHsR0FEpEA/yGiQJnBSUS2TxBK0XvUTEsYA3bhNu7RAUae7v9eN35Q==", "dependencies": { "@bbob/parser": "^2.2.0", - "@doctormckay/stdlib": "^1.15.2", + "@doctormckay/stdlib": "^1.16.0", "@doctormckay/steam-crypto": "^1.2.0", "adm-zip": "^0.5.10", - "appdirectory": "^0.1.0", "binarykvparser": "^2.2.0", "bytebuffer": "^5.0.0", "file-manager": "^2.0.0", @@ -4566,9 +4389,9 @@ } }, "node_modules/steam-user/node_modules/@doctormckay/stdlib": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@doctormckay/stdlib/-/stdlib-1.15.2.tgz", - "integrity": "sha512-PRb0kXvHbAzYZT3wIaXTBg1JxiPGZJ54KNg8z5uXkuQ07PWqA1gbXmb15NrMd6EnDa4evC/ErHXVvb9EgySR2w==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@doctormckay/stdlib/-/stdlib-1.16.0.tgz", + "integrity": "sha512-mObNOnuEgEb+hZKkd6mY2PoB+9gLfuYkmv8ggN/R3JFjaRIWDOR1QlBV3psQZs7TqGpe3ZFB6bgddQGE02psOA==", "engines": { "node": ">=6.0.0" } @@ -5091,9 +4914,9 @@ } }, "node_modules/websocket13/node_modules/@doctormckay/stdlib": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@doctormckay/stdlib/-/stdlib-1.15.2.tgz", - "integrity": "sha512-PRb0kXvHbAzYZT3wIaXTBg1JxiPGZJ54KNg8z5uXkuQ07PWqA1gbXmb15NrMd6EnDa4evC/ErHXVvb9EgySR2w==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@doctormckay/stdlib/-/stdlib-1.16.0.tgz", + "integrity": "sha512-mObNOnuEgEb+hZKkd6mY2PoB+9gLfuYkmv8ggN/R3JFjaRIWDOR1QlBV3psQZs7TqGpe3ZFB6bgddQGE02psOA==", "engines": { "node": ">=6.0.0" } diff --git a/package.json b/package.json index 859f38f4..59615a7b 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "steam-comment-bot-rest": "^1.0.4", "steam-comment-bot-webserver": "file:plugins/steam-comment-bot-webserver-1.0.0.tgz", "steam-session": "^1.2.4", - "steam-user": "^4.28.8", + "steam-user": "^4.28.9", "steamcommunity": "^3.46.1", "steamid": "^2.0.0", "steamid-resolver": "^1.3.3" diff --git a/src/controller/controller.js b/src/controller/controller.js index 97e4b088..9ec3a47b 100644 --- a/src/controller/controller.js +++ b/src/controller/controller.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 06.07.2023 22:28:04 + * Last Modified: 08.07.2023 00:36:10 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -398,7 +398,7 @@ Controller.prototype.checkLastcommentDB = function(bot) {}; // eslint-disable-li /** * Checks the remaining space on the friendlist of a bot account, sends a warning message if it is less than 10 and force unfriends oldest lastcomment db user to always keep room for 1 friend. * @param {Bot} bot Bot object of the account to check - * @param {function(number|null): void} [callback] Called with `remaining` (Number) on success or `null` on failure + * @param {function(number|null): void} callback Called with `remaining` (Number) on success or `null` on failure */ Controller.prototype.friendListCapacityCheck = function(bot, callback) {}; // eslint-disable-line @@ -425,7 +425,7 @@ Controller.prototype._handleErrors = function() {} // eslint-disable-line * Handles converting URLs to steamIDs, determining their type if unknown and checking if it matches your expectation * @param {string} str The profileID argument provided by the user * @param {string} expectedIdType The type of SteamID expected ("profile", "group" or "sharedfile") or `null` if type should be assumed. - * @param {function(string|null, string|null, string|null): void} [callback] Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion + * @param {function(string|null, string|null, string|null): void} callback Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion */ Controller.prototype.handleSteamIdResolving = (str, expectedIdType, callback) => {} // eslint-disable-line diff --git a/src/controller/helpers/friendlist.js b/src/controller/helpers/friendlist.js index dc542b4b..ebc3bb7f 100644 --- a/src/controller/helpers/friendlist.js +++ b/src/controller/helpers/friendlist.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:37:53 + * Last Modified: 08.07.2023 00:36:19 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -52,7 +52,7 @@ Controller.prototype.checkLastcommentDB = function(bot) { /** * Checks the remaining space on the friendlist of a bot account, sends a warning message if it is less than 10 and force unfriends oldest lastcomment db user to always keep room for 1 friend. * @param {Bot} bot Bot object of the account to check - * @param {function(number|null): void} [callback] Called with `remaining` (Number) on success or `null` on failure + * @param {function(number|null): void} callback Called with `remaining` (Number) on success or `null` on failure */ Controller.prototype.friendListCapacityCheck = function(bot, callback) { try { diff --git a/src/controller/helpers/handleSteamIdResolving.js b/src/controller/helpers/handleSteamIdResolving.js index 76bc843f..18320eb1 100644 --- a/src/controller/helpers/handleSteamIdResolving.js +++ b/src/controller/helpers/handleSteamIdResolving.js @@ -4,7 +4,7 @@ * Created Date: 09.03.2022 12:58:17 * Author: 3urobeat * - * Last Modified: 04.07.2023 19:38:26 + * Last Modified: 08.07.2023 00:36:23 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -28,7 +28,7 @@ const Controller = require("../controller.js"); * Handles converting URLs to steamIDs, determining their type if unknown and checking if it matches your expectation * @param {string} str The profileID argument provided by the user * @param {string} expectedIdType The type of SteamID expected ("profile", "group" or "sharedfile") or `null` if type should be assumed. - * @param {function(string|null, string|null, string|null): void} [callback] Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion + * @param {function(string|null, string|null, string|null): void} callback Called with `err` (String or null), `steamID64` (String or null), `idType` (String or null) parameters on completion */ Controller.prototype.handleSteamIdResolving = (str, expectedIdType, callback) => { diff --git a/src/controller/helpers/npminteraction.js b/src/controller/helpers/npminteraction.js index f7a60824..b1cf1066 100644 --- a/src/controller/helpers/npminteraction.js +++ b/src/controller/helpers/npminteraction.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 05.07.2023 10:48:17 + * Last Modified: 08.07.2023 00:36:35 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -22,7 +22,7 @@ const { exec } = require("child_process"); // Wanted to do it with the npm packa /** * Attempts to reinstall all modules * @param {function(string, string): void} logger The currently used logger function (real or fake, the caller decides) - * @param {function(string|null, string|null): void} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion + * @param {function(string|null, string|null): void} callback Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ module.exports.reinstallAll = (logger, callback) => { if (!fs.existsSync(srcdir + "/../node_modules")) { @@ -51,7 +51,7 @@ module.exports.reinstallAll = (logger, callback) => { /** * Updates all installed packages to versions listed in package.json from the project root directory. - * @param {function(string|null, string|null): void} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion + * @param {function(string|null, string|null): void} callback Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ module.exports.update = (callback) => { module.exports.updateFromPath(srcdir + "/..", callback); @@ -61,7 +61,7 @@ module.exports.update = (callback) => { /** * Updates all installed packages to versions listed in package.json * @param {string} path Custom path to read package.json from and install packages to - * @param {function(string|null, string|null): void} [callback] Called with `err` (String) and `stdout` (String) (npm response) parameters on completion + * @param {function(string|null, string|null): void} callback Called with `err` (String) and `stdout` (String) (npm response) parameters on completion */ module.exports.updateFromPath = (path, callback) => { logger("debug", `npminteraction update(): Running 'npm install --production' in '${path}'...`); diff --git a/src/dataManager/dataCheck.js b/src/dataManager/dataCheck.js index 99c9d3aa..18582ae9 100644 --- a/src/dataManager/dataCheck.js +++ b/src/dataManager/dataCheck.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 29.06.2023 22:35:03 + * Last Modified: 07.07.2023 15:32:44 * Modified By: 3urobeat * * Copyright (c) 2023 3urobeat @@ -46,7 +46,7 @@ DataManager.prototype.checkData = function() { // Filter all invalid ownerids which got replaced with null by processData() if (this.cachefile.ownerid.filter(e => e != null).length == 0) { logWarn("error", "Error: You did not set at least one valid ownerid in config.json! Aborting!"); - return reject("no-ownerid-found"); + return reject(new Error("No ownerid found!")); } @@ -90,7 +90,7 @@ DataManager.prototype.checkData = function() { if (Object.keys(this.logininfo).length == 0) { // Check real quick if logininfo is empty logWarn("error", `${logger.colors.fgred}Your accounts.txt or logininfo.json file doesn't seem to contain any valid login credentials! Aborting...`, true); - return reject("no-logininfo-found"); + return reject(new Error("No logininfo found!")); } if (this.config.maxOwnerComments < 1) { logWarn("info", `${logger.colors.fgred}Your maxOwnerComments value in config.json can't be smaller than 1! Automatically setting it to 1...`, true); @@ -105,14 +105,14 @@ DataManager.prototype.checkData = function() { } if (this.config.commentdelay * maxCommentsOverall > 2147483647) { // Check for 32-bit integer limit for commentcmd timeout logWarn("error", `${logger.colors.fgred}Your maxComments and/or maxOwnerComments and/or commentdelay value in the config are too high.\n Please lower these values so that 'commentdelay * maxComments' is not bigger than 2147483647 (32-bit integer limit).\n\nThis will otherwise cause an error when trying to comment. Aborting...\n`, true); - return reject("commentdelay-times-maxcomments-exceeds-32bit-limit"); + return reject(new Error("Commentdelay times maxcomments exceeds 32bit integer limit!")); } if (this.config.randomizeAccounts && Object.keys(this.logininfo).length <= 5 && maxCommentsOverall > Object.keys(this.logininfo).length * 2) { logWarn("warn", `${logger.colors.fgred}I wouldn't recommend using randomizeAccounts with 5 or less accounts when each account can/has to comment multiple times. The chance of an account getting a cooldown is higher.\n Please make sure your commentdelay is set adequately to reduce the chance of this happening.`, true); } if (this.advancedconfig.loginDelay < 500) { // Don't allow a logindelay below 500ms logWarn("error", `${logger.colors.fgred}I won't allow a logindelay below 500ms as this will probably get you blocked by Steam nearly instantly. I recommend setting it to 2500.\n If you are using one proxy per account you might try setting it to 500 (on your own risk!). Aborting...`, true); - return reject("logindelay-below-500ms"); + return reject(new Error("Logindelay is set below 500ms!")); } if (this.advancedconfig.lastQuotesSize >= this.quotes) { // Force clear lastQuotes array if we have less or equal amount of quotes to choose from than lastQuotesSize to avoid infinite loop logWarn("warn", "lastQuoteSize in 'advancedconfig.json' is greater or equal than the amount of quotes found in 'quotes.txt'. I'm therefore unable to filter recently used quotes when choosing a new one!", true); diff --git a/src/sessions/helpers/tokenStorageHandler.js b/src/sessions/helpers/tokenStorageHandler.js index be79d2e4..766dc797 100644 --- a/src/sessions/helpers/tokenStorageHandler.js +++ b/src/sessions/helpers/tokenStorageHandler.js @@ -4,7 +4,7 @@ * Created Date: 10.10.2022 12:53:20 * Author: 3urobeat * - * Last Modified: 04.07.2023 20:06:35 + * Last Modified: 08.07.2023 00:36:49 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -20,7 +20,7 @@ const SessionHandler = require("../sessionHandler.js"); /** * Internal - Attempts to get a token for this account from tokens.db and checks if it's valid - * @param {function(string|null): void} [callback] Called with `refreshToken` (String) on success or `null` on failure + * @param {function(string|null): void} callback Called with `refreshToken` (String) on success or `null` on failure */ SessionHandler.prototype._getTokenFromStorage = function(callback) { diff --git a/src/sessions/sessionHandler.js b/src/sessions/sessionHandler.js index a3908bd3..ce0bdb75 100644 --- a/src/sessions/sessionHandler.js +++ b/src/sessions/sessionHandler.js @@ -4,7 +4,7 @@ * Created Date: 09.10.2022 12:47:27 * Author: 3urobeat * - * Last Modified: 04.07.2023 20:06:48 + * Last Modified: 08.07.2023 00:36:45 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -166,7 +166,7 @@ SessionHandler.prototype._handleCredentialsLoginError = function(err) {}; // esl /** * Internal - Attempts to get a token for this account from tokens.db and checks if it's valid - * @param {function(string|null): void} [callback] Called with `refreshToken` (String) on success or `null` on failure + * @param {function(string|null): void} callback Called with `refreshToken` (String) on success or `null` on failure */ SessionHandler.prototype._getTokenFromStorage = function(callback) {}; // eslint-disable-line diff --git a/src/updater/helpers/checkForUpdate.js b/src/updater/helpers/checkForUpdate.js index ca926a4b..bff36a93 100644 --- a/src/updater/helpers/checkForUpdate.js +++ b/src/updater/helpers/checkForUpdate.js @@ -4,7 +4,7 @@ * Created Date: 09.07.2021 16:26:00 * Author: 3urobeat * - * Last Modified: 04.07.2023 20:10:27 + * Last Modified: 08.07.2023 00:36:54 * Modified By: 3urobeat * * Copyright (c) 2021 3urobeat @@ -23,7 +23,7 @@ const https = require("https"); * @param {object} datafile The current `data.json` file from the DataManager * @param {string} branch Which branch you want to check. Defaults to the current branch set in `data.json` * @param {boolean} forceUpdate If true an update will be forced, even if disableAutoUpdate is true or the newest version is already installed - * @param {function(boolean, object): void} [callback] Called with `updateFound` (Boolean) and `data` (Object) on completion. `updatefound` will be false if the check should fail. `data` includes the full data.json file found online. + * @param {function(boolean, object): void} callback Called with `updateFound` (Boolean) and `data` (Object) on completion. `updatefound` will be false if the check should fail. `data` includes the full data.json file found online. */ module.exports.check = (datafile, branch, forceUpdate, callback) => { if (!branch) branch = datafile.branch; // Set current branch as default value diff --git a/src/updater/helpers/customUpdateRules.js b/src/updater/helpers/customUpdateRules.js index 2b5d192f..fc33fe07 100644 --- a/src/updater/helpers/customUpdateRules.js +++ b/src/updater/helpers/customUpdateRules.js @@ -4,7 +4,7 @@ * Created Date: 22.02.2022 17:39:21 * Author: 3urobeat * - * Last Modified: 04.07.2023 21:57:28 + * Last Modified: 08.07.2023 00:36:58 * Modified By: 3urobeat * * Copyright (c) 2022 3urobeat @@ -24,7 +24,7 @@ const fs = require("fs"); * @param {object} oldconfig The old config from before the update * @param {object} oldadvancedconfig The old advancedconfig from before the update * @param {object} olddatafile The old datafile from before the update - * @param {function(): void} [callback] Legacy param, is unused + * @param {function(): void} callback Legacy param, is unused * @returns {Promise.} Resolves when we can proceed */ module.exports.customUpdateRules = (compatibilityfeaturedone, oldconfig, oldadvancedconfig, olddatafile, callback) => { // eslint-disable-line diff --git a/types/types.d.ts b/types/types.d.ts index 3f0940ed..e86d5e11 100644 --- a/types/types.d.ts +++ b/types/types.d.ts @@ -145,11 +145,26 @@ declare namespace Bot { */ declare type Command = { description: string; - args: { name: string; description: string; type: string; ownersOnly: boolean; }[]; + args: CommandArg[]; ownersOnly: boolean; run: (...params: any[]) => any; }; +/** + * @property name - Name of this argument. Use common phrases like "ID" or "amount" if possible. If a specific word is expected, put the word inside quotation marks. + * @property description - Description of this argument + * @property type - Expected datatype of this argument. If read from a chat it will usually be "string" + * @property isOptional - True if this argument is optional, false if it must be provided. Make sure to check for missing arguments and return an error if false. + * @property ownersOnly - True if this argument is only allowed to be provided by owners set in the config. If the command itself is `ownersOnly`, set this property to `true` as well. + */ +declare type CommandArg = { + name: string; + description: string; + type: string; + isOptional: boolean; + ownersOnly: boolean; +}; + /** * Constructor - Initializes the commandHandler which allows you to integrate core commands into your plugin or add new commands from your plugin. * @param controller - Reference to the current controller object @@ -1203,9 +1218,9 @@ declare function runCompatibility(controller: Controller): Promise; * @param datafile - The current `data.json` file from the DataManager * @param branch - Which branch you want to check. Defaults to the current branch set in `data.json` * @param forceUpdate - If true an update will be forced, even if disableAutoUpdate is true or the newest version is already installed - * @param [callback] - Called with `updateFound` (Boolean) and `data` (Object) on completion. `updatefound` will be false if the check should fail. `data` includes the full data.json file found online. + * @param callback - Called with `updateFound` (Boolean) and `data` (Object) on completion. `updatefound` will be false if the check should fail. `data` includes the full data.json file found online. */ -declare function check(datafile: any, branch: string, forceUpdate: boolean, callback?: (...params: any[]) => any): void; +declare function check(datafile: any, branch: string, forceUpdate: boolean, callback: (...params: any[]) => any): void; /** * Run the application. This function is called by start.js @@ -1218,10 +1233,10 @@ declare function run(): void; * @param oldconfig - The old config from before the update * @param oldadvancedconfig - The old advancedconfig from before the update * @param olddatafile - The old datafile from before the update - * @param [callback] - Legacy param, is unused + * @param callback - Legacy param, is unused * @returns Resolves when we can proceed */ -declare function customUpdateRules(compatibilityfeaturedone: any, oldconfig: any, oldadvancedconfig: any, olddatafile: any, callback?: (...params: any[]) => any): Promise; +declare function customUpdateRules(compatibilityfeaturedone: any, oldconfig: any, oldadvancedconfig: any, olddatafile: any, callback: (...params: any[]) => any): Promise; /** * Downloads all files from the repository and installs them From cd2683bd4b2909cd267973458ad5eecde6870900 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+3urobeat@users.noreply.github.com> Date: Sun, 9 Jul 2023 18:25:12 +0200 Subject: [PATCH 43/43] Version 2.13.5 --- docs/wiki/changelogs/CHANGELOG_v2.13.md | 35 ++++++++++++++++++++++++- package-lock.json | 10 +++---- package.json | 2 +- src/data/data.json | 10 +++---- src/libraryPatches/README.md | 1 + 5 files changed, 46 insertions(+), 12 deletions(-) diff --git a/docs/wiki/changelogs/CHANGELOG_v2.13.md b/docs/wiki/changelogs/CHANGELOG_v2.13.md index 9c93e3b8..12795086 100644 --- a/docs/wiki/changelogs/CHANGELOG_v2.13.md +++ b/docs/wiki/changelogs/CHANGELOG_v2.13.md @@ -9,6 +9,7 @@ - [2.13.2](#2.13.2) - [2.13.3](#2.13.3) - [2.13.4](#2.13.4) +- [2.13.5](#2.13.5)   @@ -365,4 +366,36 @@ Commit: [24984d6](https://github.com/3urobeat/steam-comment-service-bot/commit/2 - Updated dependencies - Minor other changes -Commit: [829c387](https://github.com/3urobeat/steam-comment-service-bot/commit/829c387) \ No newline at end of file +Commit: [829c387](https://github.com/3urobeat/steam-comment-service-bot/commit/829c387) + +  + + + +## **2023-07-09, Version 2.13.5**, co-author [@DerDeathraven](https://github.com/DerDeathraven) +**Additions:** +- Aggregate old config files for plugins [@DerDeathraven](https://github.com/DerDeathraven) [#188](https://github.com/3urobeat/steam-comment-service-bot/pull/188) +- Added arguments documentation to all commands +- Added command descriptions from wiki to all commands +- Added data export functions to DataManager to write all data files back to the disk +- Added JsDoc eslint rules and enforced them +- Added Command and CommandArg typedef in CommandHandler + +**Fixes:** +- Potentially fixed SteamCommunity library scraping sharedfile error caused by non-English page being returned by Steam +- Fixed reload not clearing plugin cache when using 'npm link' [@DerDeathraven](https://github.com/DerDeathraven) [#192](https://github.com/3urobeat/steam-comment-service-bot/pull/192) +- Fixed reload not clearing plugin cache of subfolders +- Fixed plugins reading core commands on load getting an empty array because `_importCoreCommands()` wasn't being awaited + +**Changes:** +- Wiki: Updated Integrating into your app and Creating Plugins [@DerDeathraven](https://github.com/DerDeathraven) [#189](https://github.com/3urobeat/steam-comment-service-bot/pull/189) +- Wiki: Rewrote Steam Limitations page, rewrote Integrating into your app page, updated various command descriptions, added missing step to npm link explanation and more misc improvements +- Plugin data handling functions will now throw errors on missing parameters +- Data Check will now throw errors instead of rejecting with a string +- Cleaned up a few unnecessarily nested promises +- Enforced lowercase primitive types in JsDocs +- Updated every mention of my old username +- Updated dependencies +- Minor other changes + +Commit: [](https://github.com/3urobeat/steam-comment-service-bot/commit/) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a0535f71..db321084 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "steam-comment-service-bot", - "version": "2.13.4", + "version": "2.13.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "steam-comment-service-bot", - "version": "2.13.4", + "version": "2.13.5", "license": "GPL-3.0", "dependencies": { "@seald-io/nedb": "^4.0.2", @@ -432,9 +432,9 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "node_modules/@types/node": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.0.tgz", - "integrity": "sha512-jfT7iTf/4kOQ9S7CHV9BIyRaQqHu67mOjsIQBC3BKZvzvUB6zLxEwJ6sBE3ozcvP8kF6Uk5PXN0Q+c0dfhGX0g==" + "version": "20.4.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.1.tgz", + "integrity": "sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg==" }, "node_modules/@types/qs": { "version": "6.9.7", diff --git a/package.json b/package.json index 59615a7b..addca217 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "steam-comment-service-bot", - "version": "2.13.4", + "version": "2.13.5", "description": "Request a ton of steam profile/group comments from a bot network with just one command!", "main": "start.js", "dependencies": { diff --git a/src/data/data.json b/src/data/data.json index 437a2cbf..adfc906c 100644 --- a/src/data/data.json +++ b/src/data/data.json @@ -1,14 +1,14 @@ { - "version": "21304", - "versionstr": "2.13.4", - "branch": "beta-testing", + "version": "21305", + "versionstr": "2.13.5", + "branch": "master", "filetostart": "./src/starter.js", - "filetostarturl": "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/beta-testing/src/starter.js", + "filetostarturl": "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/master/src/starter.js", "mestr": "3urobeat", "aboutstr": "This bot was created by 3urobeat.\nGitHub: https://github.com/3urobeat/steam-comment-service-bot \nSteam: https://steamcommunity.com/id/3urobeat \nIf you like my work, any donation would be appreciated! https://paypal.me/3urobeat", "firststart": true, "compatibilityfeaturedone": false, - "whatsnew": "Added REST API plugin @DerDeathraven, added proper handling of >50 missing licenses, fixed error when acc looses connection during request, fixed non-profile behaviour of !failed & !abort for non-owners and more.", + "whatsnew": "Improved plugin system and other parts related to it, (potentially) fixed getting sharedfile error, improved code quality, improved a few wiki pages and minor other changes and fixes.", "timesloggedin": 0, "totallogintime": 0 } \ No newline at end of file diff --git a/src/libraryPatches/README.md b/src/libraryPatches/README.md index 1588623d..bd78cfae 100644 --- a/src/libraryPatches/README.md +++ b/src/libraryPatches/README.md @@ -13,6 +13,7 @@ These are the patches being applied: - Re-enable primaryGroup profile setting: [#287](https://github.com/DoctorMcKay/node-steamcommunity/pull/287) & [#307](https://github.com/DoctorMcKay/node-steamcommunity/pull/307) - Add sharedfiles voteUp & voteDown support - Fix resolving vanity for private profiles returning error: [#315](https://github.com/DoctorMcKay/node-steamcommunity/pull/315) +- (Potentially) Fix sharedfile data scraping failing as a non-english page was returned by Steam These patches have been applied in the past: - Add full sharedfiles support: [#306](https://github.com/DoctorMcKay/node-steamcommunity/pull/306)