2020-06-07 19:04:43 +03:00
|
|
|
|
<?php declare(strict_types=1);
|
|
|
|
|
namespace openvk\Web\Models\Entities\Notifications;
|
|
|
|
|
use openvk\Web\Models\RowModel;
|
|
|
|
|
use openvk\Web\Models\Entities\{User};
|
|
|
|
|
use openvk\Web\Util\DateTime;
|
2021-10-15 23:05:27 +03:00
|
|
|
|
use RdKafka\{Conf, Producer};
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
class Notification
|
|
|
|
|
{
|
|
|
|
|
private $recipient;
|
|
|
|
|
private $originModel;
|
|
|
|
|
private $targetModel;
|
|
|
|
|
private $time;
|
|
|
|
|
private $data;
|
|
|
|
|
|
|
|
|
|
protected $actionCode = NULL;
|
2020-07-15 15:32:34 +03:00
|
|
|
|
protected $threshold = -1;
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
function __construct(User $recipient, $originModel, $targetModel, ?int $time = NULL, string $data = "")
|
|
|
|
|
{
|
|
|
|
|
$this->recipient = $recipient;
|
|
|
|
|
$this->originModel = $originModel;
|
|
|
|
|
$this->targetModel = $targetModel;
|
|
|
|
|
$this->time = $time ?? time();
|
|
|
|
|
$this->data = $data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function encodeType(object $model): int
|
|
|
|
|
{
|
|
|
|
|
return (int) json_decode(file_get_contents(__DIR__ . "/../../../../data/modelCodes.json"), true)[get_class($model)];
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-10 22:33:13 +03:00
|
|
|
|
function reverseModelOrder(): bool
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-07 19:04:43 +03:00
|
|
|
|
function getActionCode(): int
|
|
|
|
|
{
|
|
|
|
|
return $this->actionCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setActionCode(int $code): void
|
|
|
|
|
{
|
|
|
|
|
$this->actionCode = $this->actionCode ?? $code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getTemplatePath(): string
|
|
|
|
|
{
|
|
|
|
|
return implode("_", [
|
|
|
|
|
"./../components/notifications/$this->actionCode/",
|
|
|
|
|
$this->encodeType($this->originModel),
|
|
|
|
|
$this->encodeType($this->targetModel),
|
|
|
|
|
".xml"
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getRecipient(): User
|
|
|
|
|
{
|
|
|
|
|
return $this->recipient;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getModel(int $index): RowModel
|
|
|
|
|
{
|
|
|
|
|
switch($index) {
|
|
|
|
|
case 0:
|
|
|
|
|
return $this->originModel;
|
|
|
|
|
case 1:
|
|
|
|
|
return $this->targetModel;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getData(): string
|
|
|
|
|
{
|
|
|
|
|
return $this->data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getDateTime(): DateTime
|
|
|
|
|
{
|
|
|
|
|
return new DateTime($this->time);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function emit(): bool
|
|
|
|
|
{
|
|
|
|
|
if(!($e = eventdb()))
|
|
|
|
|
return false;
|
|
|
|
|
|
2020-07-15 15:32:34 +03:00
|
|
|
|
$data = [
|
2021-10-15 23:05:27 +03:00
|
|
|
|
"recipient" => $this->recipient->getId(),
|
|
|
|
|
"originModelType" => $this->encodeType($this->originModel),
|
|
|
|
|
"originModelId" => $this->originModel->getId(),
|
|
|
|
|
"targetModelType" => $this->encodeType($this->targetModel),
|
|
|
|
|
"targetModelId" => $this->targetModel->getId(),
|
|
|
|
|
"actionCode" => $this->actionCode,
|
|
|
|
|
"additionalPayload" => $this->data,
|
|
|
|
|
"timestamp" => $this->time,
|
2020-07-15 15:32:34 +03:00
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$edb = $e->getConnection();
|
|
|
|
|
if($this->threshold !== -1) {
|
|
|
|
|
# Event is thersholded, check if there is similar event
|
|
|
|
|
$query = <<<'QUERY'
|
|
|
|
|
SELECT * FROM `notifications` WHERE `recipientType`=0 AND `recipientId`=? AND `originModelType`=? AND `originModelId`=? AND `targetModelType`=? AND `targetModelId`=? AND `modelAction`=? AND `additionalData`=? AND `timestamp` > (? - ?)
|
|
|
|
|
QUERY;
|
2021-10-15 23:05:27 +03:00
|
|
|
|
$result = $edb->query($query, ...array_merge(array_values($data), [ $this->threshold ]));
|
2020-07-15 15:32:34 +03:00
|
|
|
|
if($result->getRowCount() > 0)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-10-15 23:05:27 +03:00
|
|
|
|
|
|
|
|
|
$edb->query("INSERT INTO notifications VALUES (0, ?, ?, ?, ?, ?, ?, ?, ?)", ...array_values($data));
|
2020-07-15 15:32:34 +03:00
|
|
|
|
|
2021-10-15 23:05:27 +03:00
|
|
|
|
$kafkaConf = OPENVK_ROOT_CONF["openvk"]["credentials"]["notificationsBroker"];
|
|
|
|
|
if($kafkaConf["enable"]) {
|
|
|
|
|
$kafkaConf = $kafkaConf["kafka"];
|
|
|
|
|
$brokerConf = new Conf();
|
|
|
|
|
$brokerConf->set("log_level", (string) LOG_DEBUG);
|
|
|
|
|
$brokerConf->set("debug", "all");
|
|
|
|
|
|
|
|
|
|
$producer = new Producer($brokerConf);
|
|
|
|
|
$producer->addBrokers($kafkaConf["addr"] . ":" . $kafkaConf["port"]);
|
|
|
|
|
|
|
|
|
|
$descriptor = implode(",", [
|
|
|
|
|
str_replace("\\", ".", get_class($this)),
|
|
|
|
|
$this->recipient->getId(),
|
|
|
|
|
base64_encode(serialize((object) $data)),
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$notifTopic = $producer->newTopic($kafkaConf["topic"]);
|
|
|
|
|
$notifTopic->produce(RD_KAFKA_PARTITION_UA, RD_KAFKA_MSG_F_BLOCK, $descriptor);
|
|
|
|
|
$producer->flush(100);
|
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2023-11-14 22:44:39 +03:00
|
|
|
|
|
|
|
|
|
function getVkApiInfo()
|
|
|
|
|
{
|
|
|
|
|
$origin_m = $this->encodeType($this->originModel);
|
|
|
|
|
$target_m = $this->encodeType($this->targetModel);
|
|
|
|
|
|
|
|
|
|
$info = [
|
|
|
|
|
"type" => "",
|
|
|
|
|
"parent" => NULL,
|
|
|
|
|
"feedback" => NULL,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
switch($this->getActionCode()) {
|
|
|
|
|
case 0:
|
|
|
|
|
$info["type"] = "like_post";
|
|
|
|
|
$info["parent"] = $this->getModel(0)->toNotifApiStruct();
|
|
|
|
|
$info["feedback"] = $this->getModel(1)->toVkApiStruct();
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
$info["type"] = "copy_post";
|
|
|
|
|
$info["parent"] = $this->getModel(0)->toNotifApiStruct();
|
|
|
|
|
$info["feedback"] = NULL; # todo
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
switch($origin_m) {
|
|
|
|
|
case 19:
|
|
|
|
|
$info["type"] = "comment_video";
|
|
|
|
|
$info["parent"] = $this->getModel(0)->toNotifApiStruct();
|
|
|
|
|
$info["feedback"] = NULL; # айди коммента не сохраняется в бд( ну пиздец блять
|
|
|
|
|
break;
|
|
|
|
|
case 13:
|
|
|
|
|
$info["type"] = "comment_photo";
|
|
|
|
|
$info["parent"] = $this->getModel(0)->toNotifApiStruct();
|
|
|
|
|
$info["feedback"] = NULL;
|
|
|
|
|
break;
|
|
|
|
|
# unstandart (vk forgor about notes)
|
|
|
|
|
case 10:
|
|
|
|
|
$info["type"] = "comment_note";
|
|
|
|
|
$info["parent"] = $this->getModel(0)->toVkApiStruct();
|
|
|
|
|
$info["feedback"] = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case 14:
|
|
|
|
|
$info["type"] = "comment_post";
|
|
|
|
|
$info["parent"] = $this->getModel(0)->toNotifApiStruct();
|
|
|
|
|
$info["feedback"] = NULL;
|
|
|
|
|
break;
|
|
|
|
|
# unused (users don't have topics bruh)
|
|
|
|
|
case 21:
|
|
|
|
|
$info["type"] = "comment_topic";
|
|
|
|
|
$info["parent"] = $this->getModel(0)->toVkApiStruct(0, 90);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
$info["type"] = "comment_unknown";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
$info["type"] = "wall";
|
|
|
|
|
$info["feedback"] = $this->getModel(0)->toNotifApiStruct();
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
switch($target_m) {
|
|
|
|
|
case 14:
|
|
|
|
|
$info["type"] = "mention";
|
|
|
|
|
$info["feedback"] = $this->getModel(1)->toNotifApiStruct();
|
|
|
|
|
break;
|
|
|
|
|
case 19:
|
|
|
|
|
$info["type"] = "mention_comment_video";
|
|
|
|
|
$info["parent"] = $this->getModel(1)->toNotifApiStruct();
|
|
|
|
|
break;
|
|
|
|
|
case 13:
|
|
|
|
|
$info["type"] = "mention_comment_photo";
|
|
|
|
|
$info["parent"] = $this->getModel(1)->toNotifApiStruct();
|
|
|
|
|
break;
|
|
|
|
|
# unstandart
|
|
|
|
|
case 10:
|
|
|
|
|
$info["type"] = "mention_comment_note";
|
|
|
|
|
$info["parent"] = $this->getModel(1)->toVkApiStruct();
|
|
|
|
|
break;
|
|
|
|
|
case 21:
|
|
|
|
|
$info["type"] = "mention_comments";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
$info["type"] = "mention_comment_unknown";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
$info["type"] = "make_you_admin";
|
|
|
|
|
$info["parent"] = $this->getModel(0)->toVkApiStruct($this->getModel(1));
|
|
|
|
|
break;
|
|
|
|
|
# Нужно доделать после мержа #935
|
|
|
|
|
case 6:
|
|
|
|
|
$info["type"] = "wall_publish";
|
|
|
|
|
break;
|
|
|
|
|
# В вк не было такого уведомления, так что unstandart
|
|
|
|
|
case 7:
|
|
|
|
|
$info["type"] = "new_posts_in_club";
|
|
|
|
|
break;
|
|
|
|
|
# В вк при передаче подарков приходит сообщение, а не уведомление, так что unstandart
|
|
|
|
|
case 9601:
|
|
|
|
|
$info["type"] = "sent_gift";
|
|
|
|
|
$info["parent"] = $this->getModel(1)->toVkApiStruct($this->getModel(1));
|
|
|
|
|
break;
|
|
|
|
|
case 9602:
|
|
|
|
|
$info["type"] = "voices_transfer";
|
|
|
|
|
$info["parent"] = $this->getModel(1)->toVkApiStruct($this->getModel(1));
|
|
|
|
|
break;
|
|
|
|
|
case 9603:
|
|
|
|
|
$info["type"] = "up_rating";
|
|
|
|
|
$info["parent"] = $this->getModel(1)->toVkApiStruct($this->getModel(1));
|
|
|
|
|
$info["parent"]->count = $this->getData();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
$info["type"] = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toVkApiStruct()
|
|
|
|
|
{
|
|
|
|
|
$res = (object)[];
|
|
|
|
|
|
|
|
|
|
$info = $this->getVkApiInfo();
|
|
|
|
|
$res->type = $info["type"];
|
|
|
|
|
$res->date = $this->getDateTime()->timestamp();
|
|
|
|
|
$res->parent = $info["parent"];
|
|
|
|
|
$res->feedback = $info["feedback"];
|
|
|
|
|
$res->reply = NULL; # Ответы на комментарии не реализованы
|
|
|
|
|
return $res;
|
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|