...
 
Commits (2)
......@@ -44,6 +44,61 @@ class Moderation extends Cli\Controller implements Interfaces\CliControllerInter
/** @var Core\Reports\Repository $reportsRepository */
$reportsRepository = Di::_()->get('Reports\Repository');
/** @var Core\Queue\Interfaces\QueueClient $queueClient */
$queueClient = Core\Queue\Client::build();
$reportUrn = $this->getOpt('report');
$cohort = $this->getOpt('cohort');
if (!$reportUrn || !$cohort) {
$this->out([
'Usage:',
' - cli.php moderation summon --report=<report_urn> --cohort=<guid1, guid2, ..., guidN>',
' - cli.php moderation summon --report=<report_urn> --cohort=auto',
]);
exit(1);
}
$guids = null;
if ($cohort !== 'auto') {
$guids = explode(',', $cohort);
}
$report = $reportsRepository->get($reportUrn);
if (!$report) {
$this->out('Error: Invalid report');
exit(1);
} elseif($report->getState() !== 'initial_jury_decided') {
$this->out("Error: Report is not appealable. State is [{$report->getState()}].");
exit(1);
}
$appeal = new Core\Reports\Appeals\Appeal();
$appeal
->setReport($report)
->setOwnerGuid($report->getEntityOwnerGuid());
$queueClient
->setQueue('ReportsAppealSummon')
->send([
'appeal' => $appeal,
'cohort' => $guids ?: null,
]);
$this->out('Sent to summon queue!');
}
public function dev_only_summon_individual()
{
error_reporting(E_ALL);
ini_set('display_errors', 1);
/** @var Core\Reports\Repository $reportsRepository */
$reportsRepository = Di::_()->get('Reports\Repository');
/** @var Core\Reports\Summons\Manager $summonsManager */
$summonsManager = Di::_()->get('Moderation\Summons\Manager');
......@@ -56,8 +111,8 @@ class Moderation extends Cli\Controller implements Interfaces\CliControllerInter
if (!$userId || !$reportUrn) {
$this->out([
'Usage:',
'- Summoning: cli.php moderation summon --user=<username_or_guid> --report=<report_urn>',
'- Responding: cli.php moderation summon --user=<username_or_guid> --report=<report_urn> --jury-type=<initial_jury|appeal_jury> --respond=<accepted|declined>',
'- Summoning: cli.php moderation dev_only_summon_individual --user=<username_or_guid> --report=<report_urn>',
'- Responding: cli.php moderation dev_only_summon_individual --user=<username_or_guid> --report=<report_urn> --jury-type=<initial_jury|appeal_jury> --respond=<accepted|declined>',
]);
exit(1);
......@@ -101,79 +156,4 @@ class Moderation extends Cli\Controller implements Interfaces\CliControllerInter
$this->out("Responded to {$user->guid}'s summons to {$reportUrn} with {$respond}");
}
}
public function dev_only_simulate_summon()
{
error_reporting(E_ALL);
ini_set('display_errors', 1);
/** @var Core\Reports\Repository $reportsRepository */
$reportsRepository = Di::_()->get('Reports\Repository');
/** @var Core\Reports\Summons\Manager $summonsManager */
$summonsManager = Di::_()->get('Moderation\Summons\Manager');
$reportUrn = $this->getOpt('report');
if (!$reportUrn) {
$this->out([
'Usage: cli.php moderation dev_only_simulate_summon --report=<report_urn>',
]);
exit(1);
}
$report = $reportsRepository->get($reportUrn);
if (!$report) {
$this->out('Error: Invalid report');
exit(1);
}
$appeal = new Core\Reports\Appeals\Appeal();
$appeal
->setReport($report)
->setOwnerGuid($report->getEntityOwnerGuid());
$cohort = $summonsManager->summon($appeal);
var_dump($cohort);
}
public function dev_only_add_strike()
{
error_reporting(E_ALL);
ini_set('display_errors', 1);
/** @var Core\Reports\Repository $reportsRepository */
$reportsRepository = Di::_()->get('Reports\Repository');
/** @var Core\Reports\Strikes\Manager $strikesManager */
$strikesManager = Di::_()->get('Moderation\Strikes\Manager');
$reportUrn = $this->getOpt('report');
if (!$reportUrn) {
$this->out([
'Usage: cli.php moderation dev_only_add_strike --report=<report_urn>',
]);
exit(1);
}
$report = $reportsRepository->get($reportUrn);
if (!$report) {
$this->out('Error: Invalid report');
exit(1);
}
$strike = new Strike;
$strike->setReport($report)
->setReportUrn($report->getUrn())
->setUserGuid($report->getEntityOwnerGuid())
->setReasonCode($report->getReasonCode())
->setSubReasonCode($report->getSubReasonCode())
->setTimestamp($report->getTimestamp()); // Strike is recored for date of first report
var_dump($strikesManager->add($strike));
}
}
......@@ -7,6 +7,7 @@
namespace Minds\Core\Channels;
use Exception;
use Minds\Core\Data\Cassandra\Client as CassandraClient;
use Minds\Core\Data\Cassandra\Prepared\Custom;
use Minds\Core\Di\Di;
......@@ -44,7 +45,7 @@ class Subscriptions
/**
* @param $opts
* @return string[]
* @throws \Exception
* @throws Exception
*/
public function getList($opts)
{
......@@ -53,7 +54,7 @@ class Subscriptions
], $opts);
if (!$this->user) {
throw new \Exception('Invalid user');
throw new Exception('Invalid user');
}
$cql = "SELECT * FROM friends WHERE key = ? LIMIT ?";
......@@ -75,9 +76,30 @@ class Subscriptions
}
return $result;
} catch (\Exception $e) {
} catch (Exception $e) {
error_log($e);
return [];
}
}
/**
* @param string|int $guid
* @return bool
*/
public function hasSubscription($guid)
{
$cql = "SELECT COUNT(*) as count FROM friends WHERE key = ? AND column1 = ? LIMIT 1";
$values = [
(string) $this->user->guid,
(string) $guid,
];
$prepared = new Custom();
$prepared->query($cql, $values);
$rows = $this->db->request($prepared);
// Should throw if needed.
return isset($rows[0]['count']) && $rows[0]['count'] > 0;
}
}
......@@ -8,6 +8,9 @@
namespace Minds\Core\Reports\Summons;
use Exception;
use Minds\Core\Channels\Subscriptions;
use Minds\Core\Di\Di;
use Minds\Entities\User;
class Cohort
{
......@@ -17,6 +20,9 @@ class Cohort
/** @var Pool */
protected $pool;
/** @var Subscriptions */
protected $subscriptions;
/** @var int */
protected $poolSize;
......@@ -27,18 +33,21 @@ class Cohort
* Cohort constructor.
* @param Repository $repository
* @param Pool $pool
* @param Subscriptions $subscriptions
* @param int $poolSize
* @param int $maxPages
*/
public function __construct(
$repository = null,
$pool = null,
$subscriptions = null,
$poolSize = null,
$maxPages = null
)
{
$this->repository = $repository ?: new Repository();
$this->pool = $pool ?: new Pool();
$this->subscriptions = $subscriptions ?: new Subscriptions();
$this->poolSize = $poolSize ?: 400;
$this->maxPages = $maxPages ?: 2; // NOTE: Normally capped to 20.
}
......@@ -63,6 +72,14 @@ class Cohort
$page = 0;
if ($opts['for']) {
$user = new User();
$user->set('guid', $opts['for']);
$this->subscriptions
->setUser($user);
}
while (true) {
if ($page >= $this->maxPages) {
// Max = PoolSize * MaxPages
......@@ -84,7 +101,16 @@ class Cohort
]);
foreach ($pool as $userGuid) {
// TODO: Check subs
if ($opts['for']) {
try {
if ($this->subscriptions->hasSubscription($userGuid)) {
continue;
}
} catch (Exception $e) {
error_log("Cannot double-check subscriptions {$userGuid}");
}
}
$cohort[] = $userGuid;
if (count($cohort) >= $opts['size']) {
......
......@@ -129,7 +129,7 @@ class Pool
if ($opts['include_only']) {
$body['query']['bool']['must'][] = [
'terms' => [
'user_guid' => $opts['include_only'],
'user_guid' => Text::buildArray($opts['include_only']),
],
];
}
......@@ -141,7 +141,7 @@ class Pool
$body['query']['bool']['must_not'][] = [
'terms' => [
'user_guid' => $opts['except'],
'user_guid' => Text::buildArray($opts['except']),
],
];
}
......@@ -153,7 +153,7 @@ class Pool
$body['query']['bool']['must_not'][] = [
'terms' => [
'user_phone_number_hash' => $opts['except_hashes'],
'user_phone_number_hash' => Text::buildArray($opts['except_hashes']),
],
];
}
......
......@@ -2,9 +2,11 @@
namespace Spec\Minds\Core\Reports\Summons;
use Minds\Core\Channels\Subscriptions;
use Minds\Core\Reports\Summons\Cohort;
use Minds\Core\Reports\Summons\Pool;
use Minds\Core\Reports\Summons\Repository;
use Minds\Entities\User;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
......@@ -16,14 +18,19 @@ class CohortSpec extends ObjectBehavior
/** @var Pool */
protected $pool;
/** @var Subscriptions */
protected $subscriptions;
function let(
Repository $repository,
Pool $pool
Pool $pool,
Subscriptions $subscriptions
)
{
$this->beConstructedWith($repository, $pool, 20, 3);
$this->beConstructedWith($repository, $pool, $subscriptions, 20, 3);
$this->repository = $repository;
$this->pool = $pool;
$this->subscriptions = $subscriptions;
}
function it_is_initializable()
......@@ -33,6 +40,12 @@ class CohortSpec extends ObjectBehavior
function it_should_pick()
{
$this->subscriptions->setUser(Argument::that(function (User $user) {
return $user->get('guid') == 1000;
}))
->shouldBeCalled()
->willReturn($this->subscriptions);
// 1st iteration
$this->pool->getList([
......@@ -50,6 +63,10 @@ class CohortSpec extends ObjectBehavior
->shouldBeCalled()
->willReturn([ 1010 ]);
$this->subscriptions->hasSubscription(1010)
->shouldBeCalled()
->willReturn(false);
// 2nd iteration
$this->pool->getList([
......@@ -67,6 +84,10 @@ class CohortSpec extends ObjectBehavior
->shouldBeCalled()
->willReturn([ 1011 ]);
$this->subscriptions->hasSubscription(1011)
->shouldBeCalled()
->willReturn(false);
// 3rd iteration
$this->pool->getList([
......@@ -84,6 +105,19 @@ class CohortSpec extends ObjectBehavior
->shouldBeCalled()
->willReturn([ 1012, 1013, 1014 ]);
$this->subscriptions->hasSubscription(1012)
->shouldBeCalled()
->willReturn(true);
$this->subscriptions->hasSubscription(1013)
->shouldBeCalled()
->willReturn(false);
$this->subscriptions->hasSubscription(1014)
->shouldNotBeCalled();
//
$this
->pick([
'size' => 3,
......@@ -93,6 +127,6 @@ class CohortSpec extends ObjectBehavior
'include_only' => null,
'active_threshold' => 100,
])
->shouldReturn([ 1010, 1011, 1012 ]);
->shouldReturn([ 1010, 1011, 1013 ]);
}
}