114 lines
3.6 KiB
PHP
114 lines
3.6 KiB
PHP
<?php
|
|
namespace App\Websocket;
|
|
|
|
use Exception;
|
|
use Ratchet\ConnectionInterface;
|
|
use Ratchet\MessageComponentInterface;
|
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use SplObjectStorage;
|
|
|
|
class MessageHandler implements MessageComponentInterface
|
|
{
|
|
protected $container;
|
|
protected $em;
|
|
|
|
protected $clients;
|
|
private $subscriptions;
|
|
private $users;
|
|
|
|
public function __construct(ContainerInterface $container, EntityManagerInterface $em)
|
|
{
|
|
$this->container = $container;
|
|
$this->em = $em;
|
|
|
|
$this->clients = new SplObjectStorage;
|
|
$this->subscriptions = [];
|
|
$this->users = [];
|
|
$this->keys = [];
|
|
}
|
|
|
|
public function onOpen(ConnectionInterface $conn)
|
|
{
|
|
$this->clients->attach($conn);
|
|
$this->users[$conn->resourceId] = $conn;
|
|
}
|
|
|
|
public function onClose(ConnectionInterface $conn)
|
|
{
|
|
$data= new \stdClass;
|
|
$data->command = "adead";
|
|
$this->sendMessage($conn,$data,false);
|
|
|
|
$this->clients->detach($conn);
|
|
unset($this->users[$conn->resourceId]);
|
|
unset($this->keys[$conn->resourceId]);
|
|
unset($this->subscriptions[$conn->resourceId]);
|
|
}
|
|
|
|
public function onError(ConnectionInterface $conn, Exception $e)
|
|
{
|
|
$conn->close();
|
|
}
|
|
|
|
public function onMessage(ConnectionInterface $conn, $msg)
|
|
{
|
|
$data = json_decode($msg);
|
|
|
|
switch ($data->command) {
|
|
case "subscribe":
|
|
$this->subscriptions[$conn->resourceId] = $data->channel;
|
|
$this->keys[$conn->resourceId] = $data->key;
|
|
break;
|
|
|
|
case "meto":
|
|
if (isset($this->subscriptions[$conn->resourceId])) {
|
|
$this->sendMessage($conn,$data,false);
|
|
}
|
|
break;
|
|
|
|
case "alive":
|
|
default:
|
|
if (isset($this->subscriptions[$conn->resourceId])) {
|
|
$this->sendMessage($conn,$data);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
private function sendMessage(ConnectionInterface $conn, $data, $tome=true) {
|
|
$target = $this->subscriptions[$conn->resourceId];
|
|
foreach ($this->subscriptions as $id=>$channel) {
|
|
if ($channel == $target) {
|
|
if($tome||(!$tome&&$id!=$conn->resourceId)) {
|
|
// From
|
|
$key= $this->keys[$conn->resourceId];
|
|
$from=$this->em->getRepository("App:User")->findOneBy(["apikey"=>$key]);
|
|
|
|
// To
|
|
$key= $this->keys[$id];
|
|
$to=$this->em->getRepository("App:User")->findOneBy(["apikey"=>$key]);
|
|
|
|
// Send
|
|
if($from && $to) {
|
|
$data->from= new \stdClass;
|
|
$data->from->id = $from->getId();
|
|
$data->from->username = $from->getUsername();
|
|
$data->from->displayname = $from->getDisplayname();
|
|
$data->from->avatar = $this->getAvatar($from->getAvatar());
|
|
|
|
$data->log="== GET MSG from ".$data->from->username." to ".$to->getUsername()." = ".$data->command;
|
|
$this->users[$id]->send(json_encode($data));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private function getAvatar($avatar) {
|
|
if(stripos($avatar,"http")===0)
|
|
return $avatar;
|
|
else
|
|
return "/".$this->container->getParameter("appAlias")."/uploads/avatar/".$avatar;
|
|
}
|
|
} |