...
 
Commits (10)
......@@ -207,7 +207,7 @@ production:fpm:
name: production
url: https://www.minds.com/
when: delayed
start_in: 2 hours # reduce? can always be deployed manually earlier too
start_in: 12 hours # reduce? can always be deployed manually earlier too
production:runners:
stage: deploy:production
......
......@@ -159,11 +159,11 @@ class recommended implements Interfaces\Api
{
$guids = [];
$entities = array_filter($entities, function ($entity) use (&$guids, $exclude) {
if (in_array($entity->guid, $guids, true)) {
if (in_array($entity->guid, $guids, false)) {
return false;
}
if (in_array($entity->guid, $exclude, true)) {
if (in_array($entity->guid, $exclude, false)) {
return false;
}
......
......@@ -290,13 +290,21 @@ class boost implements Interfaces\Api
->setType(lcfirst($pages[0]))
->setPriority(false);
if ($manager->checkExisting($boost)) {
return Factory::response([
'status' => 'error',
'message' => "There's already an ongoing boost for this entity"
]);
}
if ($manager->checkExisting($boost)) {
return Factory::response([
'status' => 'error',
'message' => "There's already an ongoing boost for this entity"
]);
}
if ($manager->isBoostLimitExceededBy($boost)) {
$maxDaily = Di::_()->get('Config')->get('max_daily_boost_views') / 1000;
return Factory::response([
'status' => 'error',
'message' => "Exceeded maximum of ".$maxDaily." offchain tokens per 24 hours."
]);
}
// Pre-set GUID
if ($bidType == 'tokens' && isset($_POST['guid'])) {
......
......@@ -30,11 +30,13 @@ class ElasticRepository
'rating' => 3,
'token' => 0,
'offset' => null,
'order' => null,
'offchain' => null,
], $opts);
$must = [];
$must_not = [];
$sort = [ '@timestamp' => 'asc' ];
$sort = [ '@timestamp' => $opts['order'] ?? 'asc' ];
$must[] = [
'term' => [
......@@ -67,8 +69,16 @@ class ElasticRepository
if ($opts['entity_guid']) {
$must[] = [
'term' => [
'entity_guid' => $opts['entity_guid']
]
'entity_guid' => $opts['entity_guid'],
],
];
}
if ($opts['owner_guid']) {
$must[] = [
'term' => [
'owner_guid' => $opts['owner_guid'],
],
];
}
......@@ -87,6 +97,14 @@ class ElasticRepository
];
}
if ($opts['offchain']) {
$must[] = [
'term' => [
'token_method' => 'offchain',
],
];
}
if ($opts['state'] === 'review') {
$must_not[] = [
'exists' => [
......@@ -96,7 +114,7 @@ class ElasticRepository
$sort = ['@timestamp' => 'asc'];
}
if ($opts['state'] === 'approved' || $opts['state'] === 'review') {
if ($opts['state'] === 'approved' || $opts['state'] === 'review' || $opts['state'] === 'active') {
$must_not[] = [
'exists' => [
'field' => '@completed',
......
......@@ -25,16 +25,21 @@ class Manager
/** @var GuidBuilder $guidBuilder */
private $guidBuilder;
/** @var Config $config */
private $config;
public function __construct(
$repository = null,
$elasticRepository = null,
$entitiesBuilder = null,
$guidBuilder = null
$guidBuilder = null,
$config = null
) {
$this->repository = $repository ?: new Repository;
$this->elasticRepository = $elasticRepository ?: new ElasticRepository;
$this->entitiesBuilder = $entitiesBuilder ?: Di::_()->get('EntitiesBuilder');
$this->guidBuilder = $guidBuilder ?: new GuidBuilder;
$this->config = $config ?: Di::_()->get('Config');
}
/**
......@@ -50,14 +55,14 @@ class Manager
'state' => null,
], $opts);
if ($opts['state'] == 'review') {
if ($opts['state'] == 'review' || $opts['state'] == 'active') {
$opts['useElastic'] = true;
}
if ($opts['useElastic']) {
$response = $this->elasticRepository->getList($opts);
if ($opts['state'] === 'review') {
if ($opts['state'] === 'review' || $opts['state'] === 'active') {
$opts['guids'] = array_map(function ($boost) {
return $boost->getGuid();
}, $response->toArray());
......@@ -156,4 +161,52 @@ class Manager
return $existingBoost->count() > 0;
}
/**
* True if the boost is invalid due to the offchain boost limit being reached
*
* @param Boost $type the Boost object.
* @return boolean true if the boost limit has been reached.
*/
public function isBoostLimitExceededBy($boost)
{
//get offchain boosts
$offchain = $this->getOffchainBoosts($boost);
//filter to get todays offchain transactions
$offlineToday = array_filter($offchain->toArray(), function ($result) {
return $result->getCreatedTimestamp() > time() - (60 * 60 * 24);
});
//reduce the impressions to count the days boosts.
$acc = array_reduce($offlineToday, function ($carry, $_boost) {
$carry += $_boost->getImpressions();
return $carry;
}, 0);
$maxDaily = $this->config->get('max_daily_boost_views');
return $acc + $boost->getImpressions() > $maxDaily; //still allow 10k
}
/**
* Gets the users last offchain boosts, from the most recent boost backwards in time.
*
* @param string $type the type of the boost
* @param integer $limit default to 10.
* @return $existingBoosts
*/
public function getOffchainBoosts($boost, $limit = 10)
{
$existingBoosts = $this->getList([
'useElastic' => true,
'state' => 'active',
'type' => $boost->getType(),
'limit' => $limit,
'order' => 'desc',
'offchain' => true,
'owner_guid' => $boost->getOwnerGuid(),
]);
return $existingBoosts;
}
}
......@@ -64,7 +64,7 @@ class Manager
break;
}
return in_array($this->vote->getActor()->guid, $votes, true);
return in_array($this->vote->getActor()->guid, $votes, false);
}
/**
......
......@@ -66,7 +66,7 @@ class Activity implements EmailBatchInterface
foreach ($iterator as $user) {
$filtered = array_filter($trendingPosts, function ($activity) use ($user, $subscribers_map) {
return in_array($activity->owner_guid, $subscribers_map[$user->guid], true);
return in_array($activity->owner_guid, $subscribers_map[$user->guid], false);
});
if ($filtered && count($filtered) >= 1) {
$campaign = new WithActivity();
......
......@@ -26,7 +26,7 @@ class WithBlogs implements EmailBatchInterface
protected $templatePath;
/** @var string $subject */
protected $subject;
protected $subject = "Top blogs from August";
public function __construct($manager = null, $trendingRepository = null, $builder = null)
{
......@@ -98,7 +98,7 @@ class WithBlogs implements EmailBatchInterface
$i = 0;
foreach ($iterator as $user) {
$user = new \Minds\Entities\User('mark');
// $user = new \Minds\Entities\User('mark');
++$i;
echo "\n[$i]: $user->guid ($iterator->offset)";
......@@ -117,7 +117,7 @@ class WithBlogs implements EmailBatchInterface
->send();
echo ' sent';
exit;
// exit;
}
}
......@@ -137,16 +137,14 @@ class WithBlogs implements EmailBatchInterface
$options['guids'] = $result['guids'];*/
$options['guids'] = [
'998738105104236544',
'999467832663445504',
'966409629405708288',
'993006058717818880',
'973946575102472192',
'1006629205218992128',
'1005557700564246528',
'1010584762553004032',
'1006684770592301056',
'977770227199016960',
'1002988949318565888',
'996468067362422784',
'993621806187380736',
'971156445331410944',
'983472046539116544',
'952732651199864832',
'1001223653028548608',
];
$blogs = $this->builder->get(array_merge([
......
......@@ -38,6 +38,9 @@ class WithBlogs extends EmailCampaign
public function send()
{
if (!method_exists($this->user, 'getEmail')) {
return;
}
$this->template->setTemplate('default.tpl');
$this->template->setBody("./Templates/missed-blogs.tpl");
......@@ -65,7 +68,7 @@ class WithBlogs extends EmailCampaign
$this->template->set('validator', $validatorHash);
$subject = "Here's 10 fascinating top articles";
$subject = "Top blogs from August";
$message = new Message();
$message->setTo($this->user)
......
......@@ -171,7 +171,7 @@ class Manager
$hydratedEntities = $this->entitiesBuilder->get(['guids' => $hydrateGuids]);
foreach ($hydratedEntities as $entity) {
if ($opts['pinned_guids'] && in_array($entity->getGuid(), $opts['pinned_guids'], true)) {
if ($opts['pinned_guids'] && in_array($entity->getGuid(), $opts['pinned_guids'], false)) {
$entity->pinned = true;
}
if ($opts['as_activities']) {
......
......@@ -226,7 +226,7 @@ class Repository
],
];
if (in_array(6, $nsfw, true)) { // 6 is legacy 'mature'
if (in_array(6, $nsfw, false)) { // 6 is legacy 'mature'
$body['query']['function_score']['query']['bool']['must_not'][] = [
'term' => [
'mature' => true,
......
......@@ -96,7 +96,7 @@ class Invitations
$result = [];
foreach ($users as $user) {
$result[$user] = in_array($user, $invited_guids, true);
$result[$user] = in_array($user, $invited_guids, false);
}
return $result;
......
......@@ -579,7 +579,7 @@ class Membership
$result = [];
foreach ($users as $user) {
$result[$user] = in_array($user, $banned_guids, true);
$result[$user] = in_array($user, $banned_guids, false);
}
return $result;
......
......@@ -62,8 +62,8 @@ class Question
$export['answer'] = $this->getAnswer();
$export['category_uuid'] = $this->getCategoryUuid();
$export['category'] = $this->getCategory() ? $this->getCategory()->export() : null;
$export['thumb_up'] = in_array(Session::getLoggedInUserGuid(), $this->getThumbsUp(), true);
$export['thumb_down'] = in_array(Session::getLoggedInUserGuid(), $this->getThumbsDown(), true);
$export['thumb_up'] = in_array(Session::getLoggedInUserGuid(), $this->getThumbsUp(), false);
$export['thumb_down'] = in_array(Session::getLoggedInUserGuid(), $this->getThumbsDown(), false);
$export['position'] = $this->getPosition();
return $export;
......
......@@ -66,7 +66,7 @@ class Repository
$prepared->setOpts([
'page_size' => (int) $opts['limit'],
'paging_state_token' => base64_decode($opts['offset'], true),
'paging_state_token' => base64_decode($opts['offset'], false),
]);
$response = new Response([]);
......
......@@ -67,7 +67,7 @@ class Manager
$array = $this->question->$getter();
if (!in_array($this->user->getGuid(), $array, true)) {
if (!in_array($this->user->getGuid(), $array, false)) {
$array[] = (string) $this->user->getGuid();
$this->question->$setter($array);
}
......
......@@ -52,8 +52,10 @@ class Conversations
if ($guids && is_array($guids) && count($guids) >= 12) {
$collection = \Cassandra\Type::collection(\Cassandra\Type::text())
->create(... $guids);
$prepared->query("SELECT * from entities_by_time WHERE key= ? AND column1 IN ? LIMIT ?",
[ "object:gathering:conversations:{$this->user->guid}", $collection, 1000 ]);
$prepared->query(
"SELECT * from entities_by_time WHERE key= ? AND column1 IN ? LIMIT ?",
[ "object:gathering:conversations:{$this->user->guid}", $collection, 1000 ]
);
$usingCache = true;
}
}
......@@ -148,7 +150,7 @@ class Conversations
foreach ($conversations as $key => $conversation) {
foreach ($conversation->getParticipants() as $participant) {
if (in_array($participant, $online, true)) {
if (in_array($participant, $online, false)) {
$conversations[$key] = $conversation->setOnline(true);
}
}
......
......@@ -75,14 +75,14 @@ class Events
$user = $params['user'];
if ($entity instanceof Entities\Message) {
if (in_array($user->guid, array_keys($entity->getMessages()), true)) {
if (in_array($user->guid, array_keys($entity->getMessages()), false)) {
$event->setResponse(true);
} else {
$event->setResponse(false);
}
}
if ($entity instanceof Entities\Conversation) {
if (in_array($user->guid, $entity->getParticipants(), true)) {
if (in_array($user->guid, $entity->getParticipants(), false)) {
$event->setResponse(true);
} else {
$event->setResponse(false);
......
......@@ -92,7 +92,7 @@ class Manager
// Remove the summonses of jurors who have already voted
$summonses = array_filter($summonses, function (Summons $summons) use ($completedJurorGuids) {
return !in_array($summons->getJurorGuid(), $completedJurorGuids, true);
return !in_array($summons->getJurorGuid(), $completedJurorGuids, false);
});
// Check how many are missing
......
......@@ -82,7 +82,7 @@ class Manager
if ($report->getReasonCode() == 2
&& $report->getEntity()->getNsfw()
&& in_array($report->getSubReasonCode(), $report->getEntity()->getNsfw(), true)
&& in_array($report->getSubReasonCode(), $report->getEntity()->getNsfw(), false)
) {
return true; // If the post is NSFW and tagged, do not allow report
}
......
......@@ -101,7 +101,7 @@ class ACL
* And check the owner is the container_guid too
*/
if (
in_array($entity->getAccessId(), [ACCESS_LOGGED_IN, ACCESS_PUBLIC], true)
in_array($entity->getAccessId(), [ACCESS_LOGGED_IN, ACCESS_PUBLIC], false)
&& (
$entity->owner_guid == $entity->container_guid
|| $entity->container_guid == 0
......
......@@ -270,7 +270,7 @@ class AutoReporter
{
$reasons = array_filter($reasons, function ($reason) use ($NSFWtags) {
if ($reason->getReasonCode() == REASON::REASON_NSFW
&& in_array($reason->getSubreasonCode(), $NSFWtags, true)) {
&& in_array($reason->getSubreasonCode(), $NSFWtags, false)) {
return false;
}
......
......@@ -96,7 +96,7 @@ class Indexes
$guids = $entity->{"thumbs:{$direction}:user_guids"} ?: [];
return in_array($actor->guid, $guids, true);
return in_array($actor->guid, $guids, false);
}
/**
......
......@@ -560,7 +560,7 @@ class Group extends NormalizedEntity
$user_guid = is_object($user) ? $user->guid : $user;
return $this->isCreator($user) || in_array($user_guid, $this->getOwnerGuids(), true);
return $this->isCreator($user) || in_array($user_guid, $this->getOwnerGuids(), false);
}
/**
......
......@@ -13,6 +13,7 @@ use Minds\Entities\Activity;
use Minds\Entities\User;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Minds\Core\Di\Di;
class ManagerSpec extends ObjectBehavior
{
......@@ -271,12 +272,12 @@ class ManagerSpec extends ObjectBehavior
public function it_should_check_if_the_entity_was_already_boosted(Boost $boost)
{
$this->elasticRepository->getList([
'hydrate' => true,
'useElastic' => true,
'state' => 'review',
'type' => 'newsfeed',
'entity_guid' => '123',
'limit' => 1,
'hydrate' => true,
'limit' => 1
])
->shouldBeCalled()
->willReturn(new Response([$boost], ''));
......@@ -295,4 +296,109 @@ class ManagerSpec extends ObjectBehavior
$this->checkExisting($boost)->shouldReturn(true);
}
public function it_should_request_offchain_boosts(Boost $boost)
{
$this->elasticRepository->getList([
"hydrate" => true,
"useElastic" => true,
"state" => "active",
"type" => "newsfeed",
"limit" => 10,
"order" => "desc",
"offchain" => true,
"owner_guid" => "123"
])
->shouldBeCalled()
->willReturn(new Response([$boost], ''));
$this->repository->getList(Argument::any())
->shouldBeCalled()
->willReturn(new Response([$boost]));
$boost->getType()
->shouldBeCalled()
->willReturn('newsfeed');
$boost->getOwnerGuid()
->shouldBeCalled()
->willReturn('123');
$this->getOffchainBoosts($boost)->shouldHaveType('Minds\Common\Repository\Response');
}
public function it_should_recognise_a_user_has_reached_the_offchain_boost_limit(Boost $boost)
{
$boostArray = [];
for ($i = 0; $i < 10; $i++) {
$newBoost = new Boost();
$newBoost->setCreatedTimestamp('9999999999999999');
$newBoost->setImpressions(1000);
array_push($boostArray, $newBoost);
}
Di::_()->get('Config')->set('max_daily_boost_views', 10000);
$this->runThroughGetList($boost, $boostArray);
$this->isBoostLimitExceededBy($boost)->shouldReturn(true);
}
public function it_should_recognise_a_user_has_NOT_reached_the_offchain_boost_limit(Boost $boost)
{
$boostArray = [];
for ($i = 0; $i < 9; $i++) {
$newBoost = new Boost();
$newBoost->setCreatedTimestamp('9999999999999999');
$newBoost->setImpressions(1000);
array_push($boostArray, $newBoost);
}
Di::_()->get('Config')->set('max_daily_boost_views', 10000);
$this->runThroughGetList($boost, $boostArray);
$this->isBoostLimitExceededBy($boost)->shouldReturn(false);
}
public function it_should_recognise_a_boost_would_take_user_above_offchain_limit(Boost $boost)
{
$boostArray = [];
for ($i = 0; $i < 2; $i++) {
$newBoost = new Boost();
$newBoost->setCreatedTimestamp('9999999999999999');
$newBoost->setImpressions(4501);
array_push($boostArray, $newBoost);
}
Di::_()->get('Config')->set('max_daily_boost_views', 10000);
$this->runThroughGetList($boost, $boostArray);
$this->isBoostLimitExceededBy($boost)->shouldReturn(true);
}
public function runThroughGetList($boost, $existingBoosts)
{
$this->elasticRepository->getList([
"hydrate" => true,
"useElastic" => true,
"state" => "active",
"type" => "newsfeed",
"limit" => 10,
"order" => "desc",
"offchain" => true,
"owner_guid" => "123"
])
->shouldBeCalled()
->willReturn(new Response($existingBoosts, ''));
$this->repository->getList(Argument::any())
->shouldBeCalled()
->willReturn(new Response($existingBoosts));
$boost->getType()
->shouldBeCalled()
->willReturn('newsfeed');
$boost->getOwnerGuid()
->shouldBeCalled()
->willReturn('123');
$boost->getImpressions()
->shouldBeCalled()
->willReturn(1000);
}
}
......@@ -269,6 +269,9 @@ $CONFIG->set('boost', [
],
]);
/* Maximum view per day */
$CONFIG->set('max_daily_boost_views', 10000);
$CONFIG->set('encryptionKeys', [
'email' => [
'private' => '{{email-private-key}}',
......