mirror of
https://github.com/pierre42100/ComunicAPI
synced 2025-07-01 06:13:30 +00:00
Compare commits
17 Commits
22-01-2019
...
25-02-2019
Author | SHA1 | Date | |
---|---|---|---|
55562f79eb | |||
6a4683e6a8 | |||
e32fbc6355 | |||
9d3fb3b342 | |||
45875a2972 | |||
bdea890aaa | |||
f99e16c23e | |||
f57a57482b | |||
bae155873a | |||
4d6ada1523 | |||
b94c859a16 | |||
10b50d4664 | |||
d1be731fb4 | |||
8d004e80f5 | |||
9d1371fd81 | |||
e41cf0161e | |||
3786c5c4e9 |
10
README.md
10
README.md
@ -4,10 +4,18 @@ This project is the main Comunic RestAPI. It assures data backend support.
|
||||
|
||||
(c) Pierre HUBERT since 2017
|
||||
|
||||
# Crons required for Comunic
|
||||
|
||||
## Calls cron
|
||||
There is a cron to automatically cleanup old conversation. Ideally this cron should be executed every 30 seconds. The file to execute is `bin/clean_calls`
|
||||
|
||||
|
||||
### Add API clients
|
||||
|
||||
# Use calls in Comunic
|
||||
To use calls in Comunic, you need a WebRTCSignalExchangerServer, a small signal exchanging server written using NodeJS. You also need to modify your configuration file located at `config/overwrite.php` by copying and pasting commented configuration located at `config/calls.php` and make it fit your needs.
|
||||
|
||||
|
||||
# Add API clients
|
||||
In order to easily add clients to the API, a script has been created.
|
||||
bin/add_client [name] [token]
|
||||
Note : The name of the client must be unique, and the token should the strongest
|
||||
|
249
RestControllers/CallsController.php
Normal file
249
RestControllers/CallsController.php
Normal file
@ -0,0 +1,249 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Calls controller
|
||||
*
|
||||
* @author Pierre HUBERT
|
||||
*/
|
||||
|
||||
class CallsController {
|
||||
|
||||
/**
|
||||
* Single user response to call
|
||||
*/
|
||||
const USER_RESPONSE_TO_CALL = array(
|
||||
CallMemberInformation::USER_ACCEPTED => "accepted",
|
||||
CallMemberInformation::USER_REJECTED => "rejected",
|
||||
CallMemberInformation::USER_UNKNOWN => "unknown",
|
||||
CallMemberInformation::USER_HANG_UP => "hang_up"
|
||||
);
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*/
|
||||
public function __construct(){
|
||||
|
||||
//Clean calls
|
||||
components()->calls->cleanCalls();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get call configuration
|
||||
*
|
||||
* @url POST /calls/config
|
||||
*/
|
||||
public function getConfig(){
|
||||
user_login_required();
|
||||
return self::CallsConfigToAPI(components()->calls->getConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a call for a conversation
|
||||
*
|
||||
* @url POST /calls/createForConversation
|
||||
*/
|
||||
public function createForConversation(){
|
||||
|
||||
user_login_required();
|
||||
|
||||
//Get conversation ID
|
||||
$conversationID = getPostConversationID("conversationID");
|
||||
|
||||
//Check if the user belongs to the conversation
|
||||
if(!components()->conversations->userBelongsTo(userID, $conversationID))
|
||||
Rest_fatal_error(401, "Specified user doesn't belongs to the conversation number ".$conversationID." !");
|
||||
|
||||
//First, check if a call alreay exists for this conversation
|
||||
$call = components()->calls->getForConversation($conversationID, true);
|
||||
|
||||
//If could not get a call, try to create a new one
|
||||
if(!$call->isValid()){
|
||||
|
||||
//Try to create the call
|
||||
if(!components()->calls->createForConversation($conversationID))
|
||||
Rest_fatal_error(500, "Could not create the call");
|
||||
|
||||
//Get the conversation again
|
||||
$call = components()->calls->getForConversation($conversationID, true);
|
||||
|
||||
if(!$call->isValid())
|
||||
Rest_fatal_error(500, "Could not get information about created call!");
|
||||
}
|
||||
|
||||
//The user automatically accept the call
|
||||
components()->calls->setMemberResponse($call->get_id(), userID, true);
|
||||
|
||||
//Returns information about the call
|
||||
return self::CallInformationToAPI($call);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about a single call
|
||||
*
|
||||
* @url POST /calls/getInfo
|
||||
*/
|
||||
public function getInfo(){
|
||||
|
||||
user_login_required();
|
||||
|
||||
//Get target call ID
|
||||
$call_id = $this->GetSafeCallIDFromRequest("call_id");
|
||||
|
||||
//Get information about the call
|
||||
$call = components()->calls->get($call_id, true);
|
||||
|
||||
if(!$call->isValid())
|
||||
Rest_fatal_error(500, "Could not get information about the call!");
|
||||
|
||||
//Update last activity of the call
|
||||
components()->calls->updateLastActivity($call_id);
|
||||
|
||||
return self::CallInformationToAPI($call);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next pending call
|
||||
*
|
||||
* @url POST /calls/nextPending
|
||||
*/
|
||||
public function GetNextPendingCall(){
|
||||
user_login_required();
|
||||
|
||||
//Get the next pending call for the user
|
||||
$call = components()->calls->getNextPendingForUser(userID, TRUE);
|
||||
|
||||
if(!$call->isValid())
|
||||
return array("notice" => "No pending call.");
|
||||
|
||||
return self::CallInformationToAPI($call);
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to a call
|
||||
*
|
||||
* @url POST /calls/respond
|
||||
*/
|
||||
public function respondToCall(){
|
||||
user_login_required();
|
||||
|
||||
//Get target call ID
|
||||
$call_id = $this->GetSafeCallIDFromRequest("call_id");
|
||||
|
||||
//Get target response
|
||||
$accept = postBool("accept");
|
||||
|
||||
//Set user response to call
|
||||
if(!components()->calls->setMemberResponse($call_id, userID, $accept))
|
||||
Rest_fatal_error(500, "Could not set response of user to call!");
|
||||
|
||||
return array(
|
||||
"success" => "User response to call has been successfully set!"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hang up a call
|
||||
*
|
||||
* @url POST /calls/hangUp
|
||||
*/
|
||||
public function hangUp(){
|
||||
user_login_required();
|
||||
|
||||
//Get target call ID
|
||||
$call_id = $this->GetSafeCallIDFromRequest("call_id");
|
||||
|
||||
//Make user hang up call
|
||||
if(!components()->calls->setMemberHangUp($call_id, userID))
|
||||
Rest_fatal_error(500, "Could not make user hang up call!");
|
||||
|
||||
return array(
|
||||
"success" => "User successfully hang up call!"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get safely the ID of a call from the request
|
||||
*
|
||||
* @param $name The name of the POST field containing call ID
|
||||
* @return int The ID of the call
|
||||
*/
|
||||
private function GetSafeCallIDFromRequest(string $name) : int {
|
||||
|
||||
//Get call ID
|
||||
$call_id = postInt($name);
|
||||
|
||||
if($call_id < 1)
|
||||
Rest_fatal_error(401, "Invalid call id !");
|
||||
|
||||
//Check if the user belongs to the call or not
|
||||
if(!components()->calls->doesUserBelongToCall($call_id, userID))
|
||||
Rest_fatal_error(401, "You do not belong to this call!");
|
||||
|
||||
return $call_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a CallsConfig object into an API entry
|
||||
*
|
||||
* @param $config The config to convert
|
||||
* @return array Generated API entry
|
||||
*/
|
||||
private static function CallsConfigToAPI(CallsConfig $config) : array {
|
||||
|
||||
$data = array();
|
||||
|
||||
$data["enabled"] = $config->get_enabled();
|
||||
|
||||
//Give full configuration calls are enabled
|
||||
if($config->get_enabled()){
|
||||
$data["maximum_number_members"] = $config->get_maximum_number_members();
|
||||
$data["signal_server_name"] = $config->get_signal_server_name();
|
||||
$data["signal_server_port"] = $config->get_signal_server_port();
|
||||
$data["is_signal_server_secure"] = $config->get_is_signal_server_secure();
|
||||
$data["stun_server"] = $config->get_stun_server();
|
||||
$data["turn_server"] = $config->get_turn_server();
|
||||
$data["turn_username"] = $config->get_turn_username();
|
||||
$data["turn_password"] = $config->get_turn_password();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a CallInformation object into an API entry
|
||||
*
|
||||
* @param $call The call to convert
|
||||
* @return array Generated API entry
|
||||
*/
|
||||
private static function CallInformationToAPI(CallInformation $call) : array {
|
||||
$data = array(
|
||||
"id" => $call->get_id(),
|
||||
"conversation_id" => $call->get_conversation_id(),
|
||||
"last_active" => $call->get_last_active(),
|
||||
"members" => array()
|
||||
);
|
||||
|
||||
foreach($call->get_members() as $member)
|
||||
$data["members"][] = self::CallMemberInformationToAPI($member);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a CallMemberInformation object into an API entry
|
||||
*
|
||||
* @param $member Member information
|
||||
* @return array User information API entry
|
||||
*/
|
||||
private static function CallMemberInformationToAPI(CallMemberInformation $member) : array {
|
||||
return array(
|
||||
"id" => $member->get_id(),
|
||||
"userID" => $member->get_userID(),
|
||||
"call_id" => $member->get_call_id(),
|
||||
"user_call_id" => $member->get_user_call_id(),
|
||||
"status" => self::USER_RESPONSE_TO_CALL[$member->get_status()]
|
||||
);
|
||||
}
|
||||
}
|
@ -50,6 +50,12 @@ class notificationsController {
|
||||
if(postBool("friends_request"))
|
||||
$data["friends_request"] = components()->friends->count_requests(userID);
|
||||
|
||||
|
||||
//Include pending calls if required
|
||||
if(isset($_POST["include_calls"]))
|
||||
if(postBool("include_calls"))
|
||||
$data["calls"] = components()->calls->countPendingResponsesForUser(userID);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
18
bin/clean_calls
Executable file
18
bin/clean_calls
Executable file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env php
|
||||
|
||||
############################
|
||||
# ComunicAPI calls cleaner #
|
||||
# #
|
||||
# @author Pierre HUBERT #
|
||||
############################
|
||||
|
||||
Automatically remove old calls
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__."/../init.php";
|
||||
|
||||
if(!components()->calls->cleanCalls())
|
||||
echo "Could not clean calls!";
|
||||
|
||||
echo "Calls successfully cleaned.";
|
14
bin/clean_calls_perpetual.sh
Executable file
14
bin/clean_calls_perpetual.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Clean call on a long period
|
||||
# This script is made to be used on dev machines only
|
||||
# @author Pierre HUBERT
|
||||
|
||||
# Place us in current directory
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd $SCRIPT_DIR;
|
||||
|
||||
while true; do
|
||||
./clean_calls
|
||||
sleep 30;
|
||||
done
|
410
classes/components/CallsComponent.php
Normal file
410
classes/components/CallsComponent.php
Normal file
@ -0,0 +1,410 @@
|
||||
<?php
|
||||
/**
|
||||
* Calls components
|
||||
*
|
||||
* @author Pierre HUBERT
|
||||
*/
|
||||
|
||||
class CallsComponents {
|
||||
|
||||
/**
|
||||
* Calls tables names
|
||||
*/
|
||||
private const CALLS_LIST_TABLE = "comunic_calls";
|
||||
private const CALLS_MEMBERS_TABLE = "comunic_calls_members";
|
||||
|
||||
/**
|
||||
* Get and return calls configuration
|
||||
*
|
||||
* @return CallsConfig Calls configuration / invalid object
|
||||
* if none found (empty config)
|
||||
*/
|
||||
public function getConfig() : CallsConfig {
|
||||
|
||||
$callConfig = cs()->config->get("calls");
|
||||
|
||||
//If no call config was found
|
||||
if(!$callConfig || !is_array($callConfig) || !$callConfig["enabled"])
|
||||
return new CallsConfig();
|
||||
|
||||
$config = new CallsConfig();
|
||||
$config->set_enabled($callConfig["enabled"]);
|
||||
$config->set_maximum_number_members($callConfig["maximum_number_members"]);
|
||||
$config->set_signal_server_name($callConfig["signal_server_name"]);
|
||||
$config->set_signal_server_port($callConfig["signal_server_port"]);
|
||||
$config->set_is_signal_server_secure($callConfig["is_signal_server_secure"]);
|
||||
$config->set_stun_server($callConfig["stun_server"]);
|
||||
$config->set_turn_server($callConfig["turn_server"]);
|
||||
$config->set_turn_username($callConfig["turn_username"]);
|
||||
$config->set_turn_password($callConfig["turn_password"]);
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the call for a conversation
|
||||
*
|
||||
* @param $conversation_id Target conversation ID
|
||||
* @param $load_members Specify whether members information should
|
||||
* be loaded too or not
|
||||
* @return CallInformation Matching call information object / invalid object
|
||||
* in case of failure
|
||||
*/
|
||||
public function getForConversation(int $conversation_id, bool $load_members) : CallInformation {
|
||||
|
||||
$entry = db()->select(
|
||||
self::CALLS_LIST_TABLE,
|
||||
"WHERE conversation_id = ?",
|
||||
array($conversation_id)
|
||||
);
|
||||
|
||||
if(count($entry) == 0)
|
||||
return new CallInformation();
|
||||
|
||||
$info = self::DBToCallInformation($entry[0]);
|
||||
|
||||
//Load call members if required
|
||||
if($load_members && !$this->getMembers($info))
|
||||
return new CallInformation();
|
||||
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about a call
|
||||
*
|
||||
* @param $call_id Target call ID
|
||||
* @param $load_members Specify whether members information should
|
||||
* be loaded too or not
|
||||
* @return CallInformation Matching call information object / invalid object
|
||||
* in case of failure
|
||||
*/
|
||||
public function get(int $call_id, bool $load_members) : CallInformation {
|
||||
|
||||
$entry = db()->select(
|
||||
self::CALLS_LIST_TABLE,
|
||||
"WHERE id = ?",
|
||||
array($call_id)
|
||||
);
|
||||
|
||||
if(count($entry) == 0)
|
||||
return new CallInformation();
|
||||
|
||||
$info = self::DBToCallInformation($entry[0]);
|
||||
|
||||
//Load call members if required
|
||||
if($load_members && !$this->getMembers($info))
|
||||
return new CallInformation();
|
||||
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update last activity time of a conversation
|
||||
*
|
||||
* @param $call_id The ID of the call to update
|
||||
* @return bool TRUE for a success / FALSE else
|
||||
*/
|
||||
public function updateLastActivity(int $call_id) : bool {
|
||||
|
||||
return db()->updateDB(
|
||||
self::CALLS_LIST_TABLE,
|
||||
"id = ?",
|
||||
array(
|
||||
"last_active" => time()
|
||||
),
|
||||
array(
|
||||
$call_id
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next call for a user
|
||||
*
|
||||
* @param $userID Target user ID
|
||||
* @param $load_members Specify whether information about members
|
||||
* should be loaded or not
|
||||
* @return CallInformation Information about the call / invalid object
|
||||
* if none found
|
||||
*/
|
||||
public function getNextPendingForUser(int $userID, bool $load_members) : CallInformation {
|
||||
|
||||
//Get the ID of a call the user has not responded yet
|
||||
$entries = db()->select(
|
||||
self::CALLS_MEMBERS_TABLE,
|
||||
"WHERE user_id = ? AND status = ?",
|
||||
array($userID, CallMemberInformation::USER_UNKNOWN),
|
||||
array("call_id")
|
||||
);
|
||||
|
||||
//Check if the user has no pending call
|
||||
if(count($entries) == 0)
|
||||
return new CallInformation();
|
||||
|
||||
return $this->get($entries[0]["call_id"], $load_members);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a call for a conversation
|
||||
*
|
||||
* @param $conversationID The ID of the target conversation
|
||||
* @return bool TRUE for a success / FALSE else
|
||||
*/
|
||||
public function createForConversation(int $conversationID) : bool {
|
||||
|
||||
//Generate call information
|
||||
$info = new CallInformation();
|
||||
$info->set_conversation_id($conversationID);
|
||||
$info->set_last_active(time());
|
||||
|
||||
//We need to get the list of members of the conversation to create members list
|
||||
$conversation_members = components()->conversations->getConversationMembers($conversationID);
|
||||
|
||||
//Check for errors
|
||||
if(count($conversation_members) == 0)
|
||||
return false;
|
||||
|
||||
|
||||
//Insert the call in the database to get its ID
|
||||
if(!db()->addLine(
|
||||
self::CALLS_LIST_TABLE,
|
||||
self::CallInformationToDB($info)
|
||||
))
|
||||
return false;
|
||||
$info->set_id(db()->getLastInsertedID());
|
||||
|
||||
foreach($conversation_members as $memberID){
|
||||
$member = new CallMemberInformation();
|
||||
$member->set_call_id($info->get_id());
|
||||
$member->set_userID($memberID);
|
||||
$member->set_user_call_id(random_str(190));
|
||||
$member->set_status(CallMemberInformation::USER_UNKNOWN);
|
||||
|
||||
//Try to add the member to the list
|
||||
if(!$this->addMember($member))
|
||||
return false;
|
||||
}
|
||||
|
||||
//Success
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new member to a call
|
||||
*
|
||||
* @param $member Information about the member to add
|
||||
* @return bool TRUE for a success / FALSE else
|
||||
*/
|
||||
private function addMember(CallMemberInformation $member) : bool {
|
||||
return db()->addLine(
|
||||
self::CALLS_MEMBERS_TABLE,
|
||||
self::CallMemberInformationToDB($member)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load information about the members related to the call
|
||||
*
|
||||
* @param $info Information about the call to process
|
||||
* @return bool TRUE in case of success / FALSE else
|
||||
*/
|
||||
private function getMembers(CallInformation $info) : bool {
|
||||
|
||||
$entries = db()->select(
|
||||
self::CALLS_MEMBERS_TABLE,
|
||||
"WHERE call_id = ?",
|
||||
array($info->get_id())
|
||||
);
|
||||
|
||||
foreach($entries as $entry)
|
||||
$info->add_member(self::DBToCallMemberInformation($entry));
|
||||
|
||||
return count($entries) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count and return the number of pending calls for a user
|
||||
*
|
||||
* @param $userID The ID of the target user
|
||||
* @return int The number of pending calls for the user
|
||||
*/
|
||||
public function countPendingResponsesForUser(int $userID) : int {
|
||||
|
||||
return db()->count(
|
||||
self::CALLS_MEMBERS_TABLE,
|
||||
"WHERE user_id = ? AND status = ?",
|
||||
array($userID, CallMemberInformation::USER_UNKNOWN)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check out whether a user belongs to a call or not
|
||||
*
|
||||
* @param $callID The ID of the target call
|
||||
* @param $userID The ID of the target user
|
||||
* @return bool TRUE if the user belongs to the call / FALSE else
|
||||
*/
|
||||
public function doesUserBelongToCall(int $callID, int $userID) : bool {
|
||||
return db()->count(
|
||||
self::CALLS_MEMBERS_TABLE,
|
||||
"WHERE call_id = ? AND user_id = ?",
|
||||
array($callID, $userID)
|
||||
) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response of a member to a call
|
||||
*
|
||||
* @param $callID The ID of the target call
|
||||
* @param $userID The ID of the target member
|
||||
* @param $accept TRUE to accept the call / FALSE else
|
||||
* @return bool TRUE for a success / FALSE else
|
||||
*/
|
||||
public function setMemberResponse(int $callID, int $userID, bool $accept) : bool {
|
||||
return $this->setMemberStatus(
|
||||
$accept ? CallMemberInformation::USER_ACCEPTED : CallMemberInformation::USER_REJECTED, $callID, $userID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make user hang up the call
|
||||
*
|
||||
* @param int $callID Target call ID
|
||||
* @param int $userID Target user ID
|
||||
* @return bool TRUE for a success / FALSE else
|
||||
*/
|
||||
public function setMemberHangUp(int $callID, int $userID) : bool {
|
||||
return $this->setMemberStatus(CallMemberInformation::USER_HANG_UP, $callID, $userID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update member status
|
||||
*
|
||||
* @param $status New status for the user
|
||||
* @param $callID Target call ID
|
||||
* @param $userID Target user ID
|
||||
* @return bool TRUE for a success / FALSE else
|
||||
*/
|
||||
private function setMemberStatus(int $status, int $callID, int $userID){
|
||||
db()->updateDB(
|
||||
self::CALLS_MEMBERS_TABLE,
|
||||
"call_id = ? AND user_id = ?",
|
||||
array(
|
||||
"status" => $status
|
||||
),
|
||||
array(
|
||||
$callID,
|
||||
$userID
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all old call
|
||||
*
|
||||
* @return bool TRUE for a success / FALSE else
|
||||
*/
|
||||
public function cleanCalls() : bool {
|
||||
|
||||
//Compute timeout time
|
||||
$old_time = time() - cs()->config->get("calls_expiration");
|
||||
|
||||
//Get the list of old calls
|
||||
$calls = db()->select(
|
||||
self::CALLS_LIST_TABLE,
|
||||
"WHERE last_active < ?",
|
||||
array($old_time),
|
||||
array("id")
|
||||
);
|
||||
|
||||
//Process each result
|
||||
foreach($calls as $call){
|
||||
|
||||
//Delete all the members of the call
|
||||
db()->deleteEntry(
|
||||
self::CALLS_MEMBERS_TABLE,
|
||||
"call_id = ?",
|
||||
array($call["id"])
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
//Delete calls entries
|
||||
db()->deleteEntry(
|
||||
self::CALLS_LIST_TABLE,
|
||||
"last_active < ?",
|
||||
array($old_time)
|
||||
);
|
||||
|
||||
//Success
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a database entry into a CallInformation object
|
||||
*
|
||||
* @param $entry The entry to convert
|
||||
* @return CallInformation Generated object
|
||||
*/
|
||||
private static function DBToCallInformation(array $entry) : CallInformation {
|
||||
$info = new CallInformation();
|
||||
$info->set_id($entry["id"]);
|
||||
$info->set_conversation_id($entry["conversation_id"]);
|
||||
$info->set_last_active($entry["last_active"]);
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a CallInformation object into a database entry
|
||||
*
|
||||
* @param $call Call information object to convert
|
||||
* @return array Generated array
|
||||
*/
|
||||
private static function CallInformationToDB(CallInformation $call) : array {
|
||||
$data = array();
|
||||
$data["conversation_id"] = $call->get_conversation_id();
|
||||
$data["last_active"] = $call->get_last_active();
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a database entry into a CallMemberInformation object
|
||||
*
|
||||
* @param $entry The entry to convert
|
||||
* @return CallMemberInformation Generated object
|
||||
*/
|
||||
private static function DBToCallMemberInformation(array $entry) : CallMemberInformation {
|
||||
$member = new CallMemberInformation();
|
||||
$member->set_id($entry["id"]);
|
||||
$member->set_call_id($entry["call_id"]);
|
||||
$member->set_userID($entry["user_id"]);
|
||||
$member->set_user_call_id($entry["user_call_id"]);
|
||||
$member->set_status($entry["status"]);
|
||||
return $member;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a CallMemberInformation object into a database entry
|
||||
*
|
||||
* @param $member The member to convert
|
||||
* @return array Generated database entry
|
||||
*/
|
||||
private static function CallMemberInformationToDB(CallMemberInformation $member) : array {
|
||||
$data = array();
|
||||
$data["call_id"] = $member->get_call_id();
|
||||
$data["user_id"] = $member->get_userID();
|
||||
$data["user_call_id"] = $member->get_user_call_id();
|
||||
$data["status"] = $member->get_status();
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
//Register class
|
||||
Components::register("calls", new CallsComponents());
|
@ -555,7 +555,7 @@ class GroupsComponent {
|
||||
*/
|
||||
private function countMembers(int $id) : int {
|
||||
return db()->count(self::GROUPS_MEMBERS_TABLE,
|
||||
"WHERE groups_id = ?",
|
||||
"WHERE groups_id = ? AND level <= ".GroupMember::MEMBER,
|
||||
array($id));
|
||||
}
|
||||
|
||||
|
55
classes/models/CallInformation.php
Normal file
55
classes/models/CallInformation.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* Call information object
|
||||
*
|
||||
* @author Pierre HUBERT
|
||||
*/
|
||||
|
||||
class CallInformation extends BaseUniqueObject {
|
||||
|
||||
//Private fields
|
||||
private $conversation_id;
|
||||
private $last_active;
|
||||
private $members;
|
||||
|
||||
public function __construct(){
|
||||
parent::__construct();
|
||||
$this->members = array();
|
||||
}
|
||||
|
||||
//Conversations ID
|
||||
public function set_conversation_id(int $conversation_id){
|
||||
$this->conversation_id = $conversation_id;
|
||||
}
|
||||
|
||||
public function has_conversation_id() : bool {
|
||||
return $this->conversation_id > -1;
|
||||
}
|
||||
|
||||
public function get_conversation_id() : int {
|
||||
return $this->conversation_id;
|
||||
}
|
||||
|
||||
|
||||
//Last activity
|
||||
public function set_last_active(int $last_active){
|
||||
$this->last_active = $last_active;
|
||||
}
|
||||
|
||||
public function has_last_active() : bool {
|
||||
return $this->last_active > -1;
|
||||
}
|
||||
|
||||
public function get_last_active() : int {
|
||||
return $this->last_active;
|
||||
}
|
||||
|
||||
//Call members list
|
||||
public function add_member(CallMemberInformation $member) {
|
||||
$this->members[] = $member;
|
||||
}
|
||||
|
||||
public function get_members() : array {
|
||||
return $this->members;
|
||||
}
|
||||
}
|
68
classes/models/CallMemberInformation.php
Normal file
68
classes/models/CallMemberInformation.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* Information about two members call
|
||||
*
|
||||
* @author Pierre HUBERT
|
||||
*/
|
||||
|
||||
class CallMemberInformation extends BaseUniqueObjectFromUser {
|
||||
|
||||
/**
|
||||
* Possible user responses
|
||||
*/
|
||||
public const USER_ACCEPTED = 1;
|
||||
public const USER_REJECTED = 0;
|
||||
public const USER_UNKNOWN = -1;
|
||||
public const USER_HANG_UP = 2;
|
||||
|
||||
|
||||
|
||||
//Private fields
|
||||
private $call_id;
|
||||
private $user_call_id;
|
||||
private $accepted;
|
||||
|
||||
|
||||
|
||||
//Call ID
|
||||
public function set_call_id(int $call_id){
|
||||
$this->call_id = $call_id;
|
||||
}
|
||||
|
||||
public function has_call_id() : bool {
|
||||
return $this->call_id > -1;
|
||||
}
|
||||
|
||||
public function get_call_id() : int {
|
||||
return $this->call_id;
|
||||
}
|
||||
|
||||
|
||||
//User Call ID
|
||||
public function set_user_call_id(string $user_call_id){
|
||||
$this->user_call_id = $user_call_id == "" ? null : $user_call_id;
|
||||
}
|
||||
|
||||
public function has_user_call_id() : bool {
|
||||
return $this->user_call_id != null;
|
||||
}
|
||||
|
||||
public function get_user_call_id() : string {
|
||||
return $this->user_call_id != null ? $this->user_call_id : "null";
|
||||
}
|
||||
|
||||
|
||||
//User response to call
|
||||
public function set_status(int $status){
|
||||
$this->status = $status;
|
||||
}
|
||||
|
||||
public function has_status() : bool {
|
||||
return $this->status > -1;
|
||||
}
|
||||
|
||||
public function get_status() : int {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
}
|
136
classes/models/CallsConfig.php
Normal file
136
classes/models/CallsConfig.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/**
|
||||
* Calls configuration object
|
||||
*
|
||||
* @author Pierre HUBERT
|
||||
*/
|
||||
|
||||
class CallsConfig {
|
||||
|
||||
//Private fields
|
||||
private $enabled = false;
|
||||
private $maximum_number_members = -1;
|
||||
private $signal_server_name;
|
||||
private $signal_server_port;
|
||||
private $is_signal_server_secure;
|
||||
private $stun_server;
|
||||
private $turn_server;
|
||||
private $turn_username;
|
||||
private $turn_password;
|
||||
|
||||
|
||||
//Set and get enabled state
|
||||
public function set_enabled(bool $enabled){
|
||||
$this->enabled = $enabled;
|
||||
}
|
||||
|
||||
public function get_enabled() : bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
|
||||
//Get the maximum number of members for a conversation
|
||||
public function set_maximum_number_members(int $maximum_number_members){
|
||||
$this->maximum_number_members = $maximum_number_members;
|
||||
}
|
||||
|
||||
public function has_maximum_number_members() : bool {
|
||||
return $this->maximum_number_members > 0;
|
||||
}
|
||||
|
||||
public function get_maximum_number_members() : int {
|
||||
return $this->maximum_number_members;
|
||||
}
|
||||
|
||||
|
||||
//Get Set Signal Server name
|
||||
public function set_signal_server_name(string $signal_server_name){
|
||||
$this->signal_server_name = $signal_server_name == "" ? null : $signal_server_name;
|
||||
}
|
||||
|
||||
public function has_signal_server_name() : bool {
|
||||
return $this->signal_server_name != null;
|
||||
}
|
||||
|
||||
public function get_signal_server_name() : string {
|
||||
return $this->signal_server_name != null ? $this->signal_server_name : "null";
|
||||
}
|
||||
|
||||
|
||||
//Set and get Signal Server Port
|
||||
public function set_signal_server_port(int $signal_server_port){
|
||||
$this->signal_server_port = $signal_server_port;
|
||||
}
|
||||
|
||||
public function has_signal_server_port() : bool {
|
||||
return $this->signal_server_port > 0;
|
||||
}
|
||||
|
||||
public function get_signal_server_port() : int {
|
||||
return $this->signal_server_port;
|
||||
}
|
||||
|
||||
//Get and set secure state of the signaling server
|
||||
public function set_is_signal_server_secure(bool $is_signal_server_secure){
|
||||
$this->is_signal_server_secure = $is_signal_server_secure;
|
||||
}
|
||||
|
||||
public function get_is_signal_server_secure() : bool {
|
||||
return $this->is_signal_server_secure;
|
||||
}
|
||||
|
||||
//Get and set stun server
|
||||
public function set_stun_server(string $stun_server){
|
||||
$this->stun_server = $stun_server == "" ? null : $stun_server;
|
||||
}
|
||||
|
||||
public function has_stun_server() : bool {
|
||||
return $this->stun_server != null;
|
||||
}
|
||||
|
||||
public function get_stun_server() : string {
|
||||
return $this->stun_server != null ? $this->stun_server : "null";
|
||||
}
|
||||
|
||||
|
||||
//Get and set turn server
|
||||
public function set_turn_server(string $turn_server){
|
||||
$this->turn_server = $turn_server == "" ? null : $turn_server;
|
||||
}
|
||||
|
||||
public function has_turn_server() : bool {
|
||||
return $this->turn_server != null;
|
||||
}
|
||||
|
||||
public function get_turn_server() : string {
|
||||
return $this->turn_server != null ? $this->turn_server : "null";
|
||||
}
|
||||
|
||||
|
||||
//Get and set turn username
|
||||
public function set_turn_username(string $turn_username){
|
||||
$this->turn_username = $turn_username == "" ? null : $turn_username;
|
||||
}
|
||||
|
||||
public function has_turn_username() : bool {
|
||||
return $this->turn_username != null;
|
||||
}
|
||||
|
||||
public function get_turn_username() : string {
|
||||
return $this->turn_username != null ? $this->turn_username : "null";
|
||||
}
|
||||
|
||||
|
||||
//Get and set turn password
|
||||
public function set_turn_password(string $turn_password){
|
||||
$this->turn_password = $turn_password == "" ? null : $turn_password;
|
||||
}
|
||||
|
||||
public function has_turn_password() : bool {
|
||||
return $this->turn_password != null;
|
||||
}
|
||||
|
||||
public function get_turn_password() : string {
|
||||
return $this->turn_password != null ? $this->turn_password : "null";
|
||||
}
|
||||
}
|
39
config/calls.php
Normal file
39
config/calls.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Calls configuration file
|
||||
*
|
||||
* @author Pierre HUBERT
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calls through clients are disabled by default.
|
||||
*/
|
||||
$config->set("calls", false);
|
||||
|
||||
/**
|
||||
* Copy the lines of code below to the overwrite.php file
|
||||
* if you would like to enable calls on your instance of
|
||||
* Comunic
|
||||
*
|
||||
*/
|
||||
/*
|
||||
$config->set("calls", array(
|
||||
"enabled" => true,
|
||||
"maximum_number_members" => 2,
|
||||
"signal_server_name" => "localhost",
|
||||
"signal_server_port" => 8081,
|
||||
"is_signal_server_secure" => false,
|
||||
"stun_server" => "stun:127.0.0.1:3478",
|
||||
"turn_server" => "turn:127.0.0.1:3478",
|
||||
"turn_username" => "anonymous",
|
||||
"turn_password" => "anonymous"
|
||||
));
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calls expiration time
|
||||
*
|
||||
* The amount of time of inactivity for what the call get
|
||||
* automatically deleted
|
||||
*/
|
||||
$config->set("calls_expiration", 30);
|
@ -103,6 +103,26 @@ CREATE TABLE `comunic_api_users_tokens` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS `comunic_calls`;
|
||||
CREATE TABLE `comunic_calls` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`conversation_id` INT NULL,
|
||||
`last_active` INT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS `comunic_calls_members`;
|
||||
CREATE TABLE `comunic_calls_members` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`call_id` INT NOT NULL,
|
||||
`user_id` INT NULL,
|
||||
`user_call_id` VARCHAR(200) NULL,
|
||||
`status` TINYINT DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS `comunic_conversations_list`;
|
||||
CREATE TABLE `comunic_conversations_list` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
|
Reference in New Issue
Block a user