Nextcloud-App/lib/Service/MatrixService.php

180 lines
5.3 KiB
PHP

<?php
namespace OCA\UPschooling\Service;
use Aryess\PhpMatrixSdk\Exceptions\MatrixException;
use Aryess\PhpMatrixSdk\Exceptions\MatrixHttpLibException;
use Aryess\PhpMatrixSdk\Exceptions\MatrixRequestException;
use Aryess\PhpMatrixSdk\Exceptions\ValidationException;
use Aryess\PhpMatrixSdk\MatrixClient;
use Aryess\PhpMatrixSdk\Room;
use OCA\UPschooling\Db\MatrixUser;
use OCA\UPschooling\Exceptions\RoomNotFoundException;
use Psr\Log\LoggerInterface;
class MatrixService
{
/** @var LoggerInterface */
private $logger;
/** @var MatrixClient */
private $client;
/** @var string */
private $registrationSecret = "oyYh_iEJ7Aim.iB+ye.Xk;Gl3iHFab5*8K,zv~IulT85P=c-38";
/**
* @throws MatrixRequestException
* @throws MatrixHttpLibException
* @throws ValidationException
* @throws MatrixException
*/
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
$serverUrl = "http://synapse:8008";
$user = "upschooling";
$this->client = new MatrixClient($serverUrl);
$this->client->login($user, "secret", true);
$this->logger->debug("Logged in as " . $user . " on server " . $serverUrl);
}
/**
* @param string $roomId a room id of an existing and joined room.
* @param string $eventType a unique property identifier with reverse domain notation, e.g. com.example.property.
* @param array $content the contents as a JSON serializable array.
* @throws RoomNotFoundException
* @throws MatrixException
*/
public function setProperty(string $roomId, string $eventType, array $content)
{
$room = $this->findRoom($roomId);
$room->sendStateEvent($eventType, $content);
$this->logger->debug(
"Set property " . $eventType . " on room " . $roomId,
array("room" => $roomId, "key" => $eventType, "value" => $content)
);
}
/**
* @param string $roomId a room id of an existing and joined room.
* @param string $eventType a unique property identifier with reverse domain notation, e.g. com.example.property.
* @return array the contents of the room state.
* @throws MatrixException
* @throws RoomNotFoundException
*/
public function getProperty(string $roomId, string $eventType): array
{
$this->findRoom($roomId); // make sure the room exists/is joined
$content = $this->client->api()->getStateEvent($roomId, $eventType);
$this->logger->debug(
"Got property " . $eventType . " from room " . $roomId,
array("room" => $roomId, "key" => $eventType, "value" => $content)
);
return $content;
}
/**
* @param string $roomId a room id of an existing and joined room.
* @throws RoomNotFoundException
* @returns int the origin server timestamp of the most recent event.
*/
public function getLastEventDate(string $roomId): int
{
$room = $this->findRoom($roomId);
$events = $room->getEvents();
if (count($events) === 0) {
$this->logger->debug("Did not have any events for room " . $roomId);
return 0;
} else {
$timestamp = array_get($events[0], 'origin_server_ts', 1);
if ($timestamp === 1) {
$this->logger->debug("Could not find origin_server_ts in last event of room " . $roomId);
} else {
$this->logger->debug("Last event in room " . $roomId . " was at " . $timestamp);
}
return $timestamp;
}
}
/**
* Registers a new matrix user with the local matrix server.
*
* @throws MatrixException
* @throws MatrixHttpLibException
* @throws MatrixRequestException
* @return MatrixUser user object without id or Nextcloud user id set.
*/
public function registerNewUser(): MatrixUser
{
$nonceResponse = $this->client->api()->send(
'GET',
'/register',
null,
[],
[],
'/_synapse/admin/v1',
true
);
$randUsername = trim(str_replace(["/", "+"], ".", base64_encode(random_bytes(6))), "=");
$username = "upschooling_" . $randUsername;
$password = base64_encode(random_bytes(32));
$hmacData = $nonceResponse["nonce"] . "\x00" . $username . "\x00" . $password . "\x00notadmin";
$hmac = hash_hmac("sha1", $hmacData, $this->registrationSecret, false);
$registrationResponse = $this->client->api()->send(
'POST',
'/register',
array(
"nonce" => $nonceResponse["nonce"],
"username" => $username,
"password" => $password,
"displayname" => "UPschooling Support User " . $randUsername,
"admin" => false,
"mac" => $hmac,
),
[],
[],
'/_synapse/admin/v1',
true
);
$matrixUser = new MatrixUser();
$matrixUser->setMatrixUser($registrationResponse["user_id"]);
$matrixUser->setMatrixToken($registrationResponse["access_token"]);
$this->logger->debug("Created a new user: " . $matrixUser->getMatrixUser());
return $matrixUser;
}
/**
* @param string $roomId a room id of an existing and joined room.
* @throws RoomNotFoundException
* @returns Room the room object, if found.
*/
private function findRoom(string $roomId): Room
{
foreach ($this->client->getRooms() as $room) {
if ($room->getRoomId() === $roomId) {
$this->logger->debug("Found room " . $roomId . " on matrix client");
return $room;
}
}
$this->logger->error("Room " . $roomId . " was not found on matrix client");
throw new RoomNotFoundException();
}
/**
* Creates a new room.
*
* @throws MatrixException
* @return string the room id of the newly created room.
*/
public function createRoom(): string
{
$roomId = $this->client->createRoom()->getRoomId();
$this->logger->debug("Created a new room: " . $roomId);
return $roomId;
}
}