diff --git a/ServiceAPI/Wall.php b/ServiceAPI/Wall.php
index c7a8362c..102c50ce 100644
--- a/ServiceAPI/Wall.php
+++ b/ServiceAPI/Wall.php
@@ -143,4 +143,30 @@ class Wall implements Handler
$resolve($arr);
}
+
+ function getIgnoredSources(int $page = 1, callable $resolve, callable $reject)
+ {
+ $surses = $this->user->getIgnoredSources($page, 10);
+
+ $arr = [
+ "count" => $this->user->getIgnoredSourcesCount(),
+ "items" => []
+ ];
+
+ foreach($surses as $surs) {
+ $arr["items"][] = [
+ "id" => $surs->getRealId(),
+ "name" => $surs->getCanonicalName(),
+ "additional" => (($surs->getRealId() > 0 ? $surs->getStatus() : $surs->getDescription()) ?? "..."),
+ "avatar" => $surs->getAvatarURL(),
+ "url" => $surs->getURL(),
+ ];
+ }
+
+ if(rand(0, 200) == 50) {
+ $arr["fact"] = $this->user->getIgnoresCount();
+ }
+
+ $resolve($arr);
+ }
}
diff --git a/VKAPI/Handlers/Newsfeed.php b/VKAPI/Handlers/Newsfeed.php
index 64ee1862..fc876b5f 100644
--- a/VKAPI/Handlers/Newsfeed.php
+++ b/VKAPI/Handlers/Newsfeed.php
@@ -1,9 +1,9 @@
requireUser();
@@ -56,12 +56,18 @@ final class Newsfeed extends VKAPIRequestHandler
if($this->getUser()->getNsfwTolerance() === User::NSFW_INTOLERANT)
$queryBase .= " AND `nsfw` = 0";
+
+ if(($ignoredCount = $this->getUser()->getIgnoredSourcesCount()) > 0 && $return_banned == 0) {
+ $sources = implode("', '", $this->getUser()->getIgnoredSources(1, $ignoredCount, true));
+
+ $queryBase .= " AND `posts`.`wall` NOT IN ('$sources')";
+ }
$start_from = empty($start_from) ? PHP_INT_MAX : $start_from;
$start_time = empty($start_time) ? 0 : $start_time;
$end_time = empty($end_time) ? PHP_INT_MAX : $end_time;
$posts = DatabaseConnection::i()->getConnection()->query("SELECT `posts`.`id` " . $queryBase . " AND `posts`.`id` <= " . $start_from . " AND " . $start_time . " <= `posts`.`created` AND `posts`.`created` <= " . $end_time . " ORDER BY `created` DESC LIMIT " . $count . " OFFSET " . $offset);
-
+
$rposts = [];
$ids = [];
foreach($posts as $post) {
@@ -74,4 +80,130 @@ final class Newsfeed extends VKAPIRequestHandler
return $response;
}
+
+ function getBanned(int $extended = 0, string $fields = "", string $name_case = "nom")
+ {
+ $this->requireUser();
+
+ $count = 50;
+ $offset = 0;
+
+ $banned = array_slice($this->getUser()->getIgnoredSources(1, $count + $offset, true), $offset);
+
+ if($extended == 0) {
+ $retArr/*d*/ = [
+ "groups" => [],
+ "members" => [] # why
+ ];
+
+ foreach($banned as $ban) {
+ if($ban > 0) {
+ $retArr["members"][] = $ban;
+ } else {
+ $retArr["groups"][] = $ban;
+ }
+ }
+
+ return $retArr;
+ } else {
+ $retArr = [
+ "groups" => [],
+ "profiles" => []
+ ];
+
+ $usIds = "";
+ $clubIds = "";
+
+ foreach($banned as $ban) {
+ if($ban > 0) {
+ $usIds .= $ban . ",";
+ } else {
+ $clubIds .= ($ban * -1) . ",";
+ }
+ }
+
+ $retArr["profiles"][] = (new Users)->get($usIds, $fields);
+ $retArr["groups"][] = (new Groups)->getById($clubIds, $fields);
+
+ return $retArr;
+ }
+ }
+
+ function addBan(string $user_ids = "", string $group_ids = "")
+ {
+ $this->requireUser();
+ $this->willExecuteWriteAction();
+
+ if(empty($user_ids) && empty($group_ids))
+ $this->fail(52, "Provide 'user_ids' or 'groups_ids'");
+
+ $arr = [];
+
+ if(!empty($user_ids)) {
+ $arr = array_merge($arr, array_map(function($el) {
+ return (int)$el;
+ }, explode(",", $user_ids)));
+ }
+
+ if(!empty($group_ids)) {
+ $arr = array_merge($arr, array_map(function($el) {
+ return abs((int)$el) * -1;
+ }, explode(",", $group_ids)));
+ }
+
+ $arr = array_unique($arr);
+ if(sizeof($arr) > 10 || sizeof($arr) < 1)
+ $this->fail(20, "You can ignore only 10 users/groups at once");
+
+ $successes = 0;
+ foreach($arr as $ar) {
+ $entity = getEntity($ar);
+
+ if(!$entity || $entity->isHideFromGlobalFeedEnabled() || $entity->isIgnoredBy($this->getUser())) continue;
+
+ $entity->toggleIgnore($this->getUser());
+ $successes += 1;
+ }
+
+ return (int)($successes > 0);
+ }
+
+ function deleteBan(string $user_ids = "", string $group_ids = "")
+ {
+ $this->requireUser();
+ $this->willExecuteWriteAction();
+
+ if(empty($user_ids) && empty($group_ids))
+ $this->fail(52, "Provide 'user_ids' or 'groups_ids'");
+
+ $arr = [];
+
+ if(!empty($user_ids)) {
+ $arr = array_merge($arr, array_map(function($el) {
+ return (int)$el;
+ }, explode(",", $user_ids)));
+ }
+
+ if(!empty($group_ids)) {
+ $arr = array_merge($arr, array_map(function($el) {
+ return abs((int)$el) * -1;
+ }, explode(",", $group_ids)));
+ }
+
+ $arr = array_unique($arr);
+ if(sizeof($arr) > 10 || sizeof($arr) < 1)
+ $this->fail(20, "You can unignore only 10 users/groups at once");
+
+ $successes = 0;
+ foreach($arr as $ar) {
+ $entity = getEntity($ar);
+
+ if(!$entity || $entity->isHideFromGlobalFeedEnabled() || !$entity->isIgnoredBy($this->getUser())) continue;
+
+ $entity->toggleIgnore($this->getUser());
+ $successes += 1;
+ }
+
+ return (int)($successes > 0);
+ }
}
diff --git a/Web/Models/Entities/Club.php b/Web/Models/Entities/Club.php
index dc1c356e..2bff8995 100644
--- a/Web/Models/Entities/Club.php
+++ b/Web/Models/Entities/Club.php
@@ -469,4 +469,5 @@ class Club extends RowModel
use Traits\TBackDrops;
use Traits\TSubscribable;
use Traits\TAudioStatuses;
+ use Traits\TIgnorable;
}
diff --git a/Web/Models/Entities/Traits/TIgnorable.php b/Web/Models/Entities/Traits/TIgnorable.php
new file mode 100644
index 00000000..a3bbc1a1
--- /dev/null
+++ b/Web/Models/Entities/Traits/TIgnorable.php
@@ -0,0 +1,48 @@
+getContext();
+ $data = [
+ "owner" => $user->getId(),
+ "ignored_source" => $this->getRealId(),
+ ];
+
+ $sub = $ctx->table("ignored_sources")->where($data);
+
+ if(!$sub->fetch()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ function getIgnoresCount()
+ {
+ return sizeof(DatabaseConnection::i()->getContext()->table("ignored_sources")->where("ignored_source", $this->getRealId()));
+ }
+
+ function toggleIgnore(User $user): bool
+ {
+ if($this->isIgnoredBy($user)) {
+ DatabaseConnection::i()->getContext()->table("ignored_sources")->where([
+ "owner" => $user->getId(),
+ "ignored_source" => $this->getRealId(),
+ ])->delete();
+
+ return false;
+ } else {
+ DatabaseConnection::i()->getContext()->table("ignored_sources")->insert([
+ "owner" => $user->getId(),
+ "ignored_source" => $this->getRealId(),
+ ]);
+
+ return true;
+ }
+ }
+}
diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php
index 4f1fbff1..697abdde 100644
--- a/Web/Models/Entities/User.php
+++ b/Web/Models/Entities/User.php
@@ -1338,7 +1338,37 @@ class User extends RowModel
return $res;
}
+
+ function getIgnoredSources(int $page = 1, int $perPage = 10, bool $onlyIds = false)
+ {
+ $sources = DatabaseConnection::i()->getContext()->table("ignored_sources")->where("owner", $this->getId())->page($page, $perPage);
+ $arr = [];
+ foreach($sources as $source) {
+ $ignoredSource = (int)$source->ignored_source;
+
+ if($ignoredSource > 0)
+ $ignoredSourceModel = (new Users)->get($ignoredSource);
+ else
+ $ignoredSourceModel = (new Clubs)->get(abs($ignoredSource));
+
+ if(!$ignoredSourceModel)
+ continue;
+
+ if(!$onlyIds)
+ $arr[] = $ignoredSourceModel;
+ else
+ $arr[] = $ignoredSourceModel->getRealId();
+ }
+
+ return $arr;
+ }
+
+ function getIgnoredSourcesCount()
+ {
+ return sizeof(DatabaseConnection::i()->getContext()->table("ignored_sources")->where("owner", $this->getId()));
+ }
+
function getAudiosCollectionSize()
{
return (new \openvk\Web\Models\Repositories\Audios)->getUserCollectionSize($this);
@@ -1378,7 +1408,13 @@ class User extends RowModel
return $returnArr;
}
+ function isHideFromGlobalFeedEnabled(): bool
+ {
+ return $this->isClosed();
+ }
+
use Traits\TBackDrops;
use Traits\TSubscribable;
use Traits\TAudioStatuses;
+ use Traits\TIgnorable;
}
diff --git a/Web/Presenters/WallPresenter.php b/Web/Presenters/WallPresenter.php
index b29968d0..04cf44ed 100644
--- a/Web/Presenters/WallPresenter.php
+++ b/Web/Presenters/WallPresenter.php
@@ -197,6 +197,12 @@ final class WallPresenter extends OpenVKPresenter
if($this->user->identity->getNsfwTolerance() === User::NSFW_INTOLERANT)
$queryBase .= " AND `nsfw` = 0";
+ if(($ignoredCount = $this->user->identity->getIgnoredSourcesCount()) > 0) {
+ $sources = implode("', '", $this->user->identity->getIgnoredSources(1, $ignoredCount, true));
+
+ $queryBase .= " AND `posts`.`wall` NOT IN ('$sources')";
+ }
+
$posts = DatabaseConnection::i()->getConnection()->query("SELECT `posts`.`id` " . $queryBase . " ORDER BY `created` DESC LIMIT " . $pPage . " OFFSET " . ($page - 1) * $pPage);
$count = DatabaseConnection::i()->getConnection()->query("SELECT COUNT(*) " . $queryBase)->fetch()->{"COUNT(*)"};
@@ -650,7 +656,61 @@ final class WallPresenter extends OpenVKPresenter
"avatar" => $post->getOwner()->getAvatarUrl()
]]);
}
+
+ function renderIgnoreSource()
+ {
+ $this->assertUserLoggedIn();
+ $this->willExecuteWriteAction(true);
+ if($_SERVER["REQUEST_METHOD"] !== "POST")
+ exit("");
+
+ $owner = $this->user->id;
+ $ignoredSource = (int)$this->postParam("source");
+
+ if($this->user->identity->getIgnoredSourcesCount() > 50)
+ $this->flashFail("err", "Error", tr("max_ignores", 50), null, true);
+
+ if($ignoredSource > 0) {
+ $ignoredSourceModel = (new Users)->get($ignoredSource);
+
+ if(!$ignoredSourceModel)
+ $this->flashFail("err", "Error", tr("invalid_user"), null, true);
+
+ if($ignoredSourceModel->getId() == $this->user->id)
+ $this->flashFail("err", "Error", tr("cant_ignore_self"), null, true);
+
+ if($ignoredSourceModel->isClosed())
+ $this->flashFail("err", "Error", tr("no_sense"), null, true);
+ } else {
+ $ignoredSourceModel = (new Clubs)->get(abs($ignoredSource));
+
+ if(!$ignoredSourceModel)
+ $this->flashFail("err", "Error", tr("invalid_club"), null, true);
+
+ if($ignoredSourceModel->isHideFromGlobalFeedEnabled())
+ $this->flashFail("err", "Error", tr("no_sense"), null, true);
+ }
+
+ if(!$ignoredSourceModel->toggleIgnore($this->user->identity)) {
+ $tr = "";
+
+ if($ignoredSource > 0)
+ $tr = tr("ignore_user");
+ else
+ $tr = tr("ignore_club");
+
+ $this->returnJson(["success" => true, "act" => "unignored", "text" => $tr]);
+ } else {
+ if($ignoredSource > 0)
+ $tr = tr("unignore_user");
+ else
+ $tr = tr("unignore_club");
+
+ $this->returnJson(["success" => true, "act" => "ignored", "text" => $tr]);
+ }
+ }
+
function renderAccept() {
$this->assertUserLoggedIn();
$this->willExecuteWriteAction(true);
diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml
index 415f930f..d1bbd5ee 100644
--- a/Web/Presenters/templates/@layout.xml
+++ b/Web/Presenters/templates/@layout.xml
@@ -401,6 +401,7 @@
{ifset $thisUser}
{script "js/al_notifs.js"}
+ {script "js/al_feed.js"}
{/ifset}
{if OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['fartscroll']}
diff --git a/Web/Presenters/templates/Group/View.xml b/Web/Presenters/templates/Group/View.xml
index 91a96119..bc0aa786 100644
--- a/Web/Presenters/templates/Group/View.xml
+++ b/Web/Presenters/templates/Group/View.xml
@@ -175,6 +175,9 @@
{var $canReport = $thisUser->getId() != $club->getOwner()->getId()}
{if $canReport}
{_report}
+
+ {if !$club->isIgnoredBy($thisUser)}{_ignore_club}{else}{_unignore_club}{/if}
+