2019-12-08 02:33:53 +01:00
< ? php
/*
* This file is part of RaspiSMS .
*
* ( c ) Pierre - Lin Bonnemaison < plebwebsas @ gmail . com >
*
* This source file is subject to the GPL - 3.0 license that is bundled
* with this source code in the file LICENSE .
*/
namespace controllers\internals ;
2023-05-30 18:05:38 +02:00
use DateInterval ;
2024-10-26 18:02:11 +02:00
use Faker\Factory ;
2023-05-30 18:05:38 +02:00
2019-12-08 02:33:53 +01:00
/**
2020-01-17 18:19:25 +01:00
* Class to call the console scripts .
2019-12-08 02:33:53 +01:00
*/
class Console extends \descartes\InternalController
{
2020-01-07 01:31:34 +01:00
/**
2020-01-17 18:19:25 +01:00
* Start launcher daemon .
2020-01-07 01:31:34 +01:00
*/
2020-01-17 18:19:25 +01:00
public function launcher ()
2019-12-08 02:33:53 +01:00
{
2020-01-08 18:20:17 +01:00
new \daemons\Launcher ();
2019-12-08 02:33:53 +01:00
}
2019-12-17 14:38:16 +01:00
2020-01-07 01:31:34 +01:00
/**
2020-01-17 18:19:25 +01:00
* Start sender daemon .
2020-01-07 01:31:34 +01:00
*/
2020-01-17 18:19:25 +01:00
public function sender ()
2019-12-17 14:38:16 +01:00
{
2020-01-07 01:31:34 +01:00
new \daemons\Sender ();
}
2020-01-17 18:19:25 +01:00
2020-01-07 01:31:34 +01:00
/**
2020-01-17 18:19:25 +01:00
* Start webhook daemon .
2020-01-07 01:31:34 +01:00
*/
2020-01-17 18:19:25 +01:00
public function webhook ()
2020-01-07 01:31:34 +01:00
{
new \daemons\Webhook ();
}
2020-06-23 21:06:13 +02:00
2020-04-16 07:50:30 +02:00
/**
* Start mailer daemon .
*/
public function mailer ()
{
new \daemons\Mailer ();
}
2020-01-07 01:31:34 +01:00
/**
2020-01-17 18:19:25 +01:00
* Start a phone daemon .
*
2020-01-07 01:31:34 +01:00
* @ param $id_phone : Phone id
*/
2020-01-17 18:19:25 +01:00
public function phone ( $id_phone )
2020-01-07 01:31:34 +01:00
{
2021-12-29 02:54:21 +01:00
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
2020-01-07 01:31:34 +01:00
$internal_phone = new \controllers\internals\Phone ( $bdd );
$phone = $internal_phone -> get ( $id_phone );
if ( ! $phone )
2024-10-26 18:02:11 +02:00
{
exit ( 1 );
2019-12-17 14:38:16 +01:00
}
2020-02-19 02:32:52 +01:00
2024-10-26 18:02:11 +02:00
new \daemons\Phone ( $phone );
}
2020-10-22 20:31:01 +02:00
2024-10-26 18:02:11 +02:00
/**
* Check if a user exists based on email .
*
* @ param string $email : User email
*/
public function user_exists ( string $email )
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_user = new \controllers\internals\User ( $bdd );
2021-01-14 03:32:17 +01:00
2024-10-26 18:02:11 +02:00
$user = $internal_user -> get_by_email ( $email );
2022-03-15 02:24:28 +01:00
2024-10-26 18:02:11 +02:00
exit ( $user ? 0 : 1 );
}
2021-08-05 17:14:53 +02:00
2024-10-26 18:02:11 +02:00
/**
* Check if a user exists based on id .
*
* @ param string $id : User id
*/
public function user_id_exists ( string $id )
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_user = new \controllers\internals\User ( $bdd );
2021-08-05 17:14:53 +02:00
2024-10-26 18:02:11 +02:00
$user = $internal_user -> get ( $id );
2020-10-22 20:31:01 +02:00
2024-10-26 18:02:11 +02:00
exit ( $user ? 0 : 1 );
}
2020-02-19 02:32:52 +01:00
2024-10-26 18:02:11 +02:00
/**
* Create a user or update an existing user .
*
* @ param $email : User email
* @ param $password : User password
* @ param $admin : Is user admin
* @ param $api_key : User API key , if null random api key is generated
* @ param $status : User status , default \models\User :: STATUS_ACTIVE
* @ param bool $encrypt_password : Should the password be encrypted , by default true
*
* exit code 0 on success | 1 on error
*/
public function create_update_user ( string $email , string $password , bool $admin , ? string $api_key = null , string $status = \models\User :: STATUS_ACTIVE , bool $encrypt_password = true )
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_user = new \controllers\internals\User ( $bdd );
2020-02-21 03:55:14 +01:00
2024-10-26 18:02:11 +02:00
$user = $internal_user -> get_by_email ( $email );
if ( $user )
{
$api_key = $api_key ? ? $internal_user -> generate_random_api_key ();
$update_datas = [
'email' => $email ,
'password' => $encrypt_password ? password_hash ( $password , PASSWORD_DEFAULT ) : $password ,
'admin' => $admin ,
'api_key' => $api_key ,
'status' => $status ,
];
$success = $internal_user -> update ( $user [ 'id' ], $update_datas );
echo json_encode ([ 'id' => $user [ 'id' ]]);
2021-01-14 03:32:17 +01:00
2024-10-26 18:02:11 +02:00
exit ( $success ? 0 : 1 );
2020-03-30 01:52:53 +02:00
}
2024-10-26 18:02:11 +02:00
$new_user_id = $internal_user -> create ( $email , $password , $admin , $api_key , $status , $encrypt_password );
echo json_encode ([ 'id' => $new_user_id ]);
2020-03-30 01:52:53 +02:00
2024-10-26 18:02:11 +02:00
exit ( $new_user_id ? 0 : 1 );
}
2020-03-30 01:52:53 +02:00
2024-10-26 18:02:11 +02:00
/**
* Update a user status .
*
* @ param string $id : User id
* @ param string $status : User status , default \models\User :: STATUS_ACTIVE
*/
public function update_user_status ( string $id , string $status )
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_user = new \controllers\internals\User ( $bdd );
2021-01-14 03:32:17 +01:00
2024-10-26 18:02:11 +02:00
$user = $internal_user -> get ( $id );
if ( ! $user )
{
exit ( 1 );
2020-02-19 02:32:52 +01:00
}
2021-01-14 03:32:17 +01:00
2024-10-26 18:02:11 +02:00
$success = $internal_user -> update_status ( $user [ 'id' ], $status );
exit ( $success ? 0 : 1 );
}
/**
* Delete a user .
*
* @ param string $id : User id
*/
public function delete_user ( string $id )
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_user = new \controllers\internals\User ( $bdd );
2020-10-22 20:31:01 +02:00
2024-10-26 18:02:11 +02:00
$success = $internal_user -> delete ( $id );
2021-01-14 03:32:17 +01:00
2024-10-26 18:02:11 +02:00
exit ( $success ? 0 : 1 );
}
/**
* Delete medias that are no longer usefull .
*/
public function clean_unused_medias ()
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_media = new \controllers\internals\Media ( $bdd );
$medias = $internal_media -> gets_unused ();
foreach ( $medias as $media )
{
$success = $internal_media -> delete_for_user ( $media [ 'id_user' ], $media [ 'id' ]);
echo ( false === $success ? '[KO]' : '[OK]' ) . ' - ' . $media [ 'path' ] . " \n " ;
2020-10-22 20:31:01 +02:00
}
2024-10-26 18:02:11 +02:00
}
2021-03-26 18:53:20 +01:00
2024-10-26 18:02:11 +02:00
/**
* Do alerting for quota limits .
*/
public function quota_limit_alerting ()
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_quota = new \controllers\internals\Quota ( $bdd );
$internal_quota -> alerting_for_limit_close_and_reached ();
}
/**
* Do quota renewal .
*/
public function renew_quotas ()
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_quota = new \controllers\internals\Quota ( $bdd );
$internal_quota -> renew_quotas ();
}
/**
* Do phone reliability verifications
*/
public function phone_reliability ()
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_user = new \controllers\internals\User ( $bdd );
$internal_settings = new \controllers\internals\Setting ( $bdd );
$internal_sended = new \controllers\internals\Sended ( $bdd );
$internal_phone_reliability = new \controllers\internals\PhoneReliability ( $bdd );
$internal_phone = new \controllers\internals\Phone ( $bdd );
$internal_webhook = new \controllers\internals\Webhook ( $bdd );
$internal_mailer = new \controllers\internals\Mailer ();
$users = $internal_user -> get_all_active ();
foreach ( $users as $user )
2021-03-26 18:53:20 +01:00
{
2024-10-26 18:02:11 +02:00
$settings = $internal_settings -> gets_for_user ( $user [ 'id' ]);
echo " \n Check phone reliability for user " . $user [ 'id' ] . " : \n " ;
if ( $settings [ 'phone_reliability_failed' ])
{
$rate_limit = intval ( $settings [ 'phone_reliability_failed_rate_limit' ]) / 100 ;
$min_volume = intval ( $settings [ 'phone_reliability_failed_volume' ]);
$period = intval ( $settings [ 'phone_reliability_failed_period' ]);
$grace_period = intval ( $settings [ 'phone_reliability_failed_grace_period' ]);
2021-03-26 18:53:20 +01:00
2024-10-26 18:02:11 +02:00
echo " Check for failed SMS with rate > " . $rate_limit . " and volume > " . $min_volume . " on period " . $period . " s with grace period of " . $grace_period . " s. \n " ;
2021-03-26 18:53:20 +01:00
2024-10-26 18:02:11 +02:00
$unreliable_phones = $internal_phone_reliability -> find_unreliable_phones ( $user [ 'id' ], \models\Sended :: STATUS_FAILED , $rate_limit , $min_volume , $period , $grace_period );
foreach ( $unreliable_phones as $unreliable_phone )
{
$phone = $internal_phone -> get ( $unreliable_phone [ 'id_phone' ]);
if ( ! $phone )
{
echo ' Cannot find phone: ' . $unreliable_phone [ 'id_phone' ] . " \n " ;
continue ;
}
echo " \n Phone " . $phone [ 'id' ] . ' - ' . $phone [ 'name' ] . " failed rate = " . $unreliable_phone [ 'rate' ] . " > " . $rate_limit . " and volume " . $unreliable_phone [ 'total' ] . " > " . $min_volume . " \n " ;
$internal_phone_reliability -> create ( $user [ 'id' ], $phone [ 'id' ], \models\Sended :: STATUS_FAILED );
if ( $settings [ 'phone_reliability_failed_email' ])
{
$success = $internal_mailer -> enqueue ( $user [ 'email' ], EMAIL_PHONE_RELIABILITY_FAILED , [
'phone' => $phone ,
'period' => $period ,
'total' => $unreliable_phone [ 'total' ],
'unreliable' => $unreliable_phone [ 'unreliable' ],
'rate' => $unreliable_phone [ 'rate' ],
]);
if ( ! $success )
{
echo ' Cannot enqueue alert for unreliable failed phone: ' . $unreliable_phone [ 'id_phone' ] . " \n " ;
continue ;
}
echo " Alert mail for unreliable failed phone " . $phone [ 'id' ] . ' - ' . $phone [ 'name' ] . " added \n " ;
}
if ( $settings [ 'phone_reliability_failed_webhook' ])
{
$webhook = [
'reliability_type' => \models\Sended :: STATUS_FAILED ,
'id_phone' => $unreliable_phone [ 'id_phone' ],
'period' => $period ,
'total' => $unreliable_phone [ 'total' ],
'unreliable' => $unreliable_phone [ 'unreliable' ],
'rate' => $unreliable_phone [ 'rate' ],
];
$internal_webhook -> trigger ( $user [ 'id' ], \models\Webhook :: TYPE_PHONE_RELIABILITY , $webhook );
echo " Webhook for unreliable failed phone " . $phone [ 'id' ] . ' - ' . $phone [ 'name' ] . " triggered \n " ;
}
if ( $settings [ 'phone_reliability_failed_auto_disable' ])
{
$internal_phone -> update_status ( $unreliable_phone [ 'id_phone' ], \models\Phone :: STATUS_DISABLED );
}
}
}
if ( $settings [ 'phone_reliability_unknown' ])
2021-03-26 18:53:20 +01:00
{
2024-10-26 18:02:11 +02:00
$rate_limit = intval ( $settings [ 'phone_reliability_unknown_rate_limit' ]) / 100 ;
$min_volume = intval ( $settings [ 'phone_reliability_unknown_volume' ]);
$period = intval ( $settings [ 'phone_reliability_unknown_period' ]);
$grace_period = intval ( $settings [ 'phone_reliability_unknown_grace_period' ]);
2021-03-26 18:53:20 +01:00
2024-10-26 18:02:11 +02:00
echo " \n Check for unknown SMS with rate > " . $rate_limit . " and volume > " . $min_volume . " on period " . $period . " s with grace period of " . $grace_period . " s. \n " ;
$unreliable_phones = $internal_phone_reliability -> find_unreliable_phones ( $user [ 'id' ], \models\Sended :: STATUS_UNKNOWN , $rate_limit , $min_volume , $period , $grace_period );
foreach ( $unreliable_phones as $unreliable_phone )
{
$phone = $internal_phone -> get ( $unreliable_phone [ 'id_phone' ]);
if ( ! $phone )
{
echo ' Cannot find phone: ' . $unreliable_phone [ 'id_phone' ] . " \n " ;
continue ;
}
echo " \n Phone " . $phone [ 'id' ] . ' - ' . $phone [ 'name' ] . " unknown rate = " . $unreliable_phone [ 'rate' ] . " > " . $rate_limit . " \n " ;
$internal_phone_reliability -> create ( $user [ 'id' ], $phone [ 'id' ], \models\Sended :: STATUS_UNKNOWN );
if ( $settings [ 'phone_reliability_unknown_email' ])
{
$success = $internal_mailer -> enqueue ( $user [ 'email' ], EMAIL_PHONE_RELIABILITY_UNKNOWN , [
'phone' => $phone ,
'period' => $period ,
'total' => $unreliable_phone [ 'total' ],
'unreliable' => $unreliable_phone [ 'unreliable' ],
'rate' => $unreliable_phone [ 'rate' ],
]);
if ( ! $success )
{
echo ' Cannot enqueue alert for unreliable unknown phone: ' . $unreliable_phone [ 'id_phone' ] . " \n " ;
continue ;
}
echo " Alert mail for unreliable unknown phone " . $phone [ 'id' ] . ' - ' . $phone [ 'name' ] . " added \n " ;
}
if ( $settings [ 'phone_reliability_unknown_webhook' ])
{
$webhook = [
'reliability_type' => \models\Sended :: STATUS_UNKNOWN ,
'id_phone' => $unreliable_phone [ 'id_phone' ],
'period' => $period ,
'total' => $unreliable_phone [ 'total' ],
'unreliable' => $unreliable_phone [ 'unreliable' ],
'rate' => $unreliable_phone [ 'rate' ],
];
$internal_webhook -> trigger ( $user [ 'id' ], \models\Webhook :: TYPE_PHONE_RELIABILITY , $webhook );
echo " Webhook for unreliable unknown phone " . $phone [ 'id' ] . ' - ' . $phone [ 'name' ] . " triggered \n " ;
}
if ( $settings [ 'phone_reliability_unknown_auto_disable' ])
{
$internal_phone -> update_status ( $unreliable_phone [ 'id_phone' ], \models\Phone :: STATUS_DISABLED );
}
}
2021-03-26 18:53:20 +01:00
}
}
2024-10-26 18:02:11 +02:00
}
2021-06-08 21:01:26 +02:00
2024-10-26 18:02:11 +02:00
/**
* Function to easily populate the database with fake data for testing .
*
* @ param int $id_user : User ID for whom data is to be generated
* @ param int $received_entries : Number of entries to add to the received table
* @ param int $sended_entries : Number of entries to add to the sended table
* @ param int $contact_entries : Number of entries to add to the contact table
*/
public function seed_database ( int $id_user , int $received_entries , int $sended_entries , int $contact_entries )
{
$this -> seed_received ( $id_user , $received_entries );
$this -> seed_sended ( $id_user , $sended_entries );
$this -> seed_contact ( $id_user , $contact_entries );
}
/**
* Fill table received with fake data
*
* @ param int $id_user : User to insert received for
* @ param int $entries : How many received to insert
*/
public function seed_received ( int $id_user , int $entries )
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_received = new \controllers\internals\Received ( $bdd );
$internal_phone = new \controllers\internals\Phone ( $bdd );
$faker = Factory :: create ();
$phones = $internal_phone -> gets_for_user ( $id_user );
for ( $i = 0 ; $i < $entries ; $i ++ )
2021-06-08 21:01:26 +02:00
{
2024-10-26 18:02:11 +02:00
$id_phone = $faker -> randomElement ( $phones )[ 'id' ];
$at = $faker -> dateTimeBetween ( '-1 year' , 'now' ) -> format ( 'Y-m-d H:i:s' );
$text = $faker -> sentence ( rand ( 5 , 10 ), true );
$origin = $faker -> e164PhoneNumber ;
$status = $faker -> randomElement ([ 'read' , 'unread' ]);
$command = false ;
$mms = false ;
$media_ids = [];
$internal_received -> create ( $id_user , $id_phone , $at , $text , $origin , $status , $command , $mms , $media_ids );
2021-06-08 21:01:26 +02:00
}
2024-10-26 18:02:11 +02:00
}
2021-06-17 00:51:33 +02:00
2024-10-26 18:02:11 +02:00
/**
* Fill table sended with fake data
*
* @ param int $id_user : User to insert sended entries for
* @ param int $entries : Number of entries to insert
*/
public function seed_sended ( int $id_user , int $entries )
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_sended = new \controllers\internals\Sended ( $bdd );
$internal_phone = new \controllers\internals\Phone ( $bdd );
$faker = Factory :: create ();
$phones = $internal_phone -> gets_for_user ( $id_user );
for ( $i = 0 ; $i < $entries ; $i ++ )
{
echo $i . " \n " ;
$phone = $faker -> randomElement ( $phones );
$id_phone = $phone [ 'id' ];
$at = $faker -> dateTimeBetween ( '-1 year' , 'now' ) -> format ( 'Y-m-d H:i:s' );
$text = $faker -> sentence ( rand ( 5 , 10 ), true );
$destination = $faker -> e164PhoneNumber ;
$uid = $faker -> uuid ;
$adapter = $phone [ 'adapter' ];
$flash = $faker -> boolean ;
$mms = $faker -> boolean ;
$tag = $faker -> optional () -> word ;
$medias = []; // Add logic for media IDs if needed
$originating_scheduled = $faker -> numberBetween ( 1 , 100 );
$status = $faker -> randomElement ([ \models\Sended :: STATUS_UNKNOWN , \models\Sended :: STATUS_DELIVERED , \models\Sended :: STATUS_FAILED ]);
$internal_sended -> create ( $id_user , $id_phone , $at , $text , $destination , $uid , $adapter , $flash , $mms , $tag , $medias , $originating_scheduled , $status );
2021-06-10 01:31:53 +02:00
}
2024-10-26 18:02:11 +02:00
}
2023-05-30 18:05:38 +02:00
2024-10-26 18:02:11 +02:00
/**
* Fill table contact with fake data
*
* @ param int $id_user : User to insert contacts for
* @ param int $entries : Number of contacts to insert
*/
public function seed_contact ( int $id_user , int $entries )
{
$bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD );
$internal_contact = new \controllers\internals\Contact ( $bdd );
$faker = Factory :: create ();
for ( $i = 0 ; $i < $entries ; $i ++ )
2023-05-30 18:05:38 +02:00
{
2024-10-26 18:02:11 +02:00
$name = $faker -> name ;
$number = $faker -> e164PhoneNumber ;
$data = '[]' ;
2023-05-30 18:05:38 +02:00
2024-10-26 18:02:11 +02:00
$internal_contact -> create ( $id_user , $number , $name , $data );
2023-05-30 18:05:38 +02:00
}
2019-12-08 02:33:53 +01:00
}
2024-10-26 18:02:11 +02:00
}