diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index ab8c853cc9..6b86318c16 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -90,5 +90,4 @@ After adding a new module to core, you need to do the following:
1. Ensure you have a clean copy of the source code without leftover files from testing. For example, clone the Nameless repository into a new directory
2. Run ./dev/scripts/release.sh. Release zip files are produced and placed in `./release`.
-3. TODO: Add instructions for producing a zip only containing files changed since the last release
-4. TODO: Add instructions for publishing a release
+3. TODO: Add instructions for publishing a release
diff --git a/CHANGELOG.md b/CHANGELOG.md
index af6fc732ef..f367e0c19e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,29 @@
# NamelessMC v2 Changelog
-## [Unreleased](https://github.com/NamelessMC/Nameless/compare/v2.1.1...v2)
-> [Milestone](https://github.com/NamelessMC/Nameless/milestone/21)
+## [Unreleased](https://github.com/NamelessMC/Nameless/compare/v2.1.2...develop)
+> [Milestone](https://github.com/NamelessMC/Nameless/milestone/22)
+
+## [2.1.2](https://github.com/NamelessMC/Nameless/compare/v2.1.1...v2.1.2) - 2023-09-30
+### Added
+- No additions this release
+
+### Changed
+- Small misc improvements [#3389](https://github.com/NamelessMC/Nameless/pull/3389)
+- Add PHP_SAPI checks on scripts [#3403](https://github.com/NamelessMC/Nameless/pull/3403)
+- Rewrite release script to fix checksums in upgrade package [#3414](https://github.com/NamelessMC/Nameless/pull/3414)
+- Ignore group sync request instead of returning error [#3433](https://github.com/NamelessMC/Nameless/pull/3433)
+- Limit logs & support group sync from modules [#3426](https://github.com/NamelessMC/Nameless/pull/3426)
+- Ignore adding group if it's invalid [#3436](https://github.com/NamelessMC/Nameless/pull/3436)
+- Updated translations
+
+### Fixed
+- Rework user group cache issue [#3398](https://github.com/NamelessMC/Nameless/pull/3398)
+- Re-add deleted term + fix Discord OAuth link success message [#3403](https://github.com/NamelessMC/Nameless/pull/3403)
+- Fix typo in en_US translation [#3412](https://github.com/NamelessMC/Nameless/pull/3412)
+- Fix auto verify OAuth email [#3413](https://github.com/NamelessMC/Nameless/pull/3413)
+- Fix forum index showing topics without view other topics permission [#3410](https://github.com/NamelessMC/Nameless/pull/3410)
+- Fix phpdoc build, pin version [#3438](https://github.com/NamelessMC/Nameless/pull/3438)
+- Fix single/double quote not working within member list username CSS [#3427](https://github.com/NamelessMC/Nameless/pull/3427)
## [2.1.1](https://github.com/NamelessMC/Nameless/compare/v2.1.0...v2.1.1) - 2023-06-18
### Added
diff --git a/Dockerfile.phpdoc b/Dockerfile.phpdoc
index 777ca827f1..2fb04ece4a 100644
--- a/Dockerfile.phpdoc
+++ b/Dockerfile.phpdoc
@@ -1,11 +1,11 @@
-FROM phpdoc/phpdoc as doc_builder
+FROM phpdoc/phpdoc:3.4 as doc_builder
COPY . /source
WORKDIR /source
RUN mkdir /target && \
- phpdoc \
+ phpdoc run \
-d 'core/classes' \
-d 'modules/Core/classes' \
-d 'modules/Discord Integration/classes' \
diff --git a/core/classes/Core/URL.php b/core/classes/Core/URL.php
index c7b3da98df..b3e51323a2 100644
--- a/core/classes/Core/URL.php
+++ b/core/classes/Core/URL.php
@@ -85,6 +85,16 @@ private static function buildNonFriendly(string $url, string $params): string {
return (defined('CONFIG_PATH') ? CONFIG_PATH : '') . '/index.php?route=' . $url . ((substr($url, -1) == '/') ? '' : '/');
}
+ /**
+ * Build an asset path
+ *
+ * @param string $path Contains the asset path relative to the root Nameless directory
+ * @return string
+ */
+ public static function buildAssetPath(string $path): string {
+ return (defined('CONFIG_PATH') ? CONFIG_PATH : '') . '/' . ltrim($path, '/');
+ }
+
/**
* Get the server name.
*
diff --git a/core/classes/Core/User.php b/core/classes/Core/User.php
index b689b32dc5..ff262f62ea 100644
--- a/core/classes/Core/User.php
+++ b/core/classes/Core/User.php
@@ -6,7 +6,7 @@
* @author Samerton
* @author Partydragen
* @author Aberdeener
- * @version 2.1.1
+ * @version 2.1.2
* @license MIT
*/
class User {
@@ -134,6 +134,12 @@ public function addGroup(int $group_id, int $expire = 0): bool {
return false;
}
+ $group = Group::find($group_id);
+ if (!$group) {
+ ErrorHandler::logWarning('Could not add invalid group ' . $group_id . ' to user ' . $this->data()->id);
+ return false;
+ }
+
$this->_db->query('INSERT INTO `nl2_users_groups` (`user_id`, `group_id`, `received`, `expire`) VALUES (?, ?, ?, ?)', [
$this->data()->id,
$group_id,
@@ -141,10 +147,8 @@ public function addGroup(int $group_id, int $expire = 0): bool {
$expire
]);
- $group = Group::find($group_id);
- if ($group) {
- $this->_groups[$group_id] = $group;
- }
+ $this->_groups[$group_id] = $group;
+ self::$_group_cache[$this->data()->id][$group_id] = $group;
EventHandler::executeEvent(new UserGroupAddedEvent(
$this,
@@ -524,28 +528,26 @@ public function getGroups(): array {
}
if (isset(self::$_group_cache[$this->data()->id])) {
- $groups_query = self::$_group_cache[$this->data()->id];
+ $this->_groups = self::$_group_cache[$this->data()->id];
} else {
$groups_query = $this->_db->query('SELECT nl2_groups.* FROM nl2_users_groups INNER JOIN nl2_groups ON group_id = nl2_groups.id WHERE user_id = ? AND deleted = 0 ORDER BY `order`', [$this->data()->id]);
if ($groups_query->count()) {
- $groups_query = $groups_query->results();
+ foreach ($groups_query->results() as $item) {
+ $this->_groups[$item->id] = new Group($item);
+ }
} else {
- $groups_query = [];
+ $this->_groups = [];
}
- self::$_group_cache[$this->data()->id] = $groups_query;
+
+ self::$_group_cache[$this->data()->id] = $this->_groups;
}
- if ($groups_query) {
- foreach ($groups_query as $item) {
- $this->_groups[$item->id] = new Group($item);
- }
- } else {
+ if (!count($this->_groups)) {
// Get default group
// TODO: Use PRE_VALIDATED_DEFAULT ?
$default_group = Group::find(1, 'default_group');
$default_group_id = $default_group->id ?? 1;
- $this->_groups = [];
$this->addGroup($default_group_id);
}
@@ -659,6 +661,12 @@ public function getMainGroup(): Group {
* @return false|void
*/
public function setGroup(int $group_id, int $expire = 0) {
+ $group = Group::find($group_id);
+ if (!$group) {
+ ErrorHandler::logWarning('Could not set invalid group ' . $group_id . ' to user ' . $this->data()->id);
+ return false;
+ }
+
if ($this->data()->id == 1) {
return false;
}
@@ -673,10 +681,9 @@ public function setGroup(int $group_id, int $expire = 0) {
]);
$this->_groups = [];
- $group = Group::find($group_id);
- if ($group) {
- $this->_groups[$group_id] = $group;
- }
+ $this->_groups[$group_id] = $group;
+ self::$_group_cache[$this->data()->id] = $this->_groups;
+
}
/**
@@ -706,6 +713,7 @@ public function removeGroup(?int $group_id): bool {
));
unset($this->_groups[$group_id]);
+ unset(self::$_group_cache[$this->data()->id][$group_id]);
return true;
}
diff --git a/core/classes/Database/DB.php b/core/classes/Database/DB.php
index 727297fe91..a1c5d88301 100644
--- a/core/classes/Database/DB.php
+++ b/core/classes/Database/DB.php
@@ -474,9 +474,9 @@ public function addColumn(string $table, string $column, string $attributes): bo
* column, operator (default =), value, and glue (default AND).
* @return array The where clause string, and parameters to bind.
*/
- private function makeWhere(array $clauses): array {
+ public static function makeWhere(array $clauses): array {
if (count($clauses) === count($clauses, COUNT_RECURSIVE)) {
- return $this->makeWhere([$clauses]);
+ return self::makeWhere([$clauses]);
}
$where_clauses = [];
@@ -486,7 +486,7 @@ private function makeWhere(array $clauses): array {
}
if (count($clause) !== count($clause, COUNT_RECURSIVE)) {
- $this->makeWhere(...$clause);
+ self::makeWhere(...$clause);
continue;
}
diff --git a/core/classes/Database/DatabaseInitialiser.php b/core/classes/Database/DatabaseInitialiser.php
index 568b0130f1..fff95658fc 100644
--- a/core/classes/Database/DatabaseInitialiser.php
+++ b/core/classes/Database/DatabaseInitialiser.php
@@ -183,7 +183,7 @@ private function initialiseSettings(): void {
Util::setSetting('recaptcha_type', 'Recaptcha3');
Util::setSetting('recaptcha_login', '0');
Util::setSetting('email_verification', '1');
- Util::setSetting('nameless_version', '2.1.1');
+ Util::setSetting('nameless_version', '2.1.2');
Util::setSetting('version_checked', date('U'));
Util::setSetting('phpmailer', '0');
Util::setSetting('user_avatars', '0');
diff --git a/core/includes/updates/211.php b/core/includes/updates/211.php
new file mode 100644
index 0000000000..e176b1c176
--- /dev/null
+++ b/core/includes/updates/211.php
@@ -0,0 +1,8 @@
+runMigrations();
+
+ $this->setVersion('2.1.2');
+ }
+};
diff --git a/custom/languages/cs_CZ.json b/custom/languages/cs_CZ.json
index db22d1e7c0..3ef1538fc1 100644
--- a/custom/languages/cs_CZ.json
+++ b/custom/languages/cs_CZ.json
@@ -158,7 +158,7 @@
"admin/email_message_message": "Zpráva",
"admin/email_message_options": "Možnosti",
"admin/email_message_subject": "Předmět",
- "admin/email_message_thanks": "Poděkování",
+ "admin/email_message_thanks": "Děkujeme",
"admin/email_password_hidden": "Heslo není z bezpečnostních důvodů zobrazeno.",
"admin/email_port_invalid": "Zadejte platný e-mailový port.",
"admin/email_preview_popup": "Náhled",
@@ -1320,5 +1320,17 @@
"admin/discord_hook": "Discord",
"admin/event_supports_discord": "Tato událost podporuje Discord webhooky a má vlastní vložení.",
"admin/event_supports_normal": "Tato událost podporuje normální webhooky.",
- "general/registration_disabled_message_fallback": "Registrace jsou momentálně zakázány."
+ "general/registration_disabled_message_fallback": "Registrace jsou momentálně zakázány.",
+ "user/integration_linked": "Úspěšně jste připojili svůj účet {{integration}}.",
+ "user/profile_posts_score": "Skóre profilových příspěvků",
+ "admin/custom_score": "Vlastní skóre",
+ "admin/profile_widgets": "Profilové widgety",
+ "admin/reaction_added_event_info": "Reakce přidána",
+ "admin/reaction_deleted_event_info": "Reakce odstraněna",
+ "admin/site_widgets": "Webové widgety",
+ "general/on": "zapnuto",
+ "user/given": "Uděleno",
+ "user/minecraft_account": "Účet Minecraft",
+ "user/reaction_score": "Reakční skóre",
+ "user/received": "Obdrženo"
}
diff --git a/custom/languages/de_DE.json b/custom/languages/de_DE.json
index f16ea8ec9a..0c74eff0f1 100644
--- a/custom/languages/de_DE.json
+++ b/custom/languages/de_DE.json
@@ -175,7 +175,7 @@
"admin/enable_player_list": "Spielerliste aktivieren?",
"admin/enable_registration": "Registrierung aktivieren?",
"admin/enable_status_query": "Aktiviere Status Abfrage?",
- "admin/enable_username_sync": "Benutzername Synchronisation aktivieren?",
+ "admin/enable_username_sync": "Benutzernamen-Synchronisation aktivieren?",
"admin/enable_username_sync_info": "Wenn diese Option aktiviert ist, werden die Benutzernamen der Website aktualisiert, damit sie mit den Benutzernamen im Spiel übereinstimmen. Dies geschieht, wenn das In-Game-Plugin eine Liste von UUIDs und Benutzernamen für Online-Spieler an die Website sendet.",
"admin/enabled": "Aktiviert",
"admin/enter_authme_db_details": "Bitte gebe gültige Datenbank Informationen ein.",
@@ -200,7 +200,7 @@
"admin/force_tfa_alert": "Für Deine Gruppe muss die Zwei-Faktor-Authentifizierung aktiviert sein.",
"admin/force_tfa_warning": "Bitte vergewissere dich, dass du weißt, was das tut, sonst riskierst du, dich und alle Gruppenmitglieder auszusperren.",
"admin/force_www": "www erzwingen?",
- "admin/forgot_password_email": "Password vergessen E-Mail",
+ "admin/forgot_password_email": "E-Mail Password vergessen",
"admin/forum_posts": "Anzeige im Forum",
"admin/forum_topic_reply_email": "Forum Thema Antwort",
"admin/general_settings": "Allgemeine Einstellungen",
@@ -436,7 +436,7 @@
"admin/select_default_avatar": "Wähle ein neues Standard Avatar:",
"admin/select_user_group": "Du musst eine Benutzergruppe auswählen.",
"admin/send": "Senden",
- "admin/send_test_email": "Sende Test E-Mail",
+ "admin/send_test_email": "Test E-Mail senden",
"admin/send_test_email_info": "Die folgende Schaltfläche versucht, eine E-Mail an Deine E-Mail-Adresse zu senden, {{email}}. Falls Irgendwelche Fehler, die beim Senden der E-Mail enstehen, werden angezeigt.",
"admin/sending_mass_message": "Massennachricht senden",
"admin/seo": "SEO",
@@ -1320,5 +1320,17 @@
"admin/discord_hook": "Discord",
"admin/event_supports_discord": "Dieses Ereignis unterstützt Discord-Webhooks und hat eine eigene Einbettung.",
"admin/event_supports_normal": "Dieses Ereignis unterstützt normale Webhooks.",
- "general/registration_disabled_message_fallback": "Die Registrierung ist derzeit deaktiviert."
+ "general/registration_disabled_message_fallback": "Die Registrierung ist derzeit deaktiviert.",
+ "admin/custom_score": "Benutzerdefinierte Punktzahl",
+ "admin/profile_widgets": "Profil Widgets",
+ "admin/reaction_added_event_info": "Reaktion hinzugefügt",
+ "admin/reaction_deleted_event_info": "Reaktion gelöscht",
+ "admin/site_widgets": "Website-Widgets",
+ "general/on": "an",
+ "user/given": "Gegeben",
+ "user/minecraft_account": "Minecraft Account",
+ "user/profile_posts_score": "Bewertung der Profilbeiträge",
+ "user/reaction_score": "Bewertung der Reaktion",
+ "user/received": "Empfangen",
+ "user/integration_linked": "Du hast dein {{integration}}-Konto erfolgreich verknüpft."
}
diff --git a/custom/languages/en_UK.json b/custom/languages/en_UK.json
index f5fb9939d4..b54e40c4a0 100644
--- a/custom/languages/en_UK.json
+++ b/custom/languages/en_UK.json
@@ -753,6 +753,7 @@
"api/finish_registration_link": "Please click on the following link to complete registration:",
"api/group_updated": "Group updated successfully",
"api/groups_updates_successfully": "Groups updated successfully",
+ "api/groups_updates_ignored": "Group sync request ignored, because the Minecraft integration is disabled or the server is not configured as the group sync server in StaffCP.",
"api/integration_identifier_already_linked": "{{integration}} identifier is already linked to another user.",
"api/integration_username_already_linked": "{{integration}} username is already linked to another user.",
"api/report_created": "Report created successfully",
@@ -1174,6 +1175,7 @@
"user/incorrect_password": "Your password is incorrect.",
"user/integration_identifier_already_linked": "{{integration}} identifier is already linked to another user.",
"user/integration_required_to_continue": "Please connect and verify the required connections before continuing to use this website.",
+ "user/integration_linked": "You have successfully linked your {{integration}} account.",
"user/integration_unlinked": "You have successfully unlinked your {{integration}} account.",
"user/integration_username_already_linked": "{{integration}} username is already linked to another user.",
"user/invalid_email": "Your email is invalid.",
diff --git a/custom/languages/ru_RU.json b/custom/languages/ru_RU.json
index 6832278db4..ece3d94587 100644
--- a/custom/languages/ru_RU.json
+++ b/custom/languages/ru_RU.json
@@ -83,7 +83,7 @@
"admin/confirm_query_error_deletion": "Вы уверены, что хотите удалить эту ошибку запроса?",
"admin/confirm_user_deletion": "Вы уверены, что хотите удалить пользователя {{user}}?",
"admin/contact_email": "Контактная электронная Почта",
- "admin/contact_email_address": "Контактный Адрес электронной Почты",
+ "admin/contact_email_address": "Контактный адрес электронной почты",
"admin/content": "Содержание",
"admin/copy": "Скопировать",
"admin/core": "Главное",
@@ -111,11 +111,11 @@
"admin/default": "По умолчанию",
"admin/default_avatar": "Аватар по умолчанию",
"admin/default_group": "Является ли эта группа группой по умолчанию (для новых пользователей)?",
- "admin/default_language": "Язык по Умолчанию",
+ "admin/default_language": "Язык по умолчанию",
"admin/default_language_help": "Пользователи смогут выбрать любой установленный язык. {{docLinkStart}}Прочитать больше »{{docLinkEnd}}",
"admin/default_server": "Сервер по умолчанию",
"admin/default_template_set": "Шаблон по умолчанию установлен на {{template}} успешно.",
- "admin/default_timezone": "Часовой Пояс по умолчанию",
+ "admin/default_timezone": "Часовой пояс по умолчанию",
"admin/delete": "Удалить",
"admin/delete_email_error": "Удалить ошибку",
"admin/delete_group": "Удалить группу",
@@ -215,7 +215,7 @@
"admin/forgot_password_email": "Восстановление Пароль Почты",
"admin/forum_posts": "Отображать на форуме",
"admin/forum_topic_reply_email": "Ответ в теме на форуме",
- "admin/general_settings": "Общие Настройки",
+ "admin/general_settings": "Общие настройки",
"admin/generate_sitemap": "Сгенерировать карту сайта",
"admin/google_analytics": "Google Аналитика",
"admin/google_analytics_help": "Добавьте Google Аналитики к вашему сайту, что бы отслеживать посетителей и статистику. Ваш нужно создать Google Аналитики аккаунт для использования этой функции. Введите ваш Google Аналитики ID Принадлежности Сайта. ID должен выглядит как UA-XXXXA-X, и вы можете найти его в информации вашего аккаунта или в коде отслежки от Google.",
@@ -245,7 +245,7 @@
"admin/head": "Голова",
"admin/header": "Заголовок",
"admin/header_required": "Придумайте заголовок.",
- "admin/homepage_type": "Тип домашней Страницы",
+ "admin/homepage_type": "Тип домашней страницы",
"admin/hook_created": "Хук создан.",
"admin/hook_deleted": "Хук удалён.",
"admin/hook_edited": "Хук обновлён",
@@ -387,7 +387,7 @@
"admin/page_url_minimum_2": "Путь страницы должен состоять не менее чем из 2 символов.",
"admin/page_url_required": "Требуется указать путь странице.",
"admin/pages": "Страницы",
- "admin/panel_templates": "Темы Панели",
+ "admin/panel_templates": "Темы панели",
"admin/parent_server": "Родительский сервер",
"admin/parent_server_help": "Родительский сервер обычно является Bungee, к которому подключен сервер, если таковой имеется.",
"admin/permissions": "Права",
@@ -422,7 +422,7 @@
"admin/pre_1_7": "Minecraft версия старше 1.7?",
"admin/privacy_and_terms": "Правила",
"admin/privacy_policy_error": "Политика конфиденциальности не должна содержать более 100 000 символов.",
- "admin/private_profiles": "Приватные Профили",
+ "admin/private_profiles": "Приватные профили",
"admin/profile_field_created_successfully": "Поле профиля было успешно создано.",
"admin/profile_field_deleted_successfully": "Поле профиля было успешно удалено.",
"admin/profile_field_editable_help": "Если этот параметр включен, пользователи будут иметь разрешение на редактирование поля в настройках своего профиля.",
@@ -511,7 +511,7 @@
"admin/sitemap_link": "Ссылка на карту сайта:",
"admin/sitemap_not_generated_yet": "Карта сайта ещё не была сгенерирована!",
"admin/sitemap_not_writable": "Каталог cache/sitemaps не доступен для записи.",
- "admin/sitename": "Название Сайта",
+ "admin/sitename": "Название сайта",
"admin/social_media": "Социальные Cети",
"admin/social_media_settings_updated": "Настройки социальных сетей успешно обновлены.",
"admin/source": "Исходный код",
@@ -574,7 +574,7 @@
"admin/updated_user_languages": "Обновлены языки пользователей.",
"admin/updated_x": "Обновлено: {{updatedAt}}",
"admin/upload_new_image": "Загрузить новое изображение",
- "admin/use_friendly_urls": "Дружеские Ссылки",
+ "admin/use_friendly_urls": "Дружеские ссылки",
"admin/use_friendly_urls_help": "Если включено, чистые веб ссылки будут использованы. Вы должны разрешить использование mod_rewrite и .htaccess чтобы это заработало. {{docLinkStart}}Прочитать больше »{{docLinkEnd}}",
"admin/user": "Пользователь",
"admin/user_deleted": "Пользователь успешно удалён.",
@@ -673,7 +673,7 @@
"general/invalid_timezone": "Часовая зона недействительна",
"general/invalid_token": "Неверный токен, пожалуйста, попробуйте снова.",
"general/ip": "IP",
- "general/latest_member": "Последний Пользователь",
+ "general/latest_member": "Последний пользователь",
"general/leaderboards": "Список лидеров",
"general/link": "Связать",
"general/links": "Ссылки",
@@ -712,7 +712,7 @@
"general/server_offline": "Сервер выключен.",
"general/server_status": "Статус сервера",
"general/sign_in": "Вход",
- "general/social": "Социальных сети",
+ "general/social": "Социальные сети",
"general/spoiler": "Спойлер",
"general/statistics": "Статистика",
"general/status": "Сервера",
@@ -988,7 +988,7 @@
"user/no_about_fields": "Этот пользователь еще не добавил никакой информации о себе.",
"user/no_alerts": "Нет новых уведомлений",
"user/no_alerts_usercp": "У вас нет никаких уведомлений.",
- "user/no_messages": "Нет новых сообщение",
+ "user/no_messages": "Нет новых сообщений",
"user/no_messages_full": "У вас нет никаких сообщений.",
"user/no_placeholders": "Плейсхолдеров нету",
"user/no_profile_posts": "Нету записей в профиле.",
@@ -1061,7 +1061,7 @@
"user/username_minimum_3": "Ваше имя пользователя должно содержать не менее 3-х символов.",
"user/username_required": "Требуется указать имя пользователя.",
"user/users_to_required": "Пожалуйста, введите получателей сообщений",
- "user/validate_account_command": "Для завершения регистрации, пожалуйста, введите команду /verify {{command}} на сервере.",
+ "user/validate_account_command": "Для завершения регистрации, пожалуйста, введите команду {{command}} на сервере.",
"user/validation_complete": "Ваша учетная запись была подтверждена, теперь вы можете войти в систему.",
"user/validation_error": "Неверный код проверки, пользователь уже прошел проверку?",
"user/view_alerts": "Посмотреть уведомления",
@@ -1251,7 +1251,7 @@
"admin/emoji_native": "Обычный",
"admin/emoji_twemoji": "Twemoji",
"admin/emoji_joypixels": "JoyPixels",
- "admin/emoji_style": "Стиль Эмодзи",
+ "admin/emoji_style": "Стиль эмодзи",
"admin/emoji_style_help": "Изменить какой сет эмодзи используется:
• Обычный {{nativeExample}}
• Twemoji {{twemojiExample}}
• JoyPixels {{joypixelsExample}}",
"admin/sent_mass_message": "Успешно отправлено рассылка.",
"admin/unable_to_load_outdated_module": "Не возможно загрузить устаревший модуль {{module}}.",
@@ -1320,5 +1320,12 @@
"admin/queue_task_output": "Вывод задачи",
"admin/queue_task_scheduled_for": "Запланировано для",
"admin/queue_task_status": "Состояние",
- "admin/queue_task_fragment_total": "Информация о фрагменте задачи"
+ "admin/queue_task_fragment_total": "Информация о фрагменте задачи",
+ "admin/reaction_added_event_info": "Реакция добавлена",
+ "admin/reaction_deleted_event_info": "Реакция удалена",
+ "admin/profile_widgets": "Виджеты профиля",
+ "admin/site_widgets": "Виджеты сайта",
+ "general/on": "вкл",
+ "user/integration_linked": "Вы успешно привязали ваш {{integration}} аккаунт.",
+ "user/minecraft_account": "Minecraft Аккаунт"
}
diff --git a/custom/languages/uk_UA.json b/custom/languages/uk_UA.json
index 65e6afdf8e..9977fbca0f 100644
--- a/custom/languages/uk_UA.json
+++ b/custom/languages/uk_UA.json
@@ -1021,7 +1021,7 @@
"user/users_to_required": "Будь ласка, введіть одержувачів повідомлень",
"user/validate_account_command": "Щоб завершити реєстрацію, будь ласка, введіть {{command}} на сервері.",
"user/validation_complete": "Ваш обліковий запис було підтверджено, тепер ви можете увійти до системи.",
- "user/validation_error": "Відбулася невідома помилка під час перевірки вашого облікового запису, будь ласка, звʼяжіться з адміністратором сайту.",
+ "user/validation_error": "Недійсний код перевірки, користувач вже пройшов перевірку?",
"user/view_alerts": "Переглянути повідомлення",
"user/view_messages": "Перегляд повідомлень",
"user/views": "Просмотров профиля:",
@@ -1215,5 +1215,28 @@
"general/problem_loading_widget": "Виникла проблема при завантаженні віджета {{widget}}",
"user/username_already_exists": "Вибране вами ім'я користувача вже використовується.",
"admin/unable_to_load_module": "Помилка {{message}} в модулі{{module}}.",
- "admin/unable_to_load_outdated_module": "Не вдалося завантажити застарілий модуль {{module}}."
+ "admin/unable_to_load_outdated_module": "Не вдалося завантажити застарілий модуль {{module}}.",
+ "admin/discord_hook": "Discord",
+ "admin/emoji_style": "Стиль Емодзі",
+ "admin/image": "Зображення",
+ "admin/profile_widgets": "Віджети профілю",
+ "admin/queue_cancel_task_confirm": "Ви впевнені, що бажаєте скасувати цю задачу?",
+ "admin/enable_auto_language": "Увімкнути автоматичний підбір мови?",
+ "admin/user_warned_webhook": "{{punished}} був попереджений користувачем {{punisher}}.",
+ "admin/authme_db_test_connection": "Перевірити підключення",
+ "admin/authme_db_connection_success": "Успішне підключення",
+ "admin/authme_db_connection_failed": "Помилка підключення",
+ "admin/clone_group": "Клонувати групу",
+ "admin/query_type": "Тип запиту",
+ "admin/internal": "Внутрішній",
+ "admin/external": "Зовнішній",
+ "admin/plugin": "Плагін",
+ "admin/queue": "Черга",
+ "admin/confirm_delete_placeholder": "Ви певні, що бажаєте видалити цей плейсхолдер?",
+ "admin/emoji_native": "Звичайний",
+ "admin/emoji_twemoji": "Twemoji",
+ "admin/emoji_joypixels": "JoyPixels",
+ "admin/queue_cancel_task": "Скасувати задачу",
+ "admin/queue_interval": "Інтервал черги (хвилини)",
+ "admin/queue_interval_required": "Будь ласка, введіть інтервал черги"
}
diff --git a/custom/panel_templates/Default/template.php b/custom/panel_templates/Default/template.php
index 7c880f0054..c558b3c9da 100644
--- a/custom/panel_templates/Default/template.php
+++ b/custom/panel_templates/Default/template.php
@@ -5,7 +5,7 @@
*
* For NamelessMC
* https://github.com/NamelessMC/Nameless/
- * NamelessMC version 2.1.1
+ * NamelessMC version 2.1.2
*
* License: MIT
*
@@ -24,8 +24,8 @@ public function __construct(Smarty $smarty, Language $language) {
parent::__construct(
'Default', // Template name
- '2.1.1', // Template version
- '2.1.1', // Nameless version template is made for
+ '2.1.2', // Template version
+ '2.1.2', // Nameless version template is made for
'Coldfire' // Author, you can use HTML here
);
diff --git a/custom/templates/DefaultRevamp/members/members.tpl b/custom/templates/DefaultRevamp/members/members.tpl
index ec3f0baf69..f52dcd28cc 100644
--- a/custom/templates/DefaultRevamp/members/members.tpl
+++ b/custom/templates/DefaultRevamp/members/members.tpl
@@ -167,7 +167,7 @@
{/if}
const nameDiv = document.createElement('span');
- nameDiv.style = member.group_style;
+ nameDiv.style = member.group_style?.replace(''', "'")?.replace('"', '"');
{if $VIEWING_LIST != "overview"}
nameDiv.innerHTML = member.username + ' ' + member.group_html.join('');
{else}
diff --git a/custom/templates/DefaultRevamp/template.php b/custom/templates/DefaultRevamp/template.php
index 138079d8e8..8db2862b1d 100755
--- a/custom/templates/DefaultRevamp/template.php
+++ b/custom/templates/DefaultRevamp/template.php
@@ -2,7 +2,7 @@
/*
* Made by Samerton | Revamped by Xemah
* https://github.com/NamelessMC/Nameless/
- * NamelessMC version 2.1.1
+ * NamelessMC version 2.1.2
*
* License: MIT
*
@@ -25,8 +25,8 @@ class DefaultRevamp_Template extends TemplateBase {
public function __construct($cache, $smarty, $language, $user, $pages) {
$template = [
'name' => 'DefaultRevamp',
- 'version' => '2.1.1',
- 'nl_version' => '2.1.1',
+ 'version' => '2.1.2',
+ 'nl_version' => '2.1.2',
'author' => 'Xemah',
];
diff --git a/dev/scripts/delete_empty_language_strings.php b/dev/scripts/delete_empty_language_strings.php
index c707b1485c..dcac194bd7 100644
--- a/dev/scripts/delete_empty_language_strings.php
+++ b/dev/scripts/delete_empty_language_strings.php
@@ -1,5 +1,9 @@
str:
+ # Copy all files that should be included to a temporary directory
+ archive_temp = tempfile.mkdtemp(prefix='nameless')
for include_file in INCLUDE_FILES:
include_path = Path(archive_source, include_file)
@@ -43,11 +47,11 @@ def create_archives(archive_name: str, archive_source: str = '.'):
if include_path.exists():
shutil.copytree(include_path, Path(archive_temp, include_dir))
- if Path(archive_source, 'vendor').exists():
- print('Archive: Generate checksums')
- subprocess.check_call(['php', 'dev/scripts/generate_checksums.php'],
- shell=False,
- cwd=archive_temp)
+ return archive_temp
+
+
+def create_archives(archive_name, cwd):
+ archive_path: str = Path('release', archive_name).absolute().as_posix()
print('Archive: Creating .zip file')
zip_command = [
@@ -57,7 +61,7 @@ def create_archives(archive_name: str, archive_source: str = '.'):
f'{archive_path}.zip',
'.',
]
- subprocess.check_call(zip_command, shell=False, cwd=archive_temp)
+ subprocess.check_call(zip_command, shell=False, cwd=cwd)
print('Archive: Creating .tar.xz file')
@@ -71,35 +75,40 @@ def create_archives(archive_name: str, archive_source: str = '.'):
'.',
]
- subprocess.check_call(tar_command, shell=False, cwd=archive_temp,
+ subprocess.check_call(tar_command, shell=False, cwd=cwd,
env={'XZ_DEFAULTS': '-T 0'}) # Enable multithreading
- shutil.rmtree(archive_temp)
+def regenerate_vendor_files():
+ print('Re-generating vendor files')
+ shutil.rmtree('core/assets/vendor', ignore_errors=True)
+ subprocess.check_call(['composer', 'update'])
+ subprocess.check_call(['composer', 'install', '--no-dev', '--no-interaction'])
-if __name__ == '__main__':
- if not Path('.git').exists():
- print('.git does not exist')
- sys.exit(1)
- print('Deleting vendor files')
- shutil.rmtree('core/assets/vendor', ignore_errors=True)
- shutil.rmtree('node_modules', ignore_errors=True)
- shutil.rmtree('vendor', ignore_errors=True)
+def create_deps_dist_archive():
+ print('Creating nameless-deps-dist archive')
+ # Copy the required files to a new temporary directory
+ deps_dist_temp = create_archive_dir()
+ # Generate checksums
+ generate_checksums(deps_dist_temp)
+ # Create .zip and .tar.xz archives
+ create_archives('nameless-deps-dist', deps_dist_temp)
+ # Temporary directory can now be deleted
+ shutil.rmtree(deps_dist_temp)
- # Create base archive
- create_archives('nameless-base')
- # Run npm and composer (production dependencies only)
- subprocess.check_call(['npm', 'ci', '-q', '--cache', '.node_cache'])
- subprocess.check_call(['composer', 'update'])
- subprocess.check_call(['composer', 'install', '--no-dev', '--no-interaction'])
+def always_in_update_package(relative_path: str) -> bool:
+ return relative_path == 'checksums.json' or relative_path.startswith('vendor/') or relative_path.startswith('core/assets/vendor')
- create_archives('nameless-deps-dist')
- # Create archive with files changed since last update
+def create_upgrade_archive():
+ print('Creating update archive')
- upgrade_temp = Path('release', 'upgrade_temp')
+ # Copy the required files to a new temporary directory
+ upgrade_temp = create_archive_dir()
+ # Generate checksums
+ generate_checksums(upgrade_temp)
# Find previous tag
previous_tag_command = ['git', 'describe', '--abbrev=0', '--tags']
@@ -109,19 +118,53 @@ def create_archives(archive_name: str, archive_source: str = '.'):
# Find all files changed between previous tag and HEAD (current state)
changed_command = ['git', 'diff', previous_tag, 'HEAD', '--name-only', '--diff-filter=d']
- changed_files = subprocess.check_output(changed_command, shell=False)[:-1].decode()
+ changed_files_output = subprocess.check_output(changed_command, shell=False)[:-1]
+ changed_files = set(changed_files_output.decode().split('\n'))
+
+ # Delete any files that have not been changed
+ for path in Path(upgrade_temp).rglob("*"):
+ relative_path = path.as_posix()[len(upgrade_temp)+1:]
+ if (
+ not always_in_update_package(relative_path) and
+ relative_path not in changed_files and
+ path.is_file()
+ ):
+ path.unlink()
+
+ # Delete empty directoryes
+ subprocess.check_call(['find', '.', '-type', 'd', '-empty', '-delete'], cwd=upgrade_temp)
+
+ # Create .zip and .tar.xz archives
+ create_archives('upgrade-from-' + previous_tag, upgrade_temp)
+
+
+def create_deps_dev_archive():
+ print('Creating nameless-deps-dev archive')
+ # Copy the required files to a new temporary directory
+ deps_dev_temp = create_archive_dir()
+ # Generate checksums
+ generate_checksums(deps_dev_temp)
+ # Create .zip and .tar.xz archives
+ create_archives('nameless-deps-dev', deps_dev_temp)
+ # Temporary directory can now be deleted
+ shutil.rmtree(deps_dev_temp)
+
+
+if __name__ == '__main__':
+ if not Path('.git').exists():
+ print('.git does not exist')
+ sys.exit(1)
- for changed_file in changed_files.split('\n'):
- changed_file_target = Path(upgrade_temp, changed_file)
- changed_file_target.parent.mkdir(parents=True, exist_ok=True)
- shutil.copy2(changed_file, changed_file_target)
+ # Re-generate vendor files (without development dependencies)
+ regenerate_vendor_files()
- # Vendor files are always included
- for vendor_dir in ['vendor', 'core/assets/vendor']:
- shutil.copytree(vendor_dir, Path(upgrade_temp, vendor_dir))
+ # Create nameless-deps-dist archive with production dependencies only
+ create_deps_dist_archive()
- create_archives('upgrade-from-' + previous_tag, archive_source=upgrade_temp.as_posix())
+ # Create update archive (files changed since last tag)
+ create_upgrade_archive()
# Run composer again, to install development dependencies
subprocess.check_call(['composer', 'install', '--no-interaction'])
- create_archives('nameless-deps-dev')
+ # Create nameless-deps-dev archive with development dependencies
+ create_deps_dev_archive()
diff --git a/dev/scripts/verify_checksums.php b/dev/scripts/verify_checksums.php
index 1c09fb8812..066a629f0f 100644
--- a/dev/scripts/verify_checksums.php
+++ b/dev/scripts/verify_checksums.php
@@ -1,5 +1,9 @@
Samerton';
- $module_version = '2.1.1';
- $nameless_version = '2.1.1';
+ $module_version = '2.1.2';
+ $nameless_version = '2.1.2';
parent::__construct($this, $name, $author, $module_version, $nameless_version);
diff --git a/modules/Core/includes/endpoints/UpdateGroupsEndpoint.php b/modules/Core/includes/endpoints/UpdateGroupsEndpoint.php
index 4a8fe0f396..d74a3101fb 100644
--- a/modules/Core/includes/endpoints/UpdateGroupsEndpoint.php
+++ b/modules/Core/includes/endpoints/UpdateGroupsEndpoint.php
@@ -13,25 +13,28 @@ public function execute(Nameless2API $api): void {
$api->validateParams($_POST, ['server_id', 'player_groups']);
$server_id = $_POST['server_id'];
- $group_sync_log = [];
- if (Util::getSetting('mc_integration') && $server_id == Util::getSetting('group_sync_mc_server')) {
- $integration = Integrations::getInstance()->getIntegration('Minecraft');
+ if (!Settings::get('mc_integration') || $server_id != Settings::get('group_sync_mc_server')) {
+ $api->returnArray(['message' => $api->getLanguage()->get('api', 'groups_updates_ignored')]);
+ }
- foreach ($_POST['player_groups'] as $uuid => $groups) {
- $integrationUser = new IntegrationUser($integration, str_replace('-', '', $uuid), 'identifier');
- if ($integrationUser->exists()) {
- $log = $this->updateGroups($integrationUser, $groups['groups']);
- if (count($log)) {
- $group_sync_log[] = $log;
- }
+ $group_sync_log = [];
+ $integration = Integrations::getInstance()->getIntegration('Minecraft');
+
+ foreach ($_POST['player_groups'] as $uuid => $groups) {
+ $integrationUser = new IntegrationUser($integration, str_replace('-', '', $uuid), 'identifier');
+ if ($integrationUser->exists()) {
+ $log = $this->updateGroups($integrationUser, $groups['groups']);
+ if (count($log)) {
+ $group_sync_log[] = $log;
}
}
-
- $api->returnArray(array_merge(['message' => $api->getLanguage()->get('api', 'groups_updates_successfully')], ['log' => $group_sync_log]));
}
- $api->throwError(CoreApiErrors::ERROR_INVALID_SERVER_ID, $server_id);
+ $api->returnArray([
+ 'message' => $api->getLanguage()->get('api', 'groups_updates_successfully'),
+ 'log' => $group_sync_log,
+ ]);
}
private function updateGroups(IntegrationUser $integrationUser, array $groups): array {
diff --git a/modules/Core/module.php b/modules/Core/module.php
index f3814fe54c..6421fceccd 100644
--- a/modules/Core/module.php
+++ b/modules/Core/module.php
@@ -2,7 +2,7 @@
/*
* Made by Samerton
* https://github.com/NamelessMC/Nameless/
- * NamelessMC version 2.1.1
+ * NamelessMC version 2.1.2
*
* License: MIT
*
@@ -21,8 +21,8 @@ public function __construct(Language $language, Pages $pages, User $user, Naviga
$name = 'Core';
$author = 'Samerton';
- $module_version = '2.1.1';
- $nameless_version = '2.1.1';
+ $module_version = '2.1.2';
+ $nameless_version = '2.1.2';
parent::__construct($this, $name, $author, $module_version, $nameless_version);
diff --git a/modules/Core/pages/panel/security.php b/modules/Core/pages/panel/security.php
index b04f0a5bb9..838bb91a12 100644
--- a/modules/Core/pages/panel/security.php
+++ b/modules/Core/pages/panel/security.php
@@ -2,7 +2,7 @@
/*
* Made by Samerton
* https://github.com/NamelessMC/Nameless/
- * NamelessMC version 2.0.0-pr9
+ * NamelessMC version 2.1.2
*
* License: MIT
*
@@ -74,7 +74,7 @@
}
$log_title = $language->get('admin', 'acp_logins');
- $logs = DB::getInstance()->orderWhere('logs', 'action = \'acp_login\'', 'time', 'DESC')->results();
+ $logs = DB::getInstance()->orderWhere('logs', 'action = \'acp_login\'', 'time', 'DESC LIMIT 500')->results();
$cols = 3;
$col_titles = [
@@ -111,7 +111,7 @@
}
$log_title = $language->get('admin', 'template_changes');
- $logs = DB::getInstance()->orderWhere('logs', 'action = \'acp_template_update\'', 'time', 'DESC')->results();
+ $logs = DB::getInstance()->orderWhere('logs', 'action = \'acp_template_update\'', 'time', 'DESC LIMIT 500')->results();
$cols = 4;
$col_titles = [
@@ -152,7 +152,7 @@
}
$log_title = $language->get('admin', 'email_logs');
- $logs = DB::getInstance()->orderWhere('logs', 'action = \'acp_email_mass_message\'', 'time', 'DESC')->results();
+ $logs = DB::getInstance()->orderWhere('logs', 'action = \'acp_email_mass_message\'', 'time', 'DESC LIMIT 500')->results();
$cols = 3;
$col_titles = [
@@ -188,7 +188,7 @@
}
$log_title = $language->get('admin', 'group_sync_logs');
- $logs_set = DB::getInstance()->orderWhere('logs', 'action = \'discord_role_set\' OR action = \'mc_group_sync_set\' ', 'time', 'DESC')->results();
+ $logs_set = DB::getInstance()->orderWhere('logs', 'action LIKE \'%_role_set\' OR action LIKE \'%_group_set\'OR action = \'mc_group_sync_set\' ', 'time', 'DESC LIMIT 500')->results();
$cols = 5;
$col_titles = [
@@ -246,7 +246,7 @@
}
$log_title = $language->get('admin', 'all_logs');
- $logs = DB::getInstance()->orderWhere('logs', 'id <> 0', 'time', 'DESC')->results();
+ $logs = DB::getInstance()->orderWhere('logs', 'id <> 0', 'time', 'DESC LIMIT 500')->results();
$cols = 5;
$col_titles = [
diff --git a/modules/Core/pages/register.php b/modules/Core/pages/register.php
index 547b39170c..2b88ecd9d7 100644
--- a/modules/Core/pages/register.php
+++ b/modules/Core/pages/register.php
@@ -2,7 +2,7 @@
/*
* Made by Samerton
* https://github.com/NamelessMC/Nameless/
- * NamelessMC version 2.0.0-pr13
+ * NamelessMC version 2.1.2
*
* License: MIT
*
@@ -278,8 +278,7 @@
$data['id'],
);
$auto_verify_oauth_email = $data['email'] === Input::get('email')
- && NamelessOAuth::getInstance()->hasVerifiedEmail($data['provider'], $data['data'])
- && DB::getInstance()->get('users', ['email', $data['email']])->count() === 0;
+ && NamelessOAuth::getInstance()->hasVerifiedEmail($data['provider'], $data['data']);
Session::delete('oauth_register_data');
}
diff --git a/modules/Discord Integration/classes/DiscordIntegration.php b/modules/Discord Integration/classes/DiscordIntegration.php
index b191d876b6..f34b26c4f3 100644
--- a/modules/Discord Integration/classes/DiscordIntegration.php
+++ b/modules/Discord Integration/classes/DiscordIntegration.php
@@ -4,7 +4,7 @@
*
* @package Modules\Core\Integrations
* @author Partydragen
- * @version 2.1.1
+ * @version 2.1.2
* @license MIT
*/
class DiscordIntegration extends IntegrationBase {
@@ -75,6 +75,7 @@ public function onSuccessfulVerification(IntegrationUser $integrationUser) {
}, $user->getAllGroupIds()));
Discord::updateDiscordRoles($user, $roles, []);
+ Session::flash('connections_success', $this->_language->get('user', 'integration_linked', ['integration' => Output::getClean($this->_name)]));
}
public function validateUsername(string $username, int $integration_user_id = 0): bool {
diff --git a/modules/Discord Integration/module.php b/modules/Discord Integration/module.php
index 03ad2dc7f4..a752617b0f 100644
--- a/modules/Discord Integration/module.php
+++ b/modules/Discord Integration/module.php
@@ -9,8 +9,8 @@ public function __construct(Language $language, Pages $pages, Endpoints $endpoin
$name = 'Discord Integration';
$author = 'Aberdeener';
- $module_version = '2.1.1';
- $nameless_version = '2.1.1';
+ $module_version = '2.1.2';
+ $nameless_version = '2.1.2';
parent::__construct($this, $name, $author, $module_version, $nameless_version);
diff --git a/modules/Forum/classes/Forum.php b/modules/Forum/classes/Forum.php
index 1c8b862457..7cdf4a57ef 100644
--- a/modules/Forum/classes/Forum.php
+++ b/modules/Forum/classes/Forum.php
@@ -62,7 +62,15 @@ public function listAllForums(array $groups = [0], int $user_id = 0): array {
// Get discussion forums
$forums = $this->_db->query(
<<getAnySubforums($item->id, $groups, 0, true, $user_id);
- $latest_post = [$item->last_post_date, $item->last_user_posted, $item->last_topic_posted];
+ if ($item->view_other_topics) {
+ $latest_post = [$item->last_post_date, $item->last_user_posted, $item->last_topic_posted];
+ } else {
+ $latest_post = $this->getLatestPostInOwnTopicForum($item->id, $user_id);
+ }
if (count($subforums)) {
$return[$forum->id]['subforums'][$item->id]->subforums = [];
@@ -733,41 +745,18 @@ public function getAnySubforums(
foreach ($subforums_query->results() as $result) {
$to_add = new stdClass();
- $to_add->id = Output::getClean($result->id);
+ $to_add->id = $result->id;
$to_add->forum_title = Output::getClean($result->forum_title);
$to_add->icon = Output::getPurified($result->icon);
$to_add->category = false;
// Latest post
- if ($onlyOwnTopics && $result->view_other_topics != '1') {
- // Get the latest topic that the user can view
- $latest_post = $this->_db->query(
- <<id, $user_id]
- );
-
- if ($latest_post->count() && $latest_post = $latest_post->first()) {
- $to_add->last_post_date = $latest_post->created ?? strtotime($latest_post->post_date);
- $to_add->last_user_posted = $latest_post->post_creator;
- $to_add->last_topic_posted = $latest_post->topic_id;
- }
+ if ($onlyOwnTopics && $result->view_other_topics !== 1) {
+ [
+ $to_add->last_post_date,
+ $to_add->last_user_posted,
+ $to_add->last_topic_posted,
+ ] = $this->getLatestPostInOwnTopicForum($result->id, $user_id);
} else {
$to_add->last_post_date = $result->last_post_date;
$to_add->last_user_posted = $result->last_user_posted;
@@ -776,7 +765,7 @@ public function getAnySubforums(
$ret[] = $to_add;
- $subforums = $this->getAnySubforums($result->id, $groups, ++$depth);
+ $subforums = $this->getAnySubforums($result->id, $groups, ++$depth, $onlyOwnTopics, $user_id);
if (count($subforums)) {
foreach ($subforums as $subforum) {
@@ -808,4 +797,47 @@ public static function getAccessibleLabels(array $labels, array $user_groups): a
return $prev;
}, []);
}
+
+ /**
+ * Get the latest post in a "View own topic" forum
+ * This could be a topic created by the user, or a sticky topic
+ *
+ * @param int $forumId
+ * @param int $userId
+ * @return array|null Time of latest post, post creator ID, topic ID
+ */
+ private function getLatestPostInOwnTopicForum(int $forumId, int $userId): ?array {
+ $latest_post = $this->_db->query(
+ <<count() && $latest_post = $latest_post->first()) {
+ return [
+ $latest_post->created ?? strtotime($latest_post->post_date),
+ $latest_post->post_creator,
+ $latest_post->topic_id,
+ ];
+ }
+
+ return null;
+ }
}
diff --git a/modules/Forum/language/cs_CZ.json b/modules/Forum/language/cs_CZ.json
index fcf278bec4..aeccee1863 100644
--- a/modules/Forum/language/cs_CZ.json
+++ b/modules/Forum/language/cs_CZ.json
@@ -177,11 +177,12 @@
"forum/label_type_in_use": "Typ štítku je používán, nelze jej odstranit.",
"forum/latest_posts_limit": "Limit nejnovějších příspěvků",
"forum/latest_posts_widget_cached": "Widget nejnovějších příspěvků je uložen v mezipaměti po dobu jedné minuty, vaše změny se nemusí projevit okamžitě.",
- "forum/highest_reaction_scores": "Nejvyšší reakční skóre",
+ "forum/highest_reaction_scores": "Nejvyšší reakční skóre fóra",
"forum/reaction_score": "Reakční skóre",
"forum/most_posts": "Nejvíce příspěvků",
"forum/no_posts_found": "Nenalezeny žádné příspěvky.",
"forum/news_items_max": "Počet novinek by měl být maximálně {{max}}",
"forum/news_items_min": "Počet novinek by měl být alespoň {{min}}",
- "forum/news_items_front_page_limit": "Počet novinek, které mají být zobrazeny na hlavní stránce"
+ "forum/news_items_front_page_limit": "Počet novinek, které mají být zobrazeny na hlavní stránce",
+ "forum/forum_score": "Skóre fóra"
}
diff --git a/modules/Forum/language/de_DE.json b/modules/Forum/language/de_DE.json
index 2b26b1a24b..daf8a95262 100644
--- a/modules/Forum/language/de_DE.json
+++ b/modules/Forum/language/de_DE.json
@@ -177,11 +177,12 @@
"forum/label_type_in_use": "Der Etikettentyp wird verwendet und kann nicht gelöscht werden.",
"forum/latest_posts_widget_cached": "Das Widget für die neuesten Beiträge wird eine Minute lang zwischengespeichert, so dass deine Änderungen möglicherweise nicht sofort wirksam werden.",
"forum/latest_posts_limit": "Letzte Beiträge begrenzen",
- "forum/highest_reaction_scores": "Höchster Reaktionsanzahl",
+ "forum/highest_reaction_scores": "Höchste Reaktionswerte im Forum",
"forum/most_posts": "Die meisten Beiträge",
"forum/reaction_score": "Reaktionsanzahl",
"forum/no_posts_found": "Keine Beiträge gefunden.",
"forum/news_items_front_page_limit": "Anzahl der News, die auf der Titelseite angezeigt werden sollen",
"forum/news_items_max": "Die Anzahl der News sollte mindestens {{max}} sein",
- "forum/news_items_min": "Die Anzahl der News sollte mindestens {{min}} sein"
+ "forum/news_items_min": "Die Anzahl der News sollte mindestens {{min}} sein",
+ "forum/forum_score": "Forum Punkte"
}
diff --git a/modules/Forum/language/ru_RU.json b/modules/Forum/language/ru_RU.json
index a3269f793a..348a5499b1 100644
--- a/modules/Forum/language/ru_RU.json
+++ b/modules/Forum/language/ru_RU.json
@@ -78,7 +78,7 @@
"forum/label_type_name": "Название типа метки",
"forum/label_types": "Типы меток",
"forum/labels": "Метки",
- "forum/last_7_days_posts": "Сообщения на форума (последние 7 дней)",
+ "forum/last_7_days_posts": "Сообщения на форуме (последние 7 дней)",
"forum/last_edited": "Последнее редактирование: {{lastEditedAt}}",
"forum/last_reply": "Последний ответ",
"forum/latest_announcements": "Последние новости",
diff --git a/modules/Forum/module.php b/modules/Forum/module.php
index 6d2ae791b1..7d0bfad6bd 100644
--- a/modules/Forum/module.php
+++ b/modules/Forum/module.php
@@ -2,7 +2,7 @@
/*
* Made by Samerton
* https://github.com/NamelessMC/Nameless/
- * NamelessMC version 2.1.1
+ * NamelessMC version 2.1.2
*
* License: MIT
*
@@ -20,8 +20,8 @@ public function __construct(Language $language, Language $forum_language, Pages
$name = 'Forum';
$author = 'Samerton';
- $module_version = '2.1.1';
- $nameless_version = '2.1.1';
+ $module_version = '2.1.2';
+ $nameless_version = '2.1.2';
parent::__construct($this, $name, $author, $module_version, $nameless_version);
diff --git a/modules/Forum/pages/forum/view_forum.php b/modules/Forum/pages/forum/view_forum.php
index e8040fca3f..742a7abbf4 100644
--- a/modules/Forum/pages/forum/view_forum.php
+++ b/modules/Forum/pages/forum/view_forum.php
@@ -192,7 +192,7 @@
if ($forum->canViewOtherTopics($subforum->id, $user_groups)) {
$latest_post = DB::getInstance()->query('SELECT * FROM nl2_topics WHERE forum_id = ? AND deleted = 0 ORDER BY topic_reply_date DESC', [$subforum->id])->results();
} else {
- $latest_post = DB::getInstance()->query('SELECT * FROM nl2_topics WHERE forum_id = ? AND deleted = 0 AND topic_creator = ? ORDER BY topic_reply_date DESC', [$subforum->id, $user_id])->results();
+ $latest_post = DB::getInstance()->query('SELECT * FROM nl2_topics WHERE forum_id = ? AND deleted = 0 AND (topic_creator = ? OR sticky = 1) ORDER BY topic_reply_date DESC', [$subforum->id, $user_id])->results();
}
$subforum_topics = count($latest_post);
diff --git a/modules/Members/language/en_US.json b/modules/Members/language/en_US.json
index 056346e2da..50a622c328 100644
--- a/modules/Members/language/en_US.json
+++ b/modules/Members/language/en_US.json
@@ -1,5 +1,5 @@
{
- "members/members": "Menbers",
+ "members/members": "Members",
"members/new_members": "New members",
"members/no_members": "No members found.",
"members/member_lists": "Member Lists",
diff --git a/modules/Members/module.php b/modules/Members/module.php
index 6a2cd24b8b..4ccfbe36a7 100644
--- a/modules/Members/module.php
+++ b/modules/Members/module.php
@@ -2,7 +2,7 @@
/*
* Made by Aberdeener
* https://github.com/NamelessMC/Nameless/
- * NamelessMC version 2.1.1
+ * NamelessMC version 2.1.2
*
* License: MIT
*
@@ -20,8 +20,8 @@ public function __construct(Language $language, Language $members_language, Page
$name = 'Members';
$author = 'Aberdeener';
- $module_version = '2.1.1';
- $nameless_version = '2.1.1';
+ $module_version = '2.1.2';
+ $nameless_version = '2.1.2';
parent::__construct($this, $name, $author, $module_version, $nameless_version);
diff --git a/package.json b/package.json
index d155a04f36..4e854444b2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "nameless",
- "version": "2.1.1",
+ "version": "2.1.2",
"repository": "https://github.com/NamelessMC/Nameless",
"license": "MIT",
"private": true,