diff --git a/.github/workflows/codeberg-mirror.yml b/.github/workflows/codeberg-mirror.yml index c3f762b4..7d4049dc 100644 --- a/.github/workflows/codeberg-mirror.yml +++ b/.github/workflows/codeberg-mirror.yml @@ -1,8 +1,6 @@ name: Codeberg Mirroring -on: - push: - branches: ["master"] +on: push jobs: to_codeberg: @@ -14,4 +12,4 @@ jobs: - uses: pixta-dev/repository-mirroring-action@v1 with: target_repo_url: "git@codeberg.org:openvk/openvk.git" - ssh_private_key: ${{ secrets.CODEBERG_PRIVSSH }} + ssh_private_key: ${{ secrets.CODEBERG_MIRRORSSH }} diff --git a/.gitignore b/.gitignore index 41e799c7..78f62184 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ themepacks/* !themepacks/midnight storage/* !storage/.gitkeep + +.idea \ No newline at end of file diff --git a/README.md b/README.md index ccaed853..5659e11a 100644 --- a/README.md +++ b/README.md @@ -2,29 +2,25 @@ _[Русский](README_RU.md)_ -**OpenVK** is an attempt to create a simple CMS that ~~cosplays~~ imitates old VK. Code provided here is not stable yet. +**OpenVK** is an attempt to create a simple CMS that ~~cosplays~~ imitates old VKontakte. Code provided here is not stable yet. VKontakte belongs to Pavel Durov and VK Group. -To be honest, we don't know whether it even works. However, this version is maintained and we will be happy to accept your bugreports [in our bug-tracker](https://github.com/openvk/openvk/projects/1). You should also be able to submit them using [ticketing system](https://openvk.su/support?act=new) (you will need an OVK account for this). +To be honest, we don't know whether if it even works. However, this version is maintained and we will be happy to accept your bugreports [in our bug tracker](https://github.com/openvk/openvk/projects/1). You should also be able to submit them using [ticketing system](https://openvk.su/support?act=new) (you will need an OpenVK account for this). ## When's the release? -We will release OpenVK as soon as it's ready. As for now you can: +We will release OpenVK as soon as it's ready. As for now, you can: * `git clone` this repo's master branch (use `git pull` to update) * Grab a prebuilt OpenVK distro from [GitHub artifacts](https://nightly.link/openvk/archive/workflows/nightly/master/OpenVK%20Archive.zip) ## Instances -* **[openvk.su](https://openvk.su/)** -* **[openvk.uk](https://openvk.uk)** - official mirror of openvk.su () -* **[openvk.co](http://openvk.co)** - yet another official mirror of openvk.su without TLS () -* [social.fetbuk.ru](http://social.fetbuk.ru/) -* [vepurovk.xyz](http://vepurovk.xyz/) +A list of instances can be found in [our wiki of this repository](https://github.com/openvk/openvk/wiki/Instances). ## Can I create my own OpenVK instance? -Yes! And you're very welcome to. +Yes! And you are very welcome to. However, OVK makes use of Chandler Application Server. This software requires extensions, that may not be provided by your hosting provider (namely, sodium and yaml. these extensions are available on most of ISPManager hostings). @@ -34,12 +30,12 @@ If you want, you can add your instance to the list above so that people can regi 1. Install PHP 7.4, web-server, Composer, Node.js, Yarn and [Chandler](https://github.com/openvk/chandler) -* PHP 8.1 is supported, but it was not tested carefully, be aware of that. +* PHP 8.1 is supported too, however it was not tested carefully, so be aware. 2. Install MySQL-compatible database. -* We recommend using Percona Server, but any MySQL-compatible server should work -* Server should be compatible with at least MySQL 5.6, MySQL 8.0+ recommended. +* We recommend using Percona Server, but any MySQL-compatible server should work too. +* Server should be compatible with at least MySQL 5.6, MySQL 8.0+ is recommended. * Support for MySQL 4.1+ is WIP, replace `utf8mb4` and `utf8mb4_unicode_520_ci` with `utf8` and `utf8_unicode_ci` in SQLs. 3. Install [commitcaptcha](https://github.com/openvk/commitcaptcha) and OpenVK as Chandler extensions like this: @@ -77,20 +73,20 @@ See `install/automated/docker/README.md` and `install/automated/kubernetes/READM ### If my website uses OpenVK, should I release it's sources? -It depends. You can keep the sources to yourself if you do not plan to distribute your website binaries. If your website software must be distributed, it can stay non-OSS provided the OpenVK is not used as a primary application and is not modified. If you modified OpenVK for your needs or your work is based on it and you're planning to redistribute this, then you should license it under terms of any LGPL-compatible license (like OSL, GPL, LGPL etc). +It depends. You can keep the sources to yourself if you do not plan to distribute your website binaries. If your website software must be distributed, it can stay non-OSS provided the OpenVK is not used as a primary application and is not modified. If you modified OpenVK for your needs or your work is based on it and you are planning to redistribute this, then you should license it under terms of any LGPL-compatible license (like OSL, GPL, LGPL etc). ## Where can I get assistance? You may reach out to us via: -* [Bug-tracker](https://github.com/openvk/openvk/projects/1) -* [Ticketing system](https://openvk.su/support?act=new) -* Telegram chat: Go to [our channel](https://t.me/openvkenglish) and open discussion in our channel menu. +* [Bug Tracker](https://github.com/openvk/openvk/projects/1) +* [Ticketing System](https://openvk.su/support?act=new) +* Telegram Chat: Go to [our channel](https://t.me/openvkenglish) and open discussion in our channel menu. * [Reddit](https://www.reddit.com/r/openvk/) -* [Discussions](https://github.com/openvk/openvk/discussions) -* Matrix chat: #openvk:matrix.org +* [GitHub Discussions](https://github.com/openvk/openvk/discussions) +* Matrix Chat: #openvk:matrix.org -**Attention**: bug tracker, board, telegram and matrix chat are public places. And ticketing system is being served by volunteers. If you need to report something, that shouldn't be immediately disclosed to general public (for instance, vulnerability report), please use contact us directly at this email: **openvk [at] tutanota [dot] com** +**Attention**: bug tracker, board, Telegram and Matrix chat are public places, ticketing system is being served by volunteers. If you need to report something that should not be immediately disclosed to general public (for instance, a vulnerability), please contact us directly via this email: **openvk [at] tutanota [dot] com** Get it on Codeberg diff --git a/README_RU.md b/README_RU.md index c30a6cf7..5af66e66 100644 --- a/README_RU.md +++ b/README_RU.md @@ -2,11 +2,11 @@ _[English](README.md)_ -**OpenVK** - это попытка создать простую CMS, которая ~~косплеит~~ имитирует старый ВКонтакте. На данный момент представленный здесь исходный код проекта пока не является стабильным. +**OpenVK** — это попытка создать простую CMS, которая ~~косплеит~~ имитирует старый ВКонтакте. На данный момент, представленный здесь исходный код проекта пока не является стабильным. ВКонтакте принадлежит Павлу Дурову и VK Group. -Честно говоря, мы даже не знаем, работает ли она вообще. Однако, эта версия поддерживается, и мы будем рады принять ваши сообщения об ошибках [в нашем баг-трекере](https://github.com/openvk/openvk/projects/1). Вы также можете отправлять их через [вкладку "Помощь"](https://openvk.su/support?act=new) (для этого вам понадобится учетная запись OVK). +Честно говоря, мы даже не знаем, работает ли она вообще. Однако, эта версия поддерживается, и мы будем рады принять ваши сообщения об ошибках [в нашем баг-трекере](https://github.com/openvk/openvk/projects/1). Вы также можете отправлять их через [вкладку "Помощь"](https://openvk.su/support?act=new) (для этого вам понадобится учетная запись OpenVK). ## Когда выйдет релизная версия? @@ -16,19 +16,15 @@ _[English](README.md)_ ## Инстанции -* **[openvk.su](https://openvk.su/)** -* **[openvk.uk](https://openvk.uk)** - официальное зеркало openvk.su () -* **[openvk.co](http://openvk.co)** - ещё одно официальное зеркало openvk.su без TLS () -* [social.fetbuk.ru](http://social.fetbuk.ru/) -* [vepurovk.xyz](http://vepurovk.xyz/) +Список инстанций находится в [нашей вики этого репозитория](https://github.com/openvk/openvk/wiki/Instances-(RU)). ## Могу ли я создать свою собственную инстанцию OpenVK? Да! И всегда пожалуйста. -Однако, OVK использует Chandler Application Server. Это программное обеспечение требует расширений, которые могут быть не предоставлены вашим хостинг-провайдером (а именно, sodium и yaml. эти расширения доступны на большинстве хостингов ISPManager). +Однако, OpenVK использует Chandler Application Server. Это программное обеспечение требует расширений, которые могут быть не предоставлены вашим хостинг-провайдером (а именно, sodium и yaml. Эти расширения доступны на большинстве хостингов ISPManager). -Если вы хотите, вы можете добавить вашу инстанцию в список выше, чтобы люди могли зарегистрироваться там. +Если хотите, вы можете добавить вашу инстанцию в список выше, чтобы люди могли зарегистрироваться там. ### Процедура установки @@ -38,7 +34,7 @@ _[English](README.md)_ 2. Установите MySQL-совместимую базу данных. -* Мы рекомендуем использовать Persona Server, но любая MySQL-совместимая база данных должна работать +* Мы рекомендуем использовать Persona Server, но любая MySQL-совместимая база данных должна работать. * Сервер должен поддерживать хотя бы MySQL 5.6, рекомендуется использовать MySQL 8.0+. * Поддержка для MySQL 4.1+ находится в процессе, а пока замените `utf8mb4` и `utf8mb4_unicode_520_ci` на `utf8` и `utf8_unicode_ci` в SQL-файлах, соответственно. @@ -87,10 +83,10 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions * [Помощь в OVK](https://openvk.su/support?act=new) * Telegram-чат: Перейдите на [наш канал](https://t.me/openvk) и откройте обсуждение в меню нашего канала. * [Reddit](https://www.reddit.com/r/openvk/) -* [Обсуждения](https://github.com/openvk/openvk/discussions) +* [GitHub Discussions](https://github.com/openvk/openvk/discussions) * Чат в Matrix: #ovk:matrix.org -**Внимание**: баг-трекер, форум, телеграм- и matrix-чат являются публичными местами, и жалобы в OVK обслуживается волонтерами. Если вам нужно сообщить о чем-то, что не должно быть раскрыто широкой публике (например, сообщение об уязвимости), пожалуйста, свяжитесь с нами напрямую по этому адресу: **openvk [собака] tutanota [точка] com**. +**Внимание**: баг-трекер, форум, Telegram- и Matrix-чат являются публичными местами, и жалобы в OVK обслуживается волонтерами. Если вам нужно сообщить о чем-то, что не должно быть раскрыто широкой публике (например, сообщение об уязвимости), пожалуйста, свяжитесь с нами напрямую по этому адресу: **openvk [собачка] tutanota [точка] com**. Get it on Codeberg diff --git a/VKAPI/Handlers/Account.php b/VKAPI/Handlers/Account.php index 4b97a266..dd6cfa7b 100644 --- a/VKAPI/Handlers/Account.php +++ b/VKAPI/Handlers/Account.php @@ -45,14 +45,12 @@ final class Account extends VKAPIRequestHandler { $this->requireUser(); - $this->getUser()->setOnline(time()); - $this->getUser()->setClient_name($this->getPlatform()); - $this->getUser()->save(); + $this->getUser()->updOnline($this->getPlatform()); return 1; } - function setOffline(): object + function setOffline(): int { $this->requireUser(); @@ -80,6 +78,8 @@ final class Account extends VKAPIRequestHandler function saveProfileInfo(string $first_name = "", string $last_name = "", string $screen_name = "", int $sex = -1, int $relation = -1, string $bdate = "", int $bdate_visibility = -1, string $home_town = "", string $status = ""): object { $this->requireUser(); + $this->willExecuteWriteAction(); + $user = $this->getUser(); $output = [ diff --git a/VKAPI/Handlers/Friends.php b/VKAPI/Handlers/Friends.php index 5040674c..f7873520 100644 --- a/VKAPI/Handlers/Friends.php +++ b/VKAPI/Handlers/Friends.php @@ -66,6 +66,7 @@ final class Friends extends VKAPIRequestHandler function add(string $user_id): int { $this->requireUser(); + $this->willExecuteWriteAction(); $users = new UsersRepo; $user = $users->get(intval($user_id)); @@ -96,6 +97,7 @@ final class Friends extends VKAPIRequestHandler function delete(string $user_id): int { $this->requireUser(); + $this->willExecuteWriteAction(); $users = new UsersRepo; @@ -152,10 +154,7 @@ final class Friends extends VKAPIRequestHandler $response = $followers; $usersApi = new Users($this->getUser()); - if($extended == 1) - $response = $usersApi->get(implode(',', $followers), $fields, 0, $count); - else - $response = $usersApi->get(implode(',', $followers), "", 0, $count); + $response = $usersApi->get(implode(',', $followers), $fields, 0, $count); foreach($response as $user) $user->user_id = $user->id; diff --git a/VKAPI/Handlers/Groups.php b/VKAPI/Handlers/Groups.php index 0150a56a..071ded81 100644 --- a/VKAPI/Handlers/Groups.php +++ b/VKAPI/Handlers/Groups.php @@ -237,6 +237,7 @@ final class Groups extends VKAPIRequestHandler function join(int $group_id) { $this->requireUser(); + $this->willExecuteWriteAction(); $club = (new ClubsRepo)->get($group_id); @@ -251,6 +252,7 @@ final class Groups extends VKAPIRequestHandler function leave(int $group_id) { $this->requireUser(); + $this->willExecuteWriteAction(); $club = (new ClubsRepo)->get($group_id); diff --git a/VKAPI/Handlers/Likes.php b/VKAPI/Handlers/Likes.php index 38a76893..644646e5 100644 --- a/VKAPI/Handlers/Likes.php +++ b/VKAPI/Handlers/Likes.php @@ -8,6 +8,7 @@ final class Likes extends VKAPIRequestHandler function add(string $type, int $owner_id, int $item_id): object { $this->requireUser(); + $this->willExecuteWriteAction(); switch($type) { case "post": @@ -28,6 +29,7 @@ final class Likes extends VKAPIRequestHandler function delete(string $type, int $owner_id, int $item_id): object { $this->requireUser(); + $this->willExecuteWriteAction(); switch($type) { case "post": diff --git a/VKAPI/Handlers/Messages.php b/VKAPI/Handlers/Messages.php index af7dcdcd..bc9035f5 100644 --- a/VKAPI/Handlers/Messages.php +++ b/VKAPI/Handlers/Messages.php @@ -65,10 +65,16 @@ final class Messages extends VKAPIRequestHandler ]; } - function send(int $user_id = -1, int $peer_id = -1, string $domain = "", int $chat_id = -1, string $user_ids = "", string $message = "", int $sticker_id = -1) + function send(int $user_id = -1, int $peer_id = -1, string $domain = "", int $chat_id = -1, string $user_ids = "", string $message = "", int $sticker_id = -1, int $forGodSakePleaseDoNotReportAboutMyOnlineActivity = 0) { $this->requireUser(); - + $this->willExecuteWriteAction(); + + if($forGodSakePleaseDoNotReportAboutMyOnlineActivity == 0) + { + $this->getUser()->updOnline($this->getPlatform()); + } + if($chat_id !== -1) $this->fail(946, "Chats are not implemented"); else if($sticker_id !== -1) @@ -117,6 +123,7 @@ final class Messages extends VKAPIRequestHandler function delete(string $message_ids, int $spam = 0, int $delete_for_all = 0): object { $this->requireUser(); + $this->willExecuteWriteAction(); $msgs = new MSGRepo; $ids = preg_split("%, ?%", $message_ids); @@ -136,6 +143,7 @@ final class Messages extends VKAPIRequestHandler function restore(int $message_id): int { $this->requireUser(); + $this->willExecuteWriteAction(); $msg = (new MSGRepo)->get($message_id); if(!$msg) diff --git a/VKAPI/Handlers/Newsfeed.php b/VKAPI/Handlers/Newsfeed.php index 5451f449..16bd3123 100644 --- a/VKAPI/Handlers/Newsfeed.php +++ b/VKAPI/Handlers/Newsfeed.php @@ -7,9 +7,14 @@ use openvk\VKAPI\Handlers\Wall; final class Newsfeed extends VKAPIRequestHandler { - function get(string $fields = "", int $start_from = 0, int $offset = 0, int $count = 30, int $extended = 0) + function get(string $fields = "", int $start_from = 0, int $offset = 0, int $count = 30, int $extended = 0, int $forGodSakePleaseDoNotReportAboutMyOnlineActivity = 0) { $this->requireUser(); + + if($forGodSakePleaseDoNotReportAboutMyOnlineActivity == 0) + { + $this->getUser()->updOnline($this->getPlatform()); + } $id = $this->getUser()->getId(); $subs = DatabaseConnection::i() diff --git a/VKAPI/Handlers/Polls.php b/VKAPI/Handlers/Polls.php index 1c20edd4..9036a02c 100755 --- a/VKAPI/Handlers/Polls.php +++ b/VKAPI/Handlers/Polls.php @@ -66,6 +66,7 @@ final class Polls extends VKAPIRequestHandler function addVote(int $poll_id, string $answers_ids) { $this->requireUser(); + $this->willExecuteWriteAction(); $poll = (new PollsRepo)->get($poll_id); @@ -87,6 +88,7 @@ final class Polls extends VKAPIRequestHandler function deleteVote(int $poll_id) { $this->requireUser(); + $this->willExecuteWriteAction(); $poll = (new PollsRepo)->get($poll_id); diff --git a/VKAPI/Handlers/VKAPIRequestHandler.php b/VKAPI/Handlers/VKAPIRequestHandler.php index e9413c12..d2fcfc74 100644 --- a/VKAPI/Handlers/VKAPIRequestHandler.php +++ b/VKAPI/Handlers/VKAPIRequestHandler.php @@ -1,7 +1,9 @@ userAuthorized()) $this->fail(5, "User authorization failed: no access_token passed."); } + + protected function willExecuteWriteAction(): void + { + $ip = (new IPs)->get(CONNECTING_IP); + $res = $ip->rateLimit(); + + if(!($res === IP::RL_RESET || $res === IP::RL_CANEXEC)) { + if($res === IP::RL_BANNED && OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["rateLimits"]["autoban"]) { + $this->user->ban("User account has been suspended for breaking API terms of service", false); + $this->fail(18, "User account has been suspended due to repeated violation of API rate limits."); + } + + $this->fail(29, "You have been rate limited."); + } + } } diff --git a/VKAPI/Handlers/Video.php b/VKAPI/Handlers/Video.php new file mode 100755 index 00000000..740ccd54 --- /dev/null +++ b/VKAPI/Handlers/Video.php @@ -0,0 +1,57 @@ +requireUser(); + + if ($videos) { + $vids = explode(',', $videos); + + foreach($vids as $vid) + { + $id = explode("_", $vid); + + $items = []; + + $video = (new VideosRepo)->getByOwnerAndVID(intval($id[0]), intval($id[1])); + if($video) { + $items[] = $video->getApiStructure(); + } + } + + return (object) [ + "count" => count($items), + "items" => $items + ]; + } else { + if ($owner_id > 0) + $user = (new UsersRepo)->get($owner_id); + else + $this->fail(1, "Not implemented"); + + $videos = (new VideosRepo)->getByUser($user, $offset + 1, $count); + $videosCount = (new VideosRepo)->getUserVideosCount($user); + + $items = []; + foreach ($videos as $video) { + $items[] = $video->getApiStructure(); + } + + return (object) [ + "count" => $videosCount, + "items" => $items + ]; + } + } +} diff --git a/VKAPI/Handlers/Wall.php b/VKAPI/Handlers/Wall.php index 5ceb7ef8..26b927ea 100644 --- a/VKAPI/Handlers/Wall.php +++ b/VKAPI/Handlers/Wall.php @@ -48,6 +48,8 @@ final class Wall extends VKAPIRequestHandler $attachments[] = $this->getApiPhoto($attachment); } else if($attachment instanceof \openvk\Web\Models\Entities\Poll) { $attachments[] = $this->getApiPoll($attachment, $this->getUser()); + } else if ($attachment instanceof \openvk\Web\Models\Entities\Video) { + $attachments[] = $attachment->getApiStructure(); } else if ($attachment instanceof \openvk\Web\Models\Entities\Post) { $repostAttachments = []; @@ -216,6 +218,8 @@ final class Wall extends VKAPIRequestHandler $attachments[] = $this->getApiPhoto($attachment); } else if($attachment instanceof \openvk\Web\Models\Entities\Poll) { $attachments[] = $this->getApiPoll($attachment, $user); + } else if ($attachment instanceof \openvk\Web\Models\Entities\Video) { + $attachments[] = $attachment->getApiStructure(); } else if ($attachment instanceof \openvk\Web\Models\Entities\Post) { $repostAttachments = []; @@ -362,6 +366,7 @@ final class Wall extends VKAPIRequestHandler function post(string $owner_id, string $message = "", int $from_group = 0, int $signed = 0): object { $this->requireUser(); + $this->willExecuteWriteAction(); $owner_id = intval($owner_id); @@ -446,6 +451,7 @@ final class Wall extends VKAPIRequestHandler function repost(string $object, string $message = "") { $this->requireUser(); + $this->willExecuteWriteAction(); $postArray; if(preg_match('/wall((?:-?)[0-9]+)_([0-9]+)/', $object, $postArray) == 0) @@ -489,6 +495,14 @@ final class Wall extends VKAPIRequestHandler $oid = $owner->getId(); if($owner instanceof Club) $oid *= -1; + + $attachments = []; + + foreach($comment->getChildren() as $attachment) { + if($attachment instanceof \openvk\Web\Models\Entities\Photo) { + $attachments[] = $this->getApiPhoto($attachment); + } + } $item = [ "id" => $comment->getId(), @@ -498,6 +512,7 @@ final class Wall extends VKAPIRequestHandler "post_id" => $post->getVirtualId(), "owner_id" => $post->isPostedOnBehalfOfGroup() ? $post->getOwner()->getId() * -1 : $post->getOwner()->getId(), "parents_stack" => [], + "attachments" => $attachments, "thread" => [ "count" => 0, "items" => [], @@ -518,6 +533,9 @@ final class Wall extends VKAPIRequestHandler $items[] = $item; if($extended == true) $profiles[] = $comment->getOwner()->getId(); + + $attachments = null; + // Reset $attachments to not duplicate prikols } $response = [ @@ -544,6 +562,14 @@ final class Wall extends VKAPIRequestHandler $profiles = []; + $attachments = []; + + foreach($comment->getChildren() as $attachment) { + if($attachment instanceof \openvk\Web\Models\Entities\Photo) { + $attachments[] = $this->getApiPhoto($attachment); + } + } + $item = [ "id" => $comment->getId(), "from_id" => $comment->getOwner()->getId(), @@ -552,6 +578,7 @@ final class Wall extends VKAPIRequestHandler "post_id" => $comment->getTarget()->getVirtualId(), "owner_id" => $comment->getTarget()->isPostedOnBehalfOfGroup() ? $comment->getTarget()->getOwner()->getId() * -1 : $comment->getTarget()->getOwner()->getId(), "parents_stack" => [], + "attachments" => $attachments, "likes" => [ "can_like" => 1, "count" => $comment->getLikesCount(), @@ -582,10 +609,15 @@ final class Wall extends VKAPIRequestHandler $response['profiles'] = (!empty($profiles) ? (new Users)->get(implode(',', $profiles), $fields) : []); } + + return $response; } function createComment(int $owner_id, int $post_id, string $message, int $from_group = 0) { + $this->requireUser(); + $this->willExecuteWriteAction(); + $post = (new PostsRepo)->getPostById($owner_id, $post_id); if(!$post || $post->isDeleted()) $this->fail(100, "One of the parameters specified was missing or invalid"); @@ -621,6 +653,7 @@ final class Wall extends VKAPIRequestHandler function deleteComment(int $comment_id) { $this->requireUser(); + $this->willExecuteWriteAction(); $comment = (new CommentsRepo)->get($comment_id); if(!$comment) $this->fail(100, "One of the parameters specified was missing or invalid");; @@ -640,7 +673,7 @@ final class Wall extends VKAPIRequestHandler "date" => $attachment->getPublicationTime()->timestamp(), "id" => $attachment->getVirtualId(), "owner_id" => $attachment->getOwner()->getId(), - "sizes" => array_values($attachment->getVkApiSizes()), + "sizes" => !is_null($attachment->getVkApiSizes()) ? array_values($attachment->getVkApiSizes()) : NULL, "text" => "", "has_tags" => false ] diff --git a/Web/Models/Entities/Photo.php b/Web/Models/Entities/Photo.php index 4fd49c57..3c4db886 100644 --- a/Web/Models/Entities/Photo.php +++ b/Web/Models/Entities/Photo.php @@ -283,6 +283,14 @@ class Photo extends Media return [$x, $y]; } + function getPageURL(): string + { + if($this->isAnonymous()) + return "/photos/" . base_convert((string) $this->getId(), 10, 32); + + return "/photo" . $this->getPrettyId(); + } + function getAlbum(): ?Album { return (new Albums)->getAlbumByPhotoId($this); diff --git a/Web/Models/Entities/Post.php b/Web/Models/Entities/Post.php index 7fffb3dd..8c1c6a62 100644 --- a/Web/Models/Entities/Post.php +++ b/Web/Models/Entities/Post.php @@ -119,7 +119,7 @@ class Post extends Postable $platform = $this->getRecord()->api_source_name; if($forAPI) { switch ($platform) { - case 'openvk_android': + case 'openvk_refresh_android': case 'openvk_legacy_android': return 'android'; break; diff --git a/Web/Models/Entities/Traits/TRichText.php b/Web/Models/Entities/Traits/TRichText.php index 7ea119e6..dc78a034 100644 --- a/Web/Models/Entities/Traits/TRichText.php +++ b/Web/Models/Entities/Traits/TRichText.php @@ -36,9 +36,9 @@ trait TRichText "%(([A-z]++):\/\/(\S*?\.\S*?))([\s)\[\]{},\"\'<]|\.\s|$)%", (function (array $matches): string { $href = str_replace("#", "#", $matches[1]); - $href = rawurlencode(str_replace(";", ";", $matches[1])); + $href = rawurlencode(str_replace(";", ";", $href)); $link = str_replace("#", "#", $matches[3]); - $link = str_replace(";", ";", $matches[3]); + $link = str_replace(";", ";", $link); $rel = $this->isAd() ? "sponsored" : "ugc"; return "$link" . htmlentities($matches[4]); @@ -49,7 +49,7 @@ trait TRichText private function removeZalgo(string $text): string { - return preg_replace("%[\x{0300}-\x{036F}]{3,}%Xu", "�", $text); + return preg_replace("%\p{M}{3,}%Xu", "", $text); } function resolveMentions(array $skipUsers = []): \Traversable diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php index dcdf6ef4..ed1e3e60 100644 --- a/Web/Models/Entities/User.php +++ b/Web/Models/Entities/User.php @@ -756,7 +756,7 @@ class User extends RowModel $platform = $this->getRecord()->client_name; if($forAPI) { switch ($platform) { - case 'openvk_android': + case 'openvk_refresh_android': case 'openvk_legacy_android': return 'android'; break; @@ -1009,6 +1009,15 @@ class User extends RowModel return true; } + function updOnline(string $platform): bool + { + $this->setOnline(time()); + $this->setClient_name($platform); + $this->save(); + + return true; + } + function changeEmail(string $email): void { DatabaseConnection::i()->getContext()->table("ChandlerUsers") diff --git a/Web/Models/Entities/Video.php b/Web/Models/Entities/Video.php index b45072b9..ee53b378 100644 --- a/Web/Models/Entities/Video.php +++ b/Web/Models/Entities/Video.php @@ -13,7 +13,7 @@ class Video extends Media const TYPE_EMBED = 1; protected $tableName = "videos"; - protected $fileExtension = "ogv"; + protected $fileExtension = "mp4"; protected $processingPlaceholder = "video/rendering"; @@ -30,7 +30,7 @@ class Video extends Media throw new \DomainException("$filename does not contain any video streams"); $durations = []; - preg_match('%duration=([0-9\.]++)%', $streams, $durations); + preg_match_all('%duration=([0-9\.]++)%', $streams, $durations); if(sizeof($durations[1]) === 0) throw new \DomainException("$filename does not contain any meaningful video streams"); @@ -104,7 +104,7 @@ class Video extends Media if(!$this->isProcessed()) return "/assets/packages/static/openvk/video/rendering.apng"; - return preg_replace("%\.[A-z]++$%", ".gif", $this->getURL()); + return preg_replace("%\.[A-z0-9]++$%", ".gif", $this->getURL()); } else { return $this->getVideoDriver()->getThumbnailURL(); } @@ -114,6 +114,56 @@ class Video extends Media { return $this->getRecord()->owner; } + + function getApiStructure(): object + { + return (object)[ + "type" => "video", + "video" => [ + "can_comment" => 1, + "can_like" => 0, // we don't h-have wikes in videos + "can_repost" => 0, + "can_subscribe" => 1, + "can_add_to_faves" => 0, + "can_add" => 0, + "comments" => $this->getCommentsCount(), + "date" => $this->getPublicationTime()->timestamp(), + "description" => $this->getDescription(), + "duration" => 0, // я хуй знает как получить длину видео + "image" => [ + [ + "url" => $this->getThumbnailURL(), + "width" => 320, + "height" => 240, + "with_padding" => 1 + ] + ], + "width" => 640, + "height" => 480, + "id" => $this->getVirtualId(), + "owner_id" => $this->getOwner()->getId(), + "user_id" => $this->getOwner()->getId(), + "title" => $this->getName(), + "is_favorite" => false, + "player" => $this->getURL(), + "files" => [ + "mp4_480" => $this->getURL() + ], + "added" => 0, + "repeat" => 0, + "type" => "video", + "views" => 0, + "likes" => [ + "count" => 0, + "user_likes" => 0 + ], + "reposts" => [ + "count" => 0, + "user_reposted" => 0 + ] + ] + ]; + } function setLink(string $link): string { diff --git a/Web/Models/VideoDrivers/VideoDriver.php b/Web/Models/VideoDrivers/VideoDriver.php index 141e738b..ca9fb74b 100644 --- a/Web/Models/VideoDrivers/VideoDriver.php +++ b/Web/Models/VideoDrivers/VideoDriver.php @@ -14,5 +14,5 @@ abstract class VideoDriver abstract function getURL(): string; - abstract function getEmbed(): string; + abstract function getEmbed(string $w = "600", string $h = "340"): string; } diff --git a/Web/Models/VideoDrivers/YouTubeVideoDriver.php b/Web/Models/VideoDrivers/YouTubeVideoDriver.php index 93aee0e5..1b9940e6 100644 --- a/Web/Models/VideoDrivers/YouTubeVideoDriver.php +++ b/Web/Models/VideoDrivers/YouTubeVideoDriver.php @@ -13,12 +13,12 @@ final class YouTubeVideoDriver extends VideoDriver return "https://youtu.be/$this->id"; } - function getEmbed(): string + function getEmbed(string $w = "600", string $h = "340"): string { return <<emailValid($this->postParam("email"))) $this->flashFail("err", tr("invalid_email_address"), tr("invalid_email_address_comment")); - + + if(OPENVK_ROOT_CONF['openvk']['preferences']['security']['forceStrongPassword']) + if(!Validator::i()->passwordStrong($this->postParam("password"))) + $this->flashFail("err", tr("error"), tr("error_weak_password")); + if (strtotime($this->postParam("birthday")) > time()) $this->flashFail("err", tr("invalid_birth_date"), tr("invalid_birth_date_comment")); diff --git a/Web/Presenters/MessengerPresenter.php b/Web/Presenters/MessengerPresenter.php index 46094c43..d5ffb988 100644 --- a/Web/Presenters/MessengerPresenter.php +++ b/Web/Presenters/MessengerPresenter.php @@ -57,6 +57,11 @@ final class MessengerPresenter extends OpenVKPresenter $correspondent = $this->getCorrespondent($sel); if(!$correspondent) $this->notFound(); + + if(!$this->user->identity->getPrivacyPermission('messages.write', $correspondent)) + { + $this->flash("err", tr("warning"), tr("user_may_not_reply")); + } $this->template->selId = $sel; $this->template->correspondent = $correspondent; diff --git a/Web/Presenters/VKAPIPresenter.php b/Web/Presenters/VKAPIPresenter.php index 7c8ed39f..4cf6e050 100644 --- a/Web/Presenters/VKAPIPresenter.php +++ b/Web/Presenters/VKAPIPresenter.php @@ -204,6 +204,9 @@ final class VKAPIPresenter extends OpenVKPresenter } } + if(!is_null($identity) && $identity->isBanned()) + $this->fail(18, "User account is deactivated", $object, $method); + $object = ucfirst(strtolower($object)); $handlerClass = "openvk\\VKAPI\\Handlers\\$object"; if(!class_exists($handlerClass)) diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml index 490225b6..82a4031a 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -218,8 +218,8 @@ - - {_registration}

+ +

{_forgot_password} {/ifset} @@ -294,6 +294,7 @@ {script "js/messagebox.js"} {script "js/notifications.js"} {script "js/scroll.js"} + {script "js/player.js"} {script "js/al_wall.js"} {script "js/al_api.js"} {script "js/al_mentions.js"} @@ -310,6 +311,8 @@ {/if} + +