Add event participants to the Nextcloud Talk room

This commit is contained in:
Aleksander Machniak 2022-09-19 13:31:19 +02:00
parent b0f306eaf1
commit b06f1e3941
2 changed files with 146 additions and 2 deletions

View file

@ -1063,6 +1063,7 @@ $("#rcmfd_new_category").keypress(function(event) {
$this->cleanup_event($event);
$this->event_save_success($event, null, $action, true);
$this->talk_room_update($event);
}
$reload = $success && !empty($event['recurrence']) ? 2 : 1;
@ -1075,6 +1076,7 @@ $("#rcmfd_new_category").keypress(function(event) {
else if ($success = $this->driver->edit_event($event)) {
$this->cleanup_event($event);
$this->event_save_success($event, $old, $action, $success);
$this->talk_room_update($event);
}
$reload = $success && (!empty($event['recurrence']) || !empty($event['_savemode']) || !empty($event['_fromcalendar'])) ? 2 : 1;
@ -3895,6 +3897,44 @@ $("#rcmfd_new_category").keypress(function(event) {
}
}
/**
* Update a Nextcould Talk room
*/
public function talk_room_update($event)
{
// If a room is assigned to the event...
if (
($talk_url = $this->rc->config->get('calendar_nextcloud_url'))
&& isset($event['attendees'])
&& !empty($event['location'])
&& strpos($event['location'], unslashify($talk_url) . '/call/') === 0
) {
$participants = [];
$organizer = null;
// ollect participants' and organizer's email addresses
foreach ($event['attendees'] as $attendee) {
if (!empty($attendee['email'])) {
if ($attendee['role'] == 'ORGANIZER') {
$organizer = $attendee['email'];
}
else if ($attendee['cutype'] == 'INDIVIDUAL') {
$participants[] = $attendee['email'];
}
}
}
// If the event is owned by the current user update the room
if ($organizer && in_array($organizer, $this->get_user_emails())) {
require_once __DIR__ . '/lib/calendar_nextcloud_api.php';
$api = new calendar_nextcloud_api();
$api->talk_room_update($event['location'], $participants);
}
}
}
/**
* Get a list of email addresses of the current user (from login and identities)
*/

View file

@ -23,6 +23,14 @@
class calendar_nextcloud_api
{
const PARTICIPANT_OWNER = 1;
const PARTICIPANT_MODERATOR = 2;
const PARTICIPANT_USER = 3;
const PARTICIPANT_GUEST = 4;
const PARTICIPANT_PUBLIC = 5;
const PARTICIPANT_GUEST_MODERATOR = 6;
/**
* Make a request to the Nextcloud API
*
@ -56,15 +64,24 @@ class calendar_nextcloud_api
]);
if (!empty($params)) {
$request->addPostParameter($params);
if ($method == 'POST') {
$request->addPostParameter($params);
}
else {
$request->setUrl($url . '?' . http_build_query($params));
}
}
// rcube::console($method . ": " . (string) $request->getUrl());
// Send the request
$response = $request->send();
$body = $response->getBody();
$code = $response->getStatus();
// rcube::console($code, $body);
if ($code < 400) {
return json_decode($body, true);
}
@ -88,9 +105,40 @@ class calendar_nextcloud_api
return false;
}
/**
* Find user by email address
*/
protected function findUserByEmail($email)
{
$email = strtolower($email);
$params = [
'search' => $email,
'itemType' => 'call',
'itemId' => ' ',
'shareTypes' => [0, 1, 7, 4],
];
// FIXME: Is this the only way to find a user by his email address?
$response = $this->request("core/autocomplete/get", 'GET', $params);
if (!empty($response['ocs']['data'])) {
foreach ($response['ocs']['data'] as $user) {
// FIXME: This is the only field that contains email address?
// Note: A Nextcloud contact (the "emails" source) will have an email address in
// the 'id' attribute instead in 'shareWithDisplayNameUnique'.
// Another option might be to parse 'label' attribute
if (strtolower($user['shareWithDisplayNameUnique']) == $email) {
return $user;
}
}
}
}
/**
* Create a Talk room
*
* @param string $name Room name
*
* @return string|false Room URL
*/
public function talk_room_create($name = '')
@ -105,10 +153,66 @@ class calendar_nextcloud_api
$response = $this->request('apps/spreed/api/v4/room', 'POST', $params);
if (is_array($response) && !empty($response['ocs']['data']['token'])) {
$token = $response['ocs']['data']['token'];
$url = unslashify($rcmail->config->get('calendar_nextcloud_url'));
return $url . '/call/' . $response['ocs']['data']['token'];
return $url . '/call/' . $token;
}
return false;
}
/**
* Update a Talk room
*
* @param string $room Room ID (or url)
* @param array $participants Room participants' email addresses (extept the owner)
*
* @return bool
*/
public function talk_room_update($room = '', $participants = [])
{
if (preg_match('|https?://|', $room)) {
$arr = explode('/', $room);
$room = $arr[count($arr) - 1];
}
// Get existing room participants
$response = $this->request("apps/spreed/api/v4/room/{$room}/participants", 'GET');
if ($response === false) {
return false;
}
$attendees = [];
foreach ($response['ocs']['data'] as $attendee) {
if ($attendee['participantType'] != self::PARTICIPANT_OWNER) {
$attendees[$attendee['actorId']] = $attendee['attendeeId'];
}
}
foreach ($participants as $email) {
if ($user = $this->findUserByEmail($email)) {
// Participant already exists, skip
// Note: We're dealing with 'users' source here for now, 'emails' source
// will have an email address in 'actorId'
if (isset($attendees[$user['id']])) {
unset($attendees[$user['id']]);
continue;
}
// Register the participant
$params = ['newParticipant' => $user['id'], 'source' => $user['source']];
$response = $this->request("apps/spreed/api/v4/room/{$room}/participants", 'POST', $params);
}
}
// Remove participants not in the event anymore
foreach ($attendees as $attendeeId) {
$params = ['attendeeId' => $attendeeId];
$response = $this->request("apps/spreed/api/v4/room/{$room}/attendees", 'DELETE', $params);
}
return true;
}
}