2019-12-12 00:56:30 +01:00
< ? php
namespace daemons ;
use \Monolog\Logger ;
use \Monolog\Handler\StreamHandler ;
/**
* Phone daemon class
*/
class Phone extends AbstractDaemon
{
private $msg_queue ;
2020-01-07 01:31:34 +01:00
private $msg_queue_id ;
private $webhook_queue ;
2019-12-17 07:47:11 +01:00
private $last_message_at ;
2020-01-07 01:31:34 +01:00
private $phone ;
private $adapter ;
private $bdd ;
2019-12-12 00:56:30 +01:00
2020-01-07 01:31:34 +01:00
/**
* Constructor
* @ param array $phone : A phone table entry
*/
public function __construct ( array $phone )
2019-12-12 00:56:30 +01:00
{
2020-01-07 01:31:34 +01:00
$this -> phone = $phone ;
$this -> msg_queue_id = ( int ) mb_substr ( $this -> phone [ 'number' ], 1 );
$name = 'RaspiSMS Daemon Phone ' . $this -> phone [ 'number' ];
2019-12-12 00:56:30 +01:00
$logger = new Logger ( $name );
$logger -> pushHandler ( new StreamHandler ( PWD_LOGS . '/raspisms.log' , Logger :: DEBUG ));
2019-12-17 07:47:11 +01:00
$pid_dir = PWD_PID ;
$additional_signals = [];
$uniq = true ; //Main server should be uniq
2019-12-12 00:56:30 +01:00
//Construct the server and add SIGUSR1 and SIGUSR2
parent :: __construct ( $name , $logger , $pid_dir , $additional_signals , $uniq );
2019-12-17 14:38:16 +01:00
2019-12-12 00:56:30 +01:00
parent :: start ();
}
public function run ()
{
2020-01-07 01:31:34 +01:00
//Stop after 5 minutes of inactivity to avoid useless daemon
2019-12-17 07:47:11 +01:00
if ( ( microtime ( true ) - $this -> last_message_at ) > 5 * 60 )
{
2020-01-07 18:06:57 +01:00
posix_kill ( getmypid (), SIGTERM ); //Send exit signal to the current process
return false ;
2019-12-17 07:47:11 +01:00
}
2020-01-07 01:31:34 +01:00
$this -> bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD , 'UTF8' );
//Send smss in queue
$this -> send_smss ();
2019-12-17 07:47:11 +01:00
2020-01-07 01:31:34 +01:00
//Read received smss
$this -> read_smss ();
usleep ( 0.5 * 1000000 );
2020-01-04 19:30:06 +01:00
}
/**
* Send sms
*/
2020-01-07 01:31:34 +01:00
private function send_smss ()
2020-01-04 19:30:06 +01:00
{
2020-01-07 01:31:34 +01:00
$find_message = true ;
while ( $find_message )
2019-12-12 00:56:30 +01:00
{
2020-01-07 17:55:16 +01:00
//Call message
$msgtype = null ;
$maxsize = 409600 ;
$message = null ;
$error_code = null ;
$success = msg_receive ( $this -> msg_queue , QUEUE_TYPE_SEND_MSG , $msgtype , $maxsize , $message , TRUE , MSG_IPC_NOWAIT , $error_code ); //MSG_IPC_NOWAIT == dont wait if no message found
if ( ! $success && $error_code !== MSG_ENOMSG )
{
$this -> logger -> critical ( 'Error reading MSG SEND Queue, error code : ' . $error );
return false ;
}
2020-01-07 01:31:34 +01:00
if ( ! $message )
{
$find_message = false ;
continue ;
}
2020-01-08 02:14:38 +01:00
$internal_sended = new \controllers\internals\Sended ( $this -> bdd );
2020-01-07 01:31:34 +01:00
//Update last message time
$this -> last_message_at = microtime ( true );
$now = new \DateTime ();
$at = $now -> format ( 'Y-m-d H:i:s' );
$message [ 'at' ] = $at ;
$this -> logger -> info ( 'Try send message : ' . json_encode ( $message ));
$sended_sms_uid = $this -> adapter -> send ( $message [ 'destination' ], $message [ 'text' ], $message [ 'flash' ]);
if ( ! $sended_sms_uid )
{
2020-01-07 17:55:16 +01:00
$this -> logger -> error ( 'Failed send message : ' . json_encode ( $message ));
2020-01-07 01:31:34 +01:00
$internal_sended -> create ( $at , $message [ 'text' ], $message [ 'origin' ], $message [ 'destination' ], $sended_sms_uid , $this -> phone [ 'adapter' ], $message [ 'flash' ], 'failed' );
continue ;
}
//Run webhook
$internal_setting = new \controllers\internals\Setting ( $this -> bdd );
$user_settings = $internal_setting -> gets_for_user ( $this -> phone [ 'id_user' ]);
2020-01-07 17:55:16 +01:00
$this -> process_for_webhook ( $message , 'send_sms' , $user_settings );
2020-01-07 01:31:34 +01:00
$this -> logger -> info ( 'Successfully send message : ' . json_encode ( $message ));
$internal_sended -> create ( $at , $message [ 'text' ], $message [ 'origin' ], $message [ 'destination' ], $sended_sms_uid , $this -> phone [ 'adapter' ], $message [ 'flash' ]);
2019-12-12 00:56:30 +01:00
}
2020-01-07 01:31:34 +01:00
}
/**
* Read smss for a number
*/
private function read_smss ()
{
$internal_received = new \controllers\internals\Received ( $this -> bdd );
$internal_setting = new \controllers\internals\Setting ( $this -> bdd );
2019-12-20 18:31:19 +01:00
2020-01-07 01:31:34 +01:00
$smss = $this -> adapter -> read ();
if ( ! $smss )
{
return true ;
}
//Get users settings
$user_settings = $internal_setting -> gets_for_user ( $this -> phone [ 'id_user' ]);
//Process smss
foreach ( $smss as $sms )
{
$this -> logger -> info ( 'Receive message : ' . json_encode ( $sms ));
$command_result = $this -> process_for_command ( $sms );
$sms [ 'text' ] = $command_result [ 'text' ];
$is_command = $command_result [ 'is_command' ];
2020-01-06 13:51:02 +01:00
2020-01-07 01:31:34 +01:00
$this -> process_for_webhook ( $sms , 'receive_sms' , $user_settings );
2020-01-06 13:51:02 +01:00
2020-01-07 17:55:16 +01:00
$internal_received -> create ( $sms [ 'at' ], $sms [ 'text' ], $sms [ 'origin' ], $sms [ 'destination' ], 'unread' , $is_command );
2020-01-07 01:31:34 +01:00
}
}
2020-01-08 02:14:38 +01:00
2020-01-07 01:31:34 +01:00
/**
* Process a sms to find if its a command and so execute it
* @ param array $sms : The sms
* @ return array : [ 'text' => new sms text , 'is_command' => bool ]
*/
private function process_for_command ( array $sms )
{
2020-01-07 17:55:16 +01:00
$internal_command = new \controllers\internals\Command ( $this -> bdd );
2020-01-07 01:31:34 +01:00
$is_command = false ;
$command = $internal_command -> check_for_command ( $this -> phone [ 'id_user' ], $sms [ 'text' ]);
if ( $command )
{
$is_command = true ;
2020-01-07 17:55:16 +01:00
$sms [ 'text' ] = $command [ 'updated_text' ];
2020-01-07 01:31:34 +01:00
exec ( $command [ 'command' ]);
}
2020-01-07 17:55:16 +01:00
return [ 'text' => $sms [ 'text' ], 'is_command' => $is_command ];
2020-01-07 01:31:34 +01:00
}
2019-12-20 18:31:19 +01:00
2020-01-07 01:31:34 +01:00
/**
* Process a sms to transmit a webhook query to webhook daemon if needed
* @ param array $sms : The sms
* @ param string $webhook_type : Type of webhook to trigger
* @ param array $user_settings : Use settings
*/
private function process_for_webhook ( array $sms , string $webhook_type , array $user_settings )
{
if ( ! $user_settings [ 'webhook' ])
{
return false ;
}
$internal_webhook = new \controllers\internals\Webhook ( $this -> bdd );
$webhooks = $internal_webhook -> gets_for_type_and_user ( $this -> phone [ 'id_user' ], $webhook_type );
foreach ( $webhooks as $webhook )
{
$message = [
'url' => $webhook [ 'url' ],
'datas' => [
'webhook_type' => $webhook [ 'type' ],
'at' => $sms [ 'at' ],
'text' => $sms [ 'text' ],
'origin' => $sms [ 'origin' ],
'destination' => $sms [ 'destination' ],
],
];
2020-01-07 17:55:16 +01:00
$error_code = null ;
$success = msg_send ( $this -> webhook_queue , QUEUE_TYPE_WEBHOOK , $message , TRUE , TRUE , $error_code );
if ( ! $success )
{
$this -> logger -> critical ( " Failed send webhook message in queue, error code : " . $error_code );
}
2020-01-07 01:31:34 +01:00
}
2019-12-12 00:56:30 +01:00
}
public function on_start ()
{
2019-12-17 07:47:11 +01:00
//Set last message at to construct time
$this -> last_message_at = microtime ( true );
2020-01-07 01:31:34 +01:00
$this -> msg_queue = msg_get_queue ( $this -> msg_queue_id );
$this -> webhook_queue = msg_get_queue ( QUEUE_ID_WEBHOOK );
//Instanciate adapter
2020-01-08 02:14:38 +01:00
$adapter_class = $this -> phone [ 'adapter' ];
$this -> adapter = new $adapter_class ( $this -> phone [ 'number' ], $this -> phone [ 'adapter_datas' ]);
2020-01-07 01:31:34 +01:00
$this -> logger -> info ( " Starting Phone daemon with pid " . getmypid ());
2019-12-12 00:56:30 +01:00
}
public function on_stop ()
{
2020-01-07 01:31:34 +01:00
//Delete queue on daemon close
$this -> logger -> info ( " Closing queue : " . $this -> msg_queue_id );
msg_remove_queue ( $this -> msg_queue );
2019-12-17 07:47:11 +01:00
2020-01-07 01:31:34 +01:00
$this -> logger -> info ( " Stopping Phone daemon with pid " . getmypid ());
2019-12-12 00:56:30 +01:00
}
public function handle_other_signals ( $signal )
{
$this -> logger -> info ( " Signal not handled by " . $this -> name . " Daemon : " . $signal );
}
}