diff --git a/ServiceAPI/Photos.php b/ServiceAPI/Photos.php deleted file mode 100644 index 16d602f2..00000000 --- a/ServiceAPI/Photos.php +++ /dev/null @@ -1,92 +0,0 @@ -user = $user; - $this->photos = new PhotosRepo; - } - - function getPhotos(int $page = 1, int $album = 0, callable $resolve, callable $reject) - { - if($album == 0) { - $photos = $this->photos->getEveryUserPhoto($this->user, $page, 24); - $count = $this->photos->getUserPhotosCount($this->user); - } else { - $album = (new Albums)->get($album); - - if(!$album || $album->isDeleted()) - $reject(55, "Invalid ."); - - if($album->getOwner() instanceof User) { - if($album->getOwner()->getId() != $this->user->getId()) - $reject(555, "Access to album denied"); - } else { - if(!$album->getOwner()->canBeModifiedBy($this->user)) - $reject(555, "Access to album denied"); - } - - $photos = $album->getPhotos($page, 24); - $count = $album->size(); - } - - $arr = [ - "count" => $count, - "items" => [], - ]; - - foreach($photos as $photo) { - $res = json_decode(json_encode($photo->toVkApiStruct()), true); - - $arr["items"][] = $res; - } - - $resolve($arr); - } - - function getAlbums(int $club, callable $resolve, callable $reject) - { - $albumsRepo = (new Albums); - - $count = $albumsRepo->getUserAlbumsCount($this->user); - $albums = $albumsRepo->getUserAlbums($this->user, 1, $count); - - $arr = [ - "count" => $count, - "items" => [], - ]; - - foreach($albums as $album) { - $res = ["id" => $album->getId(), "name" => $album->getName()]; - - $arr["items"][] = $res; - } - - if($club > 0) { - $cluber = (new Clubs)->get($club); - - if(!$cluber || !$cluber->canBeModifiedBy($this->user)) - $reject(1337, "Invalid (club), or you can't modify him"); - - $clubCount = (new Albums)->getClubAlbumsCount($cluber); - $clubAlbums = (new Albums)->getClubAlbums($cluber, 1, $clubCount); - - foreach($clubAlbums as $albumr) { - $res = ["id" => $albumr->getId(), "name" => $albumr->getName()]; - - $arr["items"][] = $res; - } - - $arr["count"] = $arr["count"] + $clubCount; - } - - $resolve($arr); - } -} diff --git a/ServiceAPI/Video.php b/ServiceAPI/Video.php deleted file mode 100644 index d0eb4ee8..00000000 --- a/ServiceAPI/Video.php +++ /dev/null @@ -1,156 +0,0 @@ -user = $user; - $this->videos = new Videos; - $this->comments = new Comments; - $this->groups = new Clubs; - } - - function getVideo(int $id, callable $resolve, callable $reject) - { - $video = $this->videos->get($id); - - if(!$video || $video->isDeleted()) { - $reject(2, "Video does not exists"); - } - - if(method_exists($video, "canBeViewedBy") && !$video->canBeViewedBy($this->user)) { - $reject(4, "Access to video denied"); - } - - if(!$video->getOwner()->getPrivacyPermission('videos.read', $this->user)) { - $reject(8, "Access to video denied: this user chose to hide his videos"); - } - - $prevVideo = NULL; - $nextVideo = NULL; - $lastVideo = $this->videos->getLastVideo($video->getOwner()); - - if($video->getVirtualId() - 1 != 0) { - for($i = $video->getVirtualId(); $i != 0; $i--) { - $maybeVideo = (new Videos)->getByOwnerAndVID($video->getOwner()->getId(), $i); - - if(!is_null($maybeVideo) && !$maybeVideo->isDeleted() && $maybeVideo->getId() != $video->getId()) { - if(method_exists($maybeVideo, "canBeViewedBy") && !$maybeVideo->canBeViewedBy($this->user)) { - continue; - } - - $prevVideo = $maybeVideo; - break; - } - } - } - - if(is_null($lastVideo) || $lastVideo->getId() == $video->getId()) { - $nextVideo = NULL; - } else { - for($i = $video->getVirtualId(); $i <= $lastVideo->getVirtualId(); $i++) { - $maybeVideo = (new Videos)->getByOwnerAndVID($video->getOwner()->getId(), $i); - - if(!is_null($maybeVideo) && !$maybeVideo->isDeleted() && $maybeVideo->getId() != $video->getId()) { - if(method_exists($maybeVideo, "canBeViewedBy") && !$maybeVideo->canBeViewedBy($this->user)) { - continue; - } - - $nextVideo = $maybeVideo; - break; - } - } - } - - $res = [ - "id" => $video->getId(), - "title" => $video->getName(), - "owner" => $video->getOwner()->getId(), - "commentsCount" => $video->getCommentsCount(), - "description" => $video->getDescription(), - "type" => $video->getType(), - "name" => $video->getOwner()->getCanonicalName(), - "pretty_id" => $video->getPrettyId(), - "virtual_id" => $video->getVirtualId(), - "published" => (string)$video->getPublicationTime(), - "likes" => $video->getLikesCount(), - "has_like" => $video->hasLikeFrom($this->user), - "author" => $video->getOwner()->getCanonicalName(), - "canBeEdited" => $video->getOwner()->getId() == $this->user->getId(), - "isProcessing" => $video->getType() == 0 && $video->getURL() == "/assets/packages/static/openvk/video/rendering.mp4", - "prevVideo" => !is_null($prevVideo) ? $prevVideo->getId() : null, - "nextVideo" => !is_null($nextVideo) ? $nextVideo->getId() : null, - ]; - - if($video->getType() == 1) { - $res["embed"] = $video->getVideoDriver()->getEmbed(); - } else { - $res["url"] = $video->getURL(); - } - - $resolve($res); - } - - function shareVideo(int $owner, int $vid, int $type, string $message, int $club, bool $signed, bool $asGroup, callable $resolve, callable $reject) - { - $video = $this->videos->getByOwnerAndVID($owner, $vid); - - if(!$video || $video->isDeleted()) { - $reject(16, "Video does not exists"); - } - - if(method_exists($video, "canBeViewedBy") && !$video->canBeViewedBy($this->user)) { - $reject(32, "Access to video denied"); - } - - if(!$video->getOwner()->getPrivacyPermission('videos.read', $this->user)) { - $reject(8, "Access to video denied: this user chose to hide his videos"); - } - - $flags = 0; - - $nPost = new Post; - $nPost->setOwner($this->user->getId()); - - if($type == 0) { - $nPost->setWall($this->user->getId()); - } else { - $club = $this->groups->get($club); - - if(!$club || $club->isDeleted() || !$club->canBeModifiedBy($this->user)) { - $reject(64, "Can't do repost to this club"); - } - - if($asGroup) - $flags |= 0b10000000; - - if($signed) - $flags |= 0b01000000; - - $nPost->setWall($club->getId() * -1); - } - - $nPost->setContent($message); - $nPost->setFlags($flags); - $nPost->save(); - - $nPost->attach($video); - - $res = [ - "id" => $nPost->getId(), - "pretty_id" => $nPost->getPrettyId(), - ]; - - $resolve($res); - } -} diff --git a/ServiceAPI/Wall.php b/ServiceAPI/Wall.php index c7a8362c..ed7251ac 100644 --- a/ServiceAPI/Wall.php +++ b/ServiceAPI/Wall.php @@ -80,67 +80,4 @@ class Wall implements Handler $resolve($post->getId()); } - - function getMyNotes(callable $resolve, callable $reject) - { - $count = $this->notes->getUserNotesCount($this->user); - $myNotes = $this->notes->getUserNotes($this->user, 1, $count); - - $arr = [ - "count" => $count, - "closed" => $this->user->getPrivacySetting("notes.read"), - "items" => [], - ]; - - foreach($myNotes as $note) { - $arr["items"][] = [ - "id" => $note->getId(), - "name" => ovk_proc_strtr($note->getName(), 30), - #"preview" => $note->getPreview() - ]; - } - - $resolve($arr); - } - - function getVideos(int $page = 1, callable $resolve, callable $reject) - { - $videos = $this->videos->getByUser($this->user, $page, 8); - $count = $this->videos->getUserVideosCount($this->user); - - $arr = [ - "count" => $count, - "items" => [], - ]; - - foreach($videos as $video) { - $res = json_decode(json_encode($video->toVkApiStruct($this->user)), true); - $res["video"]["author_name"] = $video->getOwner()->getCanonicalName(); - - $arr["items"][] = $res; - } - - $resolve($arr); - } - - function searchVideos(int $page = 1, string $query, callable $resolve, callable $reject) - { - $dbc = $this->videos->find($query); - $videos = $dbc->page($page, 8); - $count = $dbc->size(); - - $arr = [ - "count" => $count, - "items" => [], - ]; - - foreach($videos as $video) { - $res = json_decode(json_encode($video->toVkApiStruct($this->user)), true); - $res["video"]["author_name"] = $video->getOwner()->getCanonicalName(); - - $arr["items"][] = $res; - } - - $resolve($arr); - } } diff --git a/VKAPI/Handlers/Groups.php b/VKAPI/Handlers/Groups.php index f8706191..bd546c3d 100644 --- a/VKAPI/Handlers/Groups.php +++ b/VKAPI/Handlers/Groups.php @@ -11,6 +11,12 @@ final class Groups extends VKAPIRequestHandler { $this->requireUser(); + # InfoApp fix + if($filter == "admin" && ($user_id != 0 && $user_id != $this->getUser()->getId())) { + $this->fail(15, 'Access denied: filter admin is available only for current user'); + } + + $clbs = []; if($user_id == 0) { foreach($this->getUser()->getClubs($offset, $filter == "admin", $count, true) as $club) $clbs[] = $club; diff --git a/VKAPI/Handlers/Photos.php b/VKAPI/Handlers/Photos.php index d06ecde3..319ce070 100644 --- a/VKAPI/Handlers/Photos.php +++ b/VKAPI/Handlers/Photos.php @@ -427,7 +427,7 @@ final class Photos extends VKAPIRequestHandler $this->fail(15, "Access denied"); $photos = array_slice(iterator_to_array($album->getPhotos(1, $count + $offset)), $offset); - $res["count"] = sizeof($photos); + $res["count"] = $album->size(); foreach($photos as $photo) { if(!$photo || $photo->isDeleted()) continue; @@ -638,15 +638,15 @@ final class Photos extends VKAPIRequestHandler $this->fail(4, "This method doesn't works with clubs"); $user = (new UsersRepo)->get($owner_id); - if(!$user) $this->fail(4, "Invalid user"); if(!$user->getPrivacyPermission('photos.read', $this->getUser())) $this->fail(21, "This user chose to hide his albums."); - $photos = array_slice(iterator_to_array((new PhotosRepo)->getEveryUserPhoto($user, 1, $count + $offset)), $offset); + $photos = (new PhotosRepo)->getEveryUserPhoto($user, $offset, $count); $res = [ + "count" => (new PhotosRepo)->getUserPhotosCount($user), "items" => [], ]; diff --git a/VKAPI/Handlers/Video.php b/VKAPI/Handlers/Video.php index 975ce1c3..3a14f048 100755 --- a/VKAPI/Handlers/Video.php +++ b/VKAPI/Handlers/Video.php @@ -11,24 +11,55 @@ use openvk\Web\Models\Repositories\Comments as CommentsRepo; final class Video extends VKAPIRequestHandler { - function get(int $owner_id, string $videos = "", int $offset = 0, int $count = 30, int $extended = 0): object + function get(int $owner_id = 0, string $videos = "", string $fields = "", int $offset = 0, int $count = 30, int $extended = 0): object { $this->requireUser(); if(!empty($videos)) { $vids = explode(',', $videos); - - foreach($vids as $vid) - { + $profiles = []; + $groups = []; + foreach($vids as $vid) { $id = explode("_", $vid); - $items = []; $video = (new VideosRepo)->getByOwnerAndVID(intval($id[0]), intval($id[1])); - if($video) { - $items[] = $video->getApiStructure($this->getUser()); + if($video && !$video->isDeleted()) { + $out_video = $video->getApiStructure($this->getUser())->video; + $items[] = $out_video; + if($out_video['owner_id']) { + if($out_video['owner_id'] > 0) + $profiles[] = $out_video['owner_id']; + else + $groups[] = abs($out_video['owner_id']); + } } } + + if($extended == 1) { + $profiles = array_unique($profiles); + $groups = array_unique($groups); + + $profilesFormatted = []; + $groupsFormatted = []; + + foreach($profiles as $prof) { + $profile = (new UsersRepo)->get($prof); + $profilesFormatted[] = $profile->toVkApiStruct($this->getUser(), $fields); + } + + foreach($groups as $gr) { + $group = (new ClubsRepo)->get($gr); + $groupsFormatted[] = $group->toVkApiStruct($this->getUser(), $fields); + } + + return (object) [ + "count" => sizeof($items), + "items" => $items, + "profiles" => $profilesFormatted, + "groups" => $groupsFormatted, + ]; + } return (object) [ "count" => count($items), @@ -46,12 +77,46 @@ final class Video extends VKAPIRequestHandler if(!$user->getPrivacyPermission('videos.read', $this->getUser())) $this->fail(21, "This user chose to hide his videos."); - $videos = (new VideosRepo)->getByUser($user, $offset + 1, $count); + $videos = (new VideosRepo)->getByUserLimit($user, $offset, $count); $videosCount = (new VideosRepo)->getUserVideosCount($user); $items = []; - foreach ($videos as $video) { - $items[] = $video->getApiStructure($this->getUser()); + $profiles = []; + $groups = []; + foreach($videos as $video) { + $video = $video->getApiStructure($this->getUser())->video; + $items[] = $video; + if($video['owner_id']) { + if($video['owner_id'] > 0) + $profiles[] = $video['owner_id']; + else + $groups[] = abs($video['owner_id']); + } + } + + if($extended == 1) { + $profiles = array_unique($profiles); + $groups = array_unique($groups); + + $profilesFormatted = []; + $groupsFormatted = []; + + foreach($profiles as $prof) { + $profile = (new UsersRepo)->get($prof); + $profilesFormatted[] = $profile->toVkApiStruct($this->getUser(), $fields); + } + + foreach($groups as $gr) { + $group = (new ClubsRepo)->get($gr); + $groupsFormatted[] = $group->toVkApiStruct($this->getUser(), $fields); + } + + return (object) [ + "count" => $videosCount, + "items" => $items, + "profiles" => $profilesFormatted, + "groups" => $groupsFormatted, + ]; } return (object) [ diff --git a/VKAPI/Handlers/Wall.php b/VKAPI/Handlers/Wall.php index 13c42f07..f6271e69 100644 --- a/VKAPI/Handlers/Wall.php +++ b/VKAPI/Handlers/Wall.php @@ -284,12 +284,16 @@ final class Wall extends VKAPIRequestHandler foreach($psts as $pst) { $id = explode("_", $pst); - $post = (new PostsRepo)->getPostById(intval($id[0]), intval($id[1])); + $post = (new PostsRepo)->getPostById(intval($id[0]), intval($id[1]), true); if($post && !$post->isDeleted()) { if(!$post->canBeViewedBy($this->getUser())) continue; + if($post->getSuggestionType() != 0 && !$post->canBeEditedBy($this->getUser())) { + continue; + } + $from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId(); $attachments = []; $repost = []; // чел высрал семь сигарет 😳 помянем 🕯 @@ -473,7 +477,7 @@ final class Wall extends VKAPIRequestHandler ]; } - function post(string $owner_id, string $message = "", int $from_group = 0, int $signed = 0, string $attachments = "", int $post_id = 0): object + function post(string $owner_id, string $message = "", string $copyright = "", int $from_group = 0, int $signed = 0, string $attachments = "", int $post_id = 0): object { $this->requireUser(); $this->willExecuteWriteAction(); @@ -551,7 +555,17 @@ final class Wall extends VKAPIRequestHandler if($signed == 1) $flags |= 0b01000000; - if(empty($message) && empty($attachments)) + $parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'poll', 'audio']); + $final_attachments = []; + $should_be_suggested = $owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2; + foreach($parsed_attachments as $attachment) { + if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) && + !(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) { + $final_attachments[] = $attachment; + } + } + + if((empty($message) && (empty($attachments) || sizeof($final_attachments) < 1))) $this->fail(100, "Required parameter 'message' missing."); try { @@ -569,7 +583,7 @@ final class Wall extends VKAPIRequestHandler } catch(\Throwable) {} } - if($owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2) + if($should_be_suggested) $post->setSuggested(1); $post->save(); @@ -577,134 +591,70 @@ final class Wall extends VKAPIRequestHandler $this->fail(100, "One of the parameters specified was missing or invalid"); } - # TODO use parseAttachments - if(!empty($attachments)) { - $attachmentsArr = explode(",", $attachments); - # Аттачи такого вида: [тип][id владельца]_[id вложения] - # Пример: photo1_1 - - if(sizeof($attachmentsArr) > 10) - $this->fail(50, "Too many attachments"); - - preg_match_all("/poll/m", $attachments, $matches, PREG_SET_ORDER, 0); - if(sizeof($matches) > 1) - $this->fail(85, "Too many polls"); - - foreach($attachmentsArr as $attac) { - $attachmentType = NULL; - - if(str_contains($attac, "photo")) - $attachmentType = "photo"; - elseif(str_contains($attac, "video")) - $attachmentType = "video"; - elseif(str_contains($attac, "note")) - $attachmentType = "note"; - elseif(str_contains($attac, "poll")) - $attachmentType = "poll"; - elseif(str_contains($attac, "audio")) - $attachmentType = "audio"; - - else - $this->fail(205, "Unknown attachment type"); - - $attachment = str_replace($attachmentType, "", $attac); - - $attachmentOwner = (int)explode("_", $attachment)[0]; - $attachmentId = (int)end(explode("_", $attachment)); - - $attacc = NULL; - - if($attachmentType == "photo") { - $attacc = (new PhotosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId); - if(!$attacc || $attacc->isDeleted()) - $this->fail(100, "Invalid photo"); - if(!$attacc->getOwner()->getPrivacyPermission('photos.read', $this->getUser())) - $this->fail(43, "Access to photo denied"); - - $post->attach($attacc); - } elseif($attachmentType == "video") { - $attacc = (new VideosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId); - if(!$attacc || $attacc->isDeleted()) - $this->fail(100, "Video does not exists"); - if(!$attacc->getOwner()->getPrivacyPermission('videos.read', $this->getUser())) - $this->fail(43, "Access to video denied"); - - $post->attach($attacc); - } elseif($attachmentType == "note") { - $attacc = (new NotesRepo)->getNoteById($attachmentOwner, $attachmentId); - if(!$attacc || $attacc->isDeleted()) - $this->fail(100, "Note does not exist"); - if(!$attacc->getOwner()->getPrivacyPermission('notes.read', $this->getUser())) - $this->fail(11, "Access to note denied"); - - $post->attach($attacc); - } elseif($attachmentType == "poll") { - $attacc = (new PollsRepo)->get($attachmentId); - - if(!$attacc || $attacc->isDeleted()) - $this->fail(100, "Poll does not exist"); - if($attacc->getOwner()->getId() != $this->getUser()->getId()) - $this->fail(43, "You do not have access to this poll"); - - $post->attach($attacc); - } elseif($attachmentType == "audio") { - $attacc = (new AudiosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId); - if(!$attacc || $attacc->isDeleted()) - $this->fail(100, "Audio does not exist"); - - $post->attach($attacc); - } - } + foreach($final_attachments as $attachment) { + $post->attach($attachment); } if($wall > 0 && $wall !== $this->user->identity->getId()) (new WallPostNotification($wallOwner, $post, $this->user->identity))->emit(); - if($owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2) { - $suggsCount = (new PostsRepo)->getSuggestedPostsCount($wallOwner->getId()); - - if($suggsCount % 10 == 0) { - $managers = $wallOwner->getManagers(); - $owner = $wallOwner->getOwner(); - (new NewSuggestedPostsNotification($owner, $wallOwner))->emit(); - - foreach($managers as $manager) { - (new NewSuggestedPostsNotification($manager->getUser(), $wallOwner))->emit(); - } - } - - return (object)["post_id" => "on_view"]; - } - return (object)["post_id" => $post->getVirtualId()]; } - function repost(string $object, string $message = "", int $group_id = 0) { + function repost(string $object, string $message = "", string $attachments = "", int $group_id = 0, int $as_group = 0, int $signed = 0) { $this->requireUser(); $this->willExecuteWriteAction(); $postArray; - if(preg_match('/wall((?:-?)[0-9]+)_([0-9]+)/', $object, $postArray) == 0) + if(preg_match('/(wall|video|photo)((?:-?)[0-9]+)_([0-9]+)/', $object, $postArray) == 0) $this->fail(100, "One of the parameters specified was missing or invalid: object is incorrect"); - - $post = (new PostsRepo)->getPostById((int) $postArray[1], (int) $postArray[2]); - if(!$post || $post->isDeleted()) $this->fail(100, "One of the parameters specified was missing or invalid"); - - if(!$post->canBeViewedBy($this->getUser())) - $this->fail(15, "Access denied"); + + $parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio']); + $final_attachments = []; + foreach($parsed_attachments as $attachment) { + if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) && + !(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) { + $final_attachments[] = $attachment; + } + } + + $repost_entity = NULL; + $repost_type = $postArray[1]; + switch($repost_type) { + default: + case 'wall': + $repost_entity = (new PostsRepo)->getPostById((int) $postArray[2], (int) $postArray[3]); + break; + case 'photo': + $repost_entity = (new PhotosRepo)->getByOwnerAndVID((int) $postArray[2], (int) $postArray[3]); + break; + case 'video': + $repost_entity = (new VideosRepo)->getByOwnerAndVID((int) $postArray[2], (int) $postArray[3]); + break; + } + + if(!$repost_entity || $repost_entity->isDeleted() || !$repost_entity->canBeViewedBy($this->getUser())) $this->fail(100, "One of the parameters specified was missing or invalid"); $nPost = new Post; $nPost->setOwner($this->user->getId()); if($group_id > 0) { - $club = (new ClubsRepo)->get($group_id); + $club = (new ClubsRepo)->get($group_id); if(!$club) $this->fail(42, "Invalid group"); if(!$club->canBeModifiedBy($this->user)) $this->fail(16, "Access to group denied"); - $nPost->setWall($group_id * -1); + $nPost->setWall($club->getRealId()); + $flags = 0; + if($as_group === 1 || $signed === 1) + $flags |= 0b10000000; + + if($signed === 1) + $flags |= 0b01000000; + + $nPost->setFlags($flags); } else { $nPost->setWall($this->user->getId()); } @@ -712,16 +662,27 @@ final class Wall extends VKAPIRequestHandler $nPost->setContent($message); $nPost->setApi_Source_Name($this->getPlatform()); $nPost->save(); - $nPost->attach($post); - - if($post->getOwner(false)->getId() !== $this->user->getId() && !($post->getOwner() instanceof Club)) - (new RepostNotification($post->getOwner(false), $post, $this->user))->emit(); + + $nPost->attach($repost_entity); + + foreach($parsed_attachments as $attachment) { + $nPost->attach($attachment); + } + + if($repost_type == 'wall' && $repost_entity->getOwner(false)->getId() !== $this->user->getId() && !($repost_entity->getOwner() instanceof Club)) + (new RepostNotification($repost_entity->getOwner(false), $repost_entity, $this->user))->emit(); + + $repost_count = 1; + if($repost_type == 'wall') { + $repost_count = $repost_entity->getRepostCount(); + } return (object) [ "success" => 1, // 👍 "post_id" => $nPost->getVirtualId(), - "reposts_count" => $post->getRepostCount(), - "likes_count" => $post->getLikesCount() + "pretty_id" => $nPost->getPrettyId(), + "reposts_count" => $repost_count, + "likes_count" => $repost_entity->getLikesCount() ]; } @@ -767,7 +728,7 @@ final class Wall extends VKAPIRequestHandler "date" => $comment->getPublicationTime()->timestamp(), "text" => $comment->getText(false), "post_id" => $post->getVirtualId(), - "owner_id" => $post->isPostedOnBehalfOfGroup() ? $post->getOwner()->getId() * -1 : $post->getOwner()->getId(), + "owner_id" => method_exists($post, 'isPostedOnBehalfOfGroup') && $post->isPostedOnBehalfOfGroup() ? $post->getOwner()->getId() * -1 : $post->getOwner()->getId(), "parents_stack" => [], "attachments" => $attachments, "thread" => [ @@ -833,6 +794,13 @@ final class Wall extends VKAPIRequestHandler foreach($comment->getChildren() as $attachment) { if($attachment instanceof \openvk\Web\Models\Entities\Photo) { $attachments[] = $this->getApiPhoto($attachment); + } elseif($attachment instanceof \openvk\Web\Models\Entities\Video) { + $attachments[] = $attachment->getApiStructure(); + } elseif($attachment instanceof \openvk\Web\Models\Entities\Note) { + $attachments[] = [ + 'type' => 'note', + 'note' => $attachment->toVkApiStruct() + ]; } elseif($attachment instanceof \openvk\Web\Models\Entities\Audio) { $attachments[] = [ "type" => "audio", @@ -847,7 +815,7 @@ final class Wall extends VKAPIRequestHandler "date" => $comment->getPublicationTime()->timestamp(), "text" => $comment->getText(false), "post_id" => $comment->getTarget()->getVirtualId(), - "owner_id" => $comment->getTarget()->isPostedOnBehalfOfGroup() ? $comment->getTarget()->getOwner()->getId() * -1 : $comment->getTarget()->getOwner()->getId(), + "owner_id" => method_exists($comment->getTarget(), 'isPostedOnBehalfOfGroup') && $comment->getTarget()->isPostedOnBehalfOfGroup() ? $comment->getTarget()->getOwner()->getId() * -1 : $comment->getTarget()->getOwner()->getId(), "parents_stack" => [], "attachments" => $attachments, "likes" => [ @@ -899,7 +867,16 @@ final class Wall extends VKAPIRequestHandler if($post->getTargetWall() < 0) $club = (new ClubsRepo)->get(abs($post->getTargetWall())); - if(empty($message) && empty($attachments)) { + $parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio']); + $final_attachments = []; + foreach($parsed_attachments as $attachment) { + if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) && + !(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) { + $final_attachments[] = $attachment; + } + } + + if((empty($message) && (empty($attachments) || sizeof($final_attachments) < 1))) { $this->fail(100, "Required parameter 'message' missing."); } @@ -920,55 +897,8 @@ final class Wall extends VKAPIRequestHandler $this->fail(1, "ошибка про то что коммент большой слишком"); } - if(!empty($attachments)) { - $attachmentsArr = explode(",", $attachments); - - if(sizeof($attachmentsArr) > 10) - $this->fail(50, "Error: too many attachments"); - - foreach($attachmentsArr as $attac) { - $attachmentType = NULL; - - if(str_contains($attac, "photo")) - $attachmentType = "photo"; - elseif(str_contains($attac, "video")) - $attachmentType = "video"; - elseif(str_contains($attac, "audio")) - $attachmentType = "audio"; - else - $this->fail(205, "Unknown attachment type"); - - $attachment = str_replace($attachmentType, "", $attac); - - $attachmentOwner = (int)explode("_", $attachment)[0]; - $attachmentId = (int)end(explode("_", $attachment)); - - $attacc = NULL; - - if($attachmentType == "photo") { - $attacc = (new PhotosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId); - if(!$attacc || $attacc->isDeleted()) - $this->fail(100, "Photo does not exists"); - if(!$attacc->getOwner()->getPrivacyPermission('photos.read', $this->getUser())) - $this->fail(11, "Access to photo denied"); - - $comment->attach($attacc); - } elseif($attachmentType == "video") { - $attacc = (new VideosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId); - if(!$attacc || $attacc->isDeleted()) - $this->fail(100, "Video does not exists"); - if(!$attacc->getOwner()->getPrivacyPermission('videos.read', $this->getUser())) - $this->fail(11, "Access to video denied"); - - $comment->attach($attacc); - } elseif($attachmentType == "audio") { - $attacc = (new AudiosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId); - if(!$attacc || $attacc->isDeleted()) - $this->fail(100, "Audio does not exist"); - - $comment->attach($attacc); - } - } + foreach($final_attachments as $attachment) { + $comment->attach($attachment); } if($post->getOwner()->getId() !== $this->user->getId()) @@ -1019,11 +949,24 @@ final class Wall extends VKAPIRequestHandler } } - function edit(int $owner_id, int $post_id, string $message = "", string $attachments = "", string $copyright = NULL) { + function edit(int $owner_id, int $post_id, string $message = "", string $attachments = "", string $copyright = NULL, int $explicit = -1, int $from_group = 0, int $signed = 0) { $this->requireUser(); $this->willExecuteWriteAction(); - $post = (new PostsRepo)->getPostById($owner_id, $post_id); + $parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio', 'poll']); + $final_attachments = []; + foreach($parsed_attachments as $attachment) { + if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) && + !(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) { + $final_attachments[] = $attachment; + } + } + + if(empty($message) && sizeof($final_attachments) < 1) { + $this->fail(-66, "Post will be empty, don't saving."); + } + + $post = (new PostsRepo)->getPostById($owner_id, $post_id, true); if(!$post || $post->isDeleted()) $this->fail(102, "Invalid post"); @@ -1031,36 +974,43 @@ final class Wall extends VKAPIRequestHandler if(!$post->canBeEditedBy($this->getUser())) $this->fail(7, "Access to editing denied"); - if(!empty($message)) + if(!empty($message) || (empty($message) && sizeof($final_attachments) > 0)) $post->setContent($message); $post->setEdited(time()); if(!is_null($copyright) && !empty($copyright)) { - try { - $post->setSource($copyright); - } catch(\Throwable) {} + if($copyright == 'remove') { + $post->resetSource(); + } else { + try { + $post->setSource($copyright); + } catch(\Throwable) {} + } } + if($explicit != -1) { + $post->setNsfw($explicit == 1); + } + + $wallOwner = ($owner_id > 0 ? (new UsersRepo)->get($owner_id) : (new ClubsRepo)->get($owner_id * -1)); + $flags = 0; + if($from_group == 1 && $wallOwner instanceof Club && $wallOwner->canBeModifiedBy($this->getUser())) + $flags |= 0b10000000; + /*if($signed == 1) + $flags |= 0b01000000;*/ + + $post->setFlags($flags); $post->save(true); - # todo добавить такое в веб версию - if(!empty($attachments)) { - $attachs = parseAttachments($attachments); - $newAttachmentsCount = sizeof($attachs); + if($attachments == 'remove' || sizeof($final_attachments) > 0) { + foreach($post->getChildren() as $att) { + if(!($att instanceof Post)) { + $post->detach($att); + } + } - $postsAttachments = iterator_to_array($post->getChildren()); - - if(sizeof($postsAttachments) >= 10) - $this->fail(15, "Post have too many attachments"); - - if(($newAttachmentsCount + sizeof($postsAttachments)) > 10) - $this->fail(158, "Post will have too many attachments"); - - foreach($attachs as $attach) { - if($attach && !$attach->isDeleted()) - $post->attach($attach); - else - $this->fail(52, "One of the attachments is invalid"); + foreach($final_attachments as $attachment) { + $post->attach($attachment); } } @@ -1072,8 +1022,16 @@ final class Wall extends VKAPIRequestHandler $this->willExecuteWriteAction(); $comment = (new CommentsRepo)->get($comment_id); + $parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio']); + $final_attachments = []; + foreach($parsed_attachments as $attachment) { + if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) && + !(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) { + $final_attachments[] = $attachment; + } + } - if(empty($message) && empty($attachments)) + if(empty($message) && sizeof($final_attachments) < 1) $this->fail(100, "Required parameter 'message' missing."); if(!$comment || $comment->isDeleted()) @@ -1082,29 +1040,16 @@ final class Wall extends VKAPIRequestHandler if(!$comment->canBeEditedBy($this->getUser())) $this->fail(15, "Access to editing comment denied"); - if(!empty($message)) + if(!empty($message) || (empty($message) && sizeof($final_attachments) > 0)) $comment->setContent($message); $comment->setEdited(time()); $comment->save(true); - - if(!empty($attachments)) { - $attachs = parseAttachments($attachments); - $newAttachmentsCount = sizeof($attachs); - $postsAttachments = iterator_to_array($comment->getChildren()); - - if(sizeof($postsAttachments) >= 10) - $this->fail(15, "Post have too many attachments"); - - if(($newAttachmentsCount + sizeof($postsAttachments)) > 10) - $this->fail(158, "Post will have too many attachments"); - - foreach($attachs as $attach) { - if($attach && !$attach->isDeleted()) - $comment->attach($attach); - else - $this->fail(52, "One of the attachments is invalid"); + if(sizeof($final_attachments) > 0) { + $comment->unwire(); + foreach($final_attachments as $attachment) { + $comment->attach($attachment); } } diff --git a/Web/Models/Entities/Album.php b/Web/Models/Entities/Album.php index dccd4e63..cc96cc0b 100644 --- a/Web/Models/Entities/Album.php +++ b/Web/Models/Entities/Album.php @@ -87,6 +87,7 @@ class Album extends MediaCollection $res = (object) []; $res->id = $this->getPrettyId(); + $res->vid = $this->getId(); $res->thumb_id = !is_null($this->getCoverPhoto()) ? $this->getCoverPhoto()->getPrettyId() : 0; $res->owner_id = $this->getOwner()->getId(); $res->title = $this->getName(); diff --git a/Web/Models/Entities/Photo.php b/Web/Models/Entities/Photo.php index 3ea46939..90c532b2 100644 --- a/Web/Models/Entities/Photo.php +++ b/Web/Models/Entities/Photo.php @@ -308,7 +308,7 @@ class Photo extends Media $res->date = $res->created = $this->getPublicationTime()->timestamp(); if($photo_sizes) { - $res->sizes = $this->getVkApiSizes(); + $res->sizes = array_values($this->getVkApiSizes()); $res->src_small = $res->photo_75 = $this->getURLBySizeId("miniscule"); $res->src = $res->photo_130 = $this->getURLBySizeId("tiny"); $res->src_big = $res->photo_604 = $this->getURLBySizeId("normal"); diff --git a/Web/Models/Entities/Post.php b/Web/Models/Entities/Post.php index 5d5469d4..6aa09889 100644 --- a/Web/Models/Entities/Post.php +++ b/Web/Models/Entities/Post.php @@ -103,6 +103,11 @@ class Post extends Postable $this->stateChanges("source", $source); } + function resetSource() + { + $this->stateChanges("source", NULL); + } + function getVkApiCopyright(): object { return (object)[ diff --git a/Web/Models/Entities/Report.php b/Web/Models/Entities/Report.php index 1b36678c..33bf84f7 100644 --- a/Web/Models/Entities/Report.php +++ b/Web/Models/Entities/Report.php @@ -134,8 +134,13 @@ class Report extends RowModel function getContentName(): string { - if (method_exists($this->getContentObject(), "getCanonicalName")) - return $this->getContentObject()->getCanonicalName(); + $content_object = $this->getContentObject(); + if(!$content_object) { + return 'unknown'; + } + + if (method_exists($content_object, "getCanonicalName")) + return $content_object->getCanonicalName(); return $this->getContentType() . " #" . $this->getContentId(); } diff --git a/Web/Models/Entities/Traits/TAttachmentHost.php b/Web/Models/Entities/Traits/TAttachmentHost.php index db814cce..a574e657 100644 --- a/Web/Models/Entities/Traits/TAttachmentHost.php +++ b/Web/Models/Entities/Traits/TAttachmentHost.php @@ -1,6 +1,6 @@ getChildren(); + $children = iterator_to_array($this->getChildren()); $skipped = $photos = $result = []; foreach($children as $child) { - if($child instanceof Photo) { + if($child instanceof Photo || $child instanceof Video && $child->getDimensions()) { $photos[] = $child; continue; } diff --git a/Web/Models/Entities/Video.php b/Web/Models/Entities/Video.php index a4d0b898..8e3c18f0 100644 --- a/Web/Models/Entities/Video.php +++ b/Web/Models/Entities/Video.php @@ -34,9 +34,23 @@ class Video extends Media if(sizeof($durations[1]) === 0) throw new \DomainException("$filename does not contain any meaningful video streams"); - foreach($durations[1] as $duration) - if(floatval($duration) < 1.0) + $length = 0; + foreach($durations[1] as $duration) { + $duration = floatval($duration); + if($duration < 1.0) throw new \DomainException("$filename does not contain any meaningful video streams"); + else + $length = max($length, $duration); + } + + $this->stateChanges("length", (int) round($length, 0, PHP_ROUND_HALF_EVEN)); + + preg_match('%width=([0-9\.]++)%', $streams, $width); + preg_match('%height=([0-9\.]++)%', $streams, $height); + if(!empty($width) && !empty($height)) { + $this->stateChanges("width", $width[1]); + $this->stateChanges("height", $height[1]); + } try { if(!is_dir($dirId = dirname($this->pathFromHash($hash)))) @@ -118,6 +132,7 @@ class Video extends Media function getApiStructure(?User $user = NULL): object { $fromYoutube = $this->getType() == Video::TYPE_EMBED; + $dimensions = $this->getDimensions(); $res = (object)[ "type" => "video", "video" => [ @@ -130,7 +145,7 @@ class Video extends Media "comments" => $this->getCommentsCount(), "date" => $this->getPublicationTime()->timestamp(), "description" => $this->getDescription(), - "duration" => 0, // я хуй знает как получить длину видео + "duration" => $this->getLength(), "image" => [ [ "url" => $this->getThumbnailURL(), @@ -139,8 +154,8 @@ class Video extends Media "with_padding" => 1 ] ], - "width" => 640, - "height" => 480, + "width" => $dimensions ? $dimensions[0] : 640, + "height" => $dimensions ? $dimensions[1] : 480, "id" => $this->getVirtualId(), "owner_id" => $this->getOwner()->getId(), "user_id" => $this->getOwner()->getId(), @@ -155,6 +170,7 @@ class Video extends Media "repeat" => 0, "type" => "video", "views" => 0, + "is_processed" => $this->isProcessed(), "reposts" => [ "count" => 0, "user_reposted" => 0 @@ -224,6 +240,74 @@ class Video extends Media return $video; } + + function fillDimensions() + { + $hash = $this->getRecord()->hash; + $path = $this->pathFromHash($hash); + if(!file_exists($path)) { + $this->stateChanges("width", 0); + $this->stateChanges("height", 0); + $this->stateChanges("length", 0); + $this->save(); + return false; + } + + $streams = Shell::ffprobe("-i", $path, "-show_streams", "-select_streams v", "-loglevel error")->execute($error); + $durations = []; + preg_match_all('%duration=([0-9\.]++)%', $streams, $durations); + + $length = 0; + foreach($durations[1] as $duration) { + $duration = floatval($duration); + if($duration < 1.0) + continue; + else + $length = max($length, $duration); + } + $this->stateChanges("length", (int) round($length, 0, PHP_ROUND_HALF_EVEN)); + + preg_match('%width=([0-9\.]++)%', $streams, $width); + preg_match('%height=([0-9\.]++)%', $streams, $height); + + if(!empty($width) && !empty($height)) { + $this->stateChanges("width", $width[1]); + $this->stateChanges("height", $height[1]); + } + + $this->save(); + + return true; + } + + function getDimensions() + { + if($this->getType() == Video::TYPE_EMBED) return [320, 180]; + + $width = $this->getRecord()->width; + $height = $this->getRecord()->height; + + if(!$width) return NULL; + return $width != 0 ? [$width, $height] : NULL; + } + + function getLength() + { + return $this->getRecord()->length; + } + + function getFormattedLength(): string + { + $len = $this->getLength(); + if(!$len) return "00:00"; + $mins = floor($len / 60); + $secs = $len - ($mins * 60); + return ( + str_pad((string) $mins, 2, "0", STR_PAD_LEFT) + . ":" . + str_pad((string) $secs, 2, "0", STR_PAD_LEFT) + ); + } function canBeViewedBy(?User $user = NULL): bool { @@ -248,7 +332,7 @@ class Video extends Media $res->owner_id = $this->getOwner()->getId(); $res->title = $this->getName(); $res->description = $this->getDescription(); - $res->duration = "22"; + $res->duration = $this->getLength(); $res->link = "/video".$this->getOwner()->getId()."_".$this->getVirtualId(); $res->image = $this->getThumbnailURL(); $res->date = $this->getPublicationTime()->timestamp(); diff --git a/Web/Models/Repositories/Photos.php b/Web/Models/Repositories/Photos.php index 0698c914..a024747c 100644 --- a/Web/Models/Repositories/Photos.php +++ b/Web/Models/Repositories/Photos.php @@ -33,7 +33,7 @@ class Photos return new Photo($photo); } - function getEveryUserPhoto(User $user, int $page = 1, ?int $perPage = NULL): \Traversable + function getEveryUserPhoto(User $user, int $offset = 0, int $limit = 10): \Traversable { $perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE; $photos = $this->photos->where([ @@ -41,7 +41,7 @@ class Photos "deleted" => 0 ])->order("id DESC"); - foreach($photos->page($page, $perPage) as $photo) { + foreach($photos->limit($limit, $offset) as $photo) { yield new Photo($photo); } } diff --git a/Web/Models/Repositories/Videos.php b/Web/Models/Repositories/Videos.php index e91c226d..8dbda7ab 100644 --- a/Web/Models/Repositories/Videos.php +++ b/Web/Models/Repositories/Videos.php @@ -39,6 +39,13 @@ class Videos $perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE; foreach($this->videos->where("owner", $user->getId())->where(["deleted" => 0, "unlisted" => 0])->page($page, $perPage)->order("created DESC") as $video) yield new Video($video); + } + + function getByUserLimit(User $user, int $offset = 0, int $limit = 10): \Traversable + { + $perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE; + foreach($this->videos->where("owner", $user->getId())->where(["deleted" => 0, "unlisted" => 0])->limit($limit, $offset)->order("created DESC") as $video) + yield new Video($video); } function getUserVideosCount(User $user): int @@ -49,7 +56,7 @@ class Videos function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream { $query = "%$query%"; - $result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("deleted", 0); + $result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("deleted", 0)->where("unlisted", 0); $order_str = 'id'; switch($order['type']) { diff --git a/Web/Presenters/AudioPresenter.php b/Web/Presenters/AudioPresenter.php index 7e2825c1..ae38d1d0 100644 --- a/Web/Presenters/AudioPresenter.php +++ b/Web/Presenters/AudioPresenter.php @@ -33,6 +33,7 @@ final class AudioPresenter extends OpenVKPresenter function renderList(?int $owner = NULL, ?string $mode = "list"): void { + $this->assertUserLoggedIn(); $this->template->_template = "Audio/List.xml"; $page = (int)($this->queryParam("p") ?? 1); $audios = []; @@ -501,6 +502,7 @@ final class AudioPresenter extends OpenVKPresenter function renderPlaylist(int $owner_id, int $virtual_id): void { + $this->assertUserLoggedIn(); $playlist = $this->audios->getPlaylistByOwnerAndVID($owner_id, $virtual_id); $page = (int)($this->queryParam("p") ?? 1); if (!$playlist || $playlist->isDeleted()) diff --git a/Web/Presenters/CommentPresenter.php b/Web/Presenters/CommentPresenter.php index 4170cdb3..7ab74ac0 100644 --- a/Web/Presenters/CommentPresenter.php +++ b/Web/Presenters/CommentPresenter.php @@ -27,7 +27,12 @@ final class CommentPresenter extends OpenVKPresenter $this->flashFail("err", tr("error"), tr("forbidden")); if(!is_null($this->user)) $comment->toggleLike($this->user->identity); - + if($_SERVER["REQUEST_METHOD"] === "POST") { + $this->returnJson([ + 'success' => true, + ]); + } + $this->redirect($_SERVER["HTTP_REFERER"]); } @@ -70,64 +75,24 @@ final class CommentPresenter extends OpenVKPresenter $this->flashFail("err", tr("error_when_publishing_comment"), tr("error_when_publishing_comment_description")); } } - - $photos = []; - if(!empty($this->postParam("photos"))) { - $un = rtrim($this->postParam("photos"), ","); - $arr = explode(",", $un); - if(sizeof($arr) < 11) { - foreach($arr as $dat) { - $ids = explode("_", $dat); - $photo = (new Photos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]); - - if(!$photo || $photo->isDeleted()) - continue; - - $photos[] = $photo; - } + $horizontal_attachments = []; + $vertical_attachments = []; + if(!empty($this->postParam("horizontal_attachments"))) { + $horizontal_attachments_array = array_slice(explode(",", $this->postParam("horizontal_attachments")), 0, OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"]); + if(sizeof($horizontal_attachments_array) > 0) { + $horizontal_attachments = parseAttachments($horizontal_attachments_array, ['photo', 'video']); } } - $videos = []; - - if(!empty($this->postParam("videos"))) { - $un = rtrim($this->postParam("videos"), ","); - $arr = explode(",", $un); - - if(sizeof($arr) < 11) { - foreach($arr as $dat) { - $ids = explode("_", $dat); - $video = (new Videos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]); - - if(!$video || $video->isDeleted()) - continue; - - $videos[] = $video; - } - } - } - - $audios = []; - - if(!empty($this->postParam("audios"))) { - $un = rtrim($this->postParam("audios"), ","); - $arr = explode(",", $un); - - if(sizeof($arr) < 11) { - foreach($arr as $dat) { - $ids = explode("_", $dat); - $audio = (new Audios)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]); - - if(!$audio || $audio->isDeleted()) - continue; - - $audios[] = $audio; - } + if(!empty($this->postParam("vertical_attachments"))) { + $vertical_attachments_array = array_slice(explode(",", $this->postParam("vertical_attachments")), 0, OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"]); + if(sizeof($vertical_attachments_array) > 0) { + $vertical_attachments = parseAttachments($vertical_attachments_array, ['audio', 'note']); } } - if(empty($this->postParam("text")) && sizeof($photos) < 1 && sizeof($videos) < 1 && sizeof($audios) < 1) + if(empty($this->postParam("text")) && sizeof($horizontal_attachments) < 1 && sizeof($vertical_attachments) < 1) $this->flashFail("err", tr("error_when_publishing_comment"), tr("error_comment_empty")); try { @@ -143,15 +108,21 @@ final class CommentPresenter extends OpenVKPresenter $this->flashFail("err", tr("error_when_publishing_comment"), tr("error_comment_too_big")); } - foreach($photos as $photo) - $comment->attach($photo); - - if(sizeof($videos) > 0) - foreach($videos as $vid) - $comment->attach($vid); + foreach($horizontal_attachments as $horizontal_attachment) { + if(!$horizontal_attachment || $horizontal_attachment->isDeleted() || !$horizontal_attachment->canBeViewedBy($this->user->identity)) { + continue; + } - foreach($audios as $audio) - $comment->attach($audio); + $comment->attach($horizontal_attachment); + } + + foreach($vertical_attachments as $vertical_attachment) { + if(!$vertical_attachment || $vertical_attachment->isDeleted() || !$vertical_attachment->canBeViewedBy($this->user->identity)) { + continue; + } + + $comment->attach($vertical_attachment); + } if($entity->getOwner()->getId() !== $this->user->identity->getId()) if(($owner = $entity->getOwner()) instanceof User) diff --git a/Web/Presenters/InternalAPIPresenter.php b/Web/Presenters/InternalAPIPresenter.php index dca5db04..72546506 100644 --- a/Web/Presenters/InternalAPIPresenter.php +++ b/Web/Presenters/InternalAPIPresenter.php @@ -121,9 +121,9 @@ final class InternalAPIPresenter extends OpenVKPresenter { if($attachment instanceof \openvk\Web\Models\Entities\Photo) { - $response[] = [ - "url" => $attachment->getURLBySizeId('normal'), - "id" => $attachment->getPrettyId() + $response[$attachment->getPrettyId()] = [ + "url" => $attachment->getURLBySizeId('larger'), + "id" => $attachment->getPrettyId(), ]; } } @@ -133,4 +133,35 @@ final class InternalAPIPresenter extends OpenVKPresenter ]); } } + + function renderGetPostTemplate(int $owner_id, int $post_id) { + if($_SERVER["REQUEST_METHOD"] !== "POST") { + header("HTTP/1.1 405 Method Not Allowed"); + exit("ты‍ не по адресу"); + } + + $type = $this->queryParam("type", false); + if($type == "post") { + $post = (new Posts)->getPostById($owner_id, $post_id, true); + } else { + $post = (new Comments)->get($post_id); + } + + if(!$post || !$post->canBeEditedBy($this->user->identity)) { + exit(''); + } + + header("Content-Type: text/plain"); + + if($type == 'post') { + $this->template->_template = 'components/post.xml'; + $this->template->post = $post; + $this->template->commentSection = false; + } elseif($type == 'comment') { + $this->template->_template = 'components/comment.xml'; + $this->template->comment = $post; + } else { + exit(''); + } + } } diff --git a/Web/Presenters/PhotosPresenter.php b/Web/Presenters/PhotosPresenter.php index 09130c60..cec426b8 100644 --- a/Web/Presenters/PhotosPresenter.php +++ b/Web/Presenters/PhotosPresenter.php @@ -176,6 +176,7 @@ final class PhotosPresenter extends OpenVKPresenter $this->template->cCount = $photo->getCommentsCount(); $this->template->cPage = (int) ($this->queryParam("p") ?? 1); $this->template->comments = iterator_to_array($photo->getComments($this->template->cPage)); + $this->template->owner = $photo->getOwner(); } function renderAbsolutePhoto($id): void @@ -287,7 +288,8 @@ final class PhotosPresenter extends OpenVKPresenter "id" => $photo->getId(), "vid" => $photo->getVirtualId(), "owner" => $photo->getOwner()->getId(), - "link" => $photo->getURL() + "link" => $photo->getURL(), + "pretty_id" => $photo->getPrettyId(), ]; } catch(ISE $ex) { $name = $album->getName(); @@ -354,4 +356,26 @@ final class PhotosPresenter extends OpenVKPresenter $this->flash("succ", tr("photo_is_deleted"), tr("photo_is_deleted_desc")); $this->redirect($redirect); } + + function renderLike(int $wall, int $post_id): void + { + $this->assertUserLoggedIn(); + $this->willExecuteWriteAction(); + $this->assertNoCSRF(); + + $photo = $this->photos->getByOwnerAndVID($wall, $post_id); + if(!$photo || $photo->isDeleted() || !$photo->canBeViewedBy($this->user->identity)) $this->notFound(); + + if(!is_null($this->user)) { + $photo->toggleLike($this->user->identity); + } + + if($_SERVER["REQUEST_METHOD"] === "POST") { + $this->returnJson([ + 'success' => true, + ]); + } + + $this->redirect("$_SERVER[HTTP_REFERER]"); + } } diff --git a/Web/Presenters/VideosPresenter.php b/Web/Presenters/VideosPresenter.php index 625f4877..dbf4efea 100644 --- a/Web/Presenters/VideosPresenter.php +++ b/Web/Presenters/VideosPresenter.php @@ -62,6 +62,7 @@ final class VideosPresenter extends OpenVKPresenter $this->flashFail("err", tr("error"), tr("video_uploads_disabled")); if($_SERVER["REQUEST_METHOD"] === "POST") { + $is_ajax = (int)($this->postParam('ajax') ?? '0') == 1; if(!empty($this->postParam("name"))) { $video = new Video; $video->setOwner($this->user->id); @@ -75,18 +76,29 @@ final class VideosPresenter extends OpenVKPresenter else if(!empty($this->postParam("link"))) $video->setLink($this->postParam("link")); else - $this->flashFail("err", tr("no_video_error"), tr("no_video_description")); + $this->flashFail("err", tr("no_video_error"), tr("no_video_description"), 10, $is_ajax); } catch(\DomainException $ex) { - $this->flashFail("err", tr("error_video"), tr("file_corrupted")); + $this->flashFail("err", tr("error_video"), tr("file_corrupted"), 10, $is_ajax); } catch(ISE $ex) { - $this->flashFail("err", tr("error_video"), tr("link_incorrect")); + $this->flashFail("err", tr("error_video"), tr("link_incorrect"), 10, $is_ajax); } + if((int)($this->postParam("unlisted") ?? '0') == 1) { + $video->setUnlisted(true); + } + $video->save(); + if($is_ajax) { + $object = $video->getApiStructure(); + $this->returnJson([ + 'payload' => $object->video, + ]); + } + $this->redirect("/video" . $video->getPrettyId()); } else { - $this->flashFail("err", tr("error_video"), tr("no_name_error")); + $this->flashFail("err", tr("error_video"), tr("no_name_error"), 10, $is_ajax); } } } @@ -151,7 +163,13 @@ final class VideosPresenter extends OpenVKPresenter if(!is_null($this->user)) { $video->toggleLike($this->user->identity); } - - $this->returnJson(["success" => true]); + + if($_SERVER["REQUEST_METHOD"] === "POST") { + $this->returnJson([ + 'success' => true, + ]); + } + + $this->redirect("$_SERVER[HTTP_REFERER]"); } } diff --git a/Web/Presenters/WallPresenter.php b/Web/Presenters/WallPresenter.php index ca4c3ece..17cc12e1 100644 --- a/Web/Presenters/WallPresenter.php +++ b/Web/Presenters/WallPresenter.php @@ -282,25 +282,22 @@ final class WallPresenter extends OpenVKPresenter if($this->postParam("force_sign") === "on") $flags |= 0b01000000; - $photos = []; - - if(!empty($this->postParam("photos"))) { - $un = rtrim($this->postParam("photos"), ","); - $arr = explode(",", $un); - - if(sizeof($arr) < 11) { - foreach($arr as $dat) { - $ids = explode("_", $dat); - $photo = (new Photos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]); - - if(!$photo || $photo->isDeleted()) - continue; - - $photos[] = $photo; - } + $horizontal_attachments = []; + $vertical_attachments = []; + if(!empty($this->postParam("horizontal_attachments"))) { + $horizontal_attachments_array = array_slice(explode(",", $this->postParam("horizontal_attachments")), 0, OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"]); + if(sizeof($horizontal_attachments_array) > 0) { + $horizontal_attachments = parseAttachments($horizontal_attachments_array, ['photo', 'video']); } } - + + if(!empty($this->postParam("vertical_attachments"))) { + $vertical_attachments_array = array_slice(explode(",", $this->postParam("vertical_attachments")), 0, OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"]); + if(sizeof($vertical_attachments_array) > 0) { + $vertical_attachments = parseAttachments($vertical_attachments_array, ['audio', 'note']); + } + } + try { $poll = NULL; $xml = $this->postParam("poll"); @@ -312,61 +309,10 @@ final class WallPresenter extends OpenVKPresenter $this->flashFail("err", tr("failed_to_publish_post"), "Poll format invalid"); } - $note = NULL; - - if(!is_null($this->postParam("note")) && $this->postParam("note") != "none") { - $note = (new Notes)->get((int)$this->postParam("note")); - - if(!$note || $note->isDeleted() || $note->getOwner()->getId() != $this->user->id) { - $this->flashFail("err", tr("error"), tr("error_attaching_note")); - } - - if($note->getOwner()->getPrivacySetting("notes.read") < 1) { - $this->flashFail("err", " "); - } - } - - $videos = []; - - if(!empty($this->postParam("videos"))) { - $un = rtrim($this->postParam("videos"), ","); - $arr = explode(",", $un); - - if(sizeof($arr) < 11) { - foreach($arr as $dat) { - $ids = explode("_", $dat); - $video = (new Videos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]); - - if(!$video || $video->isDeleted()) - continue; - - $videos[] = $video; - } - } - } - - $audios = []; - - if(!empty($this->postParam("audios"))) { - $un = rtrim($this->postParam("audios"), ","); - $arr = explode(",", $un); - - if(sizeof($arr) < 11) { - foreach($arr as $dat) { - $ids = explode("_", $dat); - $audio = (new Audios)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]); - - if(!$audio || $audio->isDeleted()) - continue; - - $audios[] = $audio; - } - } - } - - if(empty($this->postParam("text")) && sizeof($photos) < 1 && sizeof($videos) < 1 && sizeof($audios) < 1 && !$poll && !$note) + if(empty($this->postParam("text")) && sizeof($horizontal_attachments) < 1 && sizeof($vertical_attachments) < 1 && !$poll) $this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_empty_or_too_big")); + $should_be_suggested = $wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2; try { $post = new Post; $post->setOwner($this->user->id); @@ -383,7 +329,7 @@ final class WallPresenter extends OpenVKPresenter } catch(\Throwable) {} } - if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2) + if($should_be_suggested) $post->setSuggested(1); $post->save(); @@ -391,21 +337,24 @@ final class WallPresenter extends OpenVKPresenter $this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_too_big")); } - foreach($photos as $photo) - $post->attach($photo); - - if(sizeof($videos) > 0) - foreach($videos as $vid) - $post->attach($vid); + foreach($horizontal_attachments as $horizontal_attachment) { + if(!$horizontal_attachment || $horizontal_attachment->isDeleted() || !$horizontal_attachment->canBeViewedBy($this->user->identity)) { + continue; + } + + $post->attach($horizontal_attachment); + } + + foreach($vertical_attachments as $vertical_attachment) { + if(!$vertical_attachment || $vertical_attachment->isDeleted() || !$vertical_attachment->canBeViewedBy($this->user->identity)) { + continue; + } + + $post->attach($vertical_attachment); + } if(!is_null($poll)) $post->attach($poll); - - if(!is_null($note)) - $post->attach($note); - - foreach($audios as $audio) - $post->attach($audio); if($wall > 0 && $wall !== $this->user->identity->getId()) (new WallPostNotification($wallOwner, $post, $this->user->identity))->emit(); @@ -414,9 +363,7 @@ final class WallPresenter extends OpenVKPresenter if($wall > 0) $excludeMentions[] = $wall; - if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2) { - # Чтобы не было упоминаний из предложки - } else { + if(!$should_be_suggested) { $mentions = iterator_to_array($post->resolveMentions($excludeMentions)); foreach($mentions as $mentionee) @@ -424,18 +371,7 @@ final class WallPresenter extends OpenVKPresenter (new MentionNotification($mentionee, $post, $post->getOwner(), strip_tags($post->getText())))->emit(); } - if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2) { - $suggsCount = $this->posts->getSuggestedPostsCount($wallOwner->getId()); - - if($suggsCount % 10 == 0) { - $managers = $wallOwner->getManagers(); - $owner = $wallOwner->getOwner(); - (new NewSuggestedPostsNotification($owner, $wallOwner))->emit(); - - foreach($managers as $manager) - (new NewSuggestedPostsNotification($manager->getUser(), $wallOwner))->emit(); - } - + if($should_be_suggested) { $this->redirect("/club".$wallOwner->getId()."/suggested"); } else { $this->redirect($wallOwner->getURL()); @@ -486,6 +422,12 @@ final class WallPresenter extends OpenVKPresenter if(!is_null($this->user)) { $post->toggleLike($this->user->identity); } + + if($_SERVER["REQUEST_METHOD"] === "POST") { + $this->returnJson([ + 'success' => true, + ]); + } $this->redirect("$_SERVER[HTTP_REFERER]#postGarter=" . $post->getId()); } diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml index 42a8787d..d7a15912 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -17,6 +17,7 @@ {script "js/node_modules/umbrellajs/umbrella.min.js"} {script "js/l10n.js"} {script "js/openvk.cls.js"} + {script "js/utils.js"} {script "js/node_modules/dashjs/dist/dash.all.min.js"} {script "js/al_music.js"} @@ -26,6 +27,7 @@ {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"} + {css "js/node_modules/jquery-ui/themes/base/resizable.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"} @@ -51,7 +53,10 @@
FOR TESTING PURPOSES ONLY
-
+
+
+
+
{_close} @@ -361,7 +366,7 @@
- +
{include "components/cookies.xml"} @@ -424,6 +429,9 @@ window.openvk = { "audio_genres": {\openvk\Web\Models\Entities\Audio::genres}, "at_search": {$atSearch ?? false}, + "max_attachments": {\OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"] ?? 10}, + "max_filesize_mb": 5, + "current_id": {$thisUser ? $thisUser->getId() : 0}, } diff --git a/Web/Presenters/templates/Audio/player.xml b/Web/Presenters/templates/Audio/player.xml index de8f03d7..24fe4723 100644 --- a/Web/Presenters/templates/Audio/player.xml +++ b/Web/Presenters/templates/Audio/player.xml @@ -5,17 +5,17 @@