From 89db5e219264fc28473605936a211c64c944096b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC?= <68551925+Artem13327@users.noreply.github.com> Date: Thu, 8 Sep 2022 00:02:11 +0300 Subject: [PATCH 001/285] The user must agree to the rules in order to register. (#716) --- .idea/deployment.xml | 14 ++++++++++++++ .idea/discord.xml | 7 +++++++ Web/Presenters/AuthPresenter.php | 3 +++ Web/Presenters/templates/Auth/Register.xml | 5 ++++- locales/ru.strings | 2 ++ 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 .idea/deployment.xml create mode 100644 .idea/discord.xml diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 00000000..dc2a86a5 --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 00000000..30bab2ab --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/Web/Presenters/AuthPresenter.php b/Web/Presenters/AuthPresenter.php index f934f7fe..bb9d7272 100644 --- a/Web/Presenters/AuthPresenter.php +++ b/Web/Presenters/AuthPresenter.php @@ -84,6 +84,9 @@ final class AuthPresenter extends OpenVKPresenter if (strtotime($this->postParam("birthday")) > time()) $this->flashFail("err", tr("invalid_birth_date"), tr("invalid_birth_date_comment")); + if (!$this->postParam("confirmation")) + $this->flashFail("err", tr("error"), tr("checkbox_in_registration_unchecked")); + try { $user = new User; $user->setFirst_Name($this->postParam("first_name")); diff --git a/Web/Presenters/templates/Auth/Register.xml b/Web/Presenters/templates/Auth/Register.xml index 23f40aa1..16532cb1 100644 --- a/Web/Presenters/templates/Auth/Register.xml +++ b/Web/Presenters/templates/Auth/Register.xml @@ -87,12 +87,15 @@ {captcha_template()|noescape} + - + + {_checkbox_in_registration|noescape} +

{_log_in} diff --git a/locales/ru.strings b/locales/ru.strings index abdee6ff..68f6d69f 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -15,6 +15,8 @@ "password" = "Пароль"; "registration" = "Регистрация"; "forgot_password" = "Забыли пароль?"; +"checkbox_in_registration" = "Я согласен с политикой конфиденциальности и правилами сайта"; +"checkbox_in_registration_unchecked" = "Вы должны согласиться с политикой конфиденциальности и правилами, чтобы зарегистрироваться."; "login_failed" = "Не удалось войти"; "invalid_username_or_password" = "Неверное имя пользователя или пароль. Забыли пароль?"; From 38e51a2b9d3d82622f19b816d20d6a544bd85495 Mon Sep 17 00:00:00 2001 From: n1rwana Date: Thu, 8 Sep 2022 00:06:17 +0300 Subject: [PATCH 002/285] Deleted the files added by PhpStorm in the previous commit --- .idea/.gitignore | 8 - .idea/deployment.xml | 14 - .idea/discord.xml | 7 - .idea/intellij-latte/xmlSources/Latte.dtd | 46 --- .idea/intellij-latte/xmlSources/Latte.xml | 290 ------------------ .../xmlSources/NetteApplication.xml | 59 ---- .../intellij-latte/xmlSources/NetteForms.xml | 41 --- .idea/misc.xml | 6 - .idea/modules.xml | 8 - .idea/openvk.iml | 46 --- .idea/php.xml | 48 --- .idea/runConfigurations.xml | 10 - .idea/vcs.xml | 6 - 13 files changed, 589 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/deployment.xml delete mode 100644 .idea/discord.xml delete mode 100644 .idea/intellij-latte/xmlSources/Latte.dtd delete mode 100644 .idea/intellij-latte/xmlSources/Latte.xml delete mode 100644 .idea/intellij-latte/xmlSources/NetteApplication.xml delete mode 100644 .idea/intellij-latte/xmlSources/NetteForms.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/openvk.iml delete mode 100644 .idea/php.xml delete mode 100644 .idea/runConfigurations.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/deployment.xml b/.idea/deployment.xml deleted file mode 100644 index dc2a86a5..00000000 --- a/.idea/deployment.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml deleted file mode 100644 index 30bab2ab..00000000 --- a/.idea/discord.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/intellij-latte/xmlSources/Latte.dtd b/.idea/intellij-latte/xmlSources/Latte.dtd deleted file mode 100644 index 0cf3a95a..00000000 --- a/.idea/intellij-latte/xmlSources/Latte.dtd +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.idea/intellij-latte/xmlSources/Latte.xml b/.idea/intellij-latte/xmlSources/Latte.xml deleted file mode 100644 index 0bfceaf8..00000000 --- a/.idea/intellij-latte/xmlSources/Latte.xml +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/intellij-latte/xmlSources/NetteApplication.xml b/.idea/intellij-latte/xmlSources/NetteApplication.xml deleted file mode 100644 index aa4a4685..00000000 --- a/.idea/intellij-latte/xmlSources/NetteApplication.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/intellij-latte/xmlSources/NetteForms.xml b/.idea/intellij-latte/xmlSources/NetteForms.xml deleted file mode 100644 index 036e07f6..00000000 --- a/.idea/intellij-latte/xmlSources/NetteForms.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 639900d1..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index de1f1bbf..00000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/openvk.iml b/.idea/openvk.iml deleted file mode 100644 index fe58bea6..00000000 --- a/.idea/openvk.iml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml deleted file mode 100644 index 7b4f97fd..00000000 --- a/.idea/php.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 797acea5..00000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1ddf..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From e28964c813c14b9d51ab1f748fc9d198219a3807 Mon Sep 17 00:00:00 2001 From: n1rwana Date: Thu, 8 Sep 2022 00:22:15 +0300 Subject: [PATCH 003/285] =?UTF-8?q?Now=20only=20unnecessary=20PhpStorm=20f?= =?UTF-8?q?iles=20are=20removed=F0=9F=91=89=F0=9F=8F=BB=F0=9F=91=88?= =?UTF-8?q?=F0=9F=8F=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 8 + .idea/intellij-latte/xmlSources/Latte.dtd | 35 +++ .idea/intellij-latte/xmlSources/Latte.xml | 290 ++++++++++++++++++ .../xmlSources/NetteApplication.xml | 59 ++++ .../intellij-latte/xmlSources/NetteForms.xml | 41 +++ .idea/misc.xml | 6 + .idea/modules.xml | 8 + .idea/openvk.iml | 46 +++ .idea/php.xml | 48 +++ .idea/runConfigurations.xml | 10 + .idea/vcs.xml | 6 + 11 files changed, 557 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/intellij-latte/xmlSources/Latte.dtd create mode 100644 .idea/intellij-latte/xmlSources/Latte.xml create mode 100644 .idea/intellij-latte/xmlSources/NetteApplication.xml create mode 100644 .idea/intellij-latte/xmlSources/NetteForms.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/openvk.iml create mode 100644 .idea/php.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..ecca0076 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml \ No newline at end of file diff --git a/.idea/intellij-latte/xmlSources/Latte.dtd b/.idea/intellij-latte/xmlSources/Latte.dtd new file mode 100644 index 00000000..9b8273f5 --- /dev/null +++ b/.idea/intellij-latte/xmlSources/Latte.dtd @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/intellij-latte/xmlSources/Latte.xml b/.idea/intellij-latte/xmlSources/Latte.xml new file mode 100644 index 00000000..e7bb3f7a --- /dev/null +++ b/.idea/intellij-latte/xmlSources/Latte.xml @@ -0,0 +1,290 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/intellij-latte/xmlSources/NetteApplication.xml b/.idea/intellij-latte/xmlSources/NetteApplication.xml new file mode 100644 index 00000000..aa4a4685 --- /dev/null +++ b/.idea/intellij-latte/xmlSources/NetteApplication.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/intellij-latte/xmlSources/NetteForms.xml b/.idea/intellij-latte/xmlSources/NetteForms.xml new file mode 100644 index 00000000..036e07f6 --- /dev/null +++ b/.idea/intellij-latte/xmlSources/NetteForms.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..f4364fd5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..af99c76e --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/openvk.iml b/.idea/openvk.iml new file mode 100644 index 00000000..16097db5 --- /dev/null +++ b/.idea/openvk.iml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 00000000..28cf2b65 --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 00000000..7b45e612 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..9db25eef --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 384c0da78b90085b243cb43b53c1d36df8e3483a Mon Sep 17 00:00:00 2001 From: celestora Date: Mon, 12 Sep 2022 20:46:40 +0300 Subject: [PATCH 004/285] Revert Clubs::getPopularClubs change This functionality is so unstable it causes majority of installations to fail miserably out of the box. The performance also is a major concern. Might re-add later. Sometime. btw i amended --- Web/Models/Repositories/Clubs.php | 4 ++++ Web/Presenters/AboutPresenter.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Web/Models/Repositories/Clubs.php b/Web/Models/Repositories/Clubs.php index b7b59251..4a1b28fe 100644 --- a/Web/Models/Repositories/Clubs.php +++ b/Web/Models/Repositories/Clubs.php @@ -45,6 +45,9 @@ class Clubs function getPopularClubs(): \Traversable { + // TODO rewrite + + /* $query = "SELECT ROW_NUMBER() OVER (ORDER BY `subscriptions` DESC) as `place`, `target` as `id`, COUNT(`follower`) as `subscriptions` FROM `subscriptions` WHERE `model` = \"openvk\\\Web\\\Models\\\Entities\\\Club\" GROUP BY `target` ORDER BY `subscriptions` DESC, `id` LIMIT 30;"; $entries = DatabaseConnection::i()->getConnection()->query($query); @@ -54,6 +57,7 @@ class Clubs "club" => $this->get($entry["id"]), "subscriptions" => $entry["subscriptions"], ]; + */ } use \Nette\SmartObject; diff --git a/Web/Presenters/AboutPresenter.php b/Web/Presenters/AboutPresenter.php index 6a281d07..dd503aff 100644 --- a/Web/Presenters/AboutPresenter.php +++ b/Web/Presenters/AboutPresenter.php @@ -64,7 +64,7 @@ final class AboutPresenter extends OpenVKPresenter $this->template->usersStats = (new Users)->getStatistics(); $this->template->clubsCount = (new Clubs)->getCount(); $this->template->postsCount = (new Posts)->getCount(); - $this->template->popularClubs = iterator_to_array((new Clubs)->getPopularClubs()); + $this->template->popularClubs = []; $this->template->admins = iterator_to_array((new Users)->getInstanceAdmins()); } From 2cdcb0dc4e806ad7ba2dee7cd13629f7c7511915 Mon Sep 17 00:00:00 2001 From: n1rwana Date: Wed, 14 Sep 2022 13:27:48 +0300 Subject: [PATCH 005/285] Ticket deletion fixed (#727) * Ticket deletion fixed * ?act=list --- Web/Presenters/SupportPresenter.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Web/Presenters/SupportPresenter.php b/Web/Presenters/SupportPresenter.php index 22f09201..99a1908d 100644 --- a/Web/Presenters/SupportPresenter.php +++ b/Web/Presenters/SupportPresenter.php @@ -155,11 +155,12 @@ final class SupportPresenter extends OpenVKPresenter $this->notFound(); } else { if($ticket->getUserId() !== $this->user->id && $this->hasPermission('openvk\Web\Models\Entities\TicketReply', 'write', 0)) - $this->redirect("/support/tickets"); + $_redirect = "/support/tickets"; else - $this->redirect("/support"); + $_redirect = "/support?act=list"; $ticket->delete(); + $this->redirect($_redirect); } } } From 1aed452a12d5bde469609c011b16c8af194ef68d Mon Sep 17 00:00:00 2001 From: Jaroslaw <92401420+AlesAlte@users.noreply.github.com> Date: Sat, 17 Sep 2022 00:04:35 +0300 Subject: [PATCH 006/285] Ukrainian: translation of new functions (#728) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Correction of localization errors * Переклад: Блокування посилань * Add @AlesAlte to contributor Ukrainian locale * Update ua.strings * Small fix --- locales/list.yml | 2 +- locales/ua.strings | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/locales/list.yml b/locales/list.yml index e072c152..b6ff0a44 100644 --- a/locales/list.yml +++ b/locales/list.yml @@ -13,7 +13,7 @@ list: flag: "ua" name: "Ukrainian" native_name: "Україньска" - author: "Andrej Lenťaj, Maxim Hrabovi (dechioyo) and Kirill (mbsoft)" + author: "Yaroslav Bjelograd, Andrej Lenťaj, Maxim Hrabovi (dechioyo) and Kirill (mbsoft)" - code: "by" flag: "by" name: "Belarussian" diff --git a/locales/ua.strings b/locales/ua.strings index ef701a0b..fdeca0bc 100644 --- a/locales/ua.strings +++ b/locales/ua.strings @@ -15,6 +15,8 @@ "password" = "Пароль"; "registration" = "Реєстрація"; "forgot_password" = "Забули пароль?"; +"checkbox_in_registration" = "Я згоден з політикою конфіденційності і правилами сайту"; +"checkbox_in_registration_unchecked" = "Ви повинні погодитися з політикою конфіденційності та правилами, щоб зареєструватися."; "login_failed" = "Не вдалося увійти"; "invalid_username_or_password" = "Неправильне ім'я користувача або пароль. Забули пароль?"; @@ -210,6 +212,7 @@ /* Friends */ +"friends" = "Друзі"; "followers" = "Підписники"; "follower" = "Підписник"; "friends_add" = "Додати в друзі"; @@ -218,10 +221,11 @@ "friends_accept" = "Прийняти заявку"; "send_message" = "Відправити повідомлення"; "incoming_req" = "Підписники"; +"outcoming_req" = "Вихідні"; +"req" = "Заявки"; "outcoming_req" = "Заявки"; "friends_online" = "Друзі онлайн"; "all_friends" = "Усі друзі"; -"req" = "Заявки"; "req_zero" = "Не знайдено жодної заявки..."; "req_one" = "Знайдена $1 заявка"; @@ -235,18 +239,18 @@ "friends_many" = "$1 друзів"; "friends_other" = "$1 друзів"; -"friends_list_zero" = "У вас поки немає друзів"; -"friends_list_one" = "У Вас $1 друг"; -"friends_list_few" = "У Вас $1 друг"; -"friends_many" = "$1 друзів"; -"friends_other" = "$1 друзів"; - "friends_online_zero" = "Жодного друга онлайн"; "friends_online_one" = "$1 друг онлайн"; "friends_online_few" = "$1 друга онлайн"; "friends_online_many" = "$1 друзів онлайн"; "friends_online_other" = "$1 друзів онлайн"; +"friends_list_zero" = "У вас поки немає друзів"; +"friends_list_one" = "У Вас $1 друг"; +"friends_list_few" = "У Вас $1 друг"; +"friends_many" = "$1 друзів"; +"friends_other" = "$1 друзів"; + "followers_zero" = "Жодного підписника"; "followers_one" = "$1 підписник"; "followers_few" = "$1 підписника"; @@ -1122,6 +1126,17 @@ "admin_commerce_disabled" = "Комерція відключена системним адміністратором"; "admin_commerce_disabled_desc" = "Налаштування ваучерів та подарунків будуть збережені, але не матимуть впливу."; +"admin_banned_links" = "Заблоковані посилання"; +"admin_banned_link" = "Посилання"; +"admin_banned_domain" = "Домен"; +"admin_banned_link_description" = "З протоколом (https://example.org/)"; +"admin_banned_link_regexp" = "Регулярний вираз"; +"admin_banned_link_regexp_description" = "Підставляється після домену, зазначеного вище. Не заповнюйте, якщо хочете заблокувати весь домен"; +"admin_banned_link_reason" = "Причина"; +"admin_banned_link_initiator" = "Ініціатор"; +"admin_banned_link_not_specified" = "Посилання не зазначено"; +"admin_banned_link_not_found" = "Посилання не знайдено"; + /* Paginator (deprecated) */ "paginator_back" = "Назад"; @@ -1185,3 +1200,12 @@ "cookies_popup_content" = "Цей веб-сайт використовує cookies для того, щоб ідентифікувати вашу сесію і нічого більше. Ознайомтеся з нашою політикою конфіденційності для отримання додаткової інформації."; "cookies_popup_agree" = "Згоден"; + +/* Away */ + +"url_is_banned" = "Перехід неможливий"; +"url_is_banned_comment" = "Адміністрація $1 не рекомендує переходити за цим посиланням."; +"url_is_banned_comment_r" = "Адміністрація $1 не рекомендує переходити за цим посиланням.

Підстава: $2"; +"url_is_banned_default_reason" = "Посилання, за яким Ви спробували перейти, може вести на сайт, що був створений з метою обману користувачів і отримання шляхом цього неправомірного прибутку."; +"url_is_banned_title" = "Посилання на підозрілий сайт"; +"url_is_banned_proceed" = "Перейти за посиланням"; From ed7faa4a160f55b84f4201803795098577f27aa4 Mon Sep 17 00:00:00 2001 From: Vladimir Lapskiy <94683384+el-psy-congroo-desu@users.noreply.github.com> Date: Sat, 17 Sep 2022 02:05:25 +0500 Subject: [PATCH 007/285] VKAPI: Friends.getRequests added some parameters that i forgot about and fix count requests in the response (#724) * VKAPI: Friends.getRequests method did not give more than 6 elements * VKAPI: Friends.getRequests i'm forget add some parameters LOL --- VKAPI/Handlers/Friends.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/VKAPI/Handlers/Friends.php b/VKAPI/Handlers/Friends.php index ca9b7573..20c537a5 100644 --- a/VKAPI/Handlers/Friends.php +++ b/VKAPI/Handlers/Friends.php @@ -133,15 +133,18 @@ final class Friends extends VKAPIRequestHandler return $response; } - function getRequests(string $fields = "", int $offset = 0, int $count = 100): object + function getRequests(string $fields = "", int $offset = 0, int $count = 100, int $extended = 0): object { + if ($count >= 1000) + $this->fail(100, "One of the required parameters was not passed or is invalid."); + $this->requireUser(); $i = 0; $offset++; $followers = []; - foreach($this->getUser()->getFollowers() as $follower) { + foreach($this->getUser()->getFollowers($offset, $count) as $follower) { $followers[$i] = $follower->getId(); $i++; } @@ -149,8 +152,10 @@ final class Friends extends VKAPIRequestHandler $response = $followers; $usersApi = new Users($this->getUser()); - if(!is_null($fields)) - $response = $usersApi->get(implode(',', $followers), $fields, 0, $count); # FIXME + if($extended == 1) + $response = $usersApi->get(implode(',', $followers), $fields, 0, $count); + else + $response = $usersApi->get(implode(',', $followers), "", 0, $count); foreach($response as $user) $user->user_id = $user->id; From 753be2aaff6711637fcbfacfc543748629e5e043 Mon Sep 17 00:00:00 2001 From: n1rwana Date: Sat, 17 Sep 2022 00:19:46 +0300 Subject: [PATCH 008/285] Maintenance (#719) --- Web/Presenters/AppsPresenter.php | 2 +- Web/Presenters/CommentPresenter.php | 1 + Web/Presenters/GiftsPresenter.php | 1 + Web/Presenters/GroupPresenter.php | 3 +- Web/Presenters/MaintenancePresenter.php | 35 +++++++++++++++++++ Web/Presenters/MessengerPresenter.php | 6 ++-- Web/Presenters/NotesPresenter.php | 3 +- Web/Presenters/NotificationPresenter.php | 2 ++ Web/Presenters/OpenVKPresenter.php | 28 ++++++++++----- Web/Presenters/PhotosPresenter.php | 3 +- Web/Presenters/SupportPresenter.php | 1 + Web/Presenters/TopicsPresenter.php | 3 +- Web/Presenters/UserPresenter.php | 5 +-- Web/Presenters/VideosPresenter.php | 3 +- Web/Presenters/templates/Maintenance/All.xml | 20 +++++++++++ .../templates/Maintenance/Section.xml | 20 +++++++++++ Web/di.yml | 1 + Web/routes.yml | 4 +++ locales/en.strings | 9 +++++ locales/ru.strings | 9 +++++ openvk-example.yml | 14 ++++++++ 21 files changed, 155 insertions(+), 18 deletions(-) create mode 100644 Web/Presenters/MaintenancePresenter.php create mode 100644 Web/Presenters/templates/Maintenance/All.xml create mode 100644 Web/Presenters/templates/Maintenance/Section.xml diff --git a/Web/Presenters/AppsPresenter.php b/Web/Presenters/AppsPresenter.php index 02fb8922..8dcfb8a4 100644 --- a/Web/Presenters/AppsPresenter.php +++ b/Web/Presenters/AppsPresenter.php @@ -6,7 +6,7 @@ use openvk\Web\Models\Repositories\Applications; final class AppsPresenter extends OpenVKPresenter { private $apps; - + protected $presenterName = "apps"; function __construct(Applications $apps) { $this->apps = $apps; diff --git a/Web/Presenters/CommentPresenter.php b/Web/Presenters/CommentPresenter.php index cbdac84e..0429b32e 100644 --- a/Web/Presenters/CommentPresenter.php +++ b/Web/Presenters/CommentPresenter.php @@ -6,6 +6,7 @@ use openvk\Web\Models\Repositories\{Comments, Clubs}; final class CommentPresenter extends OpenVKPresenter { + protected $presenterName = "comment"; private $models = [ "posts" => "openvk\\Web\\Models\\Repositories\\Posts", "photos" => "openvk\\Web\\Models\\Repositories\\Photos", diff --git a/Web/Presenters/GiftsPresenter.php b/Web/Presenters/GiftsPresenter.php index b99e5ba9..8f59bdcb 100644 --- a/Web/Presenters/GiftsPresenter.php +++ b/Web/Presenters/GiftsPresenter.php @@ -7,6 +7,7 @@ final class GiftsPresenter extends OpenVKPresenter { private $gifts; private $users; + protected $presenterName = "gifts"; function __construct(Gifts $gifts, Users $users) { diff --git a/Web/Presenters/GroupPresenter.php b/Web/Presenters/GroupPresenter.php index a83386db..00d74c2e 100644 --- a/Web/Presenters/GroupPresenter.php +++ b/Web/Presenters/GroupPresenter.php @@ -8,7 +8,8 @@ use Chandler\Security\Authenticator; final class GroupPresenter extends OpenVKPresenter { private $clubs; - + protected $presenterName = "group"; + function __construct(Clubs $clubs) { $this->clubs = $clubs; diff --git a/Web/Presenters/MaintenancePresenter.php b/Web/Presenters/MaintenancePresenter.php new file mode 100644 index 00000000..d4a5a6ef --- /dev/null +++ b/Web/Presenters/MaintenancePresenter.php @@ -0,0 +1,35 @@ +flashFail("err", tr("error"), tr("forbidden")); + + $this->template->name = [ + "photos" => tr("my_photos"), + "videos" => tr("my_videos"), + "messenger" => tr("my_messages"), + "user" => tr("users"), + "group" => tr("my_groups"), + "comment" => tr("comments"), + "gifts" => tr("gifts"), + "apps" => tr("apps"), + "notes" => tr("my_notes"), + "notification" => tr("my_feedback"), + "support" => tr("menu_support"), + "topics" => tr("topics") + ][$name] ?? $name; + } + + function renderAll(): void + { + + } +} diff --git a/Web/Presenters/MessengerPresenter.php b/Web/Presenters/MessengerPresenter.php index cea440ba..593d9245 100644 --- a/Web/Presenters/MessengerPresenter.php +++ b/Web/Presenters/MessengerPresenter.php @@ -9,11 +9,13 @@ final class MessengerPresenter extends OpenVKPresenter { private $messages; private $signaler; - + protected $presenterName = "messenger"; + function __construct(Messages $messages) { $this->messages = $messages; $this->signaler = SignalManager::i(); + parent::__construct(); } @@ -30,7 +32,7 @@ final class MessengerPresenter extends OpenVKPresenter function renderIndex(): void { $this->assertUserLoggedIn(); - + if(isset($_GET["sel"])) $this->pass("openvk!Messenger->app", $_GET["sel"]); diff --git a/Web/Presenters/NotesPresenter.php b/Web/Presenters/NotesPresenter.php index 363d814c..50437ad7 100644 --- a/Web/Presenters/NotesPresenter.php +++ b/Web/Presenters/NotesPresenter.php @@ -6,7 +6,8 @@ use openvk\Web\Models\Entities\Note; final class NotesPresenter extends OpenVKPresenter { private $notes; - + protected $presenterName = "notes"; + function __construct(Notes $notes) { $this->notes = $notes; diff --git a/Web/Presenters/NotificationPresenter.php b/Web/Presenters/NotificationPresenter.php index d12f27f0..3bd7a321 100644 --- a/Web/Presenters/NotificationPresenter.php +++ b/Web/Presenters/NotificationPresenter.php @@ -3,6 +3,8 @@ namespace openvk\Web\Presenters; final class NotificationPresenter extends OpenVKPresenter { + protected $presenterName = "notification"; + function renderFeed(): void { $this->assertUserLoggedIn(); diff --git a/Web/Presenters/OpenVKPresenter.php b/Web/Presenters/OpenVKPresenter.php index 2a19fa03..5b7908a8 100755 --- a/Web/Presenters/OpenVKPresenter.php +++ b/Web/Presenters/OpenVKPresenter.php @@ -17,7 +17,8 @@ abstract class OpenVKPresenter extends SimplePresenter protected $deactivationTolerant = false; protected $errorTemplate = "@error"; protected $user = NULL; - + protected $presenterName; + private function calculateQueryString(array $data): string { $rawUrl = "tcp+stratum://fakeurl.net$_SERVER[REQUEST_URI]"; #HTTP_HOST can be tainted @@ -196,12 +197,13 @@ abstract class OpenVKPresenter extends SimplePresenter function onStartup(): void { $user = Authenticator::i()->getUser(); - + $this->template->isXmas = intval(date('d')) >= 1 && date('m') == 12 || intval(date('d')) <= 15 && date('m') == 1 ? true : false; $this->template->isTimezoned = Session::i()->get("_timezoneOffset"); - + $userValidated = 0; $cacheTime = OPENVK_ROOT_CONF["openvk"]["preferences"]["nginxCacheTime"] ?? 0; + if(!is_null($user)) { $this->user = (object) []; $this->user->raw = $user; @@ -226,7 +228,7 @@ abstract class OpenVKPresenter extends SimplePresenter } exit; } - + if($this->user->identity->isBanned() && !$this->banTolerant) { header("HTTP/1.1 403 Forbidden"); $this->getTemplatingEngine()->render(__DIR__ . "/templates/@banned.xml", [ @@ -247,23 +249,33 @@ abstract class OpenVKPresenter extends SimplePresenter ]); exit; } - + $userValidated = 1; $cacheTime = 0; # Force no cache if($this->user->identity->onlineStatus() == 0 && !($this->user->identity->isDeleted() || $this->user->identity->isBanned())) { $this->user->identity->setOnline(time()); $this->user->identity->save(); } - + $this->template->ticketAnsweredCount = (new Tickets)->getTicketsCountByUserId($this->user->id, 1); if($user->can("write")->model("openvk\Web\Models\Entities\TicketReply")->whichBelongsTo(0)) $this->template->helpdeskTicketNotAnsweredCount = (new Tickets)->getTicketCount(0); } - + header("X-OpenVK-User-Validated: $userValidated"); header("X-Accel-Expires: $cacheTime"); setlocale(LC_TIME, ...(explode(";", tr("__locale")))); - + + if (!OPENVK_ROOT_CONF["openvk"]["preferences"]["maintenanceMode"]["all"]) { + if (OPENVK_ROOT_CONF["openvk"]["preferences"]["maintenanceMode"][$this->presenterName]) { + $this->pass("openvk!Maintenance->section", $this->presenterName); + } + } else { + if ($this->presenterName != "maintenance") { + $this->redirect("/maintenances/"); + } + } + parent::onStartup(); } diff --git a/Web/Presenters/PhotosPresenter.php b/Web/Presenters/PhotosPresenter.php index eacf76d4..3dd2a774 100644 --- a/Web/Presenters/PhotosPresenter.php +++ b/Web/Presenters/PhotosPresenter.php @@ -9,7 +9,8 @@ final class PhotosPresenter extends OpenVKPresenter private $users; private $photos; private $albums; - + protected $presenterName = "photos"; + function __construct(Photos $photos, Albums $albums, Users $users) { $this->users = $users; diff --git a/Web/Presenters/SupportPresenter.php b/Web/Presenters/SupportPresenter.php index 99a1908d..8f4fd7d3 100644 --- a/Web/Presenters/SupportPresenter.php +++ b/Web/Presenters/SupportPresenter.php @@ -11,6 +11,7 @@ final class SupportPresenter extends OpenVKPresenter { protected $banTolerant = true; protected $deactivationTolerant = true; + protected $presenterName = "support"; private $tickets; private $comments; diff --git a/Web/Presenters/TopicsPresenter.php b/Web/Presenters/TopicsPresenter.php index 6dd1ec6c..528b51ad 100644 --- a/Web/Presenters/TopicsPresenter.php +++ b/Web/Presenters/TopicsPresenter.php @@ -7,7 +7,8 @@ final class TopicsPresenter extends OpenVKPresenter { private $topics; private $clubs; - + protected $presenterName = "topics"; + function __construct(Topics $topics, Clubs $clubs) { $this->topics = $topics; diff --git a/Web/Presenters/UserPresenter.php b/Web/Presenters/UserPresenter.php index bfda79e8..48ebb660 100644 --- a/Web/Presenters/UserPresenter.php +++ b/Web/Presenters/UserPresenter.php @@ -15,12 +15,13 @@ use Nette\Database\UniqueConstraintViolationException; final class UserPresenter extends OpenVKPresenter { private $users; - public $deactivationTolerant = false; + protected $presenterName = "user"; + function __construct(Users $users) { $this->users = $users; - + parent::__construct(); } diff --git a/Web/Presenters/VideosPresenter.php b/Web/Presenters/VideosPresenter.php index e7b24344..6db7771d 100644 --- a/Web/Presenters/VideosPresenter.php +++ b/Web/Presenters/VideosPresenter.php @@ -8,7 +8,8 @@ final class VideosPresenter extends OpenVKPresenter { private $videos; private $users; - + protected $presenterName = "videos"; + function __construct(Videos $videos, Users $users) { $this->videos = $videos; diff --git a/Web/Presenters/templates/Maintenance/All.xml b/Web/Presenters/templates/Maintenance/All.xml new file mode 100644 index 00000000..e8f88e2c --- /dev/null +++ b/Web/Presenters/templates/Maintenance/All.xml @@ -0,0 +1,20 @@ +{extends "../@layout.xml"} + +{block title} + {_global_maintenance} +{/block} + +{block header} + {_global_maintenance} +{/block} + +{block content} +
+
+ + + {_undergoing_global_maintenance} + +
+
+{/block} diff --git a/Web/Presenters/templates/Maintenance/Section.xml b/Web/Presenters/templates/Maintenance/Section.xml new file mode 100644 index 00000000..9bdb0965 --- /dev/null +++ b/Web/Presenters/templates/Maintenance/Section.xml @@ -0,0 +1,20 @@ +{extends "../@layout.xml"} + +{block title} + {_section_maintenance} +{/block} + +{block header} + {_section_maintenance} +{/block} + +{block content} +
+
+ + + {tr("undergoing_section_maintenance", $name)|noescape} + +
+
+{/block} diff --git a/Web/di.yml b/Web/di.yml index f18654b4..f4b04650 100644 --- a/Web/di.yml +++ b/Web/di.yml @@ -44,3 +44,4 @@ services: - openvk\Web\Models\Repositories\Applications - openvk\Web\Models\Repositories\ContentSearchRepository - openvk\Web\Models\Repositories\BannedLinks + - openvk\Web\Presenters\MaintenancePresenter diff --git a/Web/routes.yml b/Web/routes.yml index 0ee44444..d6f63a11 100644 --- a/Web/routes.yml +++ b/Web/routes.yml @@ -331,3 +331,7 @@ routes: handler: "UnknownTextRouteStrategy->delegate" placeholders: shortCode: "[a-z][a-z0-9\\@\\.\\_]{0,30}[a-z0-9]" + - url: "/maintenance/{text}" + handler: "Maintenance->section" + - url: "/maintenances/" + handler: "Maintenance->all" diff --git a/locales/en.strings b/locales/en.strings index 2e3461b7..240dd5d0 100644 --- a/locales/en.strings +++ b/locales/en.strings @@ -1147,3 +1147,12 @@ "url_is_banned_default_reason" = "The link you are trying to open may lead you to a site that was created for the purpose of deceiving users with the intention of gaining profit."; "url_is_banned_title" = "Link to a suspicious site"; "url_is_banned_proceed" = "Follow the link"; + +/* Maintenance */ + +"global_maintenance" = "Undergoing maintenance"; +"section_maintenance" = "The section is not available"; +"undergoing_global_maintenance" = "Unfortunately, the instance is now closed for technical work. We are already working on troubleshooting. Please try to come back later."; +"undergoing_section_maintenance" = "Unfortunately, the $1 section is temporarily unavailable. We are already working on troubleshooting. Please try to come back later."; + +"topics" = "Topics"; diff --git a/locales/ru.strings b/locales/ru.strings index 68f6d69f..2f176233 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -1208,3 +1208,12 @@ "url_is_banned_default_reason" = "Ссылка, по которой вы попытались перейти, может вести на сайт, который был создан с целью обмана пользователей и получения за счёт этого прибыли."; "url_is_banned_title" = "Ссылка на подозрительный сайт"; "url_is_banned_proceed" = "Перейти по ссылке"; + +/* Maintenance */ + +"global_maintenance" = "Технические работы"; +"section_maintenance" = "Раздел недоступен"; +"undergoing_global_maintenance" = "К сожалению, сейчас инстанс закрыт на технические работы. Мы уже работаем над устранением неисправностей. Пожалуйста, попробуйте зайти позже."; +"undergoing_section_maintenance" = "К сожалению, раздел $1 временно недоступен. Мы уже работаем над устранением неисправностей. Пожалуйста, попробуйте зайти позже."; + +"topics" = "Темы"; diff --git a/openvk-example.yml b/openvk-example.yml index 64b7b38c..47eacd24 100644 --- a/openvk-example.yml +++ b/openvk-example.yml @@ -58,6 +58,20 @@ openvk: susLinks: warnings: true showReason: true + maintenanceMode: + all: false + photos: false + videos: false + messenger: false + user: false + group: false + comment: false + gifts: false + apps: false + notes: false + notification: false + support: false + topics: false ton: enabled: false address: "🅿" From 5b3a1f50e94cbd22655536fbb5350d2eb09b99c1 Mon Sep 17 00:00:00 2001 From: n1rwana Date: Sat, 17 Sep 2022 00:21:29 +0300 Subject: [PATCH 009/285] Shortcode aliases (#690) * Shortcode aliases * Fixes * Newline * Fixes + SQLs renamed * Fixed clubs aliases --- Web/Models/Entities/Alias.php | 34 ++++++++++++++++++ Web/Models/Entities/User.php | 4 +++ Web/Models/Repositories/Aliases.php | 35 +++++++++++++++++++ Web/Models/Repositories/Clubs.php | 13 ++++++- Web/Models/Repositories/Users.php | 15 +++++++- Web/di.yml | 1 + ...-banned-urls.sql => 00032-banned-urls.sql} | 0 install/sqls/00033-shortcode-aliases.sql | 12 +++++++ 8 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 Web/Models/Entities/Alias.php create mode 100644 Web/Models/Repositories/Aliases.php rename install/sqls/{00031-banned-urls.sql => 00032-banned-urls.sql} (100%) create mode 100644 install/sqls/00033-shortcode-aliases.sql diff --git a/Web/Models/Entities/Alias.php b/Web/Models/Entities/Alias.php new file mode 100644 index 00000000..99f7baae --- /dev/null +++ b/Web/Models/Entities/Alias.php @@ -0,0 +1,34 @@ +getRecord()->owner_id; + } + + function getType(): string + { + if ($this->getOwnerId() < 0) + return "club"; + + return "user"; + } + + function getUser(): ?User + { + return (new Users)->get($this->getOwnerId()); + } + + function getClub(): ?Club + { + return (new Clubs)->get($this->getOwnerId() * -1); + } +} diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php index 115bf8c2..f1045f62 100644 --- a/Web/Models/Entities/User.php +++ b/Web/Models/Entities/User.php @@ -908,6 +908,10 @@ class User extends RowModel $pClub = DatabaseConnection::i()->getContext()->table("groups")->where("shortcode", $code)->fetch(); if(!is_null($pClub)) return false; + + $pAlias = DatabaseConnection::i()->getContext()->table("aliases")->where("shortcode", $code)->fetch(); + if(!is_null($pAlias)) + return false; } $this->stateChanges("shortcode", $code); diff --git a/Web/Models/Repositories/Aliases.php b/Web/Models/Repositories/Aliases.php new file mode 100644 index 00000000..e74532a1 --- /dev/null +++ b/Web/Models/Repositories/Aliases.php @@ -0,0 +1,35 @@ +context = DB::i()->getContext(); + $this->aliases = $this->context->table("aliases"); + } + + private function toAlias(?ActiveRow $ar): ?Alias + { + return is_null($ar) ? NULL : new Alias($ar); + } + + function get(int $id): ?Alias + { + return $this->toAlias($this->aliases->get($id)); + } + + function getByShortcode(string $shortcode): ?Alias + { + return $this->toAlias($this->aliases->where("shortcode", $shortcode)->fetch()); + } +} diff --git a/Web/Models/Repositories/Clubs.php b/Web/Models/Repositories/Clubs.php index 4a1b28fe..edbe75c6 100644 --- a/Web/Models/Repositories/Clubs.php +++ b/Web/Models/Repositories/Clubs.php @@ -1,6 +1,7 @@ toClub($this->clubs->where("shortcode", $url)->fetch()); + $shortcode = $this->toClub($this->clubs->where("shortcode", $url)->fetch()); + + if ($shortcode) + return $shortcode; + + $alias = (new Aliases)->getByShortcode($url); + + if (!$alias) return NULL; + if ($alias->getType() !== "club") return NULL; + + return $alias->getClub(); } function get(int $id): ?Club diff --git a/Web/Models/Repositories/Users.php b/Web/Models/Repositories/Users.php index 9cd7d001..63e77df0 100644 --- a/Web/Models/Repositories/Users.php +++ b/Web/Models/Repositories/Users.php @@ -1,6 +1,7 @@ context = DatabaseConnection::i()->getContext(); $this->users = $this->context->table("profiles"); + $this->aliases = $this->context->table("aliases"); } private function toUser(?ActiveRow $ar): ?User @@ -28,7 +31,17 @@ class Users function getByShortURL(string $url): ?User { - return $this->toUser($this->users->where("shortcode", $url)->fetch()); + $shortcode = $this->toUser($this->users->where("shortcode", $url)->fetch()); + + if ($shortcode) + return $shortcode; + + $alias = (new Aliases)->getByShortcode($url); + + if (!$alias) return NULL; + if ($alias->getType() !== "user") return NULL; + + return $alias->getUser(); } function getByChandlerUser(ChandlerUser $user): ?User diff --git a/Web/di.yml b/Web/di.yml index f4b04650..ec867809 100644 --- a/Web/di.yml +++ b/Web/di.yml @@ -43,5 +43,6 @@ services: - openvk\Web\Models\Repositories\Topics - openvk\Web\Models\Repositories\Applications - openvk\Web\Models\Repositories\ContentSearchRepository + - openvk\Web\Models\Repositories\Aliases - openvk\Web\Models\Repositories\BannedLinks - openvk\Web\Presenters\MaintenancePresenter diff --git a/install/sqls/00031-banned-urls.sql b/install/sqls/00032-banned-urls.sql similarity index 100% rename from install/sqls/00031-banned-urls.sql rename to install/sqls/00032-banned-urls.sql diff --git a/install/sqls/00033-shortcode-aliases.sql b/install/sqls/00033-shortcode-aliases.sql new file mode 100644 index 00000000..520f0502 --- /dev/null +++ b/install/sqls/00033-shortcode-aliases.sql @@ -0,0 +1,12 @@ +CREATE TABLE `aliases` ( + `id` bigint UNSIGNED NOT NULL, + `owner_id` bigint NOT NULL, + `shortcode` varchar(36) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +ALTER TABLE `aliases` + ADD PRIMARY KEY (`id`); + +ALTER TABLE `aliases` + MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT; +COMMIT; From 283d8c1c2d5674e59efd0a07ddf43f640bb18eec Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Sat, 17 Sep 2022 00:25:44 +0300 Subject: [PATCH 010/285] Install SQLs: Fix MariaDB compatibility --- install/sqls/00032-banned-urls.sql | 9 ++++----- install/sqls/00033-shortcode-aliases.sql | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/install/sqls/00032-banned-urls.sql b/install/sqls/00032-banned-urls.sql index c208eb37..0df7b275 100644 --- a/install/sqls/00032-banned-urls.sql +++ b/install/sqls/00032-banned-urls.sql @@ -1,14 +1,13 @@ CREATE TABLE `links_banned` ( `id` bigint UNSIGNED NOT NULL, - `domain` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, - `regexp_rule` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, - `reason` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, + `domain` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_nopad_ci NOT NULL, + `regexp_rule` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_nopad_ci NOT NULL, + `reason` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_nopad_ci, `initiator` bigint UNSIGNED NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_nopad_ci; ALTER TABLE `links_banned` ADD PRIMARY KEY (`id`); ALTER TABLE `links_banned` MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT; -COMMIT; \ No newline at end of file diff --git a/install/sqls/00033-shortcode-aliases.sql b/install/sqls/00033-shortcode-aliases.sql index 520f0502..d47975c0 100644 --- a/install/sqls/00033-shortcode-aliases.sql +++ b/install/sqls/00033-shortcode-aliases.sql @@ -2,11 +2,10 @@ CREATE TABLE `aliases` ( `id` bigint UNSIGNED NOT NULL, `owner_id` bigint NOT NULL, `shortcode` varchar(36) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_nopad_ci; ALTER TABLE `aliases` ADD PRIMARY KEY (`id`); ALTER TABLE `aliases` MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT; -COMMIT; From 697a36520530c1efe6e13e192925b7be0d8f66a2 Mon Sep 17 00:00:00 2001 From: veselcraft Date: Mon, 19 Sep 2022 16:54:23 +0300 Subject: [PATCH 011/285] Longpool: Update format for use in modern clients --- Web/Events/NewMessageEvent.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Web/Events/NewMessageEvent.php b/Web/Events/NewMessageEvent.php index 49d102b3..3b828e90 100644 --- a/Web/Events/NewMessageEvent.php +++ b/Web/Events/NewMessageEvent.php @@ -27,14 +27,23 @@ class NewMessageEvent implements ILPEmitable if($peer === $userId) $peer = $msg->getRecipient()->getId(); + /* + * Source: + * https://github.com/danyadev/longpoll-doc + */ + return [ 4, # event type + $msg->getId(), # messageId 256, # checked for spam flag $peer, # TODO calculate peer correctly $msg->getSendTime()->timestamp(), # creation time in unix $msg->getText(), # text (formatted) + [], # empty additional info [], # empty attachments $msg->getId() << 2, # id as random_id + $peer, # conversation id + 0 # not edited yet ]; } } From b38f4f23460d9083505c58512f4db186172d46c4 Mon Sep 17 00:00:00 2001 From: veselcraft Date: Mon, 19 Sep 2022 17:13:37 +0300 Subject: [PATCH 012/285] Longpoll: Add wait parameter as in original VK --- Web/Presenters/MessengerPresenter.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Web/Presenters/MessengerPresenter.php b/Web/Presenters/MessengerPresenter.php index 593d9245..46094c43 100644 --- a/Web/Presenters/MessengerPresenter.php +++ b/Web/Presenters/MessengerPresenter.php @@ -95,6 +95,13 @@ final class MessengerPresenter extends OpenVKPresenter } $legacy = $this->queryParam("version") < 3; + + $time = intval($this->queryParam("wait")); + + if($time > 60) + $time = 60; + elseif($time == 0) + $time = 25; // default $this->signaler->listen(function($event, $eId) use ($id) { exit(json_encode([ @@ -103,7 +110,7 @@ final class MessengerPresenter extends OpenVKPresenter $event->getVKAPISummary($id), ], ])); - }, $id); + }, $id, $time); } function renderApiGetMessages(int $sel, int $lastMsg): void From 6eeb05236e9634256f9bcdd4fc42db99c4e77070 Mon Sep 17 00:00:00 2001 From: Maxim Leshchenko Date: Tue, 20 Sep 2022 16:16:34 +0200 Subject: [PATCH 013/285] Russian: Fix typo in page edit --- locales/ru.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/ru.strings b/locales/ru.strings index 2f176233..6a7b8f46 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -992,7 +992,7 @@ "changes_saved_comment" = "Новые данные появятся на вашей странице"; "photo_saved" = "Фотография сохранена"; -"photo_saved_comment" = "Новое изображние профиля появится у вас на странице"; +"photo_saved_comment" = "Новое изображение профиля появится у вас на странице"; "shared_succ" = "Запись появится на вашей стене. Нажмите на уведомление, чтобы перейти к своей стене."; From 729784ecfff4c35bbf4e062c39ae8ef57c77a1da Mon Sep 17 00:00:00 2001 From: Maxim Leshchenko Date: Fri, 23 Sep 2022 16:29:17 +0200 Subject: [PATCH 014/285] Groups: Display links not only for managed groups in My Groups Closes #664 --- Web/Presenters/templates/User/Groups.xml | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Web/Presenters/templates/User/Groups.xml b/Web/Presenters/templates/User/Groups.xml index 18c2e9d8..cc32b3d0 100644 --- a/Web/Presenters/templates/User/Groups.xml +++ b/Web/Presenters/templates/User/Groups.xml @@ -79,9 +79,9 @@ {/block} {block actions} + {_check_community} {if $x->canBeModifiedBy($thisUser ?? NULL)} {var $clubPinned = $thisUser->isClubPinned($x)} - {_check_community} {if $clubPinned} {_remove_from_left_menu} @@ -89,21 +89,21 @@ {_add_to_left_menu} {/if} - {if $x->getSubscriptionStatus($thisUser) == false} - - {else} - - {/if} + {/if} + {if $x->getSubscriptionStatus($thisUser) == false} + + {else} + {/if} {/block} From 7d72cd182bdcdcafa0bdec390245571f4f594f40 Mon Sep 17 00:00:00 2001 From: Maxim Leshchenko Date: Fri, 23 Sep 2022 17:10:29 +0200 Subject: [PATCH 015/285] Users: Do not show the request tab in the list of other user's friends Closes #605 --- Web/Presenters/templates/User/Friends.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Web/Presenters/templates/User/Friends.xml b/Web/Presenters/templates/User/Friends.xml index d85fbd56..ed140cf1 100644 --- a/Web/Presenters/templates/User/Friends.xml +++ b/Web/Presenters/templates/User/Friends.xml @@ -53,7 +53,7 @@ -
+ {/block} From 1921c7224cd74b4736e349c70beeb008c94e3cf8 Mon Sep 17 00:00:00 2001 From: lvl <90154880+apeeh@users.noreply.github.com> Date: Fri, 30 Sep 2022 17:52:32 +0400 Subject: [PATCH 016/285] Update am.strings (#736) --- locales/am.strings | 160 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 156 insertions(+), 4 deletions(-) diff --git a/locales/am.strings b/locales/am.strings index f68b582c..59404426 100644 --- a/locales/am.strings +++ b/locales/am.strings @@ -17,6 +17,8 @@ "password" = "Գաղտնաբառ"; "registration" = "Գրանցում"; "forgot_password" = "Մոռացե՞լ եք գաղտնաբառը"; +"checkbox_in_registration" = "Ես համաձայն եմ կոնֆիդենցիալության քաղաքականությանն ու կայքի կանոնադրությանը։"; +"checkbox_in_registration_unchecked" = "Դուք պետք է համաձայնվեք պայմանների հետ նախքան գրանցվելը։"; "login_failed" = "Չհաջողվեց մուտք գործել"; "invalid_username_or_password" = "Սխալ օգտատիրոջ անուն կամ գաղտնաբառ։ Դուք կարող եք վերականգնել ձեր գաղտնաբառը։"; @@ -93,6 +95,9 @@ "years_many" = "$1 տարեկան"; "years_other" = "$1 տարեկան"; +"show_my_birthday" = "Ցույց տալ ծննդյան օրը"; +"show_only_month_and_day" = "Ցուցադրել միայն ամիսն ու օրը"; + "relationship" = "Ընտանեկան դրություն"; "relationship_0" = "Ընտրված չէ"; @@ -144,8 +149,8 @@ "updated_at" = "Թարմացված է $1"; -"user_banned" = "Ցավո՛ք, մենք ստիպված $1-ի էջը կասեցրել ենք։"; -"user_banned_comment" = "Մոդերատորի մեկնաբանությունը․ "; +"user_banned" = "Ցավո՛ք, մենք ստիպված կասեցրել ենք $1-ի էջը։"; +"user_banned_comment" = "Մոդերատորի մեկնաբանությունը․"; /* Wall */ @@ -154,6 +159,10 @@ "post_writes_m" = "գրել է"; "post_writes_f" = "գրել է"; "post_writes_g" = "հրապարակել են"; +"post_deact_m" = "ջնջել է էջը հետևյալ բառերով."; +"post_deact_f" = "ջնջել է էջը հետևյալ բառերով."; +"post_deact_silent_m" = "սուս ու փուս ջնջել է էջը։"; +"post_deact_silent_f" = "սուս ու փուս ջնջել է էջը։"; "wall" = "Պատ"; "post" = "Գրություն"; "write" = "Գրել"; @@ -167,7 +176,7 @@ "comments_tip" = "Եղե՛ք առաջինը ով կթողնի իր կարծիքը։"; "your_comment" = "Ձեր մեկնաբանությունը"; "shown" = "Ցուցադրված է"; -"x_out_of" = "$1 –ը ՝"; +"x_out_of" = "$1–ը"; "wall_zero" = "գրություն չկա"; "wall_one" = "մեկ գրություն"; "wall_few" = "$1 գրություն"; @@ -215,6 +224,8 @@ "incoming_req" = "Բաժանորդներ"; "outcoming_req" = "Հայցեր"; "req" = "Հայցեր"; +"friends_online" = "Ընկերները ցանցում"; +"all_friends" = "Բոլոր ընկերները"; "req_zero" = "Ոչ մի հայտ չի գտնվել..."; "req_one" = "Գտնվեց մեկ հայտ"; @@ -246,6 +257,12 @@ "subscriptions_many" = "$1 բաժանորդագրություն"; "subscriptions_other" = "$1 բաժանորդագրություն"; +"friends_list_online_zero" = "Դուք դեռ չունեք ցանցի մեջ գտնվող ընկերներ"; +"friends_list_online_one" = "Ձեր $1 ընկերը ցանցի մեջ է"; +"friends_list_online_few" = "Ձեր $1 ընկերները ցանցի մեջ են"; +"friends_list_online_many" = "Ձեր $1 ընկերները ցանցի մեջ են"; +"friends_list_online_other" = "Ձեր $1 ընկերները ցանցի մեջ են"; + /* Group */ "name_group" = "Անվանում"; @@ -364,6 +381,10 @@ "edit_note" = "Խմբագրել նշումը"; "actions" = "Գործողություններ"; "notes_start_screen" = "Նշումների շնորհիվ Դուք կարող եք կիսվել ընկերների հետ տարբեր իրադարձություններով, և իմանալ թե ինչ է կատարվում իրենց մոտ։"; +"note_preview" = "Նախադիտում"; +"note_preview_warn" = "Սա ընդամենը նախադիտում է"; +"note_preview_warn_details" = "Պահպանելուց հետո նշումները կարող են այլ տեսք ունենալ։ Ու մեկ էլ, այդքան հաճախ նախադիտում մի արեք։"; +"note_preview_empty_err" = "Ինչու՞ նախադիտել նշումը առանց վերնագրի կամ բովանդակության։"; "edited" = "Խմբագրված է"; @@ -428,6 +449,7 @@ "avatar" = "Ավատար"; "privacy" = "Գաղտնիություն"; "interface" = "Արտաքին տեսք"; +"security" = "Անվտանգություն"; "profile_picture" = "Էջի նկար"; @@ -445,7 +467,7 @@ "arbitrary_avatars" = "Կամայական"; "cut" = "Կտրվածք"; -"round_avatars" = "Կլոր ավատար"; +"round_avatars" = "Շրջանաձև"; "apply_style_for_this_device" = "Հաստատել տեսքը միայն այս սարքի համար"; @@ -508,6 +530,33 @@ "email_change_confirm_message" = "Որպեսզի Ձեր փոփոխությունը կատարվի, հաստատե՛ք Ձեր նոր էլեկտրոնային հասցեն։ Այնտեղ մենք ուղարկել ենք հրահանգները։"; +"profile_deactivate" = "Էջի հեռացում"; +"profile_deactivate_button" = "Ջնջել էջը"; +"profile_deactivate_header" = "Մենք ցավում ենք որ Դուք ցանկանում եք ջնջել ձեր էջը։ Դրա համար Դուք կարող եք նշել հեռացման պատճառը և Ձեր կարծիքը այդ առումով։ Մեզ համար կարևոր է Ձեր կարծիքը, որպեսզի դարձնենք կայքը ավելի լավը։"; +"profile_deactivate_reason_header" = "Խնդրում ենք, նշել Ձեր էջի ջնջման պատճառները"; +"profile_deactivate_reason_1" = "Ես ունեմ այլ էջ այս կայնքում"; +"profile_deactivate_reason_1_text" = "Ես նոր էջ եմ սկսել ու ցանկանում եմ սկսել ամեն ինչ նորից"; +"profile_deactivate_reason_2" = "Կայքն ինձնից շատ ժամանակ է խլում"; +"profile_deactivate_reason_2_text" = "Թեկուզ այս կայքը լավն է, բայց ցավոք ինձնից ահագին ժամանակ է խլում։"; +"profile_deactivate_reason_3" = "Կայքը բազմաթիվ անցանկանալի մատերիալներ է պարունակում"; +"profile_deactivate_reason_3_text" = "Ես բազմաթիվ պոռնոգրաֆիա ու անօրինական կինոներ եմ գրել – բոլ ա։ Հիմա հավես չկա։"; +"profile_deactivate_reason_4" = "Меня беспокоит безопасность моих данных"; +"profile_deactivate_reason_4_text" = "Ինձ հետևում են ու շատ վախենալու է ինձ այստեղ գտնվելը"; +"profile_deactivate_reason_5" = "Իմ էջը չեն մեկնաբանում"; +"profile_deactivate_reason_5_text" = "Ինձ այստեղ շան տեղ դնող չկա ու ես տխրում եմ։ Դուք կզղջաք որ ես հեռացա..."; +"profile_deactivate_reason_6" = "Այլ պատճառ"; + +"profile_deactivated_msg" = "Ձեր էջը ջնջված է։

Եթե Դուք ուզենաք նորից օգտվել Ձեր էջով, կարող եք ապաակտիվացնել այն մինչև $1:"; +"profile_deactivated_status" = "Էջը ջնջված է"; +"profile_deactivated_info" = "Օգտատիրոջ էջը հեռացվել է։
Մանրամասն տեղեկատվությունը բացակայում է։"; + +"share_with_friends" = "Պատմել ընկերներին"; + +"end_all_sessions" = "Դուրս գալ բոլոր սեսսիաներից"; +"end_all_sessions_description" = "Եթե ցանկանում եք դուրս գալ $1–ից ամեն դեվայսից, սեղմե՛ք ներքևի կոճակը"; + +"end_all_sessions_done" = "Բոլոր սեսսիաները նետված են, ներառյալ բջջային հավելվածները"; + /* Two-factor authentication */ "two_factor_authentication" = "Երկքայլ աուտենտիֆիկացիա"; @@ -708,6 +757,75 @@ "users_gifts" = "Նվերներ"; +/* Apps */ + +"app" = "Հավելված"; +"apps" = "Հավելվածներ"; +"my_apps" = "Իմ հավելվածները"; +"all_apps" = "Բոլոր հավելվածները"; +"installed_apps" = "Տեղադրված հավելվածները"; +"own_apps" = "Կառավարում"; +"own_apps_alternate" = "Իմ այլ հավելվածները"; + +"app_play" = "միացնել"; +"app_uninstall" = "անջատել"; +"app_edit" = "խմբագրել"; +"app_dev" = "Մշակող"; + +"create_app" = "Ստեղծել հավելված"; +"edit_app" = "Խմբագրել հավելվածը"; +"new_app" = "Նոր հավելված"; +"app_news" = "Նորություններով նշում"; +"app_state" = "Կարգավիճակ"; +"app_enabled" = "Միացված է"; +"app_creation_hint_url" = "URL–ում նշեք կոնկրետ հասցեն իր սխեմայով (https), պորտով (80) և անհրաժեշտ միացման կարգավորումներով։"; +"app_creation_hint_iframe" = "Ձեր հավելվածը բացված է iframe–ով։"; +"app_balance" = "Հավելվածի հաշվին կա $1 ձայն։"; +"app_users" = "Ձեր հավելվածով օգտվում է $1 հոգի։"; +"app_withdrawal_q" = "դուրս բերե՞լ"; +"app_withdrawal" = "Միջոցների դուրս բերում"; +"app_withdrawal_empty" = "Կներեք, դատարկությունը չհաջողվեց դուրս բերել։"; +"app_withdrawal_created" = "$1 ձայնի դուրս բերման հայտը գրանցված է։ Սպասեք հաշվառմանը։"; + +"appjs_payment" = "Գնման վճարում"; +"appjs_payment_intro" = "Դուք պատրաստվում եք հավելվածի գնումը վճարել"; +"appjs_order_items" = "Գնման ցուցակ"; +"appjs_payment_total" = "Վճարման ընդհանուր գին"; +"appjs_payment_confirm" = "Վճարել"; +"appjs_err_funds" = "Չհաջողվե՛ց վճարել գնումը անբավարար միջոցների համար։"; + +"appjs_wall_post" = "Հրապարակել գրությունտը"; +"appjs_wall_post_desc" = "ցանկանում է Ձեր պատին գրություն թողնել"; + +"appjs_sperm_friends" = "ձեր ընկերներին"; +"appjs_sperm_friends_desc" = "ավելացնել օգտատերերին որպես ընկերներ և կարդալ Ձեր գրությունները"; +"appjs_sperm_wall" = "ձեր պատին"; +"appjs_sperm_wall_desc" = "դիտել Ձեր լուրերը, կարդալ պատն ու թողել գրություններ"; +"appjs_sperm_messages" = "ձեր նամակներին"; +"appjs_sperm_messages_desc" = "կարդալ և գրել նամակներ Ձեր անունից"; +"appjs_sperm_groups" = "ձեր հանրություններին"; +"appjs_sperm_groups_desc" = "դիտել Ձեր խմբերի ցուցակն ու բաժանորդագրել դեպի այլ խմբեր"; +"appjs_sperm_likes" = "լայքելու ֆունկցիոնալին"; +"appjs_sperm_likes_desc" = "տեղադրել և հանել \"Դուր գալու\" ռեակցիաները ձայնագրություններից"; + +"appjs_sperm_request" = "Հասանելիության հարցում"; +"appjs_sperm_requests" = "հասանելիություն է խնդրում"; +"appjs_sperm_can" = "Հավելվածը կարող է"; +"appjs_sperm_allow" = "Թույլատրել"; +"appjs_sperm_disallow" = "Չթույլատրել"; + +"app_uninstalled" = "Հավելվածն անջատված է"; +"app_uninstalled_desc" = "Այն Ձեր անունից էլ չի կարող կատարել գործողություններ։"; +"app_err_not_found" = "Հավելվածը չի գտնվել"; +"app_err_not_found_desc" = "Սխալ կամ անջատված իդենտիֆիկատոր։"; +"app_err_forbidden_desc" = "Այս հավելվածը Ձերը չէ։"; +"app_err_url" = "Սխալ հասցե"; +"app_err_url_desc" = "Հավելվածի հասցեն չանցավ ստուգումը. համոզվե՛ք որ այն ճիշտ է գրված:"; +"app_err_ava" = "Չհաջողվե՛ց վերբեռնել ավատարը:"; +"app_err_ava_desc" = "Ավատարը չափազանց մեծ և ծուռ է. ընդհանուր բնույթի սխալ №$res."; +"app_err_note" = "Չհաջողվե՛ց ամրացնել նորությունների նիշքը"; +"app_err_note_desc" = "Համոզվե՛ք որ հղումը ճիշտ է և պատկանում է Ձեզ։"; + /* Support */ "support_opened" = "Բաց"; @@ -767,7 +885,12 @@ "banned_alt" = "Օգտատերը արգելափակված է"; "banned_1" = "Կներե՛ք, $1, բայց Դուք կասեցված եք։"; "banned_2" = "Պատճառը հետևյալն է․ $1. Ափսոս, բայց մենք ստիպված Ձեզ հավերժ ենք կասեցրել;"; +"banned_perm" = "Ցավոք, մենք ստիպված արգելափակել ենք Ձեզ ընդմիշտ։"; +"banned_until_time" = "Այս անգամ մենք ստիպված արգելափակել ենք Ձեզ մինչև $1"; "banned_3" = "Դուք դեռ կարող եք գրել նամակ աջակցության ծառայությանը, եթե համարում եք որ դա սխալմունք է, կամ էլ կարող եք դուրս գալ։"; +"banned_unban_myself" = "Ապասառեցնել էջը"; +"banned_unban_title" = "Ձեր հաշիվը ապասառեցված է։"; +"banned_unban_description" = "Աշխատե՛ք այլևս չխախտել կանոնները։"; /* Registration confirm */ @@ -996,6 +1119,17 @@ "admin_commerce_disabled" = "Կոմմերցիան անջատված է համակարգային ադմինիստրատորի կողմից"; "admin_commerce_disabled_desc" = "Վաուչերների և նվերների կարգավորումները կպահպանվեն, բայց ոչ մի ազդեցություն չեն ունենա։"; +"admin_banned_links" = "Արգելափակված հղումներ"; +"admin_banned_link" = "Հղում"; +"admin_banned_domain" = "Դոմեն"; +"admin_banned_link_description" = "Պրոտոկոլով (https://example.com/)"; +"admin_banned_link_regexp" = "Ռեգուլյար արտահայտություն"; +"admin_banned_link_regexp_description" = "Տեղադրվում է վերոնշյալ դոմենից հետո։ Մի լրացրե՛ք, եթե ցանկանում եք արգելափակել ամբողջ դոմենը"; +"admin_banned_link_reason" = "Պատճառ"; +"admin_banned_link_initiator" = "Նախաձեռնող"; +"admin_banned_link_not_specified" = "Հղումը նշված չէ"; +"admin_banned_link_not_found" = "Հղումը չի գտնվել"; + /* Paginator (deprecated) */ "paginator_back" = "Հետ"; @@ -1059,3 +1193,21 @@ "cookies_popup_content" = "Cookie բառը անգլերենից նշանակում է թխվածքաբլիթ, իսկ թխվածքաբլիթը համեղ է։ Մեր կայքը չի ուտում թխվածք, բայց օգտագործում է այն ուղղակի սեսսիան կողմնորոշելու համար։ Ավելի մանրամասն կարող եք ծանոթանալ մեր գաղտնիության քաղաքականությանը հավելյալ ինֆորմացիայի համար։"; "cookies_popup_agree" = "Համաձայն եմ"; + +/* Away */ + +"url_is_banned" = "Անցումն անհնար է"; +"url_is_banned_comment" = "Ադմինիստրացիան $1 խորհուրդ չի տալից անցնել այս հղումով։"; +"url_is_banned_comment_r" = "Ադմինիստրացիան $1 խորհուրդ չի տալից անցնել այս հղումով։

Պատճառը: $2"; +"url_is_banned_default_reason" = "Հղումը դեպի կայք կարող է ստեղծված լինել շորթողներից ՝ օգտատերերին խաբելու և խարդախության նպատակներով, շահույթ ստանալու համար։"; +"url_is_banned_title" = "Հղում դեպի կասկածելի կայք"; +"url_is_banned_proceed" = "Անցնել հղումով"; + +/* Maintenance */ + +"global_maintenance" = "Տեխնիկական աշխատանքներ"; +"section_maintenance" = "Բաժինը անհասանելի է"; +"undergoing_global_maintenance" = "Ցավոք սրտի, հիմա հոսքը փակված է տեխնիկական աշխատանքներ անցկացնելու համար։ Մենք արդեն աշխատում ենք խնդիրները շտկելու ուղղությամբ։ Խնդրում ենք այցելել մի քիչ ուշ։"; +"undergoing_section_maintenance" = "Ցավոք սրտի, $1 բաժինը ժամանակավորապես անհասանելի է։ Մենք արդեն աշխատում ենք խնդիրները շտկելու ուղղությամբ։ Խնդրում ենք այցելել մի քիչ ուշ։"; + +"topics" = "Թեմաներ"; From d1ceb0da2512909af9a25af996cbac7e35ececd5 Mon Sep 17 00:00:00 2001 From: lvl <90154880+apeeh@users.noreply.github.com> Date: Fri, 30 Sep 2022 17:53:01 +0400 Subject: [PATCH 017/285] Update am.strings (#737) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit исправлен недоперевод (543 строка) Co-authored-by: Vladimir Barinov --- locales/am.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/am.strings b/locales/am.strings index 59404426..141768fc 100644 --- a/locales/am.strings +++ b/locales/am.strings @@ -540,7 +540,7 @@ "profile_deactivate_reason_2_text" = "Թեկուզ այս կայքը լավն է, բայց ցավոք ինձնից ահագին ժամանակ է խլում։"; "profile_deactivate_reason_3" = "Կայքը բազմաթիվ անցանկանալի մատերիալներ է պարունակում"; "profile_deactivate_reason_3_text" = "Ես բազմաթիվ պոռնոգրաֆիա ու անօրինական կինոներ եմ գրել – բոլ ա։ Հիմա հավես չկա։"; -"profile_deactivate_reason_4" = "Меня беспокоит безопасность моих данных"; +"profile_deactivate_reason_4" = "Ինձ անհանգստացնում է իմ տվյալների անվտանգությունը"; "profile_deactivate_reason_4_text" = "Ինձ հետևում են ու շատ վախենալու է ինձ այստեղ գտնվելը"; "profile_deactivate_reason_5" = "Իմ էջը չեն մեկնաբանում"; "profile_deactivate_reason_5_text" = "Ինձ այստեղ շան տեղ դնող չկա ու ես տխրում եմ։ Դուք կզղջաք որ ես հեռացա..."; From 1370c68b11bd86f7f4145d8458993ad8d4038be4 Mon Sep 17 00:00:00 2001 From: Ilya Prokopenko Date: Sun, 2 Oct 2022 23:47:34 +0700 Subject: [PATCH 018/285] Imbibe themepack "Midnight" into master (#733) wiwajapanigobugarin --- .gitignore | 1 + themepacks/midnight/res/checkbox.png | Bin 0 -> 288 bytes themepacks/midnight/res/flex_arrow_open.png | Bin 0 -> 1012 bytes themepacks/midnight/res/flex_arrow_shut.gif | Bin 0 -> 145 bytes themepacks/midnight/res/header.png | Bin 0 -> 5770 bytes themepacks/midnight/res/header_custom.png | Bin 0 -> 3697 bytes themepacks/midnight/res/header_purple.png | Bin 0 -> 162 bytes themepacks/midnight/res/input_clear.gif | Bin 0 -> 64 bytes themepacks/midnight/res/like.gif | Bin 0 -> 594 bytes themepacks/midnight/res/pin.png | Bin 0 -> 777 bytes themepacks/midnight/res/published.gif | Bin 0 -> 68 bytes themepacks/midnight/res/radio.png | Bin 0 -> 3321 bytes themepacks/midnight/res/xheader.png | Bin 0 -> 7121 bytes themepacks/midnight/res/xheader_custom.png | Bin 0 -> 5702 bytes themepacks/midnight/res/xmas.css | 7 + themepacks/midnight/stylesheet.css | 203 ++++++++++++++++++++ themepacks/midnight/theme.yml | 11 ++ 17 files changed, 222 insertions(+) create mode 100644 themepacks/midnight/res/checkbox.png create mode 100644 themepacks/midnight/res/flex_arrow_open.png create mode 100644 themepacks/midnight/res/flex_arrow_shut.gif create mode 100644 themepacks/midnight/res/header.png create mode 100644 themepacks/midnight/res/header_custom.png create mode 100644 themepacks/midnight/res/header_purple.png create mode 100644 themepacks/midnight/res/input_clear.gif create mode 100644 themepacks/midnight/res/like.gif create mode 100644 themepacks/midnight/res/pin.png create mode 100644 themepacks/midnight/res/published.gif create mode 100644 themepacks/midnight/res/radio.png create mode 100644 themepacks/midnight/res/xheader.png create mode 100644 themepacks/midnight/res/xheader_custom.png create mode 100644 themepacks/midnight/res/xmas.css create mode 100644 themepacks/midnight/stylesheet.css create mode 100644 themepacks/midnight/theme.yml diff --git a/.gitignore b/.gitignore index b3bb2167..c060b84e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,6 @@ tmp/* themepacks/* !themepacks/.gitkeep !themepacks/openvk_modern +!themepacks/midnight storage/* !storage/.gitkeep diff --git a/themepacks/midnight/res/checkbox.png b/themepacks/midnight/res/checkbox.png new file mode 100644 index 0000000000000000000000000000000000000000..57d8238182ed343208ad7c6568f51bf5dff5ea04 GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^{6K8M!3-ot%Y$-(6k~CayA#8@b22Z19F}xPUq=Rp zjs4tz5?O(Ki2$DvR|743ATu{=frO}nt9_8PxT>{@2T;WPT(udH;wTC73;quQ4ELJ% zMgqk+3p^r=85sBugD~Uq{1quc!CFrj#}Etus~1o69#G(64v>nvQUBN~-cpGBfw2Ap zjRP-kCfiJrzFSlvv$ey-+uY*hF7Iuz@6`_)OglFtpXt~Zu_>1JT*r2uFPUciYMSjm zu^)@?yqMPfcm=Edp<|mj9dr$w)O*i=(mi?a^fTKTlB2j!&5>tKzMF1&TGI6SU3(jE W&I{sJ!j(XWFnGH9xvXY99v00004XF*Lt006_$ znkEK<0008$X+uL$Nkc;*P;zf(X>4Tx065EIU|^o$=;GwcB*4H>P*hUn9^@Dq5gDbx zex8Aiftdje5|fJy90LM;K(*l4-L zYNquBn@-ynyGHv4hepR1r%vYyE;C)1xNUSl;BnFOiPujbL0>IDSO27d#=ylv$AVvn z3WeE(r$%+}eGR{wGMaC+dbRECFz#I4t=hA&PriTtM8!!zJl%H2 z$ywpEU(BtV&$nR7BAdn6mKHA;T(NOg@ai9H=dE|!@Nv`JE#6!IY+tuCX}9E_i~D*G zcpPFseEewFalezIr|zCvajxWo^CgkX&#vyiKJjMOZP&X>_Zc2Me01c=%4hvADqbbO z33zA!!Qhk97x8a=KiGdU{r>;=-~ayr4kZgmpSlJ(0000aP)t-sARr(kBO^XOK0-o5 zB_$u$yc7dHF?2-g6IWy#F~EZ*ucxB- iH}@lgdi$v7E1I3Oy$p+v#h%3g0000+|z`(_z!vF*zv1VIaTRS^DZEbBmJv|o}7dJOI2L}fo z9UXIXa{~hdkTO)jVi$1IbM;<}*Jn*R6ckEMIf$$NYQ}5Kw^51>0 hw_pR0gU8{51A-cXEYFU;>?)hbs-1cIt)CKuH2}DPDG>kw literal 0 HcmV?d00001 diff --git a/themepacks/midnight/res/header.png b/themepacks/midnight/res/header.png new file mode 100644 index 0000000000000000000000000000000000000000..53e7a0187be2ac2af44848ded38cc1e45c2df6ba GIT binary patch literal 5770 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 bKfkEsk?q@WeQ9Q#7oZW=%;2fs`OE(YN+u;$ literal 0 HcmV?d00001 diff --git a/themepacks/midnight/res/header_custom.png b/themepacks/midnight/res/header_custom.png new file mode 100644 index 0000000000000000000000000000000000000000..3df6fb594f283426dbcd5f7820ec79647d08c426 GIT binary patch literal 3697 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 literal 0 HcmV?d00001 diff --git a/themepacks/midnight/res/header_purple.png b/themepacks/midnight/res/header_purple.png new file mode 100644 index 0000000000000000000000000000000000000000..00c484a5b9353cde2e2e2018a72f60542b42c928 GIT binary patch literal 162 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{H!2~1^=N$M35-1LGcVbv~PUa<$!;&U>c zv7h@-A}f&3S>O>_%)r2R5QG_bOw4`@6g2mAaSV|N*X=nd$Y8*6=tAPJR|0qIH8R)K zRycgP5T~xXTzAX9qB1d?568@n_r6d+o>C|Gn)f9W=W?mJn-^s)1RBBM>FVdQ&MBb@ E0CdDM-2eap literal 0 HcmV?d00001 diff --git a/themepacks/midnight/res/input_clear.gif b/themepacks/midnight/res/input_clear.gif new file mode 100644 index 0000000000000000000000000000000000000000..5d2668974240c09b6b5c8af5a19e9de9303a2cdf GIT binary patch literal 64 zcmZ?wbhEHb+|z~IfG!vF*zu{KFD-B9o8!JbnbElVZE3^>^Z%=8mo zY^wZS`vTm0{ayRr?AqMz+P$5+eO!hD9BjLOIeucMR2h5nHfYeGqKs4rLnVfGchs=@Jn-X^7HeGNs6mE z+opIr=ch(5&{nrM)NxOWn46unR71r|U)wc1acM#7DnmUl8}rD#lvTOOE4^LvvJ#f1 z#Vqu4YKRY6EG?mDXPzDEJ;~BIMMlyfCTPB{roWuDiGyXnu7)C%vF z(vxJ?tzRiCw`J?fo$_L03i65yVoJ&?`@~dLPpF+Zw@+Q;{0U91%lou-bT8}adm9*@ zGcw+4V!F@Fe3!R{rKQ#D_14xOU)y|LZ~J|{oxOuC!&hBSp$!WBineV6nv>qon<(dA j@|L-yKWT5f;A2IZrk00RO{}_lnv+~S52`jYFjxZs1$TW7 literal 0 HcmV?d00001 diff --git a/themepacks/midnight/res/pin.png b/themepacks/midnight/res/pin.png new file mode 100644 index 0000000000000000000000000000000000000000..d91313dbdb69694af4c661a92aaab7e2e4e0237e GIT binary patch literal 777 zcmV+k1NQuhP)004&&004{<008|>004nL003F*009yY002DZ000@zy2&Ck0003Y zX+uL$Nkc;*P;zf(X>4Tx04UF6U|=$Eba8TJ5@2A+%_}Jia(7aQh>TKTKhMC%z{~&! ziOIzUjsXEaAa-7UUMd3y_;!tf5kz0s1)0S_8sJJUC@KNce}LF1CAB!2fq~Hg$j&Y= zDFBKy&H=JTlCr_<4Ip+=NRTs-eFVtnONX$pfY?b8_7f1h2CFd6v zfq~@@Ld>L>fnk9T0|Wn5gqWHk1A~A*1H-;K0Kmpi{cn=x1ONa432;bRa{vGf6951U z69E94oEQKA0a8gsK~yMHW55SkSvhI~J-hy~Fth1~`%PhBgoPaJN4~=p^VphaonvF+Q2x*GkBN&@@E3WfB%rWD*flW_Wk`2dye$0yV{lZf(3z& z|G)3pMAbL%?%n_Q?-y7R2>ko^=l|X#eWF15yC6QyWCj)%4q>22l79XE{sF}Q|L-pY z6C)GInam*m%1t>4#pVVvC$-eQ_Pu(0H|_b$%h&%g{A2j}``dq@sXw7g7??oe_xkPa z?J`mZN}oT!cyi+G{GEqS&C-7N{?YxXFD@N|ssjV2I}Z-K3i8Xj-MY8GRY*`?4ygGP z*bhhhm7hMp=nho}28^cqQJb&c+Me#~+WZVEh83*bl*0f3WOt6Xnh-4Y00000NkvXX Hu0mjfza>t3 literal 0 HcmV?d00001 diff --git a/themepacks/midnight/res/published.gif b/themepacks/midnight/res/published.gif new file mode 100644 index 0000000000000000000000000000000000000000..2a8e0a83a8bbb3970d37efd2993546712d1bcfd9 GIT binary patch literal 68 zcmZ?wbhEHb+|z`)F)!vF*zu|^lWcymL46Mb)>0F&q({^i1){LYiN Tc$L2AbkpZlja8LlWv~VSigFC7 literal 0 HcmV?d00001 diff --git a/themepacks/midnight/res/radio.png b/themepacks/midnight/res/radio.png new file mode 100644 index 0000000000000000000000000000000000000000..006d04e76dc74f87908bbdefb85d72eb233a6c5c GIT binary patch literal 3321 zcmV004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000Uv 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 K#!Iyu!T%2uE};Mb literal 0 HcmV?d00001 diff --git a/themepacks/midnight/res/xheader_custom.png b/themepacks/midnight/res/xheader_custom.png new file mode 100644 index 0000000000000000000000000000000000000000..ae6ff168fd219dd7383b0f410f240e50163175fb GIT binary patch literal 5702 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 literal 0 HcmV?d00001 diff --git a/themepacks/midnight/res/xmas.css b/themepacks/midnight/res/xmas.css new file mode 100644 index 00000000..17022e25 --- /dev/null +++ b/themepacks/midnight/res/xmas.css @@ -0,0 +1,7 @@ +.page_header { + background-image: url('/themepack/midnight/0.0.1.0/resource/xheader.png'); +} + +.page_custom_header { + background-image: url('/themepack/midnight/0.0.1.0/resource/xheader_custom.png'); +} \ No newline at end of file diff --git a/themepacks/midnight/stylesheet.css b/themepacks/midnight/stylesheet.css new file mode 100644 index 00000000..54ac8534 --- /dev/null +++ b/themepacks/midnight/stylesheet.css @@ -0,0 +1,203 @@ +* { + scrollbar-color: #3f365b #1d192b; +} + +html { + color-scheme: dark !important; +} + +body { + background-color: #0e0b1a; + color: #c6d2e8; +} + +span, .post-author .date, .crp-entry--message---text, .messenger-app--messages---message .time, .navigation-lang .link_new { + color: #8b9ab5 !important; +} + +.nobold, nobold { + color: #6f82a8; +} + +.page_status { + color: #c6d2e8; +} + +.profileName h2 { + color: #8eb2d0; +} + +.wrap1, .wrap2, .page-wrap, #wrapH, #wrapHI { + border-color: #1c202f; +} + +.accountInfo, .left_small_block, #profile_link, .profile_link, .navigation .link, .navigation .link:hover, .navigation_footer .link, .navigation_footer .link:hover, .completeness-gauge, input[type="text"], input[type="password"], input[type~="text"], input[type~="password"], input[type="email"], input[type="phone"], input[type~="email"], input[type~="phone"], input[type="search"], input[type~="search"], input[type~="date"], select, .content_title_expanded, .content_title_unexpanded, .content_subtitle, textarea, .post-content, .post-author, hr, h4, .postFeedWrapper, .tabs, #wallAttachmentMenu, .ovk-diag, .ovk-diag-head, #ovkDraw, #ovkDraw .literally .lc-picker, .literally .lc-options.horz-toolbar, .page_wrap, .container_gray .content, .summaryBar, .groups_options, form[action="/search"] > input, .header_search_input, .header_search_inputbt, .accent-box, .page_status_popup, .messenger-app--input, .messenger-app, .crp-entry:first-of-type, .crp-list, .crp-entry, .note_footer, .page_content > div, #editor, .note_header, center[style="background: white;border: #DEDEDE solid 1px;"], .album-photo img, .mb_tabs, .mb_tab#active div, .navigation-lang .link_new, #faqhead, #faqcontent, .post-divider, .comment, .commentsTextFieldWrap, tr, td, th, #votesBalance, .paginator a.active, .paginator a:hover { + border-color: #2c2640 !important; +} + +hr { + background-color: #2c2640 !important; +} + +.cookies-popup { + background: linear-gradient(#1e1a2b, #231e33); + box-shadow: unset; +} + +.button, #activetabs, .messagebox-content-header, .accent-box, .button_search { + background-color: #383052; +} + +.tab:hover { + background-color: #40375e; +} + +.menu_divider, .ovk-diag-action, .minilink .counter { + background-color: #2c2640; +} + +#ovkDraw .literally .lc-picker, .literally .lc-options.horz-toolbar, .mb_tab#active { + background-color: #453e5e; +} + +.ovk-diag-cont { + background-color: #272e4894; +} + +a, .page_footer .link, #profile_link, .profile_link { + color: #8fb9d8; +} + +.page_footer .link:hover, .navigation .link:hover, .navigation .edit-button:hover, #profile_link:hover, .profile_link:hover, #wallAttachmentMenu > a:hover, .crp-entry:hover, .navigation-lang .link_new:hover, .paginator a:hover, .post-share-button:hover, .post-like-button:hover { + background-color: #272138 !important; +} + +.header_navigation .link a { + color: #bcc3d0; +} + +.header_navigation .link a:hover, .home_button_custom { + color: #c7cdd9; +} + +.navigation .link { + color: #d9e0ee; +} + +.navigation .edit-button { + background-color: #0e0b1a !important; + color: #7b94c4 !important; +} + +#test-label, .msg.msg_err { + background-color: #30161d; +} + +.msg.msg_succ { + background-color: #163f13; +} + +h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { + color: #7c94c5; +} + +.notes_titles small, .post-upload { + color: #6f82a8; +} + +.content_title_expanded, .content_title_unexpanded, .ovk-diag, .settings_delete, center[style="background: white;border: #DEDEDE solid 1px;"], .album-photo img, #faqhead, td.e, tr.e { + background-color: #231e33 !important; +} + +.content_subtitle, .postFeedWrapper, .ovk-diag-head, .container_gray, .page_status_popup, .messenger-app--input, .note_header, #faqcontent, .commentsTextFieldWrap, td.v, tr.v, #votesBalance { + background-color: #1e1a2b !important; +} + +.post-author { + background-color: #1e1a2b; + /* this is fix to correct the unexpected behavior of the microblog style lol */ +} + +.content_title_expanded { + background-image: url("/themepack/midnight/0.0.1.0/resource/flex_arrow_open.png"); +} + +.content_title_unexpanded { + background-image: url("/themepack/midnight/0.0.1.0/resource/flex_arrow_shut.gif"); +} + +.ovk-video > .preview, .video-preview { + box-shadow: inset 0 0 0 1px #231e33, inset 0 0 0 2px #1e1a2b; +} + +#wallAttachmentMenu, .container_gray .content, .mb_tabs { + background-color: #120e1f; +} + +#wallAttachmentMenu > .header, .messenger-app--messages---message.unread, tr.h { + background-color: #1d192b; +} + +.toTop { + background-color: #272138; + color: #c6d2e8; +} + +.page_yellowheader { + color: #c6d2e8; + background-image: url("/themepack/midnight/0.0.1.0/resource/header_purple.png"); + background-color: #231f34; + border-color: #231f34; +} + +.page_header { + background-image: url("/themepack/midnight/0.0.1.0/resource/header.png"); +} + +.page_custom_header { + background-image: url("/themepack/midnight/0.0.1.0/resource/header_custom.png"); +} + +.page_yellowheader span, .page_yellowheader a { + color: #a48aff !important; +} + +.completeness-gauge { + background-color: #231e33; +} + +.completeness-gauge > div { + background-color: #2c2640; +} + +form[action="/search"] > input, .header_search_input, textarea { + background-color: #181826 !important; +} + +input[type="checkbox"] { + background-image: url("/themepack/midnight/0.0.1.0/resource/checkbox.png"); +} + +input[type="radio"] { + background-image: url("/themepack/midnight/0.0.1.0/resource/radio.png"); +} + +.header_navigation .link { + background: unset; +} + +.heart { + background-image: url("/themepack/midnight/0.0.1.0/resource/like.gif") !important; +} + +.pinned-mark, .post-author .pin { + background-image: url("/themepack/midnight/0.0.1.0/resource/pin.png") !important; +} + +.repost-icon { + background-image: url("/themepack/midnight/0.0.1.0/resource/published.gif") !important; +} + +.post-author .delete { + background-image: url("/themepack/midnight/0.0.1.0/resource/input_clear.gif") !important; +} \ No newline at end of file diff --git a/themepacks/midnight/theme.yml b/themepacks/midnight/theme.yml new file mode 100644 index 00000000..02c5e0d3 --- /dev/null +++ b/themepacks/midnight/theme.yml @@ -0,0 +1,11 @@ +id: midnight +version: "0.0.1.0" +openvk_version: 0 +enabled: 1 +metadata: + name: + _: "OpenVK Midnight" + en: "OpenVK Midnight" + ru: "OpenVK Midnight" + author: "Ilya Prokopenko" + description: "A dark theme for OpenVK" \ No newline at end of file From 56da94358f5b36e18fb056b9562e1de0dfba1a2d Mon Sep 17 00:00:00 2001 From: veselcraft Date: Sat, 1 Oct 2022 13:13:50 +0300 Subject: [PATCH 019/285] VKAPI: Fix 500 error when birthday is not set at all --- VKAPI/Handlers/Account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VKAPI/Handlers/Account.php b/VKAPI/Handlers/Account.php index 6f4ad0e6..75f33b53 100644 --- a/VKAPI/Handlers/Account.php +++ b/VKAPI/Handlers/Account.php @@ -13,7 +13,7 @@ final class Account extends VKAPIRequestHandler "last_name" => $this->getUser()->getLastName(), "home_town" => $this->getUser()->getHometown(), "status" => $this->getUser()->getStatus(), - "bdate" => $this->getUser()->getBirthday()->format('%e.%m.%Y'), + "bdate" => is_null($this->getUser()->getBirthday()) ? '01.01.1970' : $this->getUser()->getBirthday()->format('%e.%m.%Y'), "bdate_visibility" => $this->getUser()->getBirthdayPrivacy(), "phone" => "+420 ** *** 228", # TODO "relation" => $this->getUser()->getMaritalStatus(), From 6907c55b4a43a3e5c90422f2562562aead923257 Mon Sep 17 00:00:00 2001 From: celestora Date: Mon, 3 Oct 2022 21:57:50 +0300 Subject: [PATCH 020/285] Delete composer.lock --- composer.lock | 2504 ------------------------------------------------- 1 file changed, 2504 deletions(-) delete mode 100644 composer.lock diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 3fe4f4d8..00000000 --- a/composer.lock +++ /dev/null @@ -1,2504 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "bf1e1680113afcac0e766daba5e899e0", - "packages": [ - { - "name": "al/emoji-detector", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/AlmaArmas/emoji-detector-php.git", - "reference": "d817d586a5b22674d91e8203098987a1f2b2573e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/AlmaArmas/emoji-detector-php/zipball/d817d586a5b22674d91e8203098987a1f2b2573e", - "reference": "d817d586a5b22674d91e8203098987a1f2b2573e", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=5.3" - }, - "require-dev": { - "phpunit/phpunit": "^4.8" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/Emoji.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Parecki", - "email": "aaron@parecki.com", - "homepage": "https://aaronparecki.com/" - } - ], - "description": "Detect and return all emoji found in a string", - "homepage": "https://github.com/aaronpk/emoji-detector-php", - "support": { - "source": "https://github.com/AlmaArmas/emoji-detector-php/tree/0.2.3" - }, - "time": "2020-06-26T09:10:17+00:00" - }, - { - "name": "bhaktaraz/php-rss-generator", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/bhaktaraz/php-rss-generator.git", - "reference": "53cf11db18d87e65973e6df453fb8c1382e5a3bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bhaktaraz/php-rss-generator/zipball/53cf11db18d87e65973e6df453fb8c1382e5a3bd", - "reference": "53cf11db18d87e65973e6df453fb8c1382e5a3bd", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "Bhaktaraz\\RSSGenerator\\": "Source/Bhaktaraz/RSSGenerator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bhaktaraz Bhatta", - "email": "bhattabhakta@gmail.com" - } - ], - "description": "Simple RSS generator library for PHP 5.5 or later.", - "homepage": "https://github.com/bhaktaraz/php-rss-generator", - "keywords": [ - "Facebook product feed generator", - "feed", - "generator", - "rss", - "writer" - ], - "support": { - "issues": "https://github.com/bhaktaraz/php-rss-generator/issues", - "source": "https://github.com/bhaktaraz/php-rss-generator/tree/master" - }, - "time": "2021-03-15T10:59:47+00:00" - }, - { - "name": "chillerlan/php-qrcode", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/chillerlan/php-qrcode.git", - "reference": "c43715795d0fbcc913a2e9c5f8c757062ce0e8c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/c43715795d0fbcc913a2e9c5f8c757062ce0e8c7", - "reference": "c43715795d0fbcc913a2e9c5f8c757062ce0e8c7", - "shasum": "" - }, - "require": { - "chillerlan/php-settings-container": "^2.1.4", - "ext-mbstring": "*", - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phan/phan": "^5.3", - "phpunit/phpunit": "^9.5", - "setasign/fpdf": "^1.8.2" - }, - "suggest": { - "chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.", - "setasign/fpdf": "Required to use the QR FPDF output.", - "simple-icons/simple-icons": "SVG icons that you can use to embed as logos in the QR Code" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "chillerlan\\QRCode\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT", - "Apache-2.0" - ], - "authors": [ - { - "name": "Kazuhiko Arase", - "homepage": "https://github.com/kazuhikoarase/qrcode-generator" - }, - { - "name": "ZXing Authors", - "homepage": "https://github.com/zxing/zxing" - }, - { - "name": "Ashot Khanamiryan", - "homepage": "https://github.com/khanamiryan/php-qrcode-detector-decoder" - }, - { - "name": "Smiley", - "email": "smiley@chillerlan.net", - "homepage": "https://github.com/codemasher" - }, - { - "name": "Contributors", - "homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors" - } - ], - "description": "A QR code generator and reader with a user friendly API. PHP 7.4+", - "homepage": "https://github.com/chillerlan/php-qrcode", - "keywords": [ - "phpqrcode", - "qr", - "qr code", - "qr-reader", - "qrcode", - "qrcode-generator", - "qrcode-reader" - ], - "support": { - "issues": "https://github.com/chillerlan/php-qrcode/issues", - "source": "https://github.com/chillerlan/php-qrcode/tree/main" - }, - "funding": [ - { - "url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4", - "type": "custom" - }, - { - "url": "https://ko-fi.com/codemasher", - "type": "ko_fi" - } - ], - "time": "2022-08-09T13:01:31+00:00" - }, - { - "name": "chillerlan/php-settings-container", - "version": "2.1.4", - "source": { - "type": "git", - "url": "https://github.com/chillerlan/php-settings-container.git", - "reference": "1beb7df3c14346d4344b0b2e12f6f9a74feabd4a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/1beb7df3c14346d4344b0b2e12f6f9a74feabd4a", - "reference": "1beb7df3c14346d4344b0b2e12f6f9a74feabd4a", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phan/phan": "^5.3", - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "chillerlan\\Settings\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Smiley", - "email": "smiley@chillerlan.net", - "homepage": "https://github.com/codemasher" - } - ], - "description": "A container class for immutable settings objects. Not a DI container. PHP 7.4+", - "homepage": "https://github.com/chillerlan/php-settings-container", - "keywords": [ - "PHP7", - "Settings", - "configuration", - "container", - "helper" - ], - "support": { - "issues": "https://github.com/chillerlan/php-settings-container/issues", - "source": "https://github.com/chillerlan/php-settings-container" - }, - "funding": [ - { - "url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4", - "type": "custom" - }, - { - "url": "https://ko-fi.com/codemasher", - "type": "ko_fi" - } - ], - "time": "2022-07-05T22:32:14+00:00" - }, - { - "name": "erusev/parsedown", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/erusev/parsedown.git", - "reference": "6598f3860c2698fe2f0f1bc98212fc01d0a1893c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/6598f3860c2698fe2f0f1bc98212fc01d0a1893c", - "reference": "6598f3860c2698fe2f0f1bc98212fc01d0a1893c", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-0": { - "Parsedown": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Emanuil Rusev", - "email": "hello@erusev.com", - "homepage": "http://erusev.com" - } - ], - "description": "Parser for Markdown.", - "homepage": "http://parsedown.org", - "keywords": [ - "markdown", - "parser" - ], - "support": { - "issues": "https://github.com/erusev/parsedown/issues", - "source": "https://github.com/erusev/parsedown/tree/master" - }, - "time": "2020-08-09T14:12:21+00:00" - }, - { - "name": "ezyang/htmlpurifier", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "dff4746e133777583fbf43d2b95372e8d818df1f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/dff4746e133777583fbf43d2b95372e8d818df1f", - "reference": "dff4746e133777583fbf43d2b95372e8d818df1f", - "shasum": "" - }, - "require": { - "php": ">=5.2" - }, - "suggest": { - "cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.", - "ext-bcmath": "Used for unit conversion and imagecrash protection", - "ext-iconv": "Converts text to and from non-UTF-8 encodings", - "ext-tidy": "Used for pretty-printing HTML" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "library/HTMLPurifier.composer.php" - ], - "psr-0": { - "HTMLPurifier": "library/" - }, - "exclude-from-classmap": [ - "/library/HTMLPurifier/Language/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1-or-later" - ], - "authors": [ - { - "name": "Edward Z. Yang", - "email": "admin@htmlpurifier.org", - "homepage": "http://ezyang.com" - } - ], - "description": "Standards compliant HTML filter written in PHP", - "homepage": "http://htmlpurifier.org/", - "keywords": [ - "html" - ], - "support": { - "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/master" - }, - "time": "2022-08-16T02:59:31+00:00" - }, - { - "name": "guzzlehttp/guzzle", - "version": "6.5.x-dev", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981", - "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981", - "shasum": "" - }, - "require": { - "ext-json": "*", - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.9", - "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.17" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.1" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.5-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Jeremy Lindblom", - "email": "jeremeamia@gmail.com", - "homepage": "https://github.com/jeremeamia" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "support": { - "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/6.5.8" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", - "type": "tidelift" - } - ], - "time": "2022-06-20T22:16:07+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a872440174bcdfd3392831de339656ac56122e26" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a872440174bcdfd3392831de339656ac56122e26", - "reference": "a872440174bcdfd3392831de339656ac56122e26", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "support": { - "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/master" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", - "type": "tidelift" - } - ], - "time": "2022-07-31T08:57:45+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/e98e3e6d4f86621a9b75f623996e6bbdeb4b9318", - "reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "ext-zlib": "*", - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" - }, - "suggest": { - "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" - ], - "support": { - "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.9.0" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", - "type": "tidelift" - } - ], - "time": "2022-06-20T21:43:03+00:00" - }, - { - "name": "james-heinrich/getid3", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/JamesHeinrich/getID3.git", - "reference": "59439c58bfeedcfac551bef0d0ec9a2050b1a374" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/59439c58bfeedcfac551bef0d0ec9a2050b1a374", - "reference": "59439c58bfeedcfac551bef0d0ec9a2050b1a374", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.0" - }, - "suggest": { - "ext-SimpleXML": "SimpleXML extension is required to analyze RIFF/WAV/BWF audio files (also requires `ext-libxml`).", - "ext-com_dotnet": "COM extension is required when loading files larger than 2GB on Windows.", - "ext-ctype": "ctype extension is required when loading files larger than 2GB on 32-bit PHP (also on 64-bit PHP on Windows) or executing `getid3_lib::CopyTagsToComments`.", - "ext-dba": "DBA extension is required to use the DBA database as a cache storage.", - "ext-exif": "EXIF extension is required for graphic modules.", - "ext-iconv": "iconv extension is required to work with different character sets (when `ext-mbstring` is not available).", - "ext-json": "JSON extension is required to analyze Apple Quicktime videos.", - "ext-libxml": "libxml extension is required to analyze RIFF/WAV/BWF audio files.", - "ext-mbstring": "mbstring extension is required to work with different character sets.", - "ext-mysql": "MySQL extension is required to use the MySQL database as a cache storage (deprecated in PHP 5.5, removed in PHP >= 7.0, use `ext-mysqli` instead).", - "ext-mysqli": "MySQLi extension is required to use the MySQL database as a cache storage.", - "ext-rar": "RAR extension is required for RAR archive module.", - "ext-sqlite3": "SQLite3 extension is required to use the SQLite3 database as a cache storage.", - "ext-xml": "XML extension is required for graphic modules to analyze the XML metadata.", - "ext-zlib": "Zlib extension is required for archive modules and compressed metadata." - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9.x-dev" - } - }, - "autoload": { - "classmap": [ - "getid3/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-1.0-or-later", - "LGPL-3.0-only", - "MPL-2.0" - ], - "description": "PHP script that extracts useful information from popular multimedia file formats", - "homepage": "https://www.getid3.org/", - "keywords": [ - "codecs", - "php", - "tags" - ], - "support": { - "issues": "https://github.com/JamesHeinrich/getID3/issues", - "source": "https://github.com/JamesHeinrich/getID3/tree/master" - }, - "time": "2022-07-16T20:48:42+00:00" - }, - { - "name": "komeiji-satori/curl", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/komeiji-satori/curl.git", - "reference": "687d8fa621823809f5e90a7f5d2fd6a59b7e7948" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/komeiji-satori/curl/zipball/687d8fa621823809f5e90a7f5d2fd6a59b7e7948", - "reference": "687d8fa621823809f5e90a7f5d2fd6a59b7e7948", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "php": ">=5.6" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/cURL.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Satori", - "email": "i@ttt.moe" - } - ], - "description": "一个轻量级的PHP网络操作类,实现GET、POST、UPLOAD、DOWNLOAD常用操作,出错自动重试,支持链式写法", - "homepage": "https://github.com/komeiji-satori/curl", - "keywords": [ - "PHP cURL", - "curl download", - "curl library", - "curl lightweight", - "curl post", - "curl upload" - ], - "support": { - "issues": "https://github.com/komeiji-satori/curl/issues", - "source": "https://github.com/komeiji-satori/curl/tree/master" - }, - "time": "2019-04-20T16:06:47+00:00" - }, - { - "name": "lfkeitel/phptotp", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/lfkeitel/php-totp.git", - "reference": "5b1673e895f857856b3e75ccb442855771c9b9be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lfkeitel/php-totp/zipball/5b1673e895f857856b3e75ccb442855771c9b9be", - "reference": "5b1673e895f857856b3e75ccb442855771c9b9be", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0 || ^8.0" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "lfkeitel\\phptotp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "TOTP/HOTP library for PHP", - "keywords": [ - "Authentication", - "hotp", - "totp", - "two-factor" - ], - "support": { - "issues": "https://github.com/lfkeitel/php-totp/issues", - "source": "https://github.com/lfkeitel/php-totp/tree/v1.1.0" - }, - "time": "2022-04-07T20:52:00+00:00" - }, - { - "name": "psr/cache", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "0a7c67d0d1c8167b342eb74339d6f961663826ce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/0a7c67d0d1c8167b342eb74339d6f961663826ce", - "reference": "0a7c67d0d1c8167b342eb74339d6f961663826ce", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "suggest": { - "fig/cache-util": "Provides some useful PSR-6 utilities" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/master" - }, - "time": "2021-02-24T03:25:37+00:00" - }, - { - "name": "psr/container", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "90db7b9ac2a2c5b849fcb69dde58f3ae182c68f5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/90db7b9ac2a2c5b849fcb69dde58f3ae182c68f5", - "reference": "90db7b9ac2a2c5b849fcb69dde58f3ae182c68f5", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/master" - }, - "time": "2022-07-19T17:36:59+00:00" - }, - { - "name": "psr/http-message", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "efd67d1dc14a7ef4fc4e518e7dee91c271d524e4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/efd67d1dc14a7ef4fc4e518e7dee91c271d524e4", - "reference": "efd67d1dc14a7ef4fc4e518e7dee91c271d524e4", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/master" - }, - "time": "2019-08-29T13:16:46+00:00" - }, - { - "name": "ralouphie/getallheaders", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" - }, - "type": "library", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" - }, - "time": "2019-03-08T08:55:37+00:00" - }, - { - "name": "rybakit/msgpack", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/rybakit/msgpack.php.git", - "reference": "fc6bc45e92274e78c32d0a86f2e2cc1f8b5e017b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/rybakit/msgpack.php/zipball/fc6bc45e92274e78c32d0a86f2e2cc1f8b5e017b", - "reference": "fc6bc45e92274e78c32d0a86f2e2cc1f8b5e017b", - "shasum": "" - }, - "require": { - "php": "^7.1.1|^8" - }, - "require-dev": { - "ext-gmp": "*", - "friendsofphp/php-cs-fixer": "^2.14", - "phpunit/phpunit": "^7.1|^8|^9", - "vimeo/psalm": "^3.9|^4" - }, - "suggest": { - "ext-decimal": "For converting overflowed integers to Decimal objects", - "ext-gmp": "For converting overflowed integers to GMP objects" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "MessagePack\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Eugene Leonovich", - "email": "gen.work@gmail.com" - } - ], - "description": "A pure PHP implementation of the MessagePack serialization format.", - "keywords": [ - "messagepack", - "msgpack", - "pure", - "streaming" - ], - "support": { - "issues": "https://github.com/rybakit/msgpack.php/issues", - "source": "https://github.com/rybakit/msgpack.php/tree/v0.9.1" - }, - "funding": [ - { - "url": "https://github.com/rybakit", - "type": "github" - } - ], - "time": "2022-02-16T00:48:07+00:00" - }, - { - "name": "scssphp/scssphp", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/scssphp/scssphp.git", - "reference": "c54b0a33d296807bc44ca1305882b2d9f49a3632" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/scssphp/scssphp/zipball/c54b0a33d296807bc44ca1305882b2d9f49a3632", - "reference": "c54b0a33d296807bc44ca1305882b2d9f49a3632", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-json": "*", - "php": ">=7.2" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.4", - "phpunit/phpunit": "^8.5 || ^9.5", - "sass/sass-spec": "*", - "squizlabs/php_codesniffer": "~3.5", - "symfony/phpunit-bridge": "^5.1", - "thoughtbot/bourbon": "^7.0", - "twbs/bootstrap": "~5.0", - "twbs/bootstrap4": "4.6.1", - "zurb/foundation": "~6.5" - }, - "suggest": { - "ext-iconv": "Can be used as fallback when ext-mbstring is not available", - "ext-mbstring": "For best performance, mbstring should be installed as it is faster than ext-iconv" - }, - "default-branch": true, - "type": "library", - "extra": { - "bamarni-bin": { - "forward-command": false, - "bin-links": false - } - }, - "autoload": { - "psr-4": { - "ScssPhp\\ScssPhp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Anthon Pang", - "email": "apang@softwaredevelopment.ca", - "homepage": "https://github.com/robocoder" - }, - { - "name": "Cédric Morin", - "email": "cedric@yterium.com", - "homepage": "https://github.com/Cerdic" - } - ], - "description": "scssphp is a compiler for SCSS written in PHP.", - "homepage": "http://scssphp.github.io/scssphp/", - "keywords": [ - "css", - "less", - "sass", - "scss", - "stylesheet" - ], - "support": { - "issues": "https://github.com/scssphp/scssphp/issues", - "source": "https://github.com/scssphp/scssphp/tree/master" - }, - "time": "2022-07-27T16:35:37+00:00" - }, - { - "name": "symfony/console", - "version": "5.4.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "c072aa8f724c3af64e2c7a96b796a4863d24dba1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c072aa8f724c3af64e2c7a96b796a4863d24dba1", - "reference": "c072aa8f724c3af64e2c7a96b796a4863d24dba1", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/5.4" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-08-17T13:18:05+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "4912000e79dc2d6df029d35d8755be1ed79b6691" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/4912000e79dc2d6df029d35d8755be1ed79b6691", - "reference": "4912000e79dc2d6df029d35d8755be1ed79b6691", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.2-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/main" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-20T13:56:22+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "433d05519ce6990bf3530fba6957499d327395c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", - "reference": "433d05519ce6990bf3530fba6957499d327395c2", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-idn", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8", - "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Trevor Rowbotham", - "email": "trevor.rowbotham@pm.me" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "idn", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2", - "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-10T07:21:04+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "cb82f217a2029131afbcbd220c511d0d77ebed19" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/cb82f217a2029131afbcbd220c511d0d77ebed19", - "reference": "cb82f217a2029131afbcbd220c511d0d77ebed19", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^2.0" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.2-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/main" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-30T19:19:18+00:00" - }, - { - "name": "symfony/string", - "version": "6.2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "921ef9254d086d19c6332b390770b474fbb225c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/921ef9254d086d19c6332b390770b474fbb225c4", - "reference": "921ef9254d086d19c6332b390770b474fbb225c4", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.0" - }, - "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/intl": "^6.2", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/6.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-08-17T12:37:54+00:00" - }, - { - "name": "vearutop/php-obscene-censor-rus", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/vearutop/php-obscene-censor-rus.git", - "reference": "ff0baca1aa0c4caba875773115f50d8252487b31" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vearutop/php-obscene-censor-rus/zipball/ff0baca1aa0c4caba875773115f50d8252487b31", - "reference": "ff0baca1aa0c4caba875773115f50d8252487b31", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "Wkhooy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Viacheslav Poturaev", - "email": "vearutop@gmail.com", - "homepage": "https://github.com/vearutop" - } - ], - "description": "Класс для фильтрации нецензурных выражений (матов).", - "homepage": "https://github.com/vearutop/php-obscene-censor-rus/", - "keywords": [ - "censor", - "антимат", - "модерация", - "хуй", - "цензура" - ], - "support": { - "issues": "https://github.com/vearutop/php-obscene-censor-rus/issues", - "source": "https://github.com/vearutop/php-obscene-censor-rus/tree/master" - }, - "time": "2019-06-19T20:04:05+00:00" - }, - { - "name": "wapmorgan/binary-stream", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/wapmorgan/BinaryStream.git", - "reference": "cfe40bc12a5d5a446f9b20131957bae78fc47a12" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wapmorgan/BinaryStream/zipball/cfe40bc12a5d5a446f9b20131957bae78fc47a12", - "reference": "cfe40bc12a5d5a446f9b20131957bae78fc47a12", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8.35" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "wapmorgan\\BinaryStream\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A handy tool for working with binary data", - "keywords": [ - "binary", - "binary-data", - "reader", - "writer" - ], - "support": { - "issues": "https://github.com/wapmorgan/BinaryStream/issues", - "source": "https://github.com/wapmorgan/BinaryStream/tree/master" - }, - "time": "2018-09-26T17:10:59+00:00" - }, - { - "name": "wapmorgan/morphos", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/wapmorgan/Morphos.git", - "reference": "5550474d1cc6c8936bca66e86fee43f19c73a41a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wapmorgan/Morphos/zipball/5550474d1cc6c8936bca66e86fee43f19c73a41a", - "reference": "5550474d1cc6c8936bca66e86fee43f19c73a41a", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "php": ">=7.3", - "phpunit/phpunit": "~9.5.20" - }, - "suggest": { - "ext-readline": "For using interactive version of script" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/English/functions.php", - "src/Russian/functions.php" - ], - "psr-4": { - "morphos\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Sergey Vanyushin", - "email": "wapmorgan@gmail.com", - "role": "developer" - } - ], - "description": "A morphological solution for Russian and English language written completely in PHP. Provides classes to inflect personal names, geographical names, decline and pluralize nouns, generate cardinal and ordinal numerals, spell out money amounts and time.", - "homepage": "http://morphos.io", - "keywords": [ - "Numerals", - "adjectives", - "cardinal", - "declension", - "english", - "geographical names", - "human-friendly", - "inflection", - "language", - "money", - "morphology", - "nouns", - "ordinal", - "personal names", - "pluralization", - "russian", - "spelling", - "time" - ], - "support": { - "issues": "https://github.com/wapmorgan/Morphos/issues", - "source": "https://github.com/wapmorgan/Morphos/tree/3.2.26" - }, - "time": "2022-07-10T00:41:40+00:00" - }, - { - "name": "whichbrowser/parser", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/WhichBrowser/Parser-PHP.git", - "reference": "1044880bc792dbce5948fbff22ae731c43c280d9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/1044880bc792dbce5948fbff22ae731c43c280d9", - "reference": "1044880bc792dbce5948fbff22ae731c43c280d9", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/cache": "^1.0 || ^2.0 || ^3.0" - }, - "require-dev": { - "cache/array-adapter": "^1.1", - "icomefromthenet/reverse-regex": "0.0.6.3", - "php-coveralls/php-coveralls": "^2.0", - "phpunit/php-code-coverage": "^5.0 || ^7.0", - "phpunit/phpunit": "^6.0 || ^8.0", - "squizlabs/php_codesniffer": "^3.5", - "symfony/yaml": "~3.4 || ~4.0" - }, - "suggest": { - "cache/array-adapter": "Allows testing of the caching functionality" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "WhichBrowser\\": [ - "src/", - "tests/src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niels Leenheer", - "email": "niels@leenheer.nl", - "role": "Developer" - } - ], - "description": "Useragent sniffing library for PHP", - "homepage": "http://whichbrowser.net", - "keywords": [ - "browser", - "sniffing", - "ua", - "useragent" - ], - "support": { - "issues": "https://github.com/WhichBrowser/Parser-PHP/issues", - "source": "https://github.com/WhichBrowser/Parser-PHP/tree/v2.1.7" - }, - "time": "2022-04-19T20:14:54+00:00" - }, - { - "name": "zadarma/user-api-v1", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/zadarma/user-api-v1.git", - "reference": "23badf5232bfc0a7707fd9fa9857d805e8b8e2d1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zadarma/user-api-v1/zipball/23badf5232bfc0a7707fd9fa9857d805e8b8e2d1", - "reference": "23badf5232bfc0a7707fd9fa9857d805e8b8e2d1", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "php": ">=5.5.0" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "Zadarma_API\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Zadarma", - "email": "github@zadarma.com" - } - ], - "description": "PHP class for Zadarma API", - "homepage": "https://github.com/zadarma/user-api-v1", - "keywords": [ - "api", - "free calls", - "pbx", - "sip", - "zadarma" - ], - "support": { - "issues": "https://github.com/zadarma/user-api-v1/issues", - "source": "https://github.com/zadarma/user-api-v1/tree/v1.1.7" - }, - "time": "2021-05-31T13:19:30+00:00" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "dev", - "stability-flags": { - "komeiji-satori/curl": 20, - "whichbrowser/parser": 20, - "zadarma/user-api-v1": 20, - "james-heinrich/getid3": 20, - "rybakit/msgpack": 20, - "wapmorgan/binary-stream": 20, - "al/emoji-detector": 20, - "ezyang/htmlpurifier": 20, - "scssphp/scssphp": 20, - "lfkeitel/phptotp": 20, - "chillerlan/php-qrcode": 20, - "vearutop/php-obscene-censor-rus": 20, - "erusev/parsedown": 20, - "bhaktaraz/php-rss-generator": 20, - "symfony/console": 20, - "wapmorgan/morphos": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "~7.3||~8.1", - "ext-simplexml": "*", - "ext-sodium": "*" - }, - "platform-dev": [], - "plugin-api-version": "2.3.0" -} From 2704ba0ec3ce795614caf6fe38e2b920072ff7ce Mon Sep 17 00:00:00 2001 From: Ilya Prokopenko Date: Tue, 4 Oct 2022 21:18:55 +0700 Subject: [PATCH 021/285] OpenVK Midnight: Fix-up inputs, add new stuff --- themepacks/midnight/stylesheet.css | 34 ++++++++++++++++++------------ themepacks/midnight/theme.yml | 2 +- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/themepacks/midnight/stylesheet.css b/themepacks/midnight/stylesheet.css index 54ac8534..f143d608 100644 --- a/themepacks/midnight/stylesheet.css +++ b/themepacks/midnight/stylesheet.css @@ -31,7 +31,7 @@ span, .post-author .date, .crp-entry--message---text, .messenger-app--messages-- border-color: #1c202f; } -.accountInfo, .left_small_block, #profile_link, .profile_link, .navigation .link, .navigation .link:hover, .navigation_footer .link, .navigation_footer .link:hover, .completeness-gauge, input[type="text"], input[type="password"], input[type~="text"], input[type~="password"], input[type="email"], input[type="phone"], input[type~="email"], input[type~="phone"], input[type="search"], input[type~="search"], input[type~="date"], select, .content_title_expanded, .content_title_unexpanded, .content_subtitle, textarea, .post-content, .post-author, hr, h4, .postFeedWrapper, .tabs, #wallAttachmentMenu, .ovk-diag, .ovk-diag-head, #ovkDraw, #ovkDraw .literally .lc-picker, .literally .lc-options.horz-toolbar, .page_wrap, .container_gray .content, .summaryBar, .groups_options, form[action="/search"] > input, .header_search_input, .header_search_inputbt, .accent-box, .page_status_popup, .messenger-app--input, .messenger-app, .crp-entry:first-of-type, .crp-list, .crp-entry, .note_footer, .page_content > div, #editor, .note_header, center[style="background: white;border: #DEDEDE solid 1px;"], .album-photo img, .mb_tabs, .mb_tab#active div, .navigation-lang .link_new, #faqhead, #faqcontent, .post-divider, .comment, .commentsTextFieldWrap, tr, td, th, #votesBalance, .paginator a.active, .paginator a:hover { +.accountInfo, .left_small_block, #profile_link, .profile_link, .navigation .link, .navigation .link:hover, .navigation_footer .link, .navigation_footer .link:hover, .completeness-gauge, input[type="text"], input[type="password"], input[type~="text"], input[type~="password"], input[type="email"], input[type="phone"], input[type~="email"], input[type~="phone"], input[type="search"], input[type~="search"], input[type~="date"], select, .content_title_expanded, .content_title_unexpanded, .content_subtitle, textarea, .post-content, .post-author, hr, h4, .postFeedWrapper, .tabs, #wallAttachmentMenu, .ovk-diag, .ovk-diag-head, #ovkDraw, #ovkDraw .literally .lc-picker, .literally .lc-options.horz-toolbar, .page_wrap, .container_gray .content, .summaryBar, .groups_options, form[action="/search"] > input, .header_search_input, .header_search_inputbt, .accent-box, .page_status_popup, .messenger-app--input, .messenger-app, .crp-entry:first-of-type, .crp-list, .crp-entry, .note_footer, .page_content > div, #editor, .note_header, center[style="background: white;border: #DEDEDE solid 1px;"], .album-photo img, .mb_tabs, .mb_tab#active div, .navigation-lang .link_new, #faqhead, #faqcontent, .post-divider, .comment, .commentsTextFieldWrap, tr, td, th, #votesBalance, .paginator a.active, .paginator a:hover, .topic-list-item, #userContent blockquote { border-color: #2c2640 !important; } @@ -109,7 +109,7 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { background-color: #231e33 !important; } -.content_subtitle, .postFeedWrapper, .ovk-diag-head, .container_gray, .page_status_popup, .messenger-app--input, .note_header, #faqcontent, .commentsTextFieldWrap, td.v, tr.v, #votesBalance { +.content_subtitle, .postFeedWrapper, .ovk-diag-head, .container_gray, .page_status_popup, .messenger-app--input, .note_header, #faqcontent, .commentsTextFieldWrap, td.v, tr.v, #votesBalance, .expand_button, #userContent blockquote { background-color: #1e1a2b !important; } @@ -119,11 +119,11 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { } .content_title_expanded { - background-image: url("/themepack/midnight/0.0.1.0/resource/flex_arrow_open.png"); + background-image: url("/themepack/midnight/0.0.1.1/resource/flex_arrow_open.png"); } .content_title_unexpanded { - background-image: url("/themepack/midnight/0.0.1.0/resource/flex_arrow_shut.gif"); + background-image: url("/themepack/midnight/0.0.1.1/resource/flex_arrow_shut.gif"); } .ovk-video > .preview, .video-preview { @@ -145,17 +145,17 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { .page_yellowheader { color: #c6d2e8; - background-image: url("/themepack/midnight/0.0.1.0/resource/header_purple.png"); + background-image: url("/themepack/midnight/0.0.1.1/resource/header_purple.png"); background-color: #231f34; border-color: #231f34; } .page_header { - background-image: url("/themepack/midnight/0.0.1.0/resource/header.png"); + background-image: url("/themepack/midnight/0.0.1.1/resource/header.png"); } .page_custom_header { - background-image: url("/themepack/midnight/0.0.1.0/resource/header_custom.png"); + background-image: url("/themepack/midnight/0.0.1.1/resource/header_custom.png"); } .page_yellowheader span, .page_yellowheader a { @@ -170,16 +170,16 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { background-color: #2c2640; } -form[action="/search"] > input, .header_search_input, textarea { +form[action="/search"] > input, .header_search_input, textarea, input[type="text"] { background-color: #181826 !important; } input[type="checkbox"] { - background-image: url("/themepack/midnight/0.0.1.0/resource/checkbox.png"); + background-image: url("/themepack/midnight/0.0.1.1/resource/checkbox.png"); } input[type="radio"] { - background-image: url("/themepack/midnight/0.0.1.0/resource/radio.png"); + background-image: url("/themepack/midnight/0.0.1.1/resource/radio.png"); } .header_navigation .link { @@ -187,17 +187,23 @@ input[type="radio"] { } .heart { - background-image: url("/themepack/midnight/0.0.1.0/resource/like.gif") !important; + background-image: url("/themepack/midnight/0.0.1.1/resource/like.gif") !important; } .pinned-mark, .post-author .pin { - background-image: url("/themepack/midnight/0.0.1.0/resource/pin.png") !important; + background-image: url("/themepack/midnight/0.0.1.1/resource/pin.png") !important; } .repost-icon { - background-image: url("/themepack/midnight/0.0.1.0/resource/published.gif") !important; + background-image: url("/themepack/midnight/0.0.1.1/resource/published.gif") !important; } .post-author .delete { - background-image: url("/themepack/midnight/0.0.1.0/resource/input_clear.gif") !important; + background-image: url("/themepack/midnight/0.0.1.1/resource/input_clear.gif") !important; +} + +.user-alert { + background-color: #41311a; + color: #d5b88c; + border-color: #514534; } \ No newline at end of file diff --git a/themepacks/midnight/theme.yml b/themepacks/midnight/theme.yml index 02c5e0d3..aaf05a84 100644 --- a/themepacks/midnight/theme.yml +++ b/themepacks/midnight/theme.yml @@ -1,5 +1,5 @@ id: midnight -version: "0.0.1.0" +version: "0.0.1.1" openvk_version: 0 enabled: 1 metadata: From a950a2d7063462aee268a2b55350f596a62e07a6 Mon Sep 17 00:00:00 2001 From: celestora Date: Sat, 8 Oct 2022 23:25:09 +0300 Subject: [PATCH 022/285] y7tughtuy --- install/sqls/00032-banned-urls.sql | 8 ++++---- install/sqls/00033-shortcode-aliases.sql | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/install/sqls/00032-banned-urls.sql b/install/sqls/00032-banned-urls.sql index 0df7b275..b9b0077b 100644 --- a/install/sqls/00032-banned-urls.sql +++ b/install/sqls/00032-banned-urls.sql @@ -1,10 +1,10 @@ CREATE TABLE `links_banned` ( `id` bigint UNSIGNED NOT NULL, - `domain` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_nopad_ci NOT NULL, - `regexp_rule` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_nopad_ci NOT NULL, - `reason` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_nopad_ci, + `domain` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL, + `regexp_rule` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL, + `reason` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci, `initiator` bigint UNSIGNED NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_nopad_ci; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci; ALTER TABLE `links_banned` ADD PRIMARY KEY (`id`); diff --git a/install/sqls/00033-shortcode-aliases.sql b/install/sqls/00033-shortcode-aliases.sql index d47975c0..d825f205 100644 --- a/install/sqls/00033-shortcode-aliases.sql +++ b/install/sqls/00033-shortcode-aliases.sql @@ -2,7 +2,7 @@ CREATE TABLE `aliases` ( `id` bigint UNSIGNED NOT NULL, `owner_id` bigint NOT NULL, `shortcode` varchar(36) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_nopad_ci; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci; ALTER TABLE `aliases` ADD PRIMARY KEY (`id`); From c09694b5686275db371ceb57419ce2be983f9849 Mon Sep 17 00:00:00 2001 From: celestora Date: Sat, 8 Oct 2022 23:47:21 +0300 Subject: [PATCH 023/285] Localize "posted in ..." messages Also preliminary solved #739 --- Web/Models/Entities/Post.php | 11 ++++++++++- .../components/post/microblogpost.xml | 18 ++++++++---------- .../templates/components/post/oldpost.xml | 18 ++++++++---------- locales/en.strings | 3 +++ locales/ru.strings | 3 +++ 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/Web/Models/Entities/Post.php b/Web/Models/Entities/Post.php index 4afb4baa..fef2de68 100644 --- a/Web/Models/Entities/Post.php +++ b/Web/Models/Entities/Post.php @@ -1,7 +1,7 @@ getRecord()->wall; } + + function getWallOwner() + { + $w = $this->getRecord()->wall; + if($w < 0) + return (new Clubs)->get(abs($w)); + + return (new Users)->get($w); + } function getRepostCount(): int { diff --git a/Web/Presenters/templates/components/post/microblogpost.xml b/Web/Presenters/templates/components/post/microblogpost.xml index d8a3e594..d2991bca 100644 --- a/Web/Presenters/templates/components/post/microblogpost.xml +++ b/Web/Presenters/templates/components/post/microblogpost.xml @@ -24,17 +24,15 @@ {$post->isDeactivationMessage() ? ($author->isFemale() ? tr($deac . "_f") : tr($deac . "_m"))} {if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()} - {var $wallId = $post->getTargetWall()} - {var $wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)} - на - + {var $wallOwner = $post->getWallOwner()} + - {if isset($thisUser) && $thisUser->getId() === $wallId} - вашей - {/if} - стене - {if $wallId < 0} - группы + {if isset($thisUser) && $thisUser->getId() === $post->getTargetWall()} + {_post_on_your_wall} + {elseif $wallOwner instanceof \openvk\Web\Models\Entities\Club} + {tr("post_on_group_wall", ovk_proc_strtr($wallOwner->getName(), 52))} + {else} + {tr("post_on_user_wall", $wallOwner->getMorphedName("genitive", false))} {/if} diff --git a/Web/Presenters/templates/components/post/oldpost.xml b/Web/Presenters/templates/components/post/oldpost.xml index dbfd0ff0..057f76a5 100644 --- a/Web/Presenters/templates/components/post/oldpost.xml +++ b/Web/Presenters/templates/components/post/oldpost.xml @@ -20,17 +20,15 @@ {$post->isDeactivationMessage() ? ($author->isFemale() ? tr($deac . "_f") : tr($deac . "_m")) : ($post->isPostedOnBehalfOfGroup() ? tr("post_writes_g") : ($author->isFemale() ? tr("post_writes_f") : tr("post_writes_m")))} {if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()} - {var $wallId = $post->getTargetWall()} - {var $wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)} - на - + {var $wallOwner = $post->getWallOwner()} + - {if isset($thisUser) && $thisUser->getId() === $wallId} - вашей - {/if} - стене - {if $wallId < 0} - группы + {if isset($thisUser) && $thisUser->getId() === $post->getTargetWall()} + {_post_on_your_wall} + {elseif $wallOwner instanceof \openvk\Web\Models\Entities\Club} + {tr("post_on_group_wall", ovk_proc_strtr($wallOwner->getName(), 52))} + {else} + {tr("post_on_user_wall", $wallOwner->getMorphedName("genitive", false))} {/if} diff --git a/locales/en.strings b/locales/en.strings index 240dd5d0..65c90da1 100644 --- a/locales/en.strings +++ b/locales/en.strings @@ -154,6 +154,9 @@ "post_deact_f" = "deleted her profile saying:"; "post_deact_silent_m" = "silently deleted his profile."; "post_deact_silent_f" = "silently deleted her profile."; +"post_on_your_wall" = "on your wall"; +"post_on_group_wall" = "in $1"; +"post_on_user_wall" = "on $1's wall"; "wall" = "Wall"; "post" = "Post"; "write" = "Write"; diff --git a/locales/ru.strings b/locales/ru.strings index 6a7b8f46..af599abb 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -162,6 +162,9 @@ "post_deact_f" = "удалила страницу со словами:"; "post_deact_silent_m" = "молча удалил свою страницу."; "post_deact_silent_f" = "молча удалила свою страницу."; +"post_on_your_wall" = "на вашей стене"; +"post_on_group_wall" = "в $1"; +"post_on_user_wall" = "на стене $1"; "wall" = "Стена"; "post" = "Запись"; "write" = "Написать"; From dfee425deba4766fa12546eada9549c4693b15cd Mon Sep 17 00:00:00 2001 From: celestora Date: Sun, 9 Oct 2022 11:34:57 +0300 Subject: [PATCH 024/285] Add hovers for post signatures and wall ids Resolves #739 --- ServiceAPI/Mentions.php | 50 +++++++++++++++++++ Web/Presenters/templates/@layout.xml | 9 ++++ .../components/post/microblogpost.xml | 4 +- .../templates/components/post/oldpost.xml | 4 +- Web/static/css/style.css | 7 +++ Web/static/js/al_mentions.js | 42 ++++++++++++++++ Web/static/js/package.json | 2 + Web/static/js/yarn.lock | 49 ++++++++++++++++++ 8 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 ServiceAPI/Mentions.php create mode 100644 Web/static/js/al_mentions.js diff --git a/ServiceAPI/Mentions.php b/ServiceAPI/Mentions.php new file mode 100644 index 00000000..33c1fc01 --- /dev/null +++ b/ServiceAPI/Mentions.php @@ -0,0 +1,50 @@ +user = $user; + } + + function resolve(int $id, callable $resolve, callable $reject): void + { + if($id > 0) { + $user = (new Users)->get($id); + if(!$user) { + $reject("Not found"); + return; + } + + $resolve([ + "url" => $user->getURL(), + "name" => $user->getFullName(), + "ava" => $user->getAvatarURL("miniscule"), + "about" => $user->getStatus() ?? "", + "online" => ($user->isFemale() ? tr("was_online_f") : tr("was_online_m")) . " " . $user->getOnline(), + "verif" => $user->isVerified(), + ]); + return; + } + + $club = (new Clubs)->get(abs($id)); + if(!$club) { + $reject("Not found"); + return; + } + + $resolve([ + "url" => $club->getURL(), + "name" => $club->getName(), + "ava" => $club->getAvatarURL("miniscule"), + "about" => $club->getDescription() ?? "", + "online" => tr("participants", $club->getFollowersCount()), + "verif" => $club->isVerified(), + ]); + } +} diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml index e717acfe..1be7ba55 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -17,6 +17,14 @@ {script "js/l10n.js"} {script "js/openvk.cls.js"} + {css "js/node_modules/tippy.js/dist/backdrop.css"} + {css "js/node_modules/tippy.js/dist/border.css"} + {css "js/node_modules/tippy.js/dist/svg-arrow.css"} + {css "js/node_modules/tippy.js/themes/light.css"} + {script "js/node_modules/@popperjs/core/dist/umd/popper.min.js"} + {script "js/node_modules/tippy.js/dist/tippy-bundle.umd.min.js"} + {script "js/node_modules/handlebars/dist/handlebars.min.js"} + {if $isTimezoned == NULL} {script "js/timezone.js"} {/if} @@ -325,6 +333,7 @@ {script "js/scroll.js"} {script "js/al_wall.js"} {script "js/al_api.js"} + {script "js/al_mentions.js"} {ifset $thisUser} {script "js/al_notifs.js"} diff --git a/Web/Presenters/templates/components/post/microblogpost.xml b/Web/Presenters/templates/components/post/microblogpost.xml index d2991bca..daf2c275 100644 --- a/Web/Presenters/templates/components/post/microblogpost.xml +++ b/Web/Presenters/templates/components/post/microblogpost.xml @@ -25,7 +25,7 @@ {$post->isDeactivationMessage() ? ($author->isFemale() ? tr($deac . "_f") : tr($deac . "_m"))} {if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()} {var $wallOwner = $post->getWallOwner()} - + {if isset($thisUser) && $thisUser->getId() === $post->getTargetWall()} {_post_on_your_wall} @@ -75,7 +75,7 @@ {var $actualAuthor = $post->getOwner(false)} {_author}: - + {$actualAuthor->getCanonicalName()} diff --git a/Web/Presenters/templates/components/post/oldpost.xml b/Web/Presenters/templates/components/post/oldpost.xml index 057f76a5..f865e9d0 100644 --- a/Web/Presenters/templates/components/post/oldpost.xml +++ b/Web/Presenters/templates/components/post/oldpost.xml @@ -21,7 +21,7 @@ {$post->isDeactivationMessage() ? ($author->isFemale() ? tr($deac . "_f") : tr($deac . "_m")) : ($post->isPostedOnBehalfOfGroup() ? tr("post_writes_g") : ($author->isFemale() ? tr("post_writes_f") : tr("post_writes_m")))} {if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()} {var $wallOwner = $post->getWallOwner()} - + {if isset($thisUser) && $thisUser->getId() === $post->getTargetWall()} {_post_on_your_wall} @@ -56,7 +56,7 @@ {var $actualAuthor = $post->getOwner(false)} {_author}: - + {$actualAuthor->getCanonicalName()} diff --git a/Web/static/css/style.css b/Web/static/css/style.css index d35154c1..25516af7 100644 --- a/Web/static/css/style.css +++ b/Web/static/css/style.css @@ -2051,6 +2051,13 @@ table td[width="120"] { max-height: 250px; } +.tippy-box[data-theme~="vk"] { + user-select: none; + background-color: #fff; + border: 1px solid #DCE1E6; + border-radius: 1px; +} + @keyframes appearing { from { opacity: 0; diff --git a/Web/static/js/al_mentions.js b/Web/static/js/al_mentions.js new file mode 100644 index 00000000..f9d479ed --- /dev/null +++ b/Web/static/js/al_mentions.js @@ -0,0 +1,42 @@ +var tooltipTemplate = Handlebars.compile(` + + + + + + +
+ + + + {{name}} + {{#if verif}} + + {{/if}} +
+ {{online}}
+ {{about}} +
+`); + +tippy(".mention", { + theme: "light vk", + content: "⌛", + allowHTML: true, + interactive: true, + interactiveDebounce: 500, + + onCreate: async function(that) { + that._resolvedMention = null; + }, + + onShow: async function(that) { + if(!that._resolvedMention) { + let id = Number(that.reference.dataset.mentionRef); + that._resolvedMention = await API.Mentions.resolve(id); + } + + let res = that._resolvedMention; + that.setContent(tooltipTemplate(res)); + } +}); diff --git a/Web/static/js/package.json b/Web/static/js/package.json index e29efb2e..a082506b 100644 --- a/Web/static/js/package.json +++ b/Web/static/js/package.json @@ -2,6 +2,7 @@ "dependencies": { "@atlassian/aui": "^8.5.1", "create-react-class": "^15.7.0", + "handlebars": "^4.7.7", "jquery": "^2.1.0", "knockout": "^3.5.1", "ky": "^0.19.0", @@ -15,6 +16,7 @@ "requirejs": "^2.3.6", "soundjs": "^1.0.1", "textfit": "^2.4.0", + "tippy.js": "^6.3.7", "umbrellajs": "^3.1.0" } } diff --git a/Web/static/js/yarn.lock b/Web/static/js/yarn.lock index b507ac3c..691a64b5 100644 --- a/Web/static/js/yarn.lock +++ b/Web/static/js/yarn.lock @@ -29,6 +29,11 @@ resolved "https://registry.yarnpkg.com/@atlassian/tipsy/-/tipsy-1.3.2.tgz#ab759d461670d712425b2dac7573b79575a10502" integrity sha512-H7qWMs66bztELt2QpOCLYDU9ZM3VZfE0knbRHHLBukH7v9dMkIS5ZwqcGREjWnVt0KNETaBeXxj0FD88TEOGVw== +"@popperjs/core@^2.9.0": + version "2.11.6" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" + integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== + asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -89,6 +94,18 @@ fbjs@^0.8.0: setimmediate "^1.0.5" ua-parser-js "^0.7.18" +handlebars@^4.7.7: + version "4.7.7" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.0" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + iconv-lite@^0.6.2: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" @@ -170,6 +187,11 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: dependencies: js-tokens "^3.0.0 || ^4.0.0" +minimist@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + monaco-editor@^0.20.0: version "0.20.0" resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea" @@ -185,6 +207,11 @@ msgpack-lite@^0.1.26: int64-buffer "^0.1.9" isarray "^1.0.0" +neo-async@^2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -271,11 +298,23 @@ soundjs@^1.0.1: resolved "https://registry.yarnpkg.com/soundjs/-/soundjs-1.0.1.tgz#99970542d28d0df2a1ebd061ae75c961a98c8180" integrity sha512-MgFPvmKYfpcNiE3X5XybNvScie3DMQlZgmNzUn4puBcpw64f4LqjH/fhM8Sb/eTJ8hK57Crr7mWy0bfJOqPj6Q== +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + textfit@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/textfit/-/textfit-2.4.0.tgz#80cba8006bfb9c3d9d552739257957bdda95c79c" integrity sha512-/x4aoY5+/tJmu+iwpBH1yw75TFp86M6X15SvaaY/Eep7YySQYtqdOifEtfvVyMwzl7SZ+G4RQw00FD9g5R6i1Q== +tippy.js@^6.3.7: + version "6.3.7" + resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c" + integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ== + dependencies: + "@popperjs/core" "^2.9.0" + trim-extra-html-whitespace@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/trim-extra-html-whitespace/-/trim-extra-html-whitespace-1.3.0.tgz#b47efb0d1a5f2a56a85cc45cea525651e93404cf" @@ -286,6 +325,11 @@ ua-parser-js@^0.7.18: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31" integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g== +uglify-js@^3.1.4: + version "3.17.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.3.tgz#f0feedf019c4510f164099e8d7e72ff2d7304377" + integrity sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg== + umbrellajs@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/umbrellajs/-/umbrellajs-3.1.0.tgz#a4e6f0f6381f9d93110b5eee962e0e0864b10bd0" @@ -300,3 +344,8 @@ whatwg-fetch@>=0.10.0: version "3.6.2" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== From 8c314adf6cbf79e6082617086dabc94177ad3fd4 Mon Sep 17 00:00:00 2001 From: celestora Date: Sun, 9 Oct 2022 12:31:19 +0300 Subject: [PATCH 025/285] Fix popup colors in signatures --- Web/static/js/al_mentions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Web/static/js/al_mentions.js b/Web/static/js/al_mentions.js index f9d479ed..1be77563 100644 --- a/Web/static/js/al_mentions.js +++ b/Web/static/js/al_mentions.js @@ -12,8 +12,8 @@ var tooltipTemplate = Handlebars.compile(` {{/if}}
- {{online}}
- {{about}} + {{online}}
+ {{about}} From b3aa8e41b1c481ae469766e009cc5cfc4f04778f Mon Sep 17 00:00:00 2001 From: veselcraft Date: Sun, 9 Oct 2022 17:39:22 +0300 Subject: [PATCH 026/285] VKAPI: Fix some stupid code quirks --- VKAPI/Handlers/Wall.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VKAPI/Handlers/Wall.php b/VKAPI/Handlers/Wall.php index c669cd02..54f78a55 100644 --- a/VKAPI/Handlers/Wall.php +++ b/VKAPI/Handlers/Wall.php @@ -42,7 +42,7 @@ final class Wall extends VKAPIRequestHandler foreach($attachment->getChildren() as $repostAttachment) { if($repostAttachment instanceof \openvk\Web\Models\Entities\Photo) { - if($attachment->isDeleted()) + if($repostAttachment->isDeleted()) continue; $repostAttachments[] = $this->getApiPhoto($repostAttachment); From 13606493b6a45f46f4b42df3f867a5a54fbe496a Mon Sep 17 00:00:00 2001 From: veselcraft Date: Sun, 9 Oct 2022 18:06:43 +0300 Subject: [PATCH 027/285] VKAPI: Add new method Groups.Search --- VKAPI/Handlers/Groups.php | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/VKAPI/Handlers/Groups.php b/VKAPI/Handlers/Groups.php index 59b19fa4..173e62e9 100644 --- a/VKAPI/Handlers/Groups.php +++ b/VKAPI/Handlers/Groups.php @@ -102,23 +102,32 @@ final class Groups extends VKAPIRequestHandler ]; } - function getById(string $group_ids = "", string $group_id = "", string $fields = ""): ?array + function getById(string $group_ids = "", string $group_id = "", string $fields = "", int $offset = 0, int $count = 500): ?array { + /* Both offset and count SHOULD be used only in OpenVK code, + not in your app or script, since it's not oficially documented by VK */ + $clubs = new ClubsRepo; - if($group_ids == NULL && $group_id != NULL) + if(empty($group_ids) && !empty($group_id)) $group_ids = $group_id; - if($group_ids == NULL && $group_id == NULL) + if(empty($group_ids) && empty($group_id)) $this->fail(100, "One of the parameters specified was missing or invalid: group_ids is undefined"); $clbs = explode(',', $group_ids); - $response; + $response = array(); $ic = sizeof($clbs); + if(sizeof($clbs) > $count) + $ic = $count; + + $clbs = array_slice($clbs, $offset * $count); + + for($i=0; $i < $ic; $i++) { - if($i > 500) + if($i > 500 || $clbs[$i] == 0) break; if($clbs[$i] < 0) @@ -215,4 +224,24 @@ final class Groups extends VKAPIRequestHandler return $response; } + + function search(string $q, int $offset = 0, int $count = 100) + { + $clubs = new ClubsRepo; + + $array = []; + $find = $clubs->find($q); + + foreach ($find as $group) + $array[] = $group->getId(); + + return (object) [ + "count" => $find->size(), + "items" => $this->getById(implode(',', $array), "", "is_admin,is_member,is_advertiser,photo_50,photo_100,photo_200", $offset, $count) + /* + * As there is no thing as "fields" by the original documentation + * i'll just bake this param by the example shown here: https://dev.vk.com/method/groups.search + */ + ]; + } } From c1ce5148692e20944b48c6096eb078c51533f095 Mon Sep 17 00:00:00 2001 From: ayaao <58212796+ayaaop@users.noreply.github.com> Date: Sun, 9 Oct 2022 21:47:23 +0600 Subject: [PATCH 028/285] /themepacks/readme.md: fix grammar (#740) --- themepacks/readme.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/themepacks/readme.md b/themepacks/readme.md index a604477a..58dd181b 100755 --- a/themepacks/readme.md +++ b/themepacks/readme.md @@ -1,10 +1,10 @@ # OpenVK Themepacks -This folder contains all themes that can be used by any user on instance. +This folder contains all themes that can be used by any user on an instance. -## How do i create the theme? +## How do I create a theme? -Create a directory, the name of which should contain only Latin letters and numbers, and create a file there `theme.yml`, and fill it with the following content: +Create a directory, the name of which should contain only Latin letters and numbers, then create a file in this directory called `theme.yml`, and fill it with the following content: ```yaml id: vk2007 @@ -24,13 +24,13 @@ metadata: `id` is the name of the folder -`version` - version of the theme +`version` is the version of the theme -`openvk_version` - version OpenVK *(it is necessary to leave the value 0)* +`openvk_version` is the version of OpenVK *(it is necessary to leave the value to 0)* `metadata`: -* `name` - the name of the theme for the end user. Inside it you can leave names for different languages. `_` (underscore) - for all languages. +* `name` - the name of the theme for the end user. Inside it you can leave names for different languages. `_` (underscore) is for all languages. Next, in `stylesheet.css` you can insert any CSS code, with which you can change the elements of the site. If you need additional pictures or resources, just create a `res` folder, and access the resources via the `/themepack/{directory name}/{theme version}/resource/{resource}` path. From e9e72ff23725ba7ab6cf06672fe498f7c26ec12b Mon Sep 17 00:00:00 2001 From: Jaroslaw <92401420+AlesAlte@users.noreply.github.com> Date: Sun, 9 Oct 2022 23:18:14 +0300 Subject: [PATCH 029/285] English, Ukrainian localization: Added and corrected spelling errors (#741) --- data/knowledgebase/rules.ua.md | 26 +++++++++++++------------- locales/en.strings | 3 +++ locales/ua.strings | 12 ++++++++++++ themepacks/midnight/theme.yml | 3 ++- themepacks/openvk_modern/theme.yml | 1 + themepacks/readme.ru.md | 2 +- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/data/knowledgebase/rules.ua.md b/data/knowledgebase/rules.ua.md index e030a613..5acc5309 100644 --- a/data/knowledgebase/rules.ua.md +++ b/data/knowledgebase/rules.ua.md @@ -2,36 +2,36 @@ OpenVK-KB-Heading: Правила Адміністрація сайту дозволяє Вам користуватися сайтом на умовах, вказаних у цих правилах. -Робити можна усе те, що не відноситься до заборонених дій, а до заборонених дій відносяться: +Робити можна усе те, що не належать до заборонених дій, а до заборонених дій відносяться: 1. Відмова у підпорядкуванні правилам чи їх ігнорування, -2. Відмова від своєчасного виконання запитів агентів тех. підтримки чи адміністраціі, +2. Відмова від своєчасного виконання запитів агентів технічної підтримки чи адміністрації, 3. Використання чужих сторінок без дозволу власника, 4. Видавання себе за інших людей для отримання вигоди. Винятки: 1. Людина дозволила використання своєї особи, 2. Людина є оригінальним персонажем, та належить Вам -5. Створення массових розсилок будь-яким способом, -6. Створення ситуацій, будь-яким чином заважаючих роботі OpenVK, +5. Створення масових розсилок будь-яким способом, +6. Створення ситуацій, що заважає роботі OpenVK, 7. Публікація та зберігання на ресурсі вмісту, який: - 1. Є незаконним на територіі Франціі, + 1. Є незаконним на території Франції, 2. Містить порнографічні сцени за участю осіб молодше 18 років, - 3. Містить рекламу заборонених у Франціі препаратів чи інструкціі по їх виготовленню, - 4. Містить інформацію заборонену на територіі Франціі, + 3. Містить рекламу заборонених у Франції препаратів чи інструкції по їх виготовленню, + 4. Містить інформацію заборонену на території Франції, 5. Містить сцени нелюдського поводження з людьми або тваринами, 6. Порушує авторські та суміжні права, 7. Порушує права людини, - 8. Заважає користувачам виконувати правила чи нормально користуватися послугами, наданими проектом OpenVK. + 8. Заважає користувачам виконувати правила чи нормально користуватися послугами, наданими проєктом OpenVK. -Адміністрация є вищим органом влади, який має повне право приймати рішення на рахунок спірних ситуацій, не описаних у правилах. +Адміністрація є вищим органом влади, який має повне право приймати рішення на рахунок спірних ситуацій, не описаних у правилах. Адміністрація може видати покарання, якщо користувачі: 1. Публікують заборонений контент на сторінках інших користувачів, -2. Обдурюють адміністрацію чи агентів тех. підтримки, +2. Обдурюють адміністрацію чи агентів технічної підтримки, 3. Вводять в оману користувачів сайту, -4. Публічно необґрунтовано критикують OpenVK, чи адміністрацію з ціллю принизити чи образити учасників проекту, чи його керівників, -5. Забанені у офіційному чаті OpenVK у Telegram, -6. Не поважають адміністрацію проекту чи агентів тех. підтримки. +4. Публічно необґрунтовано критикують OpenVK чи адміністрацію з ціллю принизити, образити учасників проєкт, його керівників, +5. Заблоковані в офіційному чаті OpenVK у Telegram, +6. Не поважають адміністрацію проєкт чи агентів технічної підтримки. При порушенні правил, адміністрація може: diff --git a/locales/en.strings b/locales/en.strings index 65c90da1..f49cc3b2 100644 --- a/locales/en.strings +++ b/locales/en.strings @@ -16,6 +16,9 @@ "registration" = "Registration"; "forgot_password" = "Forgot your password?"; +"checkbox_in_registration" = "I agree to the privacy policy and site policies"; +"checkbox_in_registration_unchecked" = "You must agree to the privacy policy and rules in order to register."; + "login_failed" = "Login failed"; "invalid_username_or_password" = "The username or password you entered is incorrect. Forgot your password?"; diff --git a/locales/ua.strings b/locales/ua.strings index fdeca0bc..89562acc 100644 --- a/locales/ua.strings +++ b/locales/ua.strings @@ -162,6 +162,9 @@ "post_deact_f" = "видалила сторінку зі словами:"; "post_deact_silent_m" = "мовчки видалив свою сторінку."; "post_deact_silent_f" = "мовчки видалила свою сторінку."; +"post_on_your_wall" = "на вашій стіні"; +"post_on_group_wall" = "в $1"; +"post_on_user_wall" = "на стіні $1"; "wall" = "Стіна"; "post" = "Запис"; "write" = "Написати"; @@ -1209,3 +1212,12 @@ "url_is_banned_default_reason" = "Посилання, за яким Ви спробували перейти, може вести на сайт, що був створений з метою обману користувачів і отримання шляхом цього неправомірного прибутку."; "url_is_banned_title" = "Посилання на підозрілий сайт"; "url_is_banned_proceed" = "Перейти за посиланням"; + +/* Maintenance */ + +"global_maintenance" = "Технічні роботи"; +"section_maintenance" = "Розділ недоступний"; +"undergoing_global_maintenance" = "На жаль, зараз інстанція закрита на технічні роботи. Ми вже працюємо над усуненням неполадок. Будь ласка, спробуйте зайти пізніше."; +"undergoing_section_maintenance" = "На жаль, розділ $1 тимчасово недоступний. Ми вже працюємо над усуненням неполадок. Будь ласка, спробуйте зайти пізніше."; + +"topics" = "Теми"; diff --git a/themepacks/midnight/theme.yml b/themepacks/midnight/theme.yml index aaf05a84..0aa2e5d8 100644 --- a/themepacks/midnight/theme.yml +++ b/themepacks/midnight/theme.yml @@ -7,5 +7,6 @@ metadata: _: "OpenVK Midnight" en: "OpenVK Midnight" ru: "OpenVK Midnight" + uk: "OpenVK Midnight" author: "Ilya Prokopenko" - description: "A dark theme for OpenVK" \ No newline at end of file + description: "A dark theme for OpenVK" diff --git a/themepacks/openvk_modern/theme.yml b/themepacks/openvk_modern/theme.yml index d2fccf42..a92612dd 100644 --- a/themepacks/openvk_modern/theme.yml +++ b/themepacks/openvk_modern/theme.yml @@ -7,5 +7,6 @@ metadata: _: "OpenVK Modern" en: "OpenVK Modern" ru: "OpenVK Modern" + uk: "OpenVK Modern" author: "Mikita Wiśniewski (rudzik8)" description: "OpenVK theme in modern style" diff --git a/themepacks/readme.ru.md b/themepacks/readme.ru.md index b9b0122e..31b78980 100755 --- a/themepacks/readme.ru.md +++ b/themepacks/readme.ru.md @@ -34,7 +34,7 @@ metadata: Далее, в `stylesheet.css` вставляем любой CSS код, с помощью которого вы можете изменить элементы сайта. Если вам нужны дополнительные картинки или ресурсы, то для этого просто создайте папку `res`, и в CSS коде обращайтесь к ресурсам через путь `/themepack/{название директории}/{версия темы}/resource/{ресурс}`. -Для поддержки новогоднего насторения, которое включается автоматически с 1 декабря по 15 января, создайте файл `xmas.css` в папку `res`, и внесите вам нужные изменения. +Для поддержки новогоднего настроения, которое включается автоматически с 1 декабря по 15 января, создайте файл `xmas.css` в папку `res`, и внесите вам нужные изменения. **В конце концов, иерархия директории с темой должна выглядеть вот так:** From da41006ddb6ffb53fe0c4b4de35f498caf4d910a Mon Sep 17 00:00:00 2001 From: Ilya Prokopenko Date: Mon, 10 Oct 2022 17:55:24 +0700 Subject: [PATCH 030/285] OpenVK Midnight: Color the tippy.js boxes --- themepacks/midnight/stylesheet.css | 30 +++++++++++++++++------------- themepacks/midnight/theme.yml | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/themepacks/midnight/stylesheet.css b/themepacks/midnight/stylesheet.css index f143d608..7c3dee17 100644 --- a/themepacks/midnight/stylesheet.css +++ b/themepacks/midnight/stylesheet.css @@ -31,10 +31,14 @@ span, .post-author .date, .crp-entry--message---text, .messenger-app--messages-- border-color: #1c202f; } -.accountInfo, .left_small_block, #profile_link, .profile_link, .navigation .link, .navigation .link:hover, .navigation_footer .link, .navigation_footer .link:hover, .completeness-gauge, input[type="text"], input[type="password"], input[type~="text"], input[type~="password"], input[type="email"], input[type="phone"], input[type~="email"], input[type~="phone"], input[type="search"], input[type~="search"], input[type~="date"], select, .content_title_expanded, .content_title_unexpanded, .content_subtitle, textarea, .post-content, .post-author, hr, h4, .postFeedWrapper, .tabs, #wallAttachmentMenu, .ovk-diag, .ovk-diag-head, #ovkDraw, #ovkDraw .literally .lc-picker, .literally .lc-options.horz-toolbar, .page_wrap, .container_gray .content, .summaryBar, .groups_options, form[action="/search"] > input, .header_search_input, .header_search_inputbt, .accent-box, .page_status_popup, .messenger-app--input, .messenger-app, .crp-entry:first-of-type, .crp-list, .crp-entry, .note_footer, .page_content > div, #editor, .note_header, center[style="background: white;border: #DEDEDE solid 1px;"], .album-photo img, .mb_tabs, .mb_tab#active div, .navigation-lang .link_new, #faqhead, #faqcontent, .post-divider, .comment, .commentsTextFieldWrap, tr, td, th, #votesBalance, .paginator a.active, .paginator a:hover, .topic-list-item, #userContent blockquote { +.accountInfo, .left_small_block, #profile_link, .profile_link, .navigation .link, .navigation .link:hover, .navigation_footer .link, .navigation_footer .link:hover, .completeness-gauge, input[type="text"], input[type="password"], input[type~="text"], input[type~="password"], input[type="email"], input[type="phone"], input[type~="email"], input[type~="phone"], input[type="search"], input[type~="search"], input[type~="date"], select, .content_title_expanded, .content_title_unexpanded, .content_subtitle, textarea, .post-content, .post-author, hr, h4, .postFeedWrapper, .tabs, #wallAttachmentMenu, .ovk-diag, .ovk-diag-head, #ovkDraw, #ovkDraw .literally .lc-picker, .literally .lc-options.horz-toolbar, .page_wrap, .container_gray .content, .summaryBar, .groups_options, form[action="/search"] > input, .header_search_input, .header_search_inputbt, .accent-box, .page_status_popup, .messenger-app--input, .messenger-app, .crp-entry:first-of-type, .crp-list, .crp-entry, .note_footer, .page_content > div, #editor, .note_header, center[style="background: white;border: #DEDEDE solid 1px;"], .album-photo img, .mb_tabs, .mb_tab#active div, .navigation-lang .link_new, #faqhead, #faqcontent, .post-divider, .comment, .commentsTextFieldWrap, tr, td, th, #votesBalance, .paginator a.active, .paginator a:hover, .topic-list-item, #userContent blockquote, .tippy-box[data-theme~="vk"] { border-color: #2c2640 !important; } +.tippy-box[data-theme~="vk"][data-placement^='top'] > .tippy-arrow::before { + border-top-color: #1e1a2b; +} + hr { background-color: #2c2640 !important; } @@ -109,7 +113,7 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { background-color: #231e33 !important; } -.content_subtitle, .postFeedWrapper, .ovk-diag-head, .container_gray, .page_status_popup, .messenger-app--input, .note_header, #faqcontent, .commentsTextFieldWrap, td.v, tr.v, #votesBalance, .expand_button, #userContent blockquote { +.content_subtitle, .postFeedWrapper, .ovk-diag-head, .container_gray, .page_status_popup, .messenger-app--input, .note_header, #faqcontent, .commentsTextFieldWrap, td.v, tr.v, #votesBalance, .expand_button, #userContent blockquote, .tippy-box[data-theme~="vk"] { background-color: #1e1a2b !important; } @@ -119,11 +123,11 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { } .content_title_expanded { - background-image: url("/themepack/midnight/0.0.1.1/resource/flex_arrow_open.png"); + background-image: url("/themepack/midnight/0.0.1.2/resource/flex_arrow_open.png"); } .content_title_unexpanded { - background-image: url("/themepack/midnight/0.0.1.1/resource/flex_arrow_shut.gif"); + background-image: url("/themepack/midnight/0.0.1.2/resource/flex_arrow_shut.gif"); } .ovk-video > .preview, .video-preview { @@ -145,17 +149,17 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { .page_yellowheader { color: #c6d2e8; - background-image: url("/themepack/midnight/0.0.1.1/resource/header_purple.png"); + background-image: url("/themepack/midnight/0.0.1.2/resource/header_purple.png"); background-color: #231f34; border-color: #231f34; } .page_header { - background-image: url("/themepack/midnight/0.0.1.1/resource/header.png"); + background-image: url("/themepack/midnight/0.0.1.2/resource/header.png"); } .page_custom_header { - background-image: url("/themepack/midnight/0.0.1.1/resource/header_custom.png"); + background-image: url("/themepack/midnight/0.0.1.2/resource/header_custom.png"); } .page_yellowheader span, .page_yellowheader a { @@ -175,11 +179,11 @@ form[action="/search"] > input, .header_search_input, textarea, input[type="text } input[type="checkbox"] { - background-image: url("/themepack/midnight/0.0.1.1/resource/checkbox.png"); + background-image: url("/themepack/midnight/0.0.1.2/resource/checkbox.png"); } input[type="radio"] { - background-image: url("/themepack/midnight/0.0.1.1/resource/radio.png"); + background-image: url("/themepack/midnight/0.0.1.2/resource/radio.png"); } .header_navigation .link { @@ -187,19 +191,19 @@ input[type="radio"] { } .heart { - background-image: url("/themepack/midnight/0.0.1.1/resource/like.gif") !important; + background-image: url("/themepack/midnight/0.0.1.2/resource/like.gif") !important; } .pinned-mark, .post-author .pin { - background-image: url("/themepack/midnight/0.0.1.1/resource/pin.png") !important; + background-image: url("/themepack/midnight/0.0.1.2/resource/pin.png") !important; } .repost-icon { - background-image: url("/themepack/midnight/0.0.1.1/resource/published.gif") !important; + background-image: url("/themepack/midnight/0.0.1.2/resource/published.gif") !important; } .post-author .delete { - background-image: url("/themepack/midnight/0.0.1.1/resource/input_clear.gif") !important; + background-image: url("/themepack/midnight/0.0.1.2/resource/input_clear.gif") !important; } .user-alert { diff --git a/themepacks/midnight/theme.yml b/themepacks/midnight/theme.yml index 0aa2e5d8..83017e07 100644 --- a/themepacks/midnight/theme.yml +++ b/themepacks/midnight/theme.yml @@ -1,5 +1,5 @@ id: midnight -version: "0.0.1.1" +version: "0.0.1.2" openvk_version: 0 enabled: 1 metadata: From 307b7709cceac3dae3182cc44e855b9f86a3efc4 Mon Sep 17 00:00:00 2001 From: veselcraft Date: Tue, 11 Oct 2022 03:22:32 +0300 Subject: [PATCH 031/285] VKAPI: Fix Groups.get unworkability if owner id is less than zero --- VKAPI/Handlers/Groups.php | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/VKAPI/Handlers/Groups.php b/VKAPI/Handlers/Groups.php index 173e62e9..b73404a5 100644 --- a/VKAPI/Handlers/Groups.php +++ b/VKAPI/Handlers/Groups.php @@ -10,7 +10,7 @@ final class Groups extends VKAPIRequestHandler $this->requireUser(); if($user_id == 0) { - foreach($this->getUser()->getClubs($offset+1) as $club) + foreach($this->getUser()->getClubs((int) floor($offset/$count)+1) as $club) $clbs[] = $club; $clbsCount = $this->getUser()->getClubCount(); } else { @@ -37,13 +37,7 @@ final class Groups extends VKAPIRequestHandler for($i=0; $i < $ic; $i++) { $usr = $clbs[$i]; - if(is_null($usr)) { - $rClubs[$i] = (object)[ - "id" => $clbs[$i], - "name" => "DELETED", - "deactivated" => "deleted" - ]; - } else if($clbs[$i] == NULL) { + if(is_null($usr)) { } else { $rClubs[$i] = (object) [ @@ -151,6 +145,7 @@ final class Groups extends VKAPIRequestHandler "screen_name" => $clb->getShortCode() ?? "club".$clb->getId(), "is_closed" => false, "type" => "group", + "is_member" => !is_null($this->getUser()) ? (int) $clb->getSubscriptionStatus($this->getUser()) : 0, "can_access_closed" => true, ]; @@ -213,10 +208,6 @@ final class Groups extends VKAPIRequestHandler else $response[$i]->can_post = $clb->canPost(); break; - case "is_member": - if(!is_null($this->getUser())) - $response[$i]->is_member = (int) $clb->getSubscriptionStatus($this->getUser()); - break; } } } From 7b1182f4e88e5679dac24fbc9f5268a2661ea2a2 Mon Sep 17 00:00:00 2001 From: veselcraft Date: Tue, 11 Oct 2022 03:25:20 +0300 Subject: [PATCH 032/285] VKAPI: Fix wall.get unworkability if owner id is less than zero I was wrong about last commit. I just fixed is_member field to show up by force --- VKAPI/Handlers/Wall.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/VKAPI/Handlers/Wall.php b/VKAPI/Handlers/Wall.php index 54f78a55..3339647f 100644 --- a/VKAPI/Handlers/Wall.php +++ b/VKAPI/Handlers/Wall.php @@ -21,10 +21,17 @@ final class Wall extends VKAPIRequestHandler $groups = []; $cnt = $posts->getPostCountOnUserWall($owner_id); - $wallOnwer = (new UsersRepo)->get($owner_id); + if ($owner_id > 0) + $wallOnwer = (new UsersRepo)->get($owner_id); + else + $wallOnwer = (new ClubsRepo)->get($owner_id * -1); - if(!$wallOnwer || $wallOnwer->isDeleted() || $wallOnwer->isDeleted()) - $this->fail(18, "User was deleted or banned"); + if ($owner_id > 0) + if(!$wallOnwer || $wallOnwer->isDeleted()) + $this->fail(18, "User was deleted or banned"); + else + if(!$wallOnwer) + $this->fail(15, "Access denied: wall is disabled"); // Don't search for logic here pls foreach($posts->getPostsFromUsersWall($owner_id, 1, $count, $offset) as $post) { $from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId(); From 699df766192637208b2abb147fb75e47a6cb29e6 Mon Sep 17 00:00:00 2001 From: veselcraft Date: Tue, 11 Oct 2022 03:46:49 +0300 Subject: [PATCH 033/285] VKAPI: Make offset actually work in groups.get method Users: add count and offset (acting like switch for literal offset) param to getClubs --- VKAPI/Handlers/Groups.php | 6 ++---- Web/Models/Entities/User.php | 9 ++++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/VKAPI/Handlers/Groups.php b/VKAPI/Handlers/Groups.php index b73404a5..e2d1e779 100644 --- a/VKAPI/Handlers/Groups.php +++ b/VKAPI/Handlers/Groups.php @@ -10,7 +10,7 @@ final class Groups extends VKAPIRequestHandler $this->requireUser(); if($user_id == 0) { - foreach($this->getUser()->getClubs((int) floor($offset/$count)+1) as $club) + foreach($this->getUser()->getClubs($offset, false, $count, true) as $club) $clbs[] = $club; $clbsCount = $this->getUser()->getClubCount(); } else { @@ -20,7 +20,7 @@ final class Groups extends VKAPIRequestHandler if(is_null($user)) $this->fail(15, "Access denied"); - foreach($user->getClubs($offset+1) as $club) + foreach($user->getClubs($offset, false, $count, true) as $club) $clbs[] = $club; $clbsCount = $user->getClubCount(); @@ -33,8 +33,6 @@ final class Groups extends VKAPIRequestHandler $ic = $count; if(!empty($clbs)) { - $clbs = array_slice($clbs, $offset * $count); - for($i=0; $i < $ic; $i++) { $usr = $clbs[$i]; if(is_null($usr)) { diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php index f1045f62..b7516c90 100644 --- a/Web/Models/Entities/User.php +++ b/Web/Models/Entities/User.php @@ -535,12 +535,15 @@ class User extends RowModel return sizeof(DatabaseConnection::i()->getContext()->table("messages")->where(["recipient_id" => $this->getId(), "unread" => 1])); } - function getClubs(int $page = 1, bool $admin = false): \Traversable + function getClubs(int $page = 1, bool $admin = false, int $count = OPENVK_DEFAULT_PER_PAGE, bool $offset = false): \Traversable { + if(!$offset) + $page = ($page - 1) * $count; + if($admin) { $id = $this->getId(); $query = "SELECT `id` FROM `groups` WHERE `owner` = ? UNION SELECT `club` as `id` FROM `group_coadmins` WHERE `user` = ?"; - $query .= " LIMIT " . OPENVK_DEFAULT_PER_PAGE . " OFFSET " . ($page - 1) * OPENVK_DEFAULT_PER_PAGE; + $query .= " LIMIT " . $count . " OFFSET " . $page; $sel = DatabaseConnection::i()->getConnection()->query($query, $id, $id); foreach($sel as $target) { @@ -550,7 +553,7 @@ class User extends RowModel yield $target; } } else { - $sel = $this->getRecord()->related("subscriptions.follower")->page($page, OPENVK_DEFAULT_PER_PAGE); + $sel = $this->getRecord()->related("subscriptions.follower")->limit($count, $page); foreach($sel->where("model", "openvk\\Web\\Models\\Entities\\Club") as $target) { $target = (new Clubs)->get($target->target); if(!$target) continue; From 3f87bab3f2d71afd8c575ec781d97199ca90ebcb Mon Sep 17 00:00:00 2001 From: Ilya Prokopenko Date: Tue, 11 Oct 2022 17:35:42 +0700 Subject: [PATCH 034/285] OpenVK Midnight: FULLY color the tippy.js boxes I didn't see that coming --- themepacks/midnight/stylesheet.css | 25 +++++++++++++------------ themepacks/midnight/theme.yml | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/themepacks/midnight/stylesheet.css b/themepacks/midnight/stylesheet.css index 7c3dee17..899b70f7 100644 --- a/themepacks/midnight/stylesheet.css +++ b/themepacks/midnight/stylesheet.css @@ -35,8 +35,9 @@ span, .post-author .date, .crp-entry--message---text, .messenger-app--messages-- border-color: #2c2640 !important; } -.tippy-box[data-theme~="vk"][data-placement^='top'] > .tippy-arrow::before { +.tippy-box[data-theme~="vk"][data-placement^='top'] > .tippy-arrow::before, .tippy-box[data-theme~="vk"][data-placement^='bottom'] > .tippy-arrow::before { border-top-color: #1e1a2b; + border-bottom-color: #1e1a2b; } hr { @@ -123,11 +124,11 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { } .content_title_expanded { - background-image: url("/themepack/midnight/0.0.1.2/resource/flex_arrow_open.png"); + background-image: url("/themepack/midnight/0.0.1.3/resource/flex_arrow_open.png"); } .content_title_unexpanded { - background-image: url("/themepack/midnight/0.0.1.2/resource/flex_arrow_shut.gif"); + background-image: url("/themepack/midnight/0.0.1.3/resource/flex_arrow_shut.gif"); } .ovk-video > .preview, .video-preview { @@ -149,17 +150,17 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { .page_yellowheader { color: #c6d2e8; - background-image: url("/themepack/midnight/0.0.1.2/resource/header_purple.png"); + background-image: url("/themepack/midnight/0.0.1.3/resource/header_purple.png"); background-color: #231f34; border-color: #231f34; } .page_header { - background-image: url("/themepack/midnight/0.0.1.2/resource/header.png"); + background-image: url("/themepack/midnight/0.0.1.3/resource/header.png"); } .page_custom_header { - background-image: url("/themepack/midnight/0.0.1.2/resource/header_custom.png"); + background-image: url("/themepack/midnight/0.0.1.3/resource/header_custom.png"); } .page_yellowheader span, .page_yellowheader a { @@ -179,11 +180,11 @@ form[action="/search"] > input, .header_search_input, textarea, input[type="text } input[type="checkbox"] { - background-image: url("/themepack/midnight/0.0.1.2/resource/checkbox.png"); + background-image: url("/themepack/midnight/0.0.1.3/resource/checkbox.png"); } input[type="radio"] { - background-image: url("/themepack/midnight/0.0.1.2/resource/radio.png"); + background-image: url("/themepack/midnight/0.0.1.3/resource/radio.png"); } .header_navigation .link { @@ -191,19 +192,19 @@ input[type="radio"] { } .heart { - background-image: url("/themepack/midnight/0.0.1.2/resource/like.gif") !important; + background-image: url("/themepack/midnight/0.0.1.3/resource/like.gif") !important; } .pinned-mark, .post-author .pin { - background-image: url("/themepack/midnight/0.0.1.2/resource/pin.png") !important; + background-image: url("/themepack/midnight/0.0.1.3/resource/pin.png") !important; } .repost-icon { - background-image: url("/themepack/midnight/0.0.1.2/resource/published.gif") !important; + background-image: url("/themepack/midnight/0.0.1.3/resource/published.gif") !important; } .post-author .delete { - background-image: url("/themepack/midnight/0.0.1.2/resource/input_clear.gif") !important; + background-image: url("/themepack/midnight/0.0.1.3/resource/input_clear.gif") !important; } .user-alert { diff --git a/themepacks/midnight/theme.yml b/themepacks/midnight/theme.yml index 83017e07..254e7894 100644 --- a/themepacks/midnight/theme.yml +++ b/themepacks/midnight/theme.yml @@ -1,5 +1,5 @@ id: midnight -version: "0.0.1.2" +version: "0.0.1.3" openvk_version: 0 enabled: 1 metadata: From d8a8dd920ab344b1f1dda0cfcff06e90689dcd0a Mon Sep 17 00:00:00 2001 From: veselcraft Date: Tue, 11 Oct 2022 13:42:29 +0300 Subject: [PATCH 035/285] Global: add mobile theme support for dumbphones By setting defaultFeaturePhoneTheme, you can enable very basic html theme for old phones, like Nokia 6680 or iPhone 3GS. I'm currently making this theme, but it would take a time to make it ofc --- Web/Presenters/OpenVKPresenter.php | 37 ++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/Web/Presenters/OpenVKPresenter.php b/Web/Presenters/OpenVKPresenter.php index 5b7908a8..1505df92 100755 --- a/Web/Presenters/OpenVKPresenter.php +++ b/Web/Presenters/OpenVKPresenter.php @@ -284,10 +284,14 @@ abstract class OpenVKPresenter extends SimplePresenter parent::onBeforeRender(); $whichbrowser = new WhichBrowser\Parser(getallheaders()); + $featurephonetheme = OPENVK_ROOT_CONF["openvk"]["preferences"]["defaultFeaturePhoneTheme"]; $mobiletheme = OPENVK_ROOT_CONF["openvk"]["preferences"]["defaultMobileTheme"]; - if($mobiletheme && $whichbrowser->isType('mobile') && Session::i()->get("_tempTheme") == NULL) + + if($featurephonetheme && $this->isOldThing($whichbrowser) && Session::i()->get("_tempTheme") == NULL) { + $this->setSessionTheme($featurephonetheme); + } elseif($mobiletheme && $whichbrowser->isType('mobile') && Session::i()->get("_tempTheme") == NULL) $this->setSessionTheme($mobiletheme); - + $theme = NULL; if(Session::i()->get("_tempTheme")) { $theme = Themepacks::i()[Session::i()->get("_tempTheme", "ovk")]; @@ -318,4 +322,33 @@ abstract class OpenVKPresenter extends SimplePresenter header("Content-Length: $size"); exit($payload); } + + protected function isOldThing($whichbrowser) { + if($whichbrowser->isOs('Series60') || + $whichbrowser->isOs('Series40') || + $whichbrowser->isOs('Series80') || + $whichbrowser->isOs('Windows CE') || + $whichbrowser->isOs('Windows Mobile') || + $whichbrowser->isOs('Nokia Asha Platform') || + $whichbrowser->isOs('UIQ') || + $whichbrowser->isEngine('NetFront') || // PSP and other japanese portable systems + $whichbrowser->isOs('Android') || + $whichbrowser->isOs('iOS') || + $whichbrowser->isBrowser('Internet Explorer', '<=', '8')) { + // yeah, it's old, but ios and android are? + if($whichbrowser->isOs('iOS') && $whichbrowser->isOs('iOS', '<=', '9')) + return true; + elseif($whichbrowser->isOs('iOS') && $whichbrowser->isOs('iOS', '>', '9')) + return false; + + if($whichbrowser->isOs('Android') && $whichbrowser->isOs('Android', '<=', '5')) + return true; + elseif($whichbrowser->isOs('Android') && $whichbrowser->isOs('Android', '>', '5')) + return false; + + return true; + } else { + return false; + } + } } From f2ca6be4d5d29cee8eedf24919086684ee8afa35 Mon Sep 17 00:00:00 2001 From: celestora Date: Tue, 11 Oct 2022 19:04:43 +0300 Subject: [PATCH 036/285] Add polls (#743) --- ServiceAPI/Polls.php | 70 +++++ Web/Models/Entities/Poll.php | 295 ++++++++++++++++++ .../Exceptions/AlreadyVotedException.php | 7 + .../Exceptions/InvalidOptionException.php | 7 + Web/Models/Exceptions/PollLockedException.php | 8 + .../Exceptions/TooMuchOptionsException.php | 7 + Web/Models/Repositories/Polls.php | 23 ++ Web/Presenters/PollPresenter.php | 70 +++++ Web/Presenters/WallPresenter.php | 22 +- Web/Presenters/templates/@layout.xml | 54 +--- Web/Presenters/templates/Poll/Poll.xml | 44 +++ Web/Presenters/templates/Poll/PollResults.xml | 44 +++ Web/Presenters/templates/Poll/Voters.xml | 40 +++ Web/Presenters/templates/_includeCSS.xml | 52 +++ .../templates/components/attachment.xml | 2 + .../templates/components/textArea.xml | 8 + Web/Presenters/templates/components/wall.xml | 2 +- Web/di.yml | 2 + Web/routes.yml | 4 + Web/static/css/style.css | 90 +++++- Web/static/js/al_polls.js | 151 +++++++++ install/sqls/00034-polls.sql | 32 ++ locales/en.strings | 32 ++ locales/ru.strings | 32 ++ quirks.yml | 2 + 25 files changed, 1041 insertions(+), 59 deletions(-) create mode 100644 ServiceAPI/Polls.php create mode 100644 Web/Models/Entities/Poll.php create mode 100644 Web/Models/Exceptions/AlreadyVotedException.php create mode 100644 Web/Models/Exceptions/InvalidOptionException.php create mode 100644 Web/Models/Exceptions/PollLockedException.php create mode 100644 Web/Models/Exceptions/TooMuchOptionsException.php create mode 100644 Web/Models/Repositories/Polls.php create mode 100644 Web/Presenters/PollPresenter.php create mode 100644 Web/Presenters/templates/Poll/Poll.xml create mode 100644 Web/Presenters/templates/Poll/PollResults.xml create mode 100644 Web/Presenters/templates/Poll/Voters.xml create mode 100644 Web/Presenters/templates/_includeCSS.xml create mode 100644 Web/static/js/al_polls.js create mode 100644 install/sqls/00034-polls.sql diff --git a/ServiceAPI/Polls.php b/ServiceAPI/Polls.php new file mode 100644 index 00000000..9d3e2e7f --- /dev/null +++ b/ServiceAPI/Polls.php @@ -0,0 +1,70 @@ +user = $user; + $this->polls = new PollRepo; + } + + private function getPollHtml(int $poll): string + { + return Router::i()->execute("/poll$poll", "SAPI"); + } + + function vote(int $pollId, string $options, callable $resolve, callable $reject): void + { + $poll = $this->polls->get($pollId); + if(!$poll) { + $reject("Poll not found"); + return; + } + + try { + $options = explode(",", $options); + $poll->vote($this->user, $options); + } catch(AlreadyVotedException $ex) { + $reject("Poll state changed: user has already voted."); + return; + } catch(PollLockedException $ex) { + $reject("Poll state changed: poll has ended."); + return; + } catch(InvalidOptionException $ex) { + $reject("Foreign options passed."); + return; + } catch(UnexpectedValueException $ex) { + $reject("Too much options passed."); + return; + } + + $resolve(["html" => $this->getPollHtml($pollId)]); + } + + function unvote(int $pollId, callable $resolve, callable $reject): void + { + $poll = $this->polls->get($pollId); + if(!$poll) { + $reject("Poll not found"); + return; + } + + try { + $poll->revokeVote($this->user); + } catch(PollLockedException $ex) { + $reject("Votes can't be revoked from this poll."); + return; + } + + $resolve(["html" => $this->getPollHtml($pollId)]); + } +} \ No newline at end of file diff --git a/Web/Models/Entities/Poll.php b/Web/Models/Entities/Poll.php new file mode 100644 index 00000000..43a97074 --- /dev/null +++ b/Web/Models/Entities/Poll.php @@ -0,0 +1,295 @@ +getRecord()->title; + } + + function getMetaDescription(): string + { + $props = []; + $props[] = tr($this->isAnonymous() ? "poll_anon" : "poll_public"); + if($this->isMultipleChoice()) $props[] = tr("poll_multi"); + if(!$this->isRevotable()) $props[] = tr("poll_lock"); + if(!is_null($this->endsAt())) $props[] = tr("poll_until", $this->endsAt()); + + return implode(" • ", $props); + } + + function getOwner(): User + { + return (new Users)->get($this->getRecord()->owner); + } + + function getOptions(): array + { + $options = $this->getRecord()->related("poll_options.poll"); + $res = []; + foreach($options as $opt) + $res[$opt->id] = $opt->name; + + return $res; + } + + function getUserVote(User $user): ?array + { + $ctx = DatabaseConnection::i()->getContext(); + $votedOpts = $ctx->table("poll_votes") + ->where(["user" => $user->getId(), "poll" => $this->getId()]); + + if($votedOpts->count() == 0) + return NULL; + + $res = []; + foreach($votedOpts as $votedOpt) { + $option = $ctx->table("poll_options")->get($votedOpt->option); + $res[] = [$option->id, $option->name]; + } + + return $res; + } + + function getVoters(int $optionId, int $page = 1, ?int $perPage = NULL): array + { + $res = []; + $ctx = DatabaseConnection::i()->getContext(); + $perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE; + $voters = $ctx->table("poll_votes")->where(["poll" => $this->getId(), "option" => $optionId]); + foreach($voters->page($page, $perPage) as $vote) + $res[] = (new Users)->get($vote->user); + + return $res; + } + + function getVoterCount(?int $optionId = NULL): int + { + $votes = DatabaseConnection::i()->getContext()->table("poll_votes"); + if(!$optionId) + return $votes->select("COUNT(DISTINCT user) AS c")->where("poll", $this->getId())->fetch()->c; + + return $votes->where(["poll" => $this->getId(), "option" => $optionId])->count(); + } + + function getResults(?User $user = NULL): object + { + $ctx = DatabaseConnection::i()->getContext(); + $voted = NULL; + if(!is_null($user)) + $voted = $this->getUserVote($user); + + $result = (object) []; + $result->totalVotes = $this->getVoterCount(); + + $unsOptions = []; + foreach($this->getOptions() as $id => $title) { + $option = (object) []; + $option->id = $id; + $option->name = $title; + + $option->votes = $this->getVoterCount($id); + $option->pct = $result->totalVotes == 0 ? 0 : (($option->votes / $result->totalVotes) * 100); + $option->voters = $this->getVoters($id, 1, 10); + if(!$user || !$voted) + $option->voted = NULL; + else + $option->voted = in_array([$id, $title], $voted); + + $unsOptions[$id] = $option; + } + + $optionsC = sizeof($unsOptions); + $sOptions = $unsOptions; + usort($sOptions, function($a, $b) { return $a->votes <=> $b->votes; }); + for($i = 0; $i < $optionsC; $i++) + $unsOptions[$id]->rate = $optionsC - $i - 1; + + $result->options = array_values($unsOptions); + + return $result; + } + + function isAnonymous(): bool + { + return (bool) $this->getRecord()->is_anonymous; + } + + function isMultipleChoice(): bool + { + return (bool) $this->getRecord()->allows_multiple; + } + + function isRevotable(): bool + { + return (bool) $this->getRecord()->can_revote; + } + + function endsAt(): ?DateTime + { + if(!$this->getRecord()->until) + return NULL; + + return new DateTime($this->getRecord()->until); + } + + function hasEnded(): bool + { + if($this->getRecord()->ended) + return true; + + if(!is_null($this->getRecord()->until)) + return time() >= $this->getRecord()->until; + + return false; + } + + function hasVoted(User $user): bool + { + return !is_null($this->getUserVote($user)); + } + + function canVote(User $user): bool + { + return !$this->hasEnded() && !$this->hasVoted($user); + } + + function vote(User $user, array $optionIds): void + { + if($this->hasEnded()) + throw new PollLockedException; + + if($this->hasVoted($user)) + throw new AlreadyVotedException; + + $optionIds = array_map(function($x) { return (int) $x; }, array_unique($optionIds)); + $validOpts = array_keys($this->getOptions()); + if(empty($optionIds) || (sizeof($optionIds) > 1 && !$this->isMultipleChoice())) + throw new UnexpectedValueException; + + if(sizeof(array_diff($optionIds, $validOpts)) > 0) + throw new InvalidOptionException; + + foreach($optionIds as $opt) { + DatabaseConnection::i()->getContext()->table("poll_votes")->insert([ + "user" => $user->getId(), + "poll" => $this->getId(), + "option" => $opt, + ]); + } + } + + function revokeVote(User $user): void + { + if(!$this->isRevotable()) + throw new PollLockedException; + + $this->getRecord()->related("poll_votes.poll") + ->where("user", $user->getId())->delete(); + } + + function setOwner(User $owner): void + { + $this->stateChanges("owner", $owner->getId()); + } + + function setEndDate(int $timestamp): void + { + if(!is_null($this->getRecord())) + throw new PollLockedException; + + $this->stateChanges("until", $timestamp); + } + + function setEnded(): void + { + $this->stateChanges("ended", 1); + } + + function setOptions(array $options): void + { + if(!is_null($this->getRecord())) + throw new PollLockedException; + + if(sizeof($options) > ovkGetQuirk("polls.max-opts")) + throw new TooMuchOptionsException; + + $this->choicesToPersist = $options; + } + + function setRevotability(bool $canReVote): void + { + if(!is_null($this->getRecord())) + throw new PollLockedException; + + $this->stateChanges("can_revote", true); + } + + function setAnonymity(bool $anonymous): void + { + $this->stateChanges("is_anonymous", $anonymous); + } + + function setMultipleChoice(bool $mc): void + { + $this->stateChanges("allows_multiple", $mc); + } + + function importXML(User $owner, string $xml): void + { + $xml = simplexml_load_string($xml); + $this->setOwner($owner); + $this->setTitle($xml["title"] ?? "Untitled"); + $this->setMultipleChoice(($xml["multiple"] ?? "no") == "yes"); + $this->setAnonymity(($xml["anonymous"] ?? "no") == "yes"); + $this->setRevotability(($xml["locked"] ?? "no") == "yes"); + if(ctype_digit($xml["duration"] ?? "")) + $this->setEndDate(time() + ((86400 * (int) $xml["duration"]))); + + $options = []; + foreach($xml->options->option as $opt) + $options[] = (string) $opt; + + if(empty($options)) + throw new UnexpectedValueException; + + $this->setOptions($options); + } + + static function import(User $owner, string $xml): Poll + { + $poll = new Poll; + $poll->importXML($owner, $xml); + $poll->save(); + + return $poll; + } + + function save(): void + { + if(empty($this->choicesToPersist)) + throw new InvalidStateException; + + parent::save(); + foreach($this->choicesToPersist as $option) { + DatabaseConnection::i()->getContext()->table("poll_options")->insert([ + "poll" => $this->getId(), + "name" => $option, + ]); + } + } +} \ No newline at end of file diff --git a/Web/Models/Exceptions/AlreadyVotedException.php b/Web/Models/Exceptions/AlreadyVotedException.php new file mode 100644 index 00000000..08363b9a --- /dev/null +++ b/Web/Models/Exceptions/AlreadyVotedException.php @@ -0,0 +1,7 @@ +polls = DatabaseConnection::i()->getContext()->table("polls"); + } + + function get(int $id): ?Poll + { + $poll = $this->polls->get($id); + if(!$poll) + return NULL; + + return new Poll($poll); + } +} \ No newline at end of file diff --git a/Web/Presenters/PollPresenter.php b/Web/Presenters/PollPresenter.php new file mode 100644 index 00000000..3f7084c5 --- /dev/null +++ b/Web/Presenters/PollPresenter.php @@ -0,0 +1,70 @@ +polls = $polls; + + parent::__construct(); + } + + function renderView(int $id): void + { + $poll = $this->polls->get($id); + if(!$poll) + $this->notFound(); + + $this->template->id = $poll->getId(); + $this->template->title = $poll->getTitle(); + $this->template->isAnon = $poll->isAnonymous(); + $this->template->multiple = $poll->isMultipleChoice(); + $this->template->unlocked = $poll->isRevotable(); + $this->template->until = $poll->endsAt(); + $this->template->votes = $poll->getVoterCount(); + $this->template->meta = $poll->getMetaDescription(); + if(is_null($this->user) || $poll->canVote($this->user->identity)) { + $this->template->options = $poll->getOptions(); + + $this->template->_template = "Poll/Poll.xml"; + return; + } + + $this->template->voted = $poll->hasVoted($this->user->identity); + $this->template->ended = $poll->hasEnded(); + $this->template->results = $poll->getResults($this->user->identity); + + $this->template->_template = "Poll/PollResults.xml"; + } + + function renderVoters(int $pollId): void + { + $poll = $this->polls->get($pollId); + if(!$poll) + $this->notFound(); + + if($poll->isAnonymous()) + $this->flashFail("err", tr("forbidden"), tr("poll_err_anonymous")); + + $options = $poll->getOptions(); + $option = (int) base_convert($this->queryParam("option"), 32, 10); + if(!in_array($option, array_keys($options))) + $this->notFound(); + + $page = (int) ($this->queryParam("p") ?? 1); + $voters = $poll->getVoters($option, $page); + + $this->template->pollId = $pollId; + $this->template->options = $options; + $this->template->option = [$option, $options[$option]]; + $this->template->tabs = $options; + $this->template->iterator = $voters; + $this->template->count = $poll->getVoterCount($option); + $this->template->page = $page; + } +} \ No newline at end of file diff --git a/Web/Presenters/WallPresenter.php b/Web/Presenters/WallPresenter.php index 55c90518..ef62d0ea 100644 --- a/Web/Presenters/WallPresenter.php +++ b/Web/Presenters/WallPresenter.php @@ -1,6 +1,7 @@ user->id, $this->postParam("text"), $_FILES["_pic_attachment"], $album, $anon); } - if($_FILES["_vid_attachment"]["error"] === UPLOAD_ERR_OK) { + if($_FILES["_vid_attachment"]["error"] === UPLOAD_ERR_OK) $video = Video::fastMake($this->user->id, $this->postParam("text"), $_FILES["_vid_attachment"], $anon); - } } catch(\DomainException $ex) { $this->flashFail("err", tr("failed_to_publish_post"), tr("media_file_corrupted")); } catch(ISE $ex) { $this->flashFail("err", tr("failed_to_publish_post"), tr("media_file_corrupted_or_too_large")); } - if(empty($this->postParam("text")) && !$photo && !$video) + try { + $poll = NULL; + $xml = $this->postParam("poll"); + if (!is_null($xml) && $xml != "none") + $poll = Poll::import($this->user->identity, $xml); + } catch(TooMuchOptionsException $e) { + $this->flashFail("err", tr("failed_to_publish_post"), tr("poll_err_to_much_options")); + } catch(\UnexpectedValueException $e) { + $this->flashFail("err", tr("failed_to_publish_post"), "Poll format invalid"); + } + + if(empty($this->postParam("text")) && !$photo && !$video && !$poll) $this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_empty_or_too_big")); try { @@ -291,6 +302,9 @@ final class WallPresenter extends OpenVKPresenter if(!is_null($video)) $post->attach($video); + if(!is_null($poll)) + $post->attach($poll); + if($wall > 0 && $wall !== $this->user->identity->getId()) (new WallPostNotification($wallOwner, $post, $this->user->identity))->emit(); diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml index 1be7ba55..8fe554c7 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -29,58 +29,7 @@ {script "js/timezone.js"} {/if} - {ifset $thisUser} - {if $thisUser->getNsfwTolerance() < 2} - {css "css/nsfw-posts.css"} - {/if} - - {if $theme !== NULL} - {if $theme->inheritDefault()} - {css "css/style.css"} - {css "css/dialog.css"} - {css "css/notifications.css"} - - {if $isXmas} - {css "css/xmas.css"} - {/if} - {/if} - - - - {if $isXmas} - - {/if} - {else} - {css "css/style.css"} - {css "css/dialog.css"} - {css "css/notifications.css"} - - {if $isXmas} - {css "css/xmas.css"} - {/if} - {/if} - - {if $thisUser->getStyleAvatar() == 1} - {css "css/avatar.1.css"} - {/if} - - {if $thisUser->getStyleAvatar() == 2} - {css "css/avatar.2.css"} - {/if} - - {if $thisUser->hasMicroblogEnabled() == 1} - {css "css/microblog.css"} - {/if} - {else} - {css "css/style.css"} - {css "css/dialog.css"} - {css "css/nsfw-posts.css"} - {css "css/notifications.css"} - - {if $isXmas} - {css "css/xmas.css"} - {/if} - {/ifset} + {include "_includeCSS.xml"} {ifset headIncludes} {include headIncludes} @@ -334,6 +283,7 @@ {script "js/al_wall.js"} {script "js/al_api.js"} {script "js/al_mentions.js"} + {script "js/al_polls.js"} {ifset $thisUser} {script "js/al_notifs.js"} diff --git a/Web/Presenters/templates/Poll/Poll.xml b/Web/Presenters/templates/Poll/Poll.xml new file mode 100644 index 00000000..21378ca1 --- /dev/null +++ b/Web/Presenters/templates/Poll/Poll.xml @@ -0,0 +1,44 @@ +{if !isset($parentModule) || substr($parentModule, 0, 21) === 'libchandler:absolute.'} + + + + {script "js/node_modules/jquery/dist/jquery.min.js"} + {script "js/node_modules/umbrellajs/umbrella.min.js"} + {script "js/node_modules/msgpack-lite/dist/msgpack.min.js"} + {script "js/messagebox.js"} + {script "js/l10n.js"} + {script "js/al_api.js"} + {script "js/al_polls.js"} + {include "../_includeCSS.xml"} + + +{/if} + +
+

{$title}

+
+
+
+ +
+
+ + {if $multiple} +
+ + {/if} +
+ +
+ {tr("poll_voter_count", $votes)|noescape}
+ {$meta} +
+
diff --git a/Web/Presenters/templates/Poll/PollResults.xml b/Web/Presenters/templates/Poll/PollResults.xml new file mode 100644 index 00000000..9b61c48a --- /dev/null +++ b/Web/Presenters/templates/Poll/PollResults.xml @@ -0,0 +1,44 @@ +{if !isset($parentModule) || substr($parentModule, 0, 21) === 'libchandler:absolute.'} + + + + {script "js/node_modules/jquery/dist/jquery.min.js"} + {script "js/node_modules/umbrellajs/umbrella.min.js"} + {script "js/node_modules/msgpack-lite/dist/msgpack.min.js"} + {script "js/messagebox.js"} + {script "js/l10n.js"} + {script "js/al_api.js"} + {script "js/al_polls.js"} + {include "../_includeCSS.xml"} + + +{/if} + +
+ {_retract_vote} +

{$title}

+
+
+ {if $isAnon} + {$option->name} + {else} + {$option->name} + {/if} + +
+
+ {$option->votes} +
 
+
+
+ {$option->pct}% +
+
+
+
+ +
+ {tr("poll_voter_count", $votes)|noescape}
+ {$meta} +
+
diff --git a/Web/Presenters/templates/Poll/Voters.xml b/Web/Presenters/templates/Poll/Voters.xml new file mode 100644 index 00000000..f6348df9 --- /dev/null +++ b/Web/Presenters/templates/Poll/Voters.xml @@ -0,0 +1,40 @@ +{extends "../@listView.xml"} + +{block title} + {_poll_voters_list} +{/block} + +{block header} + {_poll_voters_list} » + {$option[1]} +{/block} + +{block tabs} + +{/block} + +{* BEGIN ELEMENTS DESCRIPTION *} + +{block link|strip|stripHtml} + {$x->getURL()} +{/block} + +{block preview} + Фотография пользователя +{/block} + +{block name} + {$x->getCanonicalName()} + +{/block} + +{block description} +{/block} + +{block actions} +{/block} diff --git a/Web/Presenters/templates/_includeCSS.xml b/Web/Presenters/templates/_includeCSS.xml new file mode 100644 index 00000000..7f83c01a --- /dev/null +++ b/Web/Presenters/templates/_includeCSS.xml @@ -0,0 +1,52 @@ +{ifset $thisUser} + {if $thisUser->getNsfwTolerance() < 2} + {css "css/nsfw-posts.css"} + {/if} + + {if $theme !== NULL} + {if $theme->inheritDefault()} + {css "css/style.css"} + {css "css/dialog.css"} + {css "css/notifications.css"} + + {if $isXmas} + {css "css/xmas.css"} + {/if} + {/if} + + + + {if $isXmas} + + {/if} + {else} + {css "css/style.css"} + {css "css/dialog.css"} + {css "css/notifications.css"} + + {if $isXmas} + {css "css/xmas.css"} + {/if} + {/if} + + {if $thisUser->getStyleAvatar() == 1} + {css "css/avatar.1.css"} + {/if} + + {if $thisUser->getStyleAvatar() == 2} + {css "css/avatar.2.css"} + {/if} + + {if $thisUser->hasMicroblogEnabled() == 1} + {css "css/microblog.css"} + {/if} +{else} + {css "css/style.css"} + {css "css/dialog.css"} + {css "css/nsfw-posts.css"} + {css "css/notifications.css"} + + {if $isXmas} + {css "css/xmas.css"} + {/if} +{/ifset} \ No newline at end of file diff --git a/Web/Presenters/templates/components/attachment.xml b/Web/Presenters/templates/components/attachment.xml index 6366a603..c54a1c03 100644 --- a/Web/Presenters/templates/components/attachment.xml +++ b/Web/Presenters/templates/components/attachment.xml @@ -11,6 +11,8 @@ {/if} {elseif $attachment instanceof \openvk\Web\Models\Entities\Video} +{elseif $attachment instanceof \openvk\Web\Models\Entities\Poll} + {presenter "openvk!Poll->view", $attachment->getId()} {elseif $attachment instanceof \openvk\Web\Models\Entities\Post} {php $GLOBALS["_nesAttGloCou"] = (isset($GLOBALS["_nesAttGloCou"]) ? $GLOBALS["_nesAttGloCou"] : 0) + 1} {if $GLOBALS["_nesAttGloCou"] > 2} diff --git a/Web/Presenters/templates/components/textArea.xml b/Web/Presenters/templates/components/textArea.xml index 0b733ec7..0d28e06e 100644 --- a/Web/Presenters/templates/components/textArea.xml +++ b/Web/Presenters/templates/components/textArea.xml @@ -11,6 +11,9 @@
{_attachment}: (unknown)
+
+ {_poll} +
{var $anonEnabled = OPENVK_ROOT_CONF['openvk']['preferences']['wall']['anonymousPosting']['enable']} @@ -50,6 +53,7 @@
+
@@ -75,6 +79,10 @@ {_graffiti} + + + {_poll} +
diff --git a/Web/Presenters/templates/components/wall.xml b/Web/Presenters/templates/components/wall.xml index feb688bc..c2f5089a 100644 --- a/Web/Presenters/templates/components/wall.xml +++ b/Web/Presenters/templates/components/wall.xml @@ -8,7 +8,7 @@
- {include "../components/textArea.xml", route => "/wall$owner/makePost", graffiti => true} + {include "../components/textArea.xml", route => "/wall$owner/makePost", graffiti => true, polls => true}
diff --git a/Web/di.yml b/Web/di.yml index ec867809..152e5db1 100644 --- a/Web/di.yml +++ b/Web/di.yml @@ -23,9 +23,11 @@ services: - openvk\Web\Presenters\AppsPresenter - openvk\Web\Presenters\ThemepacksPresenter - openvk\Web\Presenters\VKAPIPresenter + - openvk\Web\Presenters\PollPresenter - openvk\Web\Presenters\BannedLinkPresenter - openvk\Web\Models\Repositories\Users - openvk\Web\Models\Repositories\Posts + - openvk\Web\Models\Repositories\Polls - openvk\Web\Models\Repositories\Photos - openvk\Web\Models\Repositories\Albums - openvk\Web\Models\Repositories\Clubs diff --git a/Web/routes.yml b/Web/routes.yml index d6f63a11..ec7fe02d 100644 --- a/Web/routes.yml +++ b/Web/routes.yml @@ -273,6 +273,10 @@ routes: handler: "Apps->edit" - url: "/apps/uninstall" handler: "Apps->unInstall" + - url: "/poll{num}" + handler: "Poll->view" + - url: "/poll{num}/voters" + handler: "Poll->voters" - url: "/admin" handler: "Admin->index" - url: "/admin/users" diff --git a/Web/static/css/style.css b/Web/static/css/style.css index 25516af7..b935c7e0 100644 --- a/Web/static/css/style.css +++ b/Web/static/css/style.css @@ -448,6 +448,15 @@ table { color: #e8e8e8; } +.button[disabled] { + filter: opacity(0.5); + cursor: not-allowed; +} + +.button[disabled]:hover { + color: #fff; +} + .button-loading { display: inline-block; background-image: url('/assets/packages/static/openvk/img/loading_mini.gif'); @@ -801,6 +810,8 @@ table.User { padding: 0 10px; margin-left: -10px; width: 607px; + overflow-x: auto; + white-space: nowrap; } .tabs.stupid-fix { @@ -1338,14 +1349,14 @@ body.scrolled .toTop:hover { font-weight: bold; } -.post-upload { +.post-upload, .post-has-poll { margin-top: 11px; margin-left: 3px; color: #3c3c3c; display: none; } -.post-upload::before { +.post-upload::before, .post-has-poll::before { content: " "; width: 8px; height: 8px; @@ -2051,6 +2062,81 @@ table td[width="120"] { max-height: 250px; } +.poll { + padding: 8px; + transition: .1s filter ease-in; + border: 1px solid #e3e3e3; +} + +.poll.loading { + filter: opacity(0.5); + cursor: progress; + user-select: none; +} + +.poll.loading * { + pointer-events: none; +} + +.poll-embed { + float: right; +} + +.poll h4 { + padding-bottom: 4px; + margin-bottom: 8px; +} + +.poll-meta .nobold { + font-style: oblique; +} + +.poll-result-barspace { + display: flex; +} + +.poll-result { + margin-bottom: 5px; +} + +.poll-result a { + color: unset; +} + +.poll-result-bar { + position: relative; + margin: 5px 0; + background-color: #f7f7f7; + height: 13pt; + flex: 14; +} + +span.poll-result-count { + position: absolute; + top: 50%; + left: 50%; + margin-right: -50%; + transform: translate(-50%, -50%); + color: #7d96af; +} + +.poll-result-bar-sub { + height: 100%; + background-color: #d9e1ea; +} + +.poll-result-pct { + flex: 2; + display: flex; + justify-content: flex-end; + align-items: center; + padding-left: 5px; +} + +a.poll-retract-vote { + float: right; +} + .tippy-box[data-theme~="vk"] { user-select: none; background-color: #fff; diff --git a/Web/static/js/al_polls.js b/Web/static/js/al_polls.js new file mode 100644 index 00000000..14588e04 --- /dev/null +++ b/Web/static/js/al_polls.js @@ -0,0 +1,151 @@ +async function pollRetractVote(id) { + let poll = $(`.poll[data-id=${id}]`); + + poll.addClass("loading"); + try { + let html = (await API.Polls.unvote(poll.data("id"))).html; + poll.prop("outerHTML", html); + } catch(e) { + MessageBox(tr("error"), "Sorry: " + e.message, ["OK"], [Function.noop]); + } finally { + poll.removeClass("loading"); + } +} + +async function pollFormSubmit(e, form) { + e.preventDefault(); + form = $(form); + + let options; + let isMultiple = form.data("multi"); + let pollId = form.data("pid"); + + let formData = form.serializeArray(); + if(!isMultiple) { + options = [Number(formData[0].value)]; + } else { + options = []; + formData.forEach(function(record) { + if(!record.name.startsWith("option") || record.value !== "on") + return; + + options.push(Number(record.name.substr(6))); + }); + } + + let poll = form.parent(); + poll.addClass("loading"); + try { + let html = (await API.Polls.vote(pollId, options.join(","))).html; + poll.prop("outerHTML", html); + } catch(e) { + MessageBox(tr("error"), "Sorry: " + e.message, ["OK"], [Function.noop]); + } finally { + poll.removeClass("loading"); + } +} + +function pollCheckBoxPressed(cb) { + cb = $(cb); + let form = cb.parent().parent().parent().parent(); + let checked = $("input:checked", form); + if(checked.length >= 1) + $("input[type=submit]", form).removeAttr("disabled"); + else + $("input[type=submit]", form).attr("disabled", "disabled"); +} + +function pollRadioPressed(radio) { + let form = $(radio).parent().parent().parent().parent(); + form.submit(); +} + +function initPoll(id) { + let form = $(`#wall-post-input${id}`).parent(); + + let mBody = ` +
+ +
+ +
+
+
+
+ +
${tr("poll_editor_tips")}
+
+ `; + + MessageBox(tr("create_poll"), mBody, [tr("attach"), tr("cancel")], [ + function() { + let dialog = $(this.$dialog().nodes[0]); + $("input", dialog).unbind(); + + let title = $("input[name=title]", dialog).val(); + let anon = $("input[name=anon]", dialog).prop("checked") ? "yes" : "no"; + let multi = $("input[name=multi]", dialog).prop("checked") ? "yes" : "no"; + let lock = $("input[name=locked]", dialog).prop("checked") ? "yes" : "no"; + let expires = "infinite"; + if($("input[name=expires]", dialog).prop("checked")) + expires = $("select[name=expires_in]", dialog).val(); + + let options = ""; + $(".poll-option", dialog).each(function() { + if($(this).val().length === 0) + return; + + options += ``; + }); + + let xml = ` + + ${options} + + `; + $("input[name=poll]", form).val(xml); + $(".post-has-poll", form).show(); + console.log(xml); + }, + function() { + $("input", $(this.$dialog().nodes[0])).unbind(); + } + ]); + + let editor = $(`#poll_editor${id}`); + $("input[name=newOption]", editor).bind("focus", function() { + let newOption = $(''); + newOption.appendTo($(".poll-options", editor)); + newOption.focus(); + newOption.bind("keydown", function(e) { + if(e.key === "Enter" && $(this).next().length === 0) { + $("input[name=newOption]", editor).focus(); + return; + } + + if($(this).val().length > 0) + return; + + if(e.key !== "Backspace") + return; + + if($(this).siblings().length === 0) + return; + + if($(this).prev().length === 0) + $(this).next().focus(); + else + $(this).prev().focus(); + + e.preventDefault(); + $(this).unbind("keydown"); + $(this).remove(); + }); + }); +} \ No newline at end of file diff --git a/install/sqls/00034-polls.sql b/install/sqls/00034-polls.sql new file mode 100644 index 00000000..8122549b --- /dev/null +++ b/install/sqls/00034-polls.sql @@ -0,0 +1,32 @@ +CREATE TABLE IF NOT EXISTS `polls` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `owner` bigint unsigned NOT NULL, + `title` text NOT NULL, + `allows_multiple` bit(1) NOT NULL DEFAULT b'0', + `is_anonymous` bit(1) NOT NULL DEFAULT b'0', + `can_revote` bit(1) NOT NULL DEFAULT b'0', + `until` bigint unsigned DEFAULT NULL, + `ended` bit(1) NOT NULL DEFAULT b'0', + `deleted` bit(1) NOT NULL DEFAULT b'0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci; + +CREATE TABLE IF NOT EXISTS `poll_options` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `poll` bigint unsigned NOT NULL, + `name` varchar(512) NOT NULL, + PRIMARY KEY (`id`), + KEY `poll` (`poll`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci; + +CREATE TABLE IF NOT EXISTS `poll_votes` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `user` bigint unsigned NOT NULL, + `poll` bigint unsigned NOT NULL, + `option` bigint unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `user_option` (`user`,`option`), + KEY `option` (`option`), + KEY `poll` (`poll`), + KEY `user_poll` (`user`,`poll`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci; diff --git a/locales/en.strings b/locales/en.strings index f49cc3b2..7ccedb95 100644 --- a/locales/en.strings +++ b/locales/en.strings @@ -876,6 +876,38 @@ "messages_error_1" = "Message not delivered"; "messages_error_1_description" = "There was a general error in sending this message..."; +/* Polls */ +"poll" = "Poll"; +"create_poll" = "Create poll"; +"poll_title" = "Ask a question"; +"poll_add_option" = "Add an option..."; +"poll_anonymous" = "Anonymous votes"; +"poll_multiple" = "Multiple answers"; +"poll_locked" = "Quiz mode (no retraction)"; +"poll_edit_expires" = "Expires in: "; +"poll_edit_expires_days" = "days"; +"poll_editor_tips" = "Pressing backspace in empty option will remove it. Use Tab/Enter (in last option) to create new options faster."; +"poll_embed" = "Embed code"; + +"poll_voter_count_zero" = "Be the first one to vote!"; +"poll_voter_count_one" = "Only one user voted."; +"poll_voter_count_few" = "$1 users voted."; +"poll_voter_count_many" = "$1 users voted."; +"poll_voter_count_other" = "$1 users voted."; + +"poll_voters_list" = "Voters"; + +"poll_anon" = "Anonymous"; +"poll_public" = "Public"; +"poll_multi" = "multiple choice"; +"poll_lock" = "can't revoke"; +"poll_until" = "until $1"; + +"poll_err_to_much_options" = "Too much options supplied."; +"poll_err_anonymous" = "Can't access voters list: poll is anonymous."; +"cast_vote" = "Vote!"; +"retract_vote" = "Cancel my vote"; + /* Discussions */ "discussions" = "Discussions"; diff --git a/locales/ru.strings b/locales/ru.strings index af599abb..eceadc43 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -920,6 +920,38 @@ "messages_error_1" = "Сообщение не доставлено"; "messages_error_1_description" = "При отправке этого сообщения произошла ошибка общего характера..."; +/* Polls */ +"poll" = "Опрос"; +"create_poll" = "Новый опрос"; +"poll_title" = "Тема опроса"; +"poll_add_option" = "Добавить вариант ответа"; +"poll_anonymous" = "Анонимный опрос"; +"poll_multiple" = "Множественный выбор"; +"poll_locked" = "Запретить отменять свой голос"; +"poll_edit_expires" = "Голосование истекает через: "; +"poll_edit_expires_days" = "дней"; +"poll_editor_tips" = "Нажатие Backspace в пустом варианте приводит к его удалению. Tab/Enter в последнем добавляет новый."; +"poll_embed" = "Получить код"; + +"poll_voter_count_zero" = "Будьте первым, кто проголосует!"; +"poll_voter_count_one" = "В опросе проголосовал один человек."; +"poll_voter_count_few" = "В опросе проголосовало $1 человека."; +"poll_voter_count_many" = "В опросе проголосовало $1 человек."; +"poll_voter_count_other" = "В опросе проголосовало $1 человек."; + +"poll_voters_list" = "Список проголосовавших"; + +"poll_anon" = "Анонимное голосование"; +"poll_public" = "Публичное голосование"; +"poll_multi" = "много вариантов"; +"poll_lock" = "нельзя переголосовать"; +"poll_until" = "до $1"; + +"poll_err_to_much_options" = "Слишком много вариантов в опросе."; +"poll_err_anonymous" = "Невозможно просмотреть список проголосовавших в анонимном голосовании."; +"cast_vote" = "Проголосовать"; +"retract_vote" = "Отменить голос"; + /* Discussions */ "discussions" = "Обсуждения"; diff --git a/quirks.yml b/quirks.yml index c7967fc8..8a1b7878 100644 --- a/quirks.yml +++ b/quirks.yml @@ -44,3 +44,5 @@ comments.allow-graffiti: 0 # + Set this option to -1 if you want to disable the limit # + Set this option to any non-negative number to be this limit wall.repost-liking-recursion-limit: 10 + +polls.max-opts: 10 \ No newline at end of file From 5203229e9e1c66ec36aaa3daafd1c46856bb0b92 Mon Sep 17 00:00:00 2001 From: celestora Date: Tue, 11 Oct 2022 19:34:28 +0300 Subject: [PATCH 037/285] Fix pelmeni moment --- Web/Models/Entities/Poll.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Web/Models/Entities/Poll.php b/Web/Models/Entities/Poll.php index 43a97074..ccb4d3b2 100644 --- a/Web/Models/Entities/Poll.php +++ b/Web/Models/Entities/Poll.php @@ -103,7 +103,7 @@ class Poll extends Attachable $option->name = $title; $option->votes = $this->getVoterCount($id); - $option->pct = $result->totalVotes == 0 ? 0 : (($option->votes / $result->totalVotes) * 100); + $option->pct = $result->totalVotes == 0 ? 0 : min(100, floor(($option->votes / $result->totalVotes) * 100)); $option->voters = $this->getVoters($id, 1, 10); if(!$user || !$voted) $option->voted = NULL; @@ -292,4 +292,4 @@ class Poll extends Attachable ]); } } -} \ No newline at end of file +} From 0e22d1866f57757efa0beee0259827602ee51223 Mon Sep 17 00:00:00 2001 From: celestora Date: Tue, 11 Oct 2022 20:24:34 +0300 Subject: [PATCH 038/285] Fix certain poll functions Polls can now be set to quiz mode correctly, weird characters in options no longer crash OpenVK --- Web/Models/Entities/Poll.php | 6 +++--- Web/Util/DateTime.php | 6 ++---- Web/static/js/al_polls.js | 9 ++++++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Web/Models/Entities/Poll.php b/Web/Models/Entities/Poll.php index ccb4d3b2..6f2885b1 100644 --- a/Web/Models/Entities/Poll.php +++ b/Web/Models/Entities/Poll.php @@ -236,7 +236,7 @@ class Poll extends Attachable if(!is_null($this->getRecord())) throw new PollLockedException; - $this->stateChanges("can_revote", true); + $this->stateChanges("can_revote", $canReVote); } function setAnonymity(bool $anonymous): void @@ -256,8 +256,8 @@ class Poll extends Attachable $this->setTitle($xml["title"] ?? "Untitled"); $this->setMultipleChoice(($xml["multiple"] ?? "no") == "yes"); $this->setAnonymity(($xml["anonymous"] ?? "no") == "yes"); - $this->setRevotability(($xml["locked"] ?? "no") == "yes"); - if(ctype_digit($xml["duration"] ?? "")) + $this->setRevotability(($xml["locked"] ?? "no") == "no"); + if(ctype_digit((string) ($xml["duration"] ?? ""))) $this->setEndDate(time() + ((86400 * (int) $xml["duration"]))); $options = []; diff --git a/Web/Util/DateTime.php b/Web/Util/DateTime.php index 464f10c9..a7d68084 100644 --- a/Web/Util/DateTime.php +++ b/Web/Util/DateTime.php @@ -21,7 +21,8 @@ class DateTime $then = date_create("@" . $this->timestamp); $now = date_create(); $diff = date_diff($now, $then); - if($diff->invert === 0) return __OPENVK_ERROR_CLOCK_IN_FUTURE; + if($diff->invert === 0) + return ovk_strftime_safe("%e %B %Y ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp); if($this->timestamp >= strtotime("midnight")) { # Today if($diff->h >= 1) @@ -52,13 +53,10 @@ class DateTime switch($type) { case static::RELATIVE_FORMAT_NORMAL: return mb_convert_case($this->zmdate(), MB_CASE_TITLE_SIMPLE); - break; case static::RELATIVE_FORMAT_LOWER: return $this->zmdate(); - break; case static::RELATIVE_FORMAT_SHORT: return ""; - break; } } diff --git a/Web/static/js/al_polls.js b/Web/static/js/al_polls.js index 14588e04..7e1c81cd 100644 --- a/Web/static/js/al_polls.js +++ b/Web/static/js/al_polls.js @@ -1,3 +1,7 @@ +function escapeXML(text) { + return $("").text(text).html(); +} + async function pollRetractVote(id) { let poll = $(`.poll[data-id=${id}]`); @@ -72,7 +76,7 @@ function initPoll(id) {


-