mirror of
https://github.com/openvk/openvk
synced 2024-11-14 19:19:14 +03:00
Notifications: WIP: Add ajax notifications :D
This commit is contained in:
parent
931f2a1149
commit
0b7b67e2e7
10 changed files with 244 additions and 27 deletions
83
ServiceAPI/Notifications.php
Normal file
83
ServiceAPI/Notifications.php
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\ServiceAPI;
|
||||||
|
use Latte\Engine as TemplatingEngine;
|
||||||
|
use RdKafka\{Conf as RDKConf, KafkaConsumer};
|
||||||
|
use openvk\Web\Models\Entities\User;
|
||||||
|
use openvk\Web\Models\Repositories\{Notifications as N};
|
||||||
|
|
||||||
|
class Notifications implements Handler
|
||||||
|
{
|
||||||
|
protected $user;
|
||||||
|
protected $notifs;
|
||||||
|
|
||||||
|
function __construct(?User $user)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
$this->notifs = new N;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ack(callable $resolve, callable $reject): void
|
||||||
|
{
|
||||||
|
$this->user->updateNotificationOffset();
|
||||||
|
$this->user->save();
|
||||||
|
$resolve("OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetch(callable $resolve, callable $reject): void
|
||||||
|
{
|
||||||
|
$kafkaConf = OPENVK_ROOT_CONF["openvk"]["credentials"]["notificationsBroker"];
|
||||||
|
if(!$kafkaConf["enable"]) {
|
||||||
|
$reject(1999, "Disabled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$kafkaConf = $kafkaConf["kafka"];
|
||||||
|
$conf = new RDKConf();
|
||||||
|
$conf->set("metadata.broker.list", $kafkaConf["addr"] . ":" . $kafkaConf["port"]);
|
||||||
|
$conf->set("group.id", "UserFetch-" . $this->user->getId()); # Чтобы уведы приходили только на разные устройства одного чебупелика
|
||||||
|
$conf->set("auto.offset.reset", "latest");
|
||||||
|
|
||||||
|
set_time_limit(30);
|
||||||
|
$consumer = new KafkaConsumer($conf);
|
||||||
|
$consumer->subscribe([ $kafkaConf["topic"] ]);
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
$message = $consumer->consume(30*1000);
|
||||||
|
switch ($message->err) {
|
||||||
|
case RD_KAFKA_RESP_ERR_NO_ERROR:
|
||||||
|
$descriptor = $message->payload;
|
||||||
|
[,$user,] = explode(",", $descriptor);
|
||||||
|
if(((int) $user) === $this->user->getId()) {
|
||||||
|
$data = (object) [];
|
||||||
|
$notification = $this->notifs->fromDescriptor($descriptor, $data);
|
||||||
|
if(!$notification) {
|
||||||
|
$reject(1982, "Server Error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tplDir = __DIR__ . "/../Web/Presenters/templates/components/notifications/";
|
||||||
|
$tplId = "$tplDir$data->actionCode/_$data->originModelType" . "_" . $data->targetModelType . "_.xml";
|
||||||
|
$latte = new TemplatingEngine;
|
||||||
|
$latte->setTempDirectory(CHANDLER_ROOT . "/tmp/cache/templates");
|
||||||
|
$latte->addFilter("translate", fn($trId) => tr($trId));
|
||||||
|
$resolve([
|
||||||
|
"title" => tr("notif_" . $data->actionCode . "_" . $data->originModelType . "_" . $data->targetModelType),
|
||||||
|
"body" => trim(preg_replace('%(\s){2,}%', "$1", $latte->renderToString($tplId, ["notification" => $notification]))),
|
||||||
|
"ava" => $notification->getModel(1)->getAvatarUrl(),
|
||||||
|
"priority" => 1,
|
||||||
|
]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case RD_KAFKA_RESP_ERR__TIMED_OUT:
|
||||||
|
case RD_KAFKA_RESP_ERR__PARTITION_EOF:
|
||||||
|
$reject(1983, "Nothing to report");
|
||||||
|
break 2;
|
||||||
|
default:
|
||||||
|
$reject(1981, "Kafka Error: " . $message->errstr());
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ namespace openvk\Web\Models\Entities\Notifications;
|
||||||
use openvk\Web\Models\RowModel;
|
use openvk\Web\Models\RowModel;
|
||||||
use openvk\Web\Models\Entities\{User};
|
use openvk\Web\Models\Entities\{User};
|
||||||
use openvk\Web\Util\DateTime;
|
use openvk\Web\Util\DateTime;
|
||||||
|
use RdKafka\{Conf, Producer};
|
||||||
|
|
||||||
class Notification
|
class Notification
|
||||||
{
|
{
|
||||||
|
@ -80,14 +81,14 @@ class Notification
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
$this->recipient->getId(),
|
"recipient" => $this->recipient->getId(),
|
||||||
$this->encodeType($this->originModel),
|
"originModelType" => $this->encodeType($this->originModel),
|
||||||
$this->originModel->getId(),
|
"originModelId" => $this->originModel->getId(),
|
||||||
$this->encodeType($this->targetModel),
|
"targetModelType" => $this->encodeType($this->targetModel),
|
||||||
$this->targetModel->getId(),
|
"targetModelId" => $this->targetModel->getId(),
|
||||||
$this->actionCode,
|
"actionCode" => $this->actionCode,
|
||||||
$this->data,
|
"additionalPayload" => $this->data,
|
||||||
$this->time,
|
"timestamp" => $this->time,
|
||||||
];
|
];
|
||||||
|
|
||||||
$edb = $e->getConnection();
|
$edb = $e->getConnection();
|
||||||
|
@ -96,12 +97,33 @@ class Notification
|
||||||
$query = <<<'QUERY'
|
$query = <<<'QUERY'
|
||||||
SELECT * FROM `notifications` WHERE `recipientType`=0 AND `recipientId`=? AND `originModelType`=? AND `originModelId`=? AND `targetModelType`=? AND `targetModelId`=? AND `modelAction`=? AND `additionalData`=? AND `timestamp` > (? - ?)
|
SELECT * FROM `notifications` WHERE `recipientType`=0 AND `recipientId`=? AND `originModelType`=? AND `originModelId`=? AND `targetModelType`=? AND `targetModelId`=? AND `modelAction`=? AND `additionalData`=? AND `timestamp` > (? - ?)
|
||||||
QUERY;
|
QUERY;
|
||||||
$result = $edb->query($query, ...array_merge($data, [ $this->threshold ]));
|
$result = $edb->query($query, ...array_merge(array_values($data), [ $this->threshold ]));
|
||||||
if($result->getRowCount() > 0)
|
if($result->getRowCount() > 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$edb->query("INSERT INTO notifications VALUES (0, ?, ?, ?, ?, ?, ?, ?, ?)", ...$data);
|
$edb->query("INSERT INTO notifications VALUES (0, ?, ?, ?, ?, ?, ?, ?, ?)", ...array_values($data));
|
||||||
|
|
||||||
|
$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);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,19 @@ class Notifications
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function assemble(int $act, int $originModelType, int $originModelId, int $targetModelType, int $targetModelId, int $recipientId, int $timestamp, $data, ?string $class = NULL): Notification
|
||||||
|
{
|
||||||
|
$class ??= 'openvk\Web\Models\Entities\Notifications\Notification';
|
||||||
|
|
||||||
|
$originModel = $this->getModel($originModelType, $originModelId);
|
||||||
|
$targetModel = $this->getModel($targetModelType, $targetModelId);
|
||||||
|
$recipient = (new Users)->get($recipientId);
|
||||||
|
|
||||||
|
$notification = new $class($recipient, $originModel, $targetModel, $timestamp, $data);
|
||||||
|
$notification->setActionCode($act);
|
||||||
|
return $notification;
|
||||||
|
}
|
||||||
|
|
||||||
function getNotificationCountByUser(User $user, int $offset, bool $archived = false): int
|
function getNotificationCountByUser(User $user, int $offset, bool $archived = false): int
|
||||||
{
|
{
|
||||||
$db = $this->getEDB(false);
|
$db = $this->getEDB(false);
|
||||||
|
@ -64,13 +77,38 @@ class Notifications
|
||||||
|
|
||||||
$results = $this->getEDB()->query($this->getQuery($user, false, $offset, $archived, $page, $perPage));
|
$results = $this->getEDB()->query($this->getQuery($user, false, $offset, $archived, $page, $perPage));
|
||||||
foreach($results->fetchAll() as $notif) {
|
foreach($results->fetchAll() as $notif) {
|
||||||
$originModel = $this->getModel($notif->originModelType, $notif->originModelId);
|
yield $this->assemble(
|
||||||
$targetModel = $this->getModel($notif->targetModelType, $notif->targetModelId);
|
$notif->modelAction,
|
||||||
$recipient = (new Users)->get($notif->recipientId);
|
$notif->originModelType,
|
||||||
|
$notif->originModelId,
|
||||||
|
|
||||||
$notification = new Notification($recipient, $originModel, $targetModel, $notif->timestamp, $notif->additionalData);
|
$notif->targetModelType,
|
||||||
$notification->setActionCode($notif->modelAction);
|
$notif->targetModelId,
|
||||||
yield $notification;
|
|
||||||
|
$notif->recipientId,
|
||||||
|
$notif->timestamp,
|
||||||
|
$notif->additionalData
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fromDescriptor(string $descriptor, ?object &$parsedData = nullptr)
|
||||||
|
{
|
||||||
|
[$class, $recv, $data] = explode(",", $descriptor);
|
||||||
|
$class = str_replace(".", "\\", $class);
|
||||||
|
|
||||||
|
$parsedData = unserialize(base64_decode($data));
|
||||||
|
return $this->assemble(
|
||||||
|
$parsedData->actionCode,
|
||||||
|
$parsedData->originModelType,
|
||||||
|
$parsedData->originModelId,
|
||||||
|
|
||||||
|
$parsedData->targetModelType,
|
||||||
|
$parsedData->targetModelId,
|
||||||
|
|
||||||
|
$parsedData->recipient,
|
||||||
|
$parsedData->timestamp,
|
||||||
|
$parsedData->additionalPayload,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,8 +58,8 @@ final class InternalAPIPresenter extends OpenVKPresenter
|
||||||
try {
|
try {
|
||||||
$params = array_merge($input->params ?? [], [function($data) {
|
$params = array_merge($input->params ?? [], [function($data) {
|
||||||
$this->succ($data);
|
$this->succ($data);
|
||||||
}, function($data) {
|
}, function(int $errno, string $errstr) {
|
||||||
$this->fail($data);
|
$this->fail($errno, $errstr);
|
||||||
}]);
|
}]);
|
||||||
$handler->{$method}(...$params);
|
$handler->{$method}(...$params);
|
||||||
} catch(\TypeError $te) {
|
} catch(\TypeError $te) {
|
||||||
|
|
|
@ -252,12 +252,13 @@
|
||||||
<a href="/privacy" class="link">{_footer_privacy}</a>
|
<a href="/privacy" class="link">{_footer_privacy}</a>
|
||||||
</div>
|
</div>
|
||||||
<p>OpenVK <a href="/about:openvk2">{php echo OPENVK_VERSION}</a> | PHP: {phpversion()} | DB: {$dbVersion}</p>
|
<p>OpenVK <a href="/about:openvk2">{php echo OPENVK_VERSION}</a> | PHP: {phpversion()} | DB: {$dbVersion}</p>
|
||||||
<p n:ifcontent>
|
<p n:ifcontent="ifcontent">
|
||||||
{php echo OPENVK_ROOT_CONF["openvk"]["appearance"]["motd"]}
|
{php echo OPENVK_ROOT_CONF["openvk"]["appearance"]["motd"]}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://rawgit.com/kawanet/msgpack-lite/master/dist/msgpack.min.js"></script>
|
{script "js/node_modules/msgpack-lite/dist/msgpack.min.js"}
|
||||||
|
{script "js/node_modules/soundjs/lib/soundjs.min.js"}
|
||||||
{script "js/node_modules/ky/umd.js"}
|
{script "js/node_modules/ky/umd.js"}
|
||||||
{script "js/messagebox.js"}
|
{script "js/messagebox.js"}
|
||||||
{script "js/notifications.js"}
|
{script "js/notifications.js"}
|
||||||
|
@ -265,6 +266,10 @@
|
||||||
{script "js/al_wall.js"}
|
{script "js/al_wall.js"}
|
||||||
{script "js/al_api.js"}
|
{script "js/al_api.js"}
|
||||||
|
|
||||||
|
{ifset $thisUser}
|
||||||
|
{script "js/al_notifs.js"}
|
||||||
|
{/ifset}
|
||||||
|
|
||||||
<script src="https://unpkg.com/fartscroll@1.0.0/fartscroll.js"></script>
|
<script src="https://unpkg.com/fartscroll@1.0.0/fartscroll.js"></script>
|
||||||
<script n:if="OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['fartscroll']">
|
<script n:if="OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['fartscroll']">
|
||||||
fartscroll(400);
|
fartscroll(400);
|
||||||
|
|
|
@ -4,8 +4,3 @@
|
||||||
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
|
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
|
||||||
{$notification->getDateTime()} {_nt_liked_yours}
|
{$notification->getDateTime()} {_nt_liked_yours}
|
||||||
<a href="/wall{$post->getPrettyId()}"><b>{_nt_post_nominative}</b></a> {_nt_from} {$post->getPublicationTime()}.
|
<a href="/wall{$post->getPrettyId()}"><b>{_nt_post_nominative}</b></a> {_nt_from} {$post->getPublicationTime()}.
|
||||||
|
|
||||||
<?php
|
|
||||||
// костыльно скрыл лол, сами исправите проблему - гфх
|
|
||||||
//{tr('notifications_like', '<a href="'.$user->getURL().'"><b>'.$user->getCanonicalName().'</b></a>', '<a href="/wall'.$post->getPrettyId().'"><b>', '</b></a>', $post->getPublicationTime())}
|
|
||||||
?>
|
|
||||||
|
|
BIN
Web/static/audio/Bruh.mp3
Normal file
BIN
Web/static/audio/Bruh.mp3
Normal file
Binary file not shown.
37
Web/static/js/al_notifs.js
Normal file
37
Web/static/js/al_notifs.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
createjs.Sound.registerSound("/assets/packages/static/openvk/audio/Bruh.mp3", "notification");
|
||||||
|
|
||||||
|
function __actualPlayNotifSound() {
|
||||||
|
createjs.Sound.play("notification");
|
||||||
|
}
|
||||||
|
|
||||||
|
window.playNotifSound = Function.noop;
|
||||||
|
|
||||||
|
async function setupNotificationListener() {
|
||||||
|
console.warn("Setting up notifications listener...");
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
let notif;
|
||||||
|
try {
|
||||||
|
notif = await API.Notifications.fetch();
|
||||||
|
} catch(rejection) {
|
||||||
|
if(rejection.message !== "Nothing to report") {
|
||||||
|
console.error(rejection);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.info("No new notifications discovered... Redialing event broker");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
playNotifSound();
|
||||||
|
NewNotification(notif.title, notif.body, notif.ava, Function.noop, notif.priority * 6000);
|
||||||
|
console.info("New notification", notif);
|
||||||
|
|
||||||
|
API.Notifications.ack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setupNotificationListener();
|
||||||
|
|
||||||
|
u(document.body).on("click", () => window.playNotifSound = window.__actualPlayNotifSound);
|
|
@ -7,11 +7,13 @@
|
||||||
"ky": "^0.19.0",
|
"ky": "^0.19.0",
|
||||||
"literallycanvas": "^0.5.2",
|
"literallycanvas": "^0.5.2",
|
||||||
"monaco-editor": "^0.20.0",
|
"monaco-editor": "^0.20.0",
|
||||||
|
"msgpack-lite": "^0.1.26",
|
||||||
"plotly.js-dist": "^1.52.3",
|
"plotly.js-dist": "^1.52.3",
|
||||||
"react": "15.1",
|
"react": "15.1",
|
||||||
"react-dom": "15.1",
|
"react-dom": "15.1",
|
||||||
"react-dom-factories": "^1.0.2",
|
"react-dom-factories": "^1.0.2",
|
||||||
"requirejs": "^2.3.6",
|
"requirejs": "^2.3.6",
|
||||||
|
"soundjs": "^1.0.1",
|
||||||
"umbrellajs": "^3.1.0"
|
"umbrellajs": "^3.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,11 @@ encoding@^0.1.11:
|
||||||
dependencies:
|
dependencies:
|
||||||
iconv-lite "^0.6.2"
|
iconv-lite "^0.6.2"
|
||||||
|
|
||||||
|
event-lite@^0.1.1:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/event-lite/-/event-lite-0.1.2.tgz#838a3e0fdddef8cc90f128006c8e55a4e4e4c11b"
|
||||||
|
integrity sha512-HnSYx1BsJ87/p6swwzv+2v6B4X+uxUteoDfRxsAb1S1BePzQqOLevVmkdA15GHJVd9A9Ok6wygUR18Hu0YeV9g==
|
||||||
|
|
||||||
fancy-file-input@~2.0.4:
|
fancy-file-input@~2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/fancy-file-input/-/fancy-file-input-2.0.4.tgz#698c216482e07649a827681c4db3054fddc9a32b"
|
resolved "https://registry.yarnpkg.com/fancy-file-input/-/fancy-file-input-2.0.4.tgz#698c216482e07649a827681c4db3054fddc9a32b"
|
||||||
|
@ -91,11 +96,26 @@ iconv-lite@^0.6.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3.0.0"
|
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||||
|
|
||||||
|
ieee754@^1.1.8:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||||
|
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||||
|
|
||||||
|
int64-buffer@^0.1.9:
|
||||||
|
version "0.1.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/int64-buffer/-/int64-buffer-0.1.10.tgz#277b228a87d95ad777d07c13832022406a473423"
|
||||||
|
integrity sha1-J3siiofZWtd30HwTgyAiQGpHNCM=
|
||||||
|
|
||||||
is-stream@^1.0.1:
|
is-stream@^1.0.1:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||||
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
|
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
|
||||||
|
|
||||||
|
isarray@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||||
|
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||||
|
|
||||||
isomorphic-fetch@^2.1.1:
|
isomorphic-fetch@^2.1.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
|
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
|
||||||
|
@ -148,6 +168,16 @@ monaco-editor@^0.20.0:
|
||||||
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
|
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
|
||||||
integrity sha512-hkvf4EtPJRMQlPC3UbMoRs0vTAFAYdzFQ+gpMb8A+9znae1c43q8Mab9iVsgTcg/4PNiLGGn3SlDIa8uvK1FIQ==
|
integrity sha512-hkvf4EtPJRMQlPC3UbMoRs0vTAFAYdzFQ+gpMb8A+9znae1c43q8Mab9iVsgTcg/4PNiLGGn3SlDIa8uvK1FIQ==
|
||||||
|
|
||||||
|
msgpack-lite@^0.1.26:
|
||||||
|
version "0.1.26"
|
||||||
|
resolved "https://registry.yarnpkg.com/msgpack-lite/-/msgpack-lite-0.1.26.tgz#dd3c50b26f059f25e7edee3644418358e2a9ad89"
|
||||||
|
integrity sha1-3TxQsm8FnyXn7e42REGDWOKprYk=
|
||||||
|
dependencies:
|
||||||
|
event-lite "^0.1.1"
|
||||||
|
ieee754 "^1.1.8"
|
||||||
|
int64-buffer "^0.1.9"
|
||||||
|
isarray "^1.0.0"
|
||||||
|
|
||||||
node-fetch@^1.0.1:
|
node-fetch@^1.0.1:
|
||||||
version "1.7.3"
|
version "1.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
|
||||||
|
@ -229,6 +259,11 @@ skatejs@0.13.17:
|
||||||
resolved "https://registry.yarnpkg.com/skatejs/-/skatejs-0.13.17.tgz#7a21fbb3434da45e52b47b61647168ee9e778071"
|
resolved "https://registry.yarnpkg.com/skatejs/-/skatejs-0.13.17.tgz#7a21fbb3434da45e52b47b61647168ee9e778071"
|
||||||
integrity sha1-eiH7s0NNpF5StHthZHFo7p53gHE=
|
integrity sha1-eiH7s0NNpF5StHthZHFo7p53gHE=
|
||||||
|
|
||||||
|
soundjs@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/soundjs/-/soundjs-1.0.1.tgz#99970542d28d0df2a1ebd061ae75c961a98c8180"
|
||||||
|
integrity sha512-MgFPvmKYfpcNiE3X5XybNvScie3DMQlZgmNzUn4puBcpw64f4LqjH/fhM8Sb/eTJ8hK57Crr7mWy0bfJOqPj6Q==
|
||||||
|
|
||||||
trim-extra-html-whitespace@1.3.0:
|
trim-extra-html-whitespace@1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/trim-extra-html-whitespace/-/trim-extra-html-whitespace-1.3.0.tgz#b47efb0d1a5f2a56a85cc45cea525651e93404cf"
|
resolved "https://registry.yarnpkg.com/trim-extra-html-whitespace/-/trim-extra-html-whitespace-1.3.0.tgz#b47efb0d1a5f2a56a85cc45cea525651e93404cf"
|
||||||
|
|
Loading…
Reference in a new issue